diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index a36e7f8581..eeb5140bbe 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -53,8 +53,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
row = {
'item_code': d.item_code,
- 'item_name': item_record.item_name,
- 'item_group': item_record.item_group,
+ 'item_name': item_record.item_name if item_record else d.item_name,
+ 'item_group': item_record.item_group if item_record else d.item_group,
'description': d.description,
'invoice': d.parent,
'posting_date': d.posting_date,
@@ -316,6 +316,7 @@ def get_items(filters, additional_query_columns):
`tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company,
`tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total,
`tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description,
+ `tabPurchase Invoice Item`.`item_name`, `tabPurchase Invoice Item`.`item_group`,
`tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`,
`tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`,
`tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`,
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index e3aac9aba8..81f0ad3fed 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -655,6 +655,34 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(query, filters)
+@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
+def get_healthcare_service_units(doctype, txt, searchfield, start, page_len, filters):
+ query = """
+ select name
+ from `tabHealthcare Service Unit`
+ where
+ is_group = 0
+ and company = {company}
+ and name like {txt}""".format(
+ company = frappe.db.escape(filters.get('company')), txt = frappe.db.escape('%{0}%'.format(txt)))
+
+ if filters and filters.get('inpatient_record'):
+ from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit
+ service_unit = get_current_healthcare_service_unit(filters.get('inpatient_record'))
+
+ # if the patient is admitted, then appointments should be allowed against the admission service unit,
+ # inspite of it being an Inpatient Occupancy service unit
+ if service_unit:
+ query += " and (allow_appointments = 1 or name = {service_unit})".format(service_unit = frappe.db.escape(service_unit))
+ else:
+ query += " and allow_appointments = 1"
+ else:
+ query += " and allow_appointments = 1"
+
+ return frappe.db.sql(query, filters)
+
+
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
index e55a1433a5..c324228467 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
@@ -100,7 +100,6 @@ class ClinicalProcedure(Document):
allow_start = self.set_actual_qty()
if allow_start:
self.db_set('status', 'In Progress')
- insert_clinical_procedure_to_medical_record(self)
return 'success'
return 'insufficient stock'
@@ -247,21 +246,3 @@ def make_procedure(source_name, target_doc=None):
}, target_doc, set_missing_values)
return doc
-
-
-def insert_clinical_procedure_to_medical_record(doc):
- subject = frappe.bold(_("Clinical Procedure conducted: ")) + cstr(doc.procedure_template) + " "
- if doc.practitioner:
- subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
- if subject and doc.notes:
- subject += ' ' + doc.notes
-
- medical_record = frappe.new_doc('Patient Medical Record')
- medical_record.patient = doc.patient
- medical_record.subject = subject
- medical_record.status = 'Open'
- medical_record.communication_date = doc.start_date
- medical_record.reference_doctype = 'Clinical Procedure'
- medical_record.reference_name = doc.name
- medical_record.reference_owner = doc.owner
- medical_record.save(ignore_permissions=True)
diff --git a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py
index bba521313d..e7319085e4 100644
--- a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py
+++ b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py
@@ -264,7 +264,7 @@ def get_filters(entry):
def get_current_healthcare_service_unit(inpatient_record):
ip_record = frappe.get_doc('Inpatient Record', inpatient_record)
- if ip_record.inpatient_occupancies:
+ if ip_record.status in ['Admitted', 'Discharge Scheduled'] and ip_record.inpatient_occupancies:
return ip_record.inpatient_occupancies[-1].service_unit
return
diff --git a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py
index 10990d412d..8a918b0275 100644
--- a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py
+++ b/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.py
@@ -142,11 +142,15 @@ def create_inpatient(patient):
return inpatient_record
-def get_healthcare_service_unit():
- service_unit = get_random("Healthcare Service Unit", filters={"inpatient_occupancy": 1})
+def get_healthcare_service_unit(unit_name=None):
+ if not unit_name:
+ service_unit = get_random("Healthcare Service Unit", filters={"inpatient_occupancy": 1})
+ else:
+ service_unit = frappe.db.exists("Healthcare Service Unit", {"healthcare_service_unit_name": unit_name})
+
if not service_unit:
service_unit = frappe.new_doc("Healthcare Service Unit")
- service_unit.healthcare_service_unit_name = "Test Service Unit Ip Occupancy"
+ service_unit.healthcare_service_unit_name = unit_name or "Test Service Unit Ip Occupancy"
service_unit.company = "_Test Company"
service_unit.service_unit_type = get_service_unit_type()
service_unit.inpatient_occupancy = 1
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.json b/erpnext/healthcare/doctype/lab_test/lab_test.json
index edf1d911aa..ac61fea3ad 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.json
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.json
@@ -359,6 +359,7 @@
{
"fieldname": "normal_test_items",
"fieldtype": "Table",
+ "label": "Normal Test Result",
"options": "Normal Test Result",
"print_hide": 1
},
@@ -380,6 +381,7 @@
{
"fieldname": "sensitivity_test_items",
"fieldtype": "Table",
+ "label": "Sensitivity Test Result",
"options": "Sensitivity Test Result",
"print_hide": 1,
"report_hide": 1
@@ -529,6 +531,7 @@
{
"fieldname": "descriptive_test_items",
"fieldtype": "Table",
+ "label": "Descriptive Test Result",
"options": "Descriptive Test Result",
"print_hide": 1,
"report_hide": 1
@@ -549,13 +552,14 @@
{
"fieldname": "organism_test_items",
"fieldtype": "Table",
+ "label": "Organism Test Result",
"options": "Organism Test Result",
"print_hide": 1
}
],
"is_submittable": 1,
"links": [],
- "modified": "2020-07-30 18:18:38.516215",
+ "modified": "2020-11-30 11:04:17.195848",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Lab Test",
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py
index 2db7743865..4b57cd073d 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.py
@@ -17,11 +17,9 @@ class LabTest(Document):
self.validate_result_values()
self.db_set('submitted_date', getdate())
self.db_set('status', 'Completed')
- insert_lab_test_to_medical_record(self)
def on_cancel(self):
self.db_set('status', 'Cancelled')
- delete_lab_test_from_medical_record(self)
self.reload()
def on_update(self):
@@ -330,60 +328,6 @@ def get_employee_by_user_id(user_id):
return frappe.get_doc('Employee', emp_id)
return None
-def insert_lab_test_to_medical_record(doc):
- table_row = False
- subject = cstr(doc.lab_test_name)
- if doc.practitioner:
- subject += frappe.bold(_('Healthcare Practitioner: '))+ doc.practitioner + ' '
- if doc.normal_test_items:
- item = doc.normal_test_items[0]
- comment = ''
- if item.lab_test_comment:
- comment = str(item.lab_test_comment)
- table_row = frappe.bold(_('Lab Test Conducted: ')) + item.lab_test_name
-
- if item.lab_test_event:
- table_row += frappe.bold(_('Lab Test Event: ')) + item.lab_test_event
-
- if item.result_value:
- table_row += ' ' + frappe.bold(_('Lab Test Result: ')) + item.result_value
-
- if item.normal_range:
- table_row += ' ' + _('Normal Range: ') + item.normal_range
- table_row += ' ' + comment
-
- elif doc.descriptive_test_items:
- item = doc.descriptive_test_items[0]
-
- if item.lab_test_particulars and item.result_value:
- table_row = item.lab_test_particulars + ' ' + item.result_value
-
- elif doc.sensitivity_test_items:
- item = doc.sensitivity_test_items[0]
-
- if item.antibiotic and item.antibiotic_sensitivity:
- table_row = item.antibiotic + ' ' + item.antibiotic_sensitivity
-
- if table_row:
- subject += ' ' + table_row
- if doc.lab_test_comment:
- subject += ' ' + cstr(doc.lab_test_comment)
-
- medical_record = frappe.new_doc('Patient Medical Record')
- medical_record.patient = doc.patient
- medical_record.subject = subject
- medical_record.status = 'Open'
- medical_record.communication_date = doc.result_date
- medical_record.reference_doctype = 'Lab Test'
- medical_record.reference_name = doc.name
- medical_record.reference_owner = doc.owner
- medical_record.save(ignore_permissions = True)
-
-def delete_lab_test_from_medical_record(self):
- medical_record_id = frappe.db.sql('select name from `tabPatient Medical Record` where reference_name=%s', (self.name))
-
- if medical_record_id and medical_record_id[0][0]:
- frappe.delete_doc('Patient Medical Record', medical_record_id[0][0])
@frappe.whitelist()
def get_lab_test_prescribed(patient):
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
index 79e1775b9d..3d5073b13e 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
@@ -31,12 +31,12 @@ frappe.ui.form.on('Patient Appointment', {
};
});
- frm.set_query('service_unit', function(){
+ frm.set_query('service_unit', function() {
return {
+ query: 'erpnext.controllers.queries.get_healthcare_service_units',
filters: {
- 'is_group': false,
- 'allow_appointments': true,
- 'company': frm.doc.company
+ company: frm.doc.company,
+ inpatient_record: frm.doc.inpatient_record
}
};
});
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index dc820cb464..b05c673d84 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -18,6 +18,7 @@ from erpnext.healthcare.utils import check_fee_validity, get_service_item_and_pr
class PatientAppointment(Document):
def validate(self):
self.validate_overlaps()
+ self.validate_service_unit()
self.set_appointment_datetime()
self.validate_customer_created()
self.set_status()
@@ -68,6 +69,19 @@ class PatientAppointment(Document):
overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4])
frappe.throw(overlapping_details, title=_('Appointments Overlapping'))
+ def validate_service_unit(self):
+ if self.inpatient_record and self.service_unit:
+ from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit
+
+ is_inpatient_occupancy_unit = frappe.db.get_value('Healthcare Service Unit', self.service_unit,
+ 'inpatient_occupancy')
+ service_unit = get_current_healthcare_service_unit(self.inpatient_record)
+ if is_inpatient_occupancy_unit and service_unit != self.service_unit:
+ msg = _('Patient {0} is not admitted in the service unit {1}').format(frappe.bold(self.patient), frappe.bold(self.service_unit)) + ' '
+ msg += _('Appointment for service units with Inpatient Occupancy can only be created against the unit where patient has been admitted.')
+ frappe.throw(msg, title=_('Invalid Healthcare Service Unit'))
+
+
def set_appointment_datetime(self):
self.appointment_datetime = "%s %s" % (self.appointment_date, self.appointment_time or "00:00:00")
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index b681ed1a22..f7ec6f58fc 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import unittest
import frappe
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status, make_encounter
-from frappe.utils import nowdate, add_days
+from frappe.utils import nowdate, add_days, now_datetime
from frappe.utils.make_random import get_random
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
@@ -78,6 +78,59 @@ class TestPatientAppointment(unittest.TestCase):
sales_invoice_name = frappe.db.get_value('Sales Invoice Item', {'reference_dn': appointment.name}, 'parent')
self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'status'), 'Cancelled')
+ def test_appointment_booking_for_admission_service_unit(self):
+ from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
+ from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import \
+ create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
+
+ frappe.db.sql("""delete from `tabInpatient Record`""")
+ patient, medical_department, practitioner = create_healthcare_docs()
+ patient = create_patient()
+ # Schedule Admission
+ ip_record = create_inpatient(patient)
+ ip_record.expected_length_of_stay = 0
+ ip_record.save(ignore_permissions = True)
+
+ # Admit
+ service_unit = get_healthcare_service_unit('Test Service Unit Ip Occupancy')
+ admit_patient(ip_record, service_unit, now_datetime())
+
+ appointment = create_appointment(patient, practitioner, nowdate(), service_unit=service_unit)
+ self.assertEqual(appointment.service_unit, service_unit)
+
+ # Discharge
+ schedule_discharge(frappe.as_json({'patient': patient}))
+ ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
+ mark_invoiced_inpatient_occupancy(ip_record1)
+ discharge_patient(ip_record1)
+
+ def test_invalid_healthcare_service_unit_validation(self):
+ from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
+ from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import \
+ create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
+
+ frappe.db.sql("""delete from `tabInpatient Record`""")
+ patient, medical_department, practitioner = create_healthcare_docs()
+ patient = create_patient()
+ # Schedule Admission
+ ip_record = create_inpatient(patient)
+ ip_record.expected_length_of_stay = 0
+ ip_record.save(ignore_permissions = True)
+
+ # Admit
+ service_unit = get_healthcare_service_unit('Test Service Unit Ip Occupancy')
+ admit_patient(ip_record, service_unit, now_datetime())
+
+ appointment_service_unit = get_healthcare_service_unit('Test Service Unit Ip Occupancy for Appointment')
+ appointment = create_appointment(patient, practitioner, nowdate(), service_unit=appointment_service_unit, save=0)
+ self.assertRaises(frappe.exceptions.ValidationError, appointment.save)
+
+ # Discharge
+ schedule_discharge(frappe.as_json({'patient': patient}))
+ ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
+ mark_invoiced_inpatient_occupancy(ip_record1)
+ discharge_patient(ip_record1)
+
def create_healthcare_docs():
patient = create_patient()
@@ -125,7 +178,7 @@ def create_encounter(appointment):
encounter.submit()
return encounter
-def create_appointment(patient, practitioner, appointment_date, invoice=0, procedure_template=0):
+def create_appointment(patient, practitioner, appointment_date, invoice=0, procedure_template=0, service_unit=None, save=1):
item = create_healthcare_service_items()
frappe.db.set_value('Healthcare Settings', None, 'inpatient_visit_charge_item', item)
frappe.db.set_value('Healthcare Settings', None, 'op_consulting_charge_item', item)
@@ -136,12 +189,15 @@ def create_appointment(patient, practitioner, appointment_date, invoice=0, proce
appointment.appointment_date = appointment_date
appointment.company = '_Test Company'
appointment.duration = 15
+ if service_unit:
+ appointment.service_unit = service_unit
if invoice:
appointment.mode_of_payment = 'Cash'
appointment.paid_amount = 500
if procedure_template:
appointment.procedure_template = create_clinical_procedure_template().get('name')
- appointment.save(ignore_permissions=True)
+ if save:
+ appointment.save(ignore_permissions=True)
return appointment
def create_healthcare_service_items():
@@ -152,6 +208,7 @@ def create_healthcare_service_items():
item.item_name = 'Consulting Charges'
item.item_group = 'Services'
item.is_stock_item = 0
+ item.stock_uom = 'Nos'
item.save()
return item.name
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
index 15675f4673..b646ff9ebe 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
@@ -210,7 +210,7 @@
{
"fieldname": "drug_prescription",
"fieldtype": "Table",
- "label": "Items",
+ "label": "Drug Prescription",
"options": "Drug Prescription"
},
{
@@ -328,7 +328,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-05-16 21:00:08.644531",
+ "modified": "2020-11-30 10:39:00.783119",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Patient Encounter",
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
index 87f42491fc..cc2141790f 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
@@ -17,10 +17,6 @@ class PatientEncounter(Document):
def on_update(self):
if self.appointment:
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
- update_encounter_medical_record(self)
-
- def after_insert(self):
- insert_encounter_to_medical_record(self)
def on_submit(self):
if self.therapies:
@@ -33,8 +29,6 @@ class PatientEncounter(Document):
if self.inpatient_record and self.drug_prescription:
delete_ip_medication_order(self)
- delete_medical_record(self)
-
def set_title(self):
self.title = _('{0} with {1}').format(self.patient_name or self.patient,
self.practitioner_name or self.practitioner)[:100]
@@ -102,61 +96,7 @@ def create_therapy_plan(encounter):
frappe.msgprint(_('Therapy Plan {0} created successfully.').format(frappe.bold(doc.name)), alert=True)
-def insert_encounter_to_medical_record(doc):
- subject = set_subject_field(doc)
- medical_record = frappe.new_doc('Patient Medical Record')
- medical_record.patient = doc.patient
- medical_record.subject = subject
- medical_record.status = 'Open'
- medical_record.communication_date = doc.encounter_date
- medical_record.reference_doctype = 'Patient Encounter'
- medical_record.reference_name = doc.name
- medical_record.reference_owner = doc.owner
- medical_record.save(ignore_permissions=True)
-
-
-def update_encounter_medical_record(encounter):
- medical_record_id = frappe.db.exists('Patient Medical Record', {'reference_name': encounter.name})
-
- if medical_record_id and medical_record_id[0][0]:
- subject = set_subject_field(encounter)
- frappe.db.set_value('Patient Medical Record', medical_record_id[0][0], 'subject', subject)
- else:
- insert_encounter_to_medical_record(encounter)
-
-
-def delete_medical_record(encounter):
- record = frappe.db.exists('Patient Medical Record', {'reference_name', encounter.name})
- if record:
- frappe.delete_doc('Patient Medical Record', record, force=1)
-
def delete_ip_medication_order(encounter):
record = frappe.db.exists('Inpatient Medication Order', {'patient_encounter': encounter.name})
if record:
- frappe.delete_doc('Inpatient Medication Order', record, force=1)
-
-
-def set_subject_field(encounter):
- subject = frappe.bold(_('Healthcare Practitioner: ')) + encounter.practitioner + ' '
- if encounter.symptoms:
- subject += frappe.bold(_('Symptoms: ')) + ' '
- for entry in encounter.symptoms:
- subject += cstr(entry.complaint) + ' '
- else:
- subject += frappe.bold(_('No Symptoms')) + ' '
-
- if encounter.diagnosis:
- subject += frappe.bold(_('Diagnosis: ')) + ' '
- for entry in encounter.diagnosis:
- subject += cstr(entry.diagnosis) + ' '
- else:
- subject += frappe.bold(_('No Diagnosis')) + ' '
-
- if encounter.drug_prescription:
- subject += ' ' + _('Drug(s) Prescribed.')
- if encounter.lab_test_prescription:
- subject += ' ' + _('Test(s) Prescribed.')
- if encounter.procedure_prescription:
- subject += ' ' + _('Procedure(s) Prescribed.')
-
- return subject
+ frappe.delete_doc('Inpatient Medication Order', record, force=1)
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_history_custom_document_type/__init__.py b/erpnext/healthcare/doctype/patient_history_custom_document_type/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.json b/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.json
new file mode 100644
index 0000000000..3025c7b06d
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.json
@@ -0,0 +1,55 @@
+{
+ "actions": [],
+ "creation": "2020-11-25 13:40:23.054469",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "document_type",
+ "date_fieldname",
+ "add_edit_fields",
+ "selected_fields"
+ ],
+ "fields": [
+ {
+ "fieldname": "document_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Document Type",
+ "options": "DocType",
+ "reqd": 1
+ },
+ {
+ "fieldname": "selected_fields",
+ "fieldtype": "Code",
+ "label": "Selected Fields",
+ "read_only": 1
+ },
+ {
+ "fieldname": "add_edit_fields",
+ "fieldtype": "Button",
+ "in_list_view": 1,
+ "label": "Add / Edit Fields"
+ },
+ {
+ "fieldname": "date_fieldname",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Date Fieldname",
+ "reqd": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-11-30 13:54:37.474671",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient History Custom Document Type",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.py b/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.py
new file mode 100644
index 0000000000..f0a1f929f4
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_custom_document_type/patient_history_custom_document_type.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientHistoryCustomDocumentType(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_history_settings/__init__.py b/erpnext/healthcare/doctype/patient_history_settings/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.js b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.js
new file mode 100644
index 0000000000..453da6a12b
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.js
@@ -0,0 +1,133 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Patient History Settings', {
+ refresh: function(frm) {
+ frm.set_query('document_type', 'custom_doctypes', () => {
+ return {
+ filters: {
+ custom: 1,
+ is_submittable: 1,
+ module: 'Healthcare',
+ }
+ };
+ });
+ },
+
+ field_selector: function(frm, doc, standard=1) {
+ let document_fields = [];
+ if (doc.selected_fields)
+ document_fields = (JSON.parse(doc.selected_fields)).map(f => f.fieldname);
+
+ frm.call({
+ method: 'get_doctype_fields',
+ doc: frm.doc,
+ args: {
+ document_type: doc.document_type,
+ fields: document_fields
+ },
+ freeze: true,
+ callback: function(r) {
+ if (r.message) {
+ let doctype = 'Patient History Custom Document Type';
+ if (standard)
+ doctype = 'Patient History Standard Document Type';
+
+ frm.events.show_field_selector_dialog(frm, doc, doctype, r.message);
+ }
+ }
+ });
+ },
+
+ show_field_selector_dialog: function(frm, doc, doctype, doc_fields) {
+ let d = new frappe.ui.Dialog({
+ title: __('{0} Fields', [__(doc.document_type)]),
+ fields: [
+ {
+ label: __('Select Fields'),
+ fieldtype: 'MultiCheck',
+ fieldname: 'fields',
+ options: doc_fields,
+ columns: 2
+ }
+ ]
+ });
+
+ d.$body.prepend(`
+
+
+
`
+ );
+
+ frappe.utils.setup_search(d.$body, '.unit-checkbox', '.label-area');
+
+ d.set_primary_action(__('Save'), () => {
+ let values = d.get_values().fields;
+
+ let selected_fields = [];
+
+ frappe.model.with_doctype(doc.document_type, function() {
+ for (let idx in values) {
+ let value = values[idx];
+
+ let field = frappe.get_meta(doc.document_type).fields.filter((df) => df.fieldname == value)[0];
+ if (field) {
+ selected_fields.push({
+ label: field.label,
+ fieldname: field.fieldname,
+ fieldtype: field.fieldtype
+ });
+ }
+ }
+
+ d.refresh();
+ frappe.model.set_value(doctype, doc.name, 'selected_fields', JSON.stringify(selected_fields));
+ });
+
+ d.hide();
+ });
+
+ d.show();
+ },
+
+ get_date_field_for_dt: function(frm, row) {
+ frm.call({
+ method: 'get_date_field_for_dt',
+ doc: frm.doc,
+ args: {
+ document_type: row.document_type
+ },
+ callback: function(data) {
+ if (data.message) {
+ frappe.model.set_value('Patient History Custom Document Type',
+ row.name, 'date_fieldname', data.message);
+ }
+ }
+ });
+ }
+});
+
+frappe.ui.form.on('Patient History Custom Document Type', {
+ document_type: function(frm, cdt, cdn) {
+ let row = locals[cdt][cdn];
+ if (row.document_type) {
+ frm.events.get_date_field_for_dt(frm, row);
+ }
+ },
+
+ add_edit_fields: function(frm, cdt, cdn) {
+ let row = locals[cdt][cdn];
+ if (row.document_type) {
+ frm.events.field_selector(frm, row, 0);
+ }
+ }
+});
+
+frappe.ui.form.on('Patient History Standard Document Type', {
+ add_edit_fields: function(frm, cdt, cdn) {
+ let row = locals[cdt][cdn];
+ if (row.document_type) {
+ frm.events.field_selector(frm, row);
+ }
+ }
+});
diff --git a/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.json b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.json
new file mode 100644
index 0000000000..143e2c91eb
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.json
@@ -0,0 +1,55 @@
+{
+ "actions": [],
+ "creation": "2020-11-25 13:41:37.675518",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "standard_doctypes",
+ "section_break_2",
+ "custom_doctypes"
+ ],
+ "fields": [
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "custom_doctypes",
+ "fieldtype": "Table",
+ "label": "Custom Document Types",
+ "options": "Patient History Custom Document Type"
+ },
+ {
+ "fieldname": "standard_doctypes",
+ "fieldtype": "Table",
+ "label": "Standard Document Types",
+ "options": "Patient History Standard Document Type",
+ "read_only": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-11-25 13:43:38.511771",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient History Settings",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.py b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.py
new file mode 100644
index 0000000000..2e8c994c3d
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_settings/patient_history_settings.py
@@ -0,0 +1,188 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import json
+from frappe import _
+from frappe.utils import cstr, cint
+from frappe.model.document import Document
+from erpnext.healthcare.page.patient_history.patient_history import get_patient_history_doctypes
+
+class PatientHistorySettings(Document):
+ def validate(self):
+ self.validate_submittable_doctypes()
+ self.validate_date_fieldnames()
+
+ def validate_submittable_doctypes(self):
+ for entry in self.custom_doctypes:
+ if not cint(frappe.db.get_value('DocType', entry.document_type, 'is_submittable')):
+ msg = _('Row #{0}: Document Type {1} is not submittable. ').format(
+ entry.idx, frappe.bold(entry.document_type))
+ msg += _('Patient Medical Record can only be created for submittable document types.')
+ frappe.throw(msg)
+
+ def validate_date_fieldnames(self):
+ for entry in self.custom_doctypes:
+ field = frappe.get_meta(entry.document_type).get_field(entry.date_fieldname)
+ if not field:
+ frappe.throw(_('Row #{0}: No such Field named {1} found in the Document Type {2}.').format(
+ entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)))
+
+ if field.fieldtype not in ['Date', 'Datetime']:
+ frappe.throw(_('Row #{0}: Field {1} in Document Type {2} is not a Date / Datetime field.').format(
+ entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)))
+
+ def get_doctype_fields(self, document_type, fields):
+ multicheck_fields = []
+ doc_fields = frappe.get_meta(document_type).fields
+
+ for field in doc_fields:
+ if field.fieldtype not in frappe.model.no_value_fields or \
+ field.fieldtype in frappe.model.table_fields and not field.hidden:
+ multicheck_fields.append({
+ 'label': field.label,
+ 'value': field.fieldname,
+ 'checked': 1 if field.fieldname in fields else 0
+ })
+
+ return multicheck_fields
+
+ def get_date_field_for_dt(self, document_type):
+ meta = frappe.get_meta(document_type)
+ date_fields = meta.get('fields', {
+ 'fieldtype': ['in', ['Date', 'Datetime']]
+ })
+
+ if date_fields:
+ return date_fields[0].get('fieldname')
+
+def create_medical_record(doc, method=None):
+ medical_record_required = validate_medical_record_required(doc)
+ if not medical_record_required:
+ return
+
+ if frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name }):
+ return
+
+ subject = set_subject_field(doc)
+ date_field = get_date_field(doc.doctype)
+ medical_record = frappe.new_doc('Patient Medical Record')
+ medical_record.patient = doc.patient
+ medical_record.subject = subject
+ medical_record.status = 'Open'
+ medical_record.communication_date = doc.get(date_field)
+ medical_record.reference_doctype = doc.doctype
+ medical_record.reference_name = doc.name
+ medical_record.reference_owner = doc.owner
+ medical_record.save(ignore_permissions=True)
+
+
+def update_medical_record(doc, method=None):
+ medical_record_required = validate_medical_record_required(doc)
+ if not medical_record_required:
+ return
+
+ medical_record_id = frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name })
+
+ if medical_record_id:
+ subject = set_subject_field(doc)
+ frappe.db.set_value('Patient Medical Record', medical_record_id[0][0], 'subject', subject)
+ else:
+ create_medical_record(doc)
+
+
+def delete_medical_record(doc, method=None):
+ medical_record_required = validate_medical_record_required(doc)
+ if not medical_record_required:
+ return
+
+ record = frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name })
+ if record:
+ frappe.delete_doc('Patient Medical Record', record, force=1)
+
+
+def set_subject_field(doc):
+ from frappe.utils.formatters import format_value
+
+ meta = frappe.get_meta(doc.doctype)
+ subject = ''
+ patient_history_fields = get_patient_history_fields(doc)
+
+ for entry in patient_history_fields:
+ fieldname = entry.get('fieldname')
+ if entry.get('fieldtype') == 'Table' and doc.get(fieldname):
+ formatted_value = get_formatted_value_for_table_field(doc.get(fieldname), meta.get_field(fieldname))
+ subject += frappe.bold(_(entry.get('label')) + ': ') + ' ' + cstr(formatted_value) + ' '
+
+ else:
+ if doc.get(fieldname):
+ formatted_value = format_value(doc.get(fieldname), meta.get_field(fieldname), doc)
+ subject += frappe.bold(_(entry.get('label')) + ': ') + cstr(formatted_value) + ' '
+
+ return subject
+
+
+def get_date_field(doctype):
+ dt = get_patient_history_config_dt(doctype)
+
+ return frappe.db.get_value(dt, { 'document_type': doctype }, 'date_fieldname')
+
+
+def get_patient_history_fields(doc):
+ dt = get_patient_history_config_dt(doc.doctype)
+ patient_history_fields = frappe.db.get_value(dt, { 'document_type': doc.doctype }, 'selected_fields')
+
+ if patient_history_fields:
+ return json.loads(patient_history_fields)
+
+
+def get_formatted_value_for_table_field(items, df):
+ child_meta = frappe.get_meta(df.options)
+
+ table_head = ''
+ table_row = ''
+ html = ''
+ create_head = True
+ for item in items:
+ table_row += ''
+ for cdf in child_meta.fields:
+ if cdf.in_list_view:
+ if create_head:
+ table_head += '' + cdf.label + ' '
+ if item.get(cdf.fieldname):
+ table_row += '' + str(item.get(cdf.fieldname)) + ' '
+ else:
+ table_row += ' '
+ create_head = False
+ table_row += ' '
+
+ html += "" + table_head + table_row + "
"
+
+ return html
+
+
+def get_patient_history_config_dt(doctype):
+ if frappe.db.get_value('DocType', doctype, 'custom'):
+ return 'Patient History Custom Document Type'
+ else:
+ return 'Patient History Standard Document Type'
+
+
+def validate_medical_record_required(doc):
+ if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_setup_wizard \
+ or get_module(doc) != 'Healthcare':
+ return False
+
+ if doc.doctype not in get_patient_history_doctypes():
+ return False
+
+ return True
+
+def get_module(doc):
+ module = doc.meta.module
+ if not module:
+ module = frappe.db.get_value('DocType', doc.doctype, 'module')
+
+ return module
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_history_settings/test_patient_history_settings.py b/erpnext/healthcare/doctype/patient_history_settings/test_patient_history_settings.py
new file mode 100644
index 0000000000..c93b788aed
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_settings/test_patient_history_settings.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+import json
+from frappe.utils import getdate
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient
+
+class TestPatientHistorySettings(unittest.TestCase):
+ def setUp(self):
+ dt = create_custom_doctype()
+ settings = frappe.get_single("Patient History Settings")
+ settings.append("custom_doctypes", {
+ "document_type": dt.name,
+ "date_fieldname": "date",
+ "selected_fields": json.dumps([{
+ "label": "Date",
+ "fieldname": "date",
+ "fieldtype": "Date"
+ },
+ {
+ "label": "Rating",
+ "fieldname": "rating",
+ "fieldtype": "Rating"
+ },
+ {
+ "label": "Feedback",
+ "fieldname": "feedback",
+ "fieldtype": "Small Text"
+ }])
+ })
+ settings.save()
+
+ def test_custom_doctype_medical_record(self):
+ # tests for medical record creation of standard doctypes in test_patient_medical_record.py
+ patient = create_patient()
+ doc = create_doc(patient)
+
+ # check for medical record
+ medical_rec = frappe.db.exists("Patient Medical Record", {"status": "Open", "reference_name": doc.name})
+ self.assertTrue(medical_rec)
+
+ medical_rec = frappe.get_doc("Patient Medical Record", medical_rec)
+ expected_subject = "Date: {0}Rating: 3Feedback: Test Patient History Settings ".format(
+ frappe.utils.format_date(getdate()))
+ self.assertEqual(medical_rec.subject, expected_subject)
+ self.assertEqual(medical_rec.patient, patient)
+ self.assertEqual(medical_rec.communication_date, getdate())
+
+
+def create_custom_doctype():
+ if not frappe.db.exists("DocType", "Test Patient Feedback"):
+ doc = frappe.get_doc({
+ "doctype": "DocType",
+ "module": "Healthcare",
+ "custom": 1,
+ "is_submittable": 1,
+ "fields": [{
+ "label": "Date",
+ "fieldname": "date",
+ "fieldtype": "Date"
+ },
+ {
+ "label": "Patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "options": "Patient"
+ },
+ {
+ "label": "Rating",
+ "fieldname": "rating",
+ "fieldtype": "Rating"
+ },
+ {
+ "label": "Feedback",
+ "fieldname": "feedback",
+ "fieldtype": "Small Text"
+ }],
+ "permissions": [{
+ "role": "System Manager",
+ "read": 1
+ }],
+ "name": "Test Patient Feedback",
+ })
+ doc.insert()
+ return doc
+ else:
+ return frappe.get_doc("DocType", "Test Patient Feedback")
+
+
+def create_doc(patient):
+ doc = frappe.get_doc({
+ "doctype": "Test Patient Feedback",
+ "patient": patient,
+ "date": getdate(),
+ "rating": 3,
+ "feedback": "Test Patient History Settings"
+ }).insert()
+ doc.submit()
+
+ return doc
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_history_standard_document_type/__init__.py b/erpnext/healthcare/doctype/patient_history_standard_document_type/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.json b/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.json
new file mode 100644
index 0000000000..b43099c4ea
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.json
@@ -0,0 +1,57 @@
+{
+ "actions": [],
+ "creation": "2020-11-25 13:39:36.014814",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "document_type",
+ "date_fieldname",
+ "add_edit_fields",
+ "selected_fields"
+ ],
+ "fields": [
+ {
+ "fieldname": "document_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Document Type",
+ "options": "DocType",
+ "read_only": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname": "selected_fields",
+ "fieldtype": "Code",
+ "label": "Selected Fields",
+ "read_only": 1
+ },
+ {
+ "fieldname": "add_edit_fields",
+ "fieldtype": "Button",
+ "in_list_view": 1,
+ "label": "Add / Edit Fields"
+ },
+ {
+ "fieldname": "date_fieldname",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Date Fieldname",
+ "read_only": 1,
+ "reqd": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-11-30 13:54:56.773325",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient History Standard Document Type",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.py b/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.py
new file mode 100644
index 0000000000..2d94911855
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_history_standard_document_type/patient_history_standard_document_type.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientHistoryStandardDocumentType(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
index 419d956425..c1d9872a01 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
+++ b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
@@ -18,6 +18,7 @@ class TestPatientMedicalRecord(unittest.TestCase):
patient, medical_department, practitioner = create_healthcare_docs()
appointment = create_appointment(patient, practitioner, nowdate(), invoice=1)
encounter = create_encounter(appointment)
+
# check for encounter
medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': encounter.name})
self.assertTrue(medical_rec)
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.py b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
index c00054421d..51f267f949 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.py
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
@@ -41,7 +41,6 @@ class TherapySession(Document):
def on_submit(self):
self.update_sessions_count_in_therapy_plan()
- insert_session_medical_record(self)
def on_update(self):
if self.appointment:
@@ -142,23 +141,3 @@ def get_therapy_item(therapy, item):
item.reference_dt = 'Therapy Session'
item.reference_dn = therapy.name
return item
-
-
-def insert_session_medical_record(doc):
- subject = frappe.bold(_('Therapy: ')) + cstr(doc.therapy_type) + ' '
- if doc.therapy_plan:
- subject += frappe.bold(_('Therapy Plan: ')) + cstr(doc.therapy_plan) + ' '
- if doc.practitioner:
- subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
- subject += frappe.bold(_('Total Counts Targeted: ')) + cstr(doc.total_counts_targeted) + ' '
- subject += frappe.bold(_('Total Counts Completed: ')) + cstr(doc.total_counts_completed) + ' '
-
- medical_record = frappe.new_doc('Patient Medical Record')
- medical_record.patient = doc.patient
- medical_record.subject = subject
- medical_record.status = 'Open'
- medical_record.communication_date = doc.start_date
- medical_record.reference_doctype = 'Therapy Session'
- medical_record.reference_name = doc.name
- medical_record.reference_owner = doc.owner
- medical_record.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.py b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
index 69d81ff4b0..35c823d739 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.py
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
@@ -12,47 +12,7 @@ class VitalSigns(Document):
def validate(self):
self.set_title()
- def on_submit(self):
- insert_vital_signs_to_medical_record(self)
-
- def on_cancel(self):
- delete_vital_signs_from_medical_record(self)
-
def set_title(self):
self.title = _('{0} on {1}').format(self.patient_name or self.patient,
frappe.utils.format_date(self.signs_date))[:100]
-def insert_vital_signs_to_medical_record(doc):
- subject = set_subject_field(doc)
- medical_record = frappe.new_doc('Patient Medical Record')
- medical_record.patient = doc.patient
- medical_record.subject = subject
- medical_record.status = 'Open'
- medical_record.communication_date = doc.signs_date
- medical_record.reference_doctype = 'Vital Signs'
- medical_record.reference_name = doc.name
- medical_record.reference_owner = doc.owner
- medical_record.flags.ignore_mandatory = True
- medical_record.save(ignore_permissions=True)
-
-def delete_vital_signs_from_medical_record(doc):
- medical_record = frappe.db.get_value('Patient Medical Record', {'reference_name': doc.name})
- if medical_record:
- frappe.delete_doc('Patient Medical Record', medical_record)
-
-def set_subject_field(doc):
- subject = ''
- if doc.temperature:
- subject += frappe.bold(_('Temperature: ')) + cstr(doc.temperature) + ' '
- if doc.pulse:
- subject += frappe.bold(_('Pulse: ')) + cstr(doc.pulse) + ' '
- if doc.respiratory_rate:
- subject += frappe.bold(_('Respiratory Rate: ')) + cstr(doc.respiratory_rate) + ' '
- if doc.bp:
- subject += frappe.bold(_('BP: ')) + cstr(doc.bp) + ' '
- if doc.bmi:
- subject += frappe.bold(_('BMI: ')) + cstr(doc.bmi) + ' '
- if doc.nutrition_note:
- subject += frappe.bold(_('Note: ')) + cstr(doc.nutrition_note) + ' '
-
- return subject
diff --git a/erpnext/healthcare/page/patient_history/patient_history.css b/erpnext/healthcare/page/patient_history/patient_history.css
index 865d6abee0..1bb589164e 100644
--- a/erpnext/healthcare/page/patient_history/patient_history.css
+++ b/erpnext/healthcare/page/patient_history/patient_history.css
@@ -109,6 +109,11 @@
padding-right: 0px;
}
+.patient-history-filter {
+ margin-left: 35px;
+ width: 25%;
+}
+
#page-medical_record .plot-wrapper {
padding: 20px 15px;
border-bottom: 1px solid #d1d8dd;
diff --git a/erpnext/healthcare/page/patient_history/patient_history.html b/erpnext/healthcare/page/patient_history/patient_history.html
index 7a9446dffd..be486c62d1 100644
--- a/erpnext/healthcare/page/patient_history/patient_history.html
+++ b/erpnext/healthcare/page/patient_history/patient_history.html
@@ -1,6 +1,5 @@
-
{%= __("Select Patient") %}
@@ -11,6 +10,13 @@
+
+
diff --git a/erpnext/healthcare/page/patient_history/patient_history.js b/erpnext/healthcare/page/patient_history/patient_history.js
index fe5b7bc488..54343aae44 100644
--- a/erpnext/healthcare/page/patient_history/patient_history.js
+++ b/erpnext/healthcare/page/patient_history/patient_history.js
@@ -1,141 +1,225 @@
-frappe.provide("frappe.patient_history");
+frappe.provide('frappe.patient_history');
frappe.pages['patient_history'].on_page_load = function(wrapper) {
- var me = this;
- var page = frappe.ui.make_app_page({
+ let me = this;
+ let page = frappe.ui.make_app_page({
parent: wrapper,
title: 'Patient History',
single_column: true
});
- frappe.breadcrumbs.add("Healthcare");
+ frappe.breadcrumbs.add('Healthcare');
let pid = '';
- page.main.html(frappe.render_template("patient_history", {}));
- var patient = frappe.ui.form.make_control({
- parent: page.main.find(".patient"),
+ page.main.html(frappe.render_template('patient_history', {}));
+ page.main.find('.header-separator').hide();
+
+ let patient = frappe.ui.form.make_control({
+ parent: page.main.find('.patient'),
df: {
- fieldtype: "Link",
- options: "Patient",
- fieldname: "patient",
- change: function(){
- if(pid != patient.get_value() && patient.get_value()){
+ fieldtype: 'Link',
+ options: 'Patient',
+ fieldname: 'patient',
+ placeholder: __('Select Patient'),
+ only_select: true,
+ change: function() {
+ let patient_id = patient.get_value();
+ if (pid != patient_id && patient_id) {
me.start = 0;
- me.page.main.find(".patient_documents_list").html("");
- get_documents(patient.get_value(), me);
- show_patient_info(patient.get_value(), me);
- show_patient_vital_charts(patient.get_value(), me, "bp", "mmHg", "Blood Pressure");
+ me.page.main.find('.patient_documents_list').html('');
+ setup_filters(patient_id, me);
+ get_documents(patient_id, me);
+ show_patient_info(patient_id, me);
+ show_patient_vital_charts(patient_id, me, 'bp', 'mmHg', 'Blood Pressure');
}
- pid = patient.get_value();
+ pid = patient_id;
}
},
- only_input: true,
});
patient.refresh();
- if (frappe.route_options){
+ if (frappe.route_options) {
patient.set_value(frappe.route_options.patient);
}
- this.page.main.on("click", ".btn-show-chart", function() {
- var btn_show_id = $(this).attr("data-show-chart-id"), pts = $(this).attr("data-pts");
- var title = $(this).attr("data-title");
+ this.page.main.on('click', '.btn-show-chart', function() {
+ let btn_show_id = $(this).attr('data-show-chart-id'), pts = $(this).attr('data-pts');
+ let title = $(this).attr('data-title');
show_patient_vital_charts(patient.get_value(), me, btn_show_id, pts, title);
});
- this.page.main.on("click", ".btn-more", function() {
- var doctype = $(this).attr("data-doctype"), docname = $(this).attr("data-docname");
- if(me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched') == "1"){
- me.page.main.find("."+docname).hide();
- me.page.main.find("."+docname).parent().find('.document-html').show();
- }else{
- if(doctype && docname){
- let exclude = ["patient", "patient_name", 'patient_sex', "encounter_date"];
+ this.page.main.on('click', '.btn-more', function() {
+ let doctype = $(this).attr('data-doctype'), docname = $(this).attr('data-docname');
+ if (me.page.main.find('.'+docname).parent().find('.document-html').attr('data-fetched') == '1') {
+ me.page.main.find('.'+docname).hide();
+ me.page.main.find('.'+docname).parent().find('.document-html').show();
+ } else {
+ if (doctype && docname) {
+ let exclude = ['patient', 'patient_name', 'patient_sex', 'encounter_date'];
frappe.call({
- method: "erpnext.healthcare.utils.render_doc_as_html",
+ method: 'erpnext.healthcare.utils.render_doc_as_html',
args:{
doctype: doctype,
docname: docname,
exclude_fields: exclude
},
+ freeze: true,
callback: function(r) {
- if (r.message){
- me.page.main.find("."+docname).hide();
- me.page.main.find("."+docname).parent().find('.document-html').html(r.message.html+"\
-
");
- me.page.main.find("."+docname).parent().find('.document-html').show();
- me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched', "1");
+ if (r.message) {
+ me.page.main.find('.' + docname).hide();
+
+ me.page.main.find('.' + docname).parent().find('.document-html').html(
+ `${r.message.html}
+
+ `);
+
+ me.page.main.find('.' + docname).parent().find('.document-html').show();
+ me.page.main.find('.' + docname).parent().find('.document-html').attr('data-fetched', '1');
}
- },
- freeze: true
+ }
});
}
}
});
- this.page.main.on("click", ".btn-less", function() {
- var docname = $(this).attr("data-docname");
- me.page.main.find("."+docname).parent().find('.document-id').show();
- me.page.main.find("."+docname).parent().find('.document-html').hide();
+ this.page.main.on('click', '.btn-less', function() {
+ let docname = $(this).attr('data-docname');
+ me.page.main.find('.' + docname).parent().find('.document-id').show();
+ me.page.main.find('.' + docname).parent().find('.document-html').hide();
});
me.start = 0;
- me.page.main.on("click", ".btn-get-records", function(){
+ me.page.main.on('click', '.btn-get-records', function() {
get_documents(patient.get_value(), me);
});
};
-var get_documents = function(patient, me){
+let setup_filters = function(patient, me) {
+ $('.doctype-filter').empty();
+ frappe.xcall(
+ 'erpnext.healthcare.page.patient_history.patient_history.get_patient_history_doctypes'
+ ).then(document_types => {
+ let doctype_filter = frappe.ui.form.make_control({
+ parent: $('.doctype-filter'),
+ df: {
+ fieldtype: 'MultiSelectList',
+ fieldname: 'document_type',
+ placeholder: __('Select Document Type'),
+ input_class: 'input-xs',
+ change: () => {
+ me.start = 0;
+ me.page.main.find('.patient_documents_list').html('');
+ get_documents(patient, me, doctype_filter.get_value(), date_range_field.get_value());
+ },
+ get_data: () => {
+ return document_types.map(document_type => {
+ return {
+ description: document_type,
+ value: document_type
+ };
+ });
+ },
+ }
+ });
+ doctype_filter.refresh();
+
+ $('.date-filter').empty();
+ let date_range_field = frappe.ui.form.make_control({
+ df: {
+ fieldtype: 'DateRange',
+ fieldname: 'date_range',
+ placeholder: __('Date Range'),
+ input_class: 'input-xs',
+ change: () => {
+ let selected_date_range = date_range_field.get_value();
+ if (selected_date_range && selected_date_range.length === 2) {
+ me.start = 0;
+ me.page.main.find('.patient_documents_list').html('');
+ get_documents(patient, me, doctype_filter.get_value(), selected_date_range);
+ }
+ }
+ },
+ parent: $('.date-filter')
+ });
+ date_range_field.refresh();
+ });
+};
+
+let get_documents = function(patient, me, document_types="", selected_date_range="") {
+ let filters = {
+ name: patient,
+ start: me.start,
+ page_length: 20
+ };
+ if (document_types)
+ filters['document_types'] = document_types;
+ if (selected_date_range)
+ filters['date_range'] = selected_date_range;
+
frappe.call({
- "method": "erpnext.healthcare.page.patient_history.patient_history.get_feed",
- args: {
- name: patient,
- start: me.start,
- page_length: 20
- },
- callback: function (r) {
- var data = r.message;
- if(data.length){
+ 'method': 'erpnext.healthcare.page.patient_history.patient_history.get_feed',
+ args: filters,
+ callback: function(r) {
+ let data = r.message;
+ if (data.length) {
add_to_records(me, data);
- }else{
- me.page.main.find(".patient_documents_list").append("
No more records..
");
- me.page.main.find(".btn-get-records").hide();
+ } else {
+ me.page.main.find('.patient_documents_list').append(`
+
+ ${__('No more records..')}
+
`);
+ me.page.main.find('.btn-get-records').hide();
}
}
});
};
-var add_to_records = function(me, data){
- var details = "
";
- var i;
- for(i=0; i "+data[i].subject;
+ if (data[i].subject) {
+ label += " " + data[i].subject;
}
data[i] = add_date_separator(data[i]);
- if(frappe.user_info(data[i].owner).image){
+
+ if (frappe.user_info(data[i].owner).image) {
data[i].imgsrc = frappe.utils.get_file_link(frappe.user_info(data[i].owner).image);
- }
- else{
+ } else {
data[i].imgsrc = false;
}
- var time_line_heading = data[i].practitioner ? `${data[i].practitioner} ` : ``;
- time_line_heading += data[i].reference_doctype + " - "+ data[i].reference_name;
- details += `