Ejemplo n.º 1
0
class PatientContactDetails(models.Model):
    class RelationEnum(enum.IntEnum):
        FAMILY_MEMBER = 1
        FRIEND = 2
        RELATIVE = 3
        NEIGHBOUR = 4
        TRAVEL_TOGETHER = 5
        WHILE_AT_HOSPITAL = 6
        WHILE_AT_SHOP = 7
        WHILE_AT_OFFICE_OR_ESTABLISHMENT = 8
        WORSHIP_PLACE = 9
        OTHERS = 10

    class ModeOfContactEnum(enum.IntEnum):
        # "1. Touched body fluids of the patient (respiratory tract secretions/blood/vomit/saliva/urine/faces)"
        TOUCHED_BODY_FLUIDS = 1
        # "2. Had direct physical contact with the body of the patient
        # including physical examination without full precautions."
        DIRECT_PHYSICAL_CONTACT = 2
        # "3. Touched or cleaned the linens/clothes/or dishes of the patient"
        CLEANED_USED_ITEMS = 3
        # "4. Lives in the same household as the patient."
        LIVE_IN_SAME_HOUSEHOLD = 4
        # "5. Close contact within 3ft (1m) of the confirmed case without precautions."
        CLOSE_CONTACT_WITHOUT_PRECAUTION = 5
        # "6. Passenger of the aeroplane with a confirmed COVID -19 passenger for more than 6 hours."
        CO_PASSENGER_AEROPLANE = 6
        # "7. Health care workers and other contacts who had full PPE while handling the +ve case"
        HEALTH_CARE_WITH_PPE = 7
        # "8. Shared the same space(same class for school/worked in
        # same room/similar and not having a high risk exposure"
        SHARED_SAME_SPACE_WITHOUT_HIGH_EXPOSURE = 8
        # "9. Travel in the same environment (bus/train/Flight) but not having a high-risk exposure as cited above."
        TRAVELLED_TOGETHER_WITHOUT_HIGH_EXPOSURE = 9

    RelationChoices = [(item.value, item.name) for item in RelationEnum]
    ModeOfContactChoices = [(item.value, item.name) for item in ModeOfContactEnum]

    patient = models.ForeignKey(
        PatientRegistration, on_delete=models.PROTECT, related_name="contacted_patients"
    )
    patient_in_contact = models.ForeignKey(
        PatientRegistration,
        on_delete=models.PROTECT,
        null=True,
        related_name="contacts",
    )
    relation_with_patient = models.IntegerField(choices=RelationChoices)
    mode_of_contact = models.IntegerField(choices=ModeOfContactChoices)
    date_of_first_contact = models.DateField(null=True)
    date_of_last_contact = models.DateField(null=True)

    is_primary = models.BooleanField(help_text="If false, then secondary contact")
    condition_of_contact_is_symptomatic = models.BooleanField(
        help_text="While in contact, did the patient showing symptoms"
    )

    deleted = models.BooleanField(default=False)

    objects = BaseManager()
Ejemplo n.º 2
0
class Disease(models.Model):
    patient = models.ForeignKey(PatientRegistration, on_delete=models.CASCADE, related_name="medical_history")
    disease = models.IntegerField(choices=DISEASE_CHOICES)
    details = models.TextField(blank=True, null=True)
    deleted = models.BooleanField(default=False)

    objects = BaseManager()

    class Meta:
        indexes = [PartialIndex(fields=["patient", "disease"], unique=True, where=PQ(deleted=False))]
