fix(healthcare): Duplicate Contact error on add Patient (#27427)
* fix: duplicate contact error when linking existing Customer to Patient validation for existing User email and mobile before creating user on Patient update * test: patient - test contact, user creation * fix: test_patient_contact clearing contact breaking other tests sider issues * fix: use db_set instead of set_value * fix(test): overlapping appointments Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
This commit is contained in:
@@ -40,7 +40,7 @@ class Patient(Document):
|
||||
frappe.db.set_value('Patient', self.name, 'status', 'Disabled')
|
||||
else:
|
||||
send_registration_sms(self)
|
||||
self.reload() # self.notify_update()
|
||||
self.reload()
|
||||
|
||||
def on_update(self):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient'):
|
||||
@@ -93,23 +93,27 @@ class Patient(Document):
|
||||
self.language = frappe.db.get_single_value('System Settings', 'language')
|
||||
|
||||
def create_website_user(self):
|
||||
if self.email and not frappe.db.exists('User', self.email):
|
||||
user = frappe.get_doc({
|
||||
'doctype': 'User',
|
||||
'first_name': self.first_name,
|
||||
'last_name': self.last_name,
|
||||
'email': self.email,
|
||||
'user_type': 'Website User',
|
||||
'gender': self.sex,
|
||||
'phone': self.phone,
|
||||
'mobile_no': self.mobile,
|
||||
'birth_date': self.dob
|
||||
})
|
||||
user.flags.ignore_permissions = True
|
||||
user.enabled = True
|
||||
user.send_welcome_email = True
|
||||
user.add_roles('Patient')
|
||||
frappe.db.set_value(self.doctype, self.name, 'user_id', user.name)
|
||||
users = frappe.db.get_all('User', fields=['email', 'mobile_no'], or_filters={'email': self.email, 'mobile_no': self.mobile})
|
||||
if users and users[0]:
|
||||
frappe.throw(_("User exists with Email {}, Mobile {}<br>Please check email / mobile or disable 'Invite as User' to skip creating User")
|
||||
.format(frappe.bold(users[0].email), frappe.bold(users[0].mobile_no)), frappe.DuplicateEntryError)
|
||||
|
||||
user = frappe.get_doc({
|
||||
'doctype': 'User',
|
||||
'first_name': self.first_name,
|
||||
'last_name': self.last_name,
|
||||
'email': self.email,
|
||||
'user_type': 'Website User',
|
||||
'gender': self.sex,
|
||||
'phone': self.phone,
|
||||
'mobile_no': self.mobile,
|
||||
'birth_date': self.dob
|
||||
})
|
||||
user.flags.ignore_permissions = True
|
||||
user.enabled = True
|
||||
user.send_welcome_email = True
|
||||
user.add_roles('Patient')
|
||||
self.db_set('user_id', user.name)
|
||||
|
||||
def autoname(self):
|
||||
patient_name_by = frappe.db.get_single_value('Healthcare Settings', 'patient_name_by')
|
||||
@@ -159,54 +163,65 @@ class Patient(Document):
|
||||
return {'invoice': sales_invoice.name}
|
||||
|
||||
def set_contact(self):
|
||||
if frappe.db.exists('Dynamic Link', {'parenttype':'Contact', 'link_doctype':'Patient', 'link_name':self.name}):
|
||||
old_doc = self.get_doc_before_save()
|
||||
if old_doc.email != self.email or old_doc.mobile != self.mobile or old_doc.phone != self.phone:
|
||||
self.update_contact()
|
||||
else:
|
||||
self.reload()
|
||||
if self.email or self.mobile or self.phone:
|
||||
contact = frappe.get_doc({
|
||||
'doctype': 'Contact',
|
||||
'first_name': self.first_name,
|
||||
'middle_name': self.middle_name,
|
||||
'last_name': self.last_name,
|
||||
'gender': self.sex,
|
||||
'is_primary_contact': 1
|
||||
})
|
||||
contact.append('links', dict(link_doctype='Patient', link_name=self.name))
|
||||
if self.customer:
|
||||
contact.append('links', dict(link_doctype='Customer', link_name=self.customer))
|
||||
|
||||
contact.insert(ignore_permissions=True)
|
||||
self.update_contact(contact) # update email, mobile and phone
|
||||
|
||||
def update_contact(self, contact=None):
|
||||
if not contact:
|
||||
contact_name = get_default_contact(self.doctype, self.name)
|
||||
if contact_name:
|
||||
contact = frappe.get_doc('Contact', contact_name)
|
||||
contact = get_default_contact(self.doctype, self.name)
|
||||
|
||||
if contact:
|
||||
if self.email and self.email != contact.email_id:
|
||||
for email in contact.email_ids:
|
||||
email.is_primary = True if email.email_id == self.email else False
|
||||
contact.add_email(self.email, is_primary=True)
|
||||
contact.set_primary_email()
|
||||
old_doc = self.get_doc_before_save()
|
||||
if not old_doc:
|
||||
return
|
||||
|
||||
if self.mobile and self.mobile != contact.mobile_no:
|
||||
for mobile in contact.phone_nos:
|
||||
mobile.is_primary_mobile_no = True if mobile.phone == self.mobile else False
|
||||
contact.add_phone(self.mobile, is_primary_mobile_no=True)
|
||||
contact.set_primary('mobile_no')
|
||||
if old_doc.email != self.email or old_doc.mobile != self.mobile or old_doc.phone != self.phone:
|
||||
self.update_contact(contact)
|
||||
else:
|
||||
if self.customer:
|
||||
# customer contact exists, link patient
|
||||
contact = get_default_contact('Customer', self.customer)
|
||||
|
||||
if self.phone and self.phone != contact.phone:
|
||||
for phone in contact.phone_nos:
|
||||
phone.is_primary_phone = True if phone.phone == self.phone else False
|
||||
contact.add_phone(self.phone, is_primary_phone=True)
|
||||
contact.set_primary('phone')
|
||||
if contact:
|
||||
self.update_contact(contact)
|
||||
else:
|
||||
self.reload()
|
||||
if self.email or self.mobile or self.phone:
|
||||
contact = frappe.get_doc({
|
||||
'doctype': 'Contact',
|
||||
'first_name': self.first_name,
|
||||
'middle_name': self.middle_name,
|
||||
'last_name': self.last_name,
|
||||
'gender': self.sex,
|
||||
'is_primary_contact': 1
|
||||
})
|
||||
contact.append('links', dict(link_doctype='Patient', link_name=self.name))
|
||||
if self.customer:
|
||||
contact.append('links', dict(link_doctype='Customer', link_name=self.customer))
|
||||
|
||||
contact.flags.ignore_validate = True # disable hook TODO: safe?
|
||||
contact.insert(ignore_permissions=True)
|
||||
self.update_contact(contact.name)
|
||||
|
||||
def update_contact(self, contact):
|
||||
contact = frappe.get_doc('Contact', contact)
|
||||
|
||||
if not contact.has_link(self.doctype, self.name):
|
||||
contact.append('links', dict(link_doctype=self.doctype, link_name=self.name))
|
||||
|
||||
if self.email and self.email != contact.email_id:
|
||||
for email in contact.email_ids:
|
||||
email.is_primary = True if email.email_id == self.email else False
|
||||
contact.add_email(self.email, is_primary=True)
|
||||
contact.set_primary_email()
|
||||
|
||||
if self.mobile and self.mobile != contact.mobile_no:
|
||||
for mobile in contact.phone_nos:
|
||||
mobile.is_primary_mobile_no = True if mobile.phone == self.mobile else False
|
||||
contact.add_phone(self.mobile, is_primary_mobile_no=True)
|
||||
contact.set_primary('mobile_no')
|
||||
|
||||
if self.phone and self.phone != contact.phone:
|
||||
for phone in contact.phone_nos:
|
||||
phone.is_primary_phone = True if phone.phone == self.phone else False
|
||||
contact.add_phone(self.phone, is_primary_phone=True)
|
||||
contact.set_primary('phone')
|
||||
|
||||
contact.flags.skip_patient_update = True
|
||||
contact.save(ignore_permissions=True)
|
||||
|
||||
|
||||
|
||||
@@ -35,3 +35,40 @@ class TestPatient(unittest.TestCase):
|
||||
|
||||
settings.collect_registration_fee = 0
|
||||
settings.save()
|
||||
|
||||
def test_patient_contact(self):
|
||||
frappe.db.sql("""delete from `tabPatient` where name like '_Test Patient%'""")
|
||||
frappe.db.sql("""delete from `tabCustomer` where name like '_Test Patient%'""")
|
||||
frappe.db.sql("""delete from `tabContact` where name like'_Test Patient%'""")
|
||||
frappe.db.sql("""delete from `tabDynamic Link` where parent like '_Test Patient%'""")
|
||||
|
||||
patient = create_patient(patient_name='_Test Patient Contact', email='test-patient@example.com', mobile='+91 0000000001')
|
||||
customer = frappe.db.get_value('Patient', patient, 'customer')
|
||||
self.assertTrue(customer)
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Patient', 'link_name': patient}))
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Customer', 'link_name': customer}))
|
||||
|
||||
# a second patient linking with same customer
|
||||
new_patient = create_patient(email='test-patient@example.com', mobile='+91 0000000009', customer=customer)
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Patient', 'link_name': new_patient}))
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Customer', 'link_name': customer}))
|
||||
|
||||
def test_patient_user(self):
|
||||
frappe.db.sql("""delete from `tabUser` where email='test-patient-user@example.com'""")
|
||||
frappe.db.sql("""delete from `tabDynamic Link` where parent like '_Test Patient%'""")
|
||||
frappe.db.sql("""delete from `tabPatient` where name like '_Test Patient%'""")
|
||||
|
||||
patient = create_patient(patient_name='_Test Patient User', email='test-patient-user@example.com', mobile='+91 0000000009', create_user=True)
|
||||
user = frappe.db.get_value('Patient', patient, 'user_id')
|
||||
self.assertTrue(frappe.db.exists('User', user))
|
||||
|
||||
new_patient = frappe.get_doc({
|
||||
'doctype': 'Patient',
|
||||
'first_name': '_Test Patient Duplicate User',
|
||||
'sex': 'Male',
|
||||
'email': 'test-patient-user@example.com',
|
||||
'mobile': '+91 0000000009',
|
||||
'invite_user': 1
|
||||
})
|
||||
|
||||
self.assertRaises(frappe.exceptions.DuplicateEntryError, new_patient.insert)
|
||||
|
||||
@@ -307,14 +307,18 @@ def create_healthcare_docs(id=0):
|
||||
return patient, practitioner
|
||||
|
||||
|
||||
def create_patient(id=0):
|
||||
def create_patient(id=0, patient_name=None, email=None, mobile=None, customer=None, create_user=False):
|
||||
if frappe.db.exists('Patient', {'firstname':f'_Test Patient {str(id)}'}):
|
||||
patient = frappe.db.get_value('Patient', {'first_name': f'_Test Patient {str(id)}'}, ['name'])
|
||||
return patient
|
||||
|
||||
patient = frappe.new_doc('Patient')
|
||||
patient.first_name = f'_Test Patient {str(id)}'
|
||||
patient.first_name = patient_name if patient_name else f'_Test Patient {str(id)}'
|
||||
patient.sex = 'Female'
|
||||
patient.mobile = mobile
|
||||
patient.email = email
|
||||
patient.customer = customer
|
||||
patient.invite_user = create_user
|
||||
patient.save(ignore_permissions=True)
|
||||
|
||||
return patient.name
|
||||
|
||||
@@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.utils import nowdate
|
||||
from frappe.utils import add_days, nowdate
|
||||
|
||||
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
||||
from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import (
|
||||
@@ -38,7 +38,7 @@ class TestPatientMedicalRecord(unittest.TestCase):
|
||||
medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': vital_signs.name})
|
||||
self.assertTrue(medical_rec)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), invoice=1, procedure_template=1)
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 1), invoice=1, procedure_template=1)
|
||||
procedure = create_procedure(appointment)
|
||||
procedure.start_procedure()
|
||||
procedure.complete_procedure()
|
||||
|
||||
@@ -776,7 +776,7 @@ def update_patient_email_and_phone_numbers(contact, method):
|
||||
Hook validate Contact
|
||||
Update linked Patients' primary mobile and phone numbers
|
||||
'''
|
||||
if 'Healthcare' not in frappe.get_active_domains():
|
||||
if 'Healthcare' not in frappe.get_active_domains() or contact.flags.skip_patient_update:
|
||||
return
|
||||
|
||||
if contact.is_primary_contact and (contact.email_id or contact.mobile_no or contact.phone):
|
||||
@@ -784,9 +784,15 @@ def update_patient_email_and_phone_numbers(contact, method):
|
||||
|
||||
for link in patient_links:
|
||||
contact_details = frappe.db.get_value('Patient', link.get('link_name'), ['email', 'mobile', 'phone'], as_dict=1)
|
||||
|
||||
new_contact_details = {}
|
||||
|
||||
if contact.email_id and contact.email_id != contact_details.get('email'):
|
||||
frappe.db.set_value('Patient', link.get('link_name'), 'email', contact.email_id)
|
||||
new_contact_details.update({'email': contact.email_id})
|
||||
if contact.mobile_no and contact.mobile_no != contact_details.get('mobile'):
|
||||
frappe.db.set_value('Patient', link.get('link_name'), 'mobile', contact.mobile_no)
|
||||
new_contact_details.update({'mobile': contact.mobile_no})
|
||||
if contact.phone and contact.phone != contact_details.get('phone'):
|
||||
frappe.db.set_value('Patient', link.get('link_name'), 'phone', contact.phone)
|
||||
new_contact_details.update({'phone': contact.phone})
|
||||
|
||||
if new_contact_details:
|
||||
frappe.db.set_value('Patient', link.get('link_name'), new_contact_details)
|
||||
|
||||
Reference in New Issue
Block a user