Ejemplo n.º 3
0
class PatientRegistration(PatientBaseModel, PatientPermissionMixin):
    # fields in the PatientSearch model
    PATIENT_SEARCH_KEYS = [
        "name",
        "gender",
        "phone_number",
        "date_of_birth",
        "year_of_birth",
        "state_id",
    ]

    class SourceEnum(enum.Enum):
        CARE = 10
        COVID_TRACKER = 20
        STAY = 30

    SourceChoices = [(e.value, e.name) for e in SourceEnum]

    class ActionEnum(enum.Enum):
        PENDING = 10
        SPECIALIST_REQUIRED = 30
        PLAN_FOR_HOME_CARE = 40
        FOLLOW_UP_NOT_REQUIRED = 50
        COMPLETE = 60
        REVIEW = 70
        NOT_REACHABLE = 80

    ActionChoices = [(e.value, e.name) for e in ActionEnum]

    class TestTypeEnum(enum.Enum):
        UNK = 10
        ANTIGEN = 20
        RTPCR = 30
        CBNAAT = 40
        TRUENAT = 50

    TestTypeChoices = [(e.value, e.name) for e in TestTypeEnum]

    source = models.IntegerField(choices=SourceChoices,
                                 default=SourceEnum.CARE.value)
    facility = models.ForeignKey("Facility",
                                 on_delete=models.SET_NULL,
                                 null=True)
    nearest_facility = models.ForeignKey(
        "Facility",
        on_delete=models.SET_NULL,
        null=True,
        related_name="nearest_facility",
    )
    meta_info = models.OneToOneField("PatientMetaInfo",
                                     on_delete=models.SET_NULL,
                                     null=True)

    # name_old = EncryptedCharField(max_length=200, default="")
    name = models.CharField(max_length=200, default="")

    age = models.PositiveIntegerField(null=True, blank=True)
    gender = models.IntegerField(choices=GENDER_CHOICES, blank=False)

    # phone_number_old = EncryptedCharField(max_length=14, validators=[phone_number_regex], default="")
    phone_number = models.CharField(max_length=14,
                                    validators=[phone_number_regex],
                                    default="")

    emergency_phone_number = models.CharField(max_length=14,
                                              validators=[phone_number_regex],
                                              default="")

    # address_old = EncryptedTextField(default="")
    address = models.TextField(default="")

    pincode = models.IntegerField(default=0, blank=True, null=True)

    date_of_birth = models.DateField(default=None, null=True)
    year_of_birth = models.IntegerField(default=0, null=True)

    nationality = models.CharField(max_length=255,
                                   default="",
                                   verbose_name="Nationality of Patient")
    passport_no = models.CharField(
        max_length=255,
        default="",
        verbose_name="Passport Number of Foreign Patients")
    # aadhar_no = models.CharField(max_length=255, default="", verbose_name="Aadhar Number of Patient")

    is_medical_worker = models.BooleanField(
        default=False, verbose_name="Is the Patient a Medical Worker")

    blood_group = models.CharField(
        choices=BLOOD_GROUP_CHOICES,
        null=True,
        blank=False,
        max_length=4,
        verbose_name="Blood Group of Patient",
    )

    contact_with_confirmed_carrier = models.BooleanField(
        default=False, verbose_name="Confirmed Contact with a Covid19 Carrier")
    contact_with_suspected_carrier = models.BooleanField(
        default=False, verbose_name="Suspected Contact with a Covid19 Carrier")
    estimated_contact_date = models.DateTimeField(null=True, blank=True)

    past_travel = models.BooleanField(
        default=False,
        verbose_name="Travelled to Any Foreign Countries in the last 28 Days",
    )
    countries_travelled_old = models.TextField(
        null=True,
        blank=True,
        verbose_name="Countries Patient has Travelled to",
        editable=False,
    )
    countries_travelled = JSONField(
        null=True,
        blank=True,
        verbose_name="Countries Patient has Travelled to")
    date_of_return = models.DateTimeField(
        blank=True,
        null=True,
        verbose_name="Return Date from the Last Country if Travelled",
    )

    allergies = models.TextField(default="",
                                 blank=True,
                                 verbose_name="Patient's Known Allergies")

    present_health = models.TextField(
        default="",
        blank=True,
        verbose_name="Patient's Current Health Details")
    ongoing_medication = models.TextField(
        default="",
        blank=True,
        verbose_name="Already pescribed medication if any")
    has_SARI = models.BooleanField(
        default=False, verbose_name="Does the Patient Suffer from SARI")

    is_antenatal = models.BooleanField(
        default=False, verbose_name="Does the patient require Prenatal Care ?")

    ward_old = models.CharField(max_length=255,
                                default="",
                                verbose_name="Ward of Patient",
                                blank=False)

    ward = models.ForeignKey(Ward,
                             on_delete=models.SET_NULL,
                             null=True,
                             blank=True)
    local_body = models.ForeignKey(LocalBody,
                                   on_delete=models.SET_NULL,
                                   null=True,
                                   blank=True)
    district = models.ForeignKey(District,
                                 on_delete=models.SET_NULL,
                                 null=True,
                                 blank=True)
    state = models.ForeignKey(State,
                              on_delete=models.SET_NULL,
                              null=True,
                              blank=True)

    is_migrant_worker = models.BooleanField(
        default=False,
        verbose_name="Is Patient a Migrant Worker",
    )

    disease_status = models.IntegerField(
        choices=DISEASE_STATUS_CHOICES,
        default=1,
        blank=True,
        verbose_name="Disease Status",
    )

    number_of_aged_dependents = models.IntegerField(
        default=0,
        verbose_name="Number of people aged above 60 living with the patient",
        blank=True,
    )
    number_of_chronic_diseased_dependents = models.IntegerField(
        default=0,
        verbose_name=
        "Number of people who have chronic diseases living with the patient",
        blank=True,
    )

    last_edited = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        related_name="patient_last_edited_by",
    )

    action = models.IntegerField(choices=ActionChoices,
                                 default=ActionEnum.PENDING.value)
    review_time = models.DateTimeField(
        null=True, blank=True, verbose_name="Patient's next review time")

    created_by = models.ForeignKey(User,
                                   on_delete=models.SET_NULL,
                                   null=True,
                                   related_name="patient_created_by")
    is_active = models.BooleanField(
        default=True,
        help_text="Not active when discharged, or removed from the watchlist",
    )

    patient_search_id = EncryptedIntegerField(
        help_text="FKey to PatientSearch", null=True)
    date_of_receipt_of_information = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="Patient's information received date")

    test_id = models.CharField(default="",
                               max_length=100,
                               null=True,
                               blank=True)

    # Issue #600 Care_Fe
    date_of_test = models.DateTimeField(null=True,
                                        blank=True,
                                        verbose_name="Patient's test Date")
    srf_id = models.CharField(max_length=200, blank=True, default="")
    test_type = models.IntegerField(choices=TestTypeChoices,
                                    default=TestTypeEnum.UNK.value)

    allow_transfer = models.BooleanField(default=False)

    last_consultation = models.ForeignKey(PatientConsultation,
                                          on_delete=models.SET_NULL,
                                          null=True,
                                          default=None)

    will_donate_blood = models.BooleanField(
        default=None,
        null=True,
        verbose_name="Is Patient Willing to donate Blood",
    )

    fit_for_blood_donation = models.BooleanField(
        default=None,
        null=True,
        verbose_name="Is Patient fit for donating Blood",
    )

    # IDSP REQUIREMENTS
    village = models.CharField(
        max_length=255,
        default=None,
        verbose_name="Vilalge Name of Patient (IDSP Req)",
        null=True,
        blank=True,
    )
    designation_of_health_care_worker = models.CharField(
        max_length=255,
        default=None,
        verbose_name="Designation of Health Care Worker (IDSP Req)",
        null=True,
        blank=True,
    )
    instituion_of_health_care_worker = models.CharField(
        max_length=255,
        default=None,
        verbose_name="Institution of Healtcare Worker (IDSP Req)",
        null=True,
        blank=True,
    )
    transit_details = models.CharField(
        max_length=255,
        default=None,
        verbose_name="Transit Details (IDSP Req)",
        null=True,
        blank=True,
    )
    frontline_worker = models.CharField(
        max_length=255,
        default=None,
        verbose_name="Front Line Worker (IDSP Req)",
        null=True,
        blank=True,
    )
    date_of_result = models.DateTimeField(null=True,
                                          blank=True,
                                          default=None,
                                          verbose_name="Patient's result Date")
    number_of_primary_contacts = models.IntegerField(
        null=True,
        default=None,
        blank=True,
        verbose_name="Number of Primary Contacts")
    number_of_secondary_contacts = models.IntegerField(
        null=True,
        default=None,
        blank=True,
        verbose_name="Number of Secondary Contacts")
    # IDSP Requirements End

    # Vaccination Fields

    is_vaccinated = models.BooleanField(
        default=False,
        verbose_name="Is the Patient Vaccinated Against COVID-19")
    covin_id = models.CharField(
        max_length=15,
        default=None,
        null=True,
        blank=True,
        verbose_name="COVID-19 Vaccination ID",
    )

    # Extras
    cluster_name = models.CharField(
        max_length=255,
        default=None,
        verbose_name="Name/ Cluster of Contact",
        null=True,
        blank=True,
    )
    is_declared_positive = models.BooleanField(
        default=None,
        null=True,
        verbose_name="Is Patient Declared Positive",
    )
    date_declared_positive = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="Date Patient is Declared Positive")

    history = HistoricalRecords(
        excluded_fields=["patient_search_id", "meta_info"])

    objects = BaseManager()

    def __str__(self):
        return "{} - {} - {}".format(self.name, self.age,
                                     self.get_gender_display())

    @property
    def tele_consultation_history(self):
        return self.patientteleconsultation_set.order_by("-id")

    def _alias_recovery_to_recovered(self) -> None:
        if self.disease_status == DiseaseStatusEnum.RECOVERY.value:
            self.disease_status = DiseaseStatusEnum.RECOVERED.value

    def save(self, *args, **kwargs) -> None:
        """
        While saving, if the local body is not null, then district will be local body's district
        Overriding save will help in a collision where the local body's district and district fields are different.

        It also aliases the DiseaseStatus RECOVERED to RECOVERY
        It also creates/updates the PatientSearch model

        Parameters
        ----------
        args: list of args - not used
        kwargs: keyword args - not used

        Returns
        -------
        None
        """
        if self.local_body is not None:
            self.district = self.local_body.district
        if self.district is not None:
            self.state = self.district.state

        self.year_of_birth = (self.date_of_birth.year if self.date_of_birth
                              is not None else datetime.datetime.now().year -
                              self.age)

        today = datetime.date.today()

        if self.date_of_birth:
            self.age = (today.year - self.date_of_birth.year -
                        ((today.month, today.day) <
                         (self.date_of_birth.month, self.date_of_birth.day)))
        elif self.year_of_birth:
            self.age = today.year - self.year_of_birth

        self.date_of_receipt_of_information = (
            self.date_of_receipt_of_information
            if self.date_of_receipt_of_information is not None else
            datetime.datetime.now())

        is_create = self.pk is None
        self._alias_recovery_to_recovered()
        super().save(*args, **kwargs)
        if is_create or self.patient_search_id is None:
            ps = PatientSearch.objects.create(
                patient_external_id=self.external_id,
                name=self.name,
                gender=self.gender,
                phone_number=self.phone_number,
                date_of_birth=self.date_of_birth,
                year_of_birth=self.year_of_birth,
                state_id=self.state_id,
                patient_id=self.pk,
                facility=self.facility,
                allow_transfer=self.allow_transfer,
            )
            self.patient_search_id = ps.pk
            self.save()
        else:
            PatientSearch.objects.filter(pk=self.patient_search_id).update(
                patient_external_id=self.external_id,
                name=self.name,
                gender=self.gender,
                phone_number=self.phone_number,
                date_of_birth=self.date_of_birth,
                year_of_birth=self.year_of_birth,
                state_id=self.state_id,
                facility=self.facility,
                allow_transfer=self.allow_transfer,
                is_active=self.is_active,
            )

    CSV_MAPPING = {
        "external_id": "Patient ID",
        "name": "Patient Name",
        "phone_number": "Patient Phone Number",
        "date_of_birth": "Date of Birth",
        # "year_of_birth": "Year of Birth",
        "facility__name": "Facility Name",
        # "nearest_facility__name": "Nearest Facility",
        "age": "Age",
        "gender": "Gender",
        "ward__name": "Ward Name",
        "ward__number": "Ward Number",
        "local_body__name": "Local Body",
        "district__name": "District",
        "state__name": "State",
        "address": "Address",
        "nationality": "Nationality",
        "disease_status": "Disease Status",
        # "state_test_id": "State Test ID",
        "last_consultation__admitted": "Admission Status",
        "last_consultation__admitted_to": "Admission Room Type",
        # Reffered or transferred
        # remarks
        "number_of_aged_dependents":
        "Number of people aged above 60 living with the patient",
        "number_of_chronic_diseased_dependents":
        "Number of people who have chronic diseases living with the patient",
        "blood_group": "Blood Group",
        "is_medical_worker": "Is the Patient a Medical Worker",
        "contact_with_confirmed_carrier":
        "Confirmed Contact with a Covid19 Carrier",
        "contact_with_suspected_carrier":
        "Suspected Contact with a Covid19 Carrier",
        "estimated_contact_date": "Estimated Contact Date",
        "past_travel":
        "Travelled to Any Foreign Countries in the last 28 Days",
        "countries_travelled": "Countries Patient has Travelled to",
        "date_of_return": "Return Date from the Last Country if Travelled",
        "is_migrant_worker": "Is the Patient a Migrant Worker",
        "present_health": "Patient's Current Health Details",
        "ongoing_medication": "Already pescribed medication if any",
        "has_SARI": "Does the Patient Suffer from SARI",
        "date_of_receipt_of_information":
        "Patient's information received date",
        "will_donate_blood": "Will Patient Donate Blood?",
        "fit_for_blood_donation": "Is Patient Fit for Blood Donation?",
        "date_of_test": "Date of Sample Test",
        "srf_id": "SRF Test Id",
        # IDSP Data
        "village": "Village",
        "designation_of_health_care_worker":
        "Designation of Health Care Worker",
        "instituion_of_health_care_worker":
        "Institution of Health Care Worker",
        "transit_details": "Transit Details",
        "frontline_worker": "FrontLine Worker",
        "date_of_result": "Date of Result",
        "number_of_primary_contacts": "Number of Primary Contacts",
        "number_of_secondary_contacts": "Number of Secondary Contacts",
        "cluster_name": "Name/ Cluster of Contact",
        "is_declared_positive": "Is Patient Declared Positive",
        "date_declared_positive": "Date Patient is Declared Positive",
        # Consultation Data
        "last_consultation__admission_date": "Date of Admission",
        "last_consultation__symptoms_onset_date": "Date of Onset of Symptoms",
        "last_consultation__symptoms": "Symptoms at time of consultation",
        "last_consultation__category": "Category",
        "last_consultation__examination_details": "Examination Details",
        "last_consultation__suggestion": "Suggestion",
        "last_consultation__created_date": "Date of Consultation",
        "last_consultation__discharge_date": "Date of Discharge",
    }

    CSV_MAKE_PRETTY = {
        "gender": (lambda x: REVERSE_GENDER_CHOICES[x]),
        "blood_group": (lambda x: REVERSE_BLOOD_GROUP_CHOICES[x]),
        "disease_status": (lambda x: REVERSE_DISEASE_STATUS_CHOICES[x]),
        "is_medical_worker":
        pretty_boolean,
        "will_donate_blood":
        pretty_boolean,
        "fit_for_blood_donation":
        pretty_boolean,
        "is_migrant_worker":
        pretty_boolean,
        "is_declared_positive":
        pretty_boolean,
        # Consultation Data
        "last_consultation__category":
        (lambda x: REVERSE_SYMPTOM_CATEGORY_CHOICES.get(x, "-")),
        "last_consultation__suggestion":
        (lambda x: PatientConsultation.REVERSE_SUGGESTION_CHOICES.get(x, "-")),
        "last_consultation__admitted":
        pretty_boolean,
        "last_consultation__admitted_to":
        (lambda x: REVERSE_ADMIT_CHOICES.get(x, "-")),
    }
Ejemplo n.º 4
0
class PatientRegistration(PatientBaseModel, PatientPermissionMixin):
    # fields in the PatientSearch model
    PATIENT_SEARCH_KEYS = ["name", "gender", "phone_number", "date_of_birth", "year_of_birth", "state_id"]

    class SourceEnum(enum.Enum):
        CARE = 10
        COVID_TRACKER = 20
        STAY = 30

    SourceChoices = [(e.value, e.name) for e in SourceEnum]

    source = models.IntegerField(choices=SourceChoices, default=SourceEnum.CARE.value)
    facility = models.ForeignKey("Facility", on_delete=models.SET_NULL, null=True)
    nearest_facility = models.ForeignKey(
        "Facility", on_delete=models.SET_NULL, null=True, related_name="nearest_facility"
    )
    meta_info = models.OneToOneField("PatientMetaInfo", on_delete=models.SET_NULL, null=True)

    name = EncryptedCharField(max_length=200)
    age = models.PositiveIntegerField(null=True, blank=True)
    gender = models.IntegerField(choices=GENDER_CHOICES, blank=False)
    phone_number = EncryptedCharField(max_length=14, validators=[phone_number_regex])
    address = EncryptedTextField(default="")

    date_of_birth = models.DateField(default=None, null=True)
    year_of_birth = models.IntegerField(default=0, null=True)

    nationality = models.CharField(max_length=255, default="", verbose_name="Nationality of Patient")
    passport_no = models.CharField(max_length=255, default="", verbose_name="Passport Number of Foreign Patients")
    aadhar_no = models.CharField(max_length=255, default="", verbose_name="Aadhar Number of Patient")

    is_medical_worker = models.BooleanField(default=False, verbose_name="Is the Patient a Medical Worker")

    blood_group = models.CharField(
        choices=BLOOD_GROUP_CHOICES, null=True, blank=True, max_length=4, verbose_name="Blood Group of Patient"
    )

    contact_with_confirmed_carrier = models.BooleanField(
        default=False, verbose_name="Confirmed Contact with a Covid19 Carrier"
    )
    contact_with_suspected_carrier = models.BooleanField(
        default=False, verbose_name="Suspected Contact with a Covid19 Carrier"
    )
    estimated_contact_date = models.DateTimeField(null=True, blank=True)

    past_travel = models.BooleanField(
        default=False, verbose_name="Travelled to Any Foreign Countries in the last 28 Days",
    )
    countries_travelled_old = models.TextField(
        null=True, blank=True, verbose_name="Countries Patient has Travelled to", editable=False
    )
    countries_travelled = JSONField(null=True, blank=True, verbose_name="Countries Patient has Travelled to")
    date_of_return = models.DateTimeField(
        blank=True, null=True, verbose_name="Return Date from the Last Country if Travelled"
    )

    present_health = models.TextField(default="", blank=True, verbose_name="Patient's Current Health Details")
    ongoing_medication = models.TextField(default="", blank=True, verbose_name="Already pescribed medication if any")
    has_SARI = models.BooleanField(default=False, verbose_name="Does the Patient Suffer from SARI")

    local_body = models.ForeignKey(LocalBody, on_delete=models.SET_NULL, null=True, blank=True)
    district = models.ForeignKey(District, on_delete=models.SET_NULL, null=True, blank=True)
    state = models.ForeignKey(State, on_delete=models.SET_NULL, null=True, blank=True)

    disease_status = models.IntegerField(
        choices=DISEASE_STATUS_CHOICES, default=1, blank=True, verbose_name="Disease Status"
    )

    number_of_aged_dependents = models.IntegerField(
        default=0, verbose_name="Number of people aged above 60 living with the patient", blank=True
    )
    number_of_chronic_diseased_dependents = models.IntegerField(
        default=0, verbose_name="Number of people who have chronic diseases living with the patient", blank=True
    )

    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    is_active = models.BooleanField(
        default=True, help_text="Not active when discharged, or removed from the watchlist",
    )

    patient_search_id = EncryptedIntegerField(help_text="FKey to PatientSearch", null=True)
    date_of_receipt_of_information = models.DateTimeField(
        null=True, blank=True, verbose_name="Patient's information received date"
    )

    history = HistoricalRecords(excluded_fields=["patient_search_id", "meta_info"])

    objects = BaseManager()

    def __str__(self):
        return "{} - {} - {}".format(self.name, self.age, self.get_gender_display())

    @property
    def tele_consultation_history(self):
        return self.patientteleconsultation_set.order_by("-id")

    def save(self, *args, **kwargs) -> None:
        """
        While saving, if the local body is not null, then district will be local body's district
        Overriding save will help in a collision where the local body's district and district fields are different.

        It also creates/updates the PatientSearch model

        Parameters
        ----------
        args: list of args - not used
        kwargs: keyword args - not used

        Returns
        -------
        None
        """
        if self.local_body is not None:
            self.district = self.local_body.district
        if self.district is not None:
            self.state = self.district.state

        self.year_of_birth = (
            self.date_of_birth.year if self.date_of_birth is not None else datetime.datetime.now().year - self.age
        )
        self.date_of_receipt_of_information = (
            self.date_of_receipt_of_information
            if self.date_of_receipt_of_information is not None
            else datetime.datetime.now()
        )

        is_create = self.pk is None
        super().save(*args, **kwargs)
        if is_create or self.patient_search_id is None:
            ps = PatientSearch.objects.create(
                name=self.name,
                gender=self.gender,
                phone_number=self.phone_number,
                date_of_birth=self.date_of_birth,
                year_of_birth=self.year_of_birth,
                state_id=self.state_id,
                patient_id=self.pk,
            )
            self.patient_search_id = ps.pk
            self.save()
        else:
            PatientSearch.objects.filter(pk=self.patient_search_id).update(
                name=self.name,
                gender=self.gender,
                phone_number=self.phone_number,
                date_of_birth=self.date_of_birth,
                year_of_birth=self.year_of_birth,
                state_id=self.state_id,
            )