From 3441d123b68497a90e5c4b6a9669c76f01a63f6f Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 11:36:06 +0530 Subject: [PATCH 1/8] feat: additional customer fileds add customer_group, price list, currency etc. rearrange and group fields disable cusotmer edit after save (temp fix) --- erpnext/healthcare/doctype/patient/patient.js | 1 + .../healthcare/doctype/patient/patient.json | 81 +++++++++++++------ erpnext/healthcare/doctype/patient/patient.py | 10 ++- 3 files changed, 65 insertions(+), 27 deletions(-) diff --git a/erpnext/healthcare/doctype/patient/patient.js b/erpnext/healthcare/doctype/patient/patient.js index d5df9567ec..a11faf5806 100644 --- a/erpnext/healthcare/doctype/patient/patient.js +++ b/erpnext/healthcare/doctype/patient/patient.js @@ -40,6 +40,7 @@ frappe.ui.form.on('Patient', { frm.add_custom_button(__('Patient Encounter'), function () { create_encounter(frm); }, 'Create'); + frm.toggle_enable(['customer'], 0); // ToDo, allow change only if no transactions booked or better, add merge option } }, onload: function (frm) { diff --git a/erpnext/healthcare/doctype/patient/patient.json b/erpnext/healthcare/doctype/patient/patient.json index 4258e4011d..2c701fbf94 100644 --- a/erpnext/healthcare/doctype/patient/patient.json +++ b/erpnext/healthcare/doctype/patient/patient.json @@ -24,13 +24,20 @@ "image", "column_break_14", "status", - "inpatient_status", "inpatient_record", - "customer", + "inpatient_status", + "report_preference", "mobile", "email", "phone", - "report_preference", + "customer_details_section", + "customer", + "customer_group", + "territory", + "column_break_24", + "default_currency", + "default_price_list", + "language", "personal_and_social_history", "occupation", "column_break_25", @@ -52,9 +59,7 @@ "surrounding_factors", "other_risk_factors", "more_info", - "patient_details", - "ac_sb", - "default_currency" + "patient_details" ], "fields": [ { @@ -156,6 +161,7 @@ "fieldname": "customer", "fieldtype": "Link", "ignore_user_permissions": 1, + "in_preview": 1, "label": "Customer", "options": "Customer" }, @@ -171,7 +177,8 @@ "fieldtype": "Data", "in_list_view": 1, "in_standard_filter": 1, - "label": "Mobile" + "label": "Mobile", + "options": "Phone" }, { "bold": 1, @@ -186,7 +193,8 @@ "fieldname": "phone", "fieldtype": "Data", "in_filter": 1, - "label": "Phone" + "label": "Phone", + "options": "Phone" }, { "collapsible": 1, @@ -268,25 +276,25 @@ "fieldname": "tobacco_past_use", "fieldtype": "Data", "ignore_xss_filter": 1, - "label": "Tobacco Consumption Habbits (Past)" + "label": "Tobacco Consumption (Past)" }, { "fieldname": "tobacco_current_use", "fieldtype": "Data", "ignore_xss_filter": 1, - "label": "Tobacco Consumption Habbits (Present)" + "label": "Tobacco Consumption (Present)" }, { "fieldname": "alcohol_past_use", "fieldtype": "Data", "ignore_xss_filter": 1, - "label": "Alcohol Consumption Habbits (Past)" + "label": "Alcohol Consumption (Past)" }, { "fieldname": "alcohol_current_use", "fieldtype": "Data", "ignore_user_permissions": 1, - "label": "Alcohol Consumption Habbits (Present)" + "label": "Alcohol Consumption (Present)" }, { "fieldname": "column_break_32", @@ -320,20 +328,11 @@ "ignore_xss_filter": 1, "label": "Patient Details" }, - { - "collapsible": 1, - "fieldname": "ac_sb", - "fieldtype": "Section Break", - "label": "Account Details" - }, { "fieldname": "default_currency", "fieldtype": "Link", - "hidden": 1, - "ignore_xss_filter": 1, - "label": "Default Currency", - "options": "Currency", - "print_hide": 1 + "label": "Billing Currency", + "options": "Currency" }, { "fieldname": "last_name", @@ -351,13 +350,47 @@ "fieldname": "middle_name", "fieldtype": "Data", "label": "Middle Name (optional)" + }, + { + "collapsible": 1, + "fieldname": "customer_details_section", + "fieldtype": "Section Break", + "label": "Customer Details" + }, + { + "fieldname": "customer_group", + "fieldtype": "Link", + "label": "Customer Group", + "options": "Customer Group" + }, + { + "fieldname": "territory", + "fieldtype": "Link", + "label": "Territory", + "options": "Territory" + }, + { + "fieldname": "column_break_24", + "fieldtype": "Column Break" + }, + { + "fieldname": "default_price_list", + "fieldtype": "Link", + "label": "Default Price List", + "options": "Price List" + }, + { + "fieldname": "language", + "fieldtype": "Link", + "label": "Print Language", + "options": "Language" } ], "icon": "fa fa-user", "image_field": "image", "links": [], "max_attachments": 50, - "modified": "2020-04-06 12:55:30.807744", + "modified": "2020-04-11 14:53:48.767245", "modified_by": "Administrator", "module": "Healthcare", "name": "Patient", diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py index e304a0bbc3..f83fac03a6 100644 --- a/erpnext/healthcare/doctype/patient/patient.py +++ b/erpnext/healthcare/doctype/patient/patient.py @@ -26,6 +26,7 @@ class Patient(Document): frappe.db.set_value('Patient', self.name, 'status', 'Disabled') else: send_registration_sms(self) + self.reload() # self.notify_update() def set_full_name(self): if self.last_name: @@ -86,8 +87,8 @@ class Patient(Document): return {'invoice': sales_invoice.name} def create_customer(doc): - customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') - territory = frappe.db.get_single_value('Selling Settings', 'territory') + customer_group = doc.customer_group or frappe.db.get_single_value('Selling Settings', 'customer_group') + territory = doc.territory or frappe.db.get_single_value('Selling Settings', 'territory') if not (customer_group and territory): customer_group = get_root_of('Customer Group') territory = get_root_of('Territory') @@ -98,7 +99,10 @@ def create_customer(doc): 'customer_name': doc.patient_name, 'customer_group': customer_group, 'territory' : territory, - 'customer_type': 'Individual' + 'customer_type': 'Individual', + 'default_currency': doc.default_currency, + 'default_price_ist': doc.default_price_list, + 'language': doc.language }).insert(ignore_permissions=True, ignore_mandatory=True) frappe.db.set_value('Patient', doc.name, 'customer', customer.name) From 9a6bf4e0c97c1b28ae663ab26f5363d25c6bedde Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 11:56:09 +0530 Subject: [PATCH 2/8] fix: vitals added naimg series, minor field rearrangements --- .../healthcare_practitioner.json | 10 +++++++--- .../sample_collection/sample_collection.json | 8 ++++---- .../doctype/vital_signs/vital_signs.json | 20 ++++++++++++++----- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json index fd5b6e12f6..cb747f95ef 100644 --- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json +++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json @@ -1,6 +1,5 @@ { "actions": [], - "allow_copy": 1, "allow_import": 1, "allow_rename": 1, "autoname": "naming_series:", @@ -51,17 +50,20 @@ "fieldname": "first_name", "fieldtype": "Data", "label": "First Name", + "no_copy": 1, "reqd": 1 }, { "fieldname": "middle_name", "fieldtype": "Data", - "label": "Middle Name (Optional)" + "label": "Middle Name (Optional)", + "no_copy": 1 }, { "fieldname": "last_name", "fieldtype": "Data", - "label": "Last Name" + "label": "Last Name", + "no_copy": 1 }, { "fieldname": "image", @@ -226,6 +228,7 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Full Name", + "no_copy": 1, "read_only": 1, "search_index": 1 }, @@ -233,6 +236,7 @@ "fieldname": "naming_series", "fieldtype": "Select", "label": "Series", + "no_copy": 1, "options": "HLC-PRAC-.YYYY.-", "report_hide": 1, "set_only_once": 1 diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.json b/erpnext/healthcare/doctype/sample_collection/sample_collection.json index 39cead8862..c352287faf 100644 --- a/erpnext/healthcare/doctype/sample_collection/sample_collection.json +++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.json @@ -9,14 +9,14 @@ "document_type": "Document", "engine": "InnoDB", "field_order": [ - "inpatient_record", "naming_series", - "invoiced", "patient", - "column_break_4", "patient_age", "patient_sex", + "column_break_4", + "inpatient_record", "company", + "invoiced", "section_break_6", "sample", "sample_uom", @@ -167,7 +167,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-03-25 16:55:52.376834", + "modified": "2020-04-04 19:17:02.707203", "modified_by": "Administrator", "module": "Healthcare", "name": "Sample Collection", diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.json b/erpnext/healthcare/doctype/vital_signs/vital_signs.json index 75726dbe07..fdacda6277 100644 --- a/erpnext/healthcare/doctype/vital_signs/vital_signs.json +++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.json @@ -8,11 +8,8 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "inpatient_record", "patient", "patient_name", - "appointment", - "encounter", "column_break_2", "signs_date", "signs_time", @@ -34,6 +31,11 @@ "bmi", "column_break_14", "nutrition_note", + "sb_references", + "inpatient_record", + "appointment", + "encounter", + "column_break_28", "company", "amended_from" ], @@ -217,7 +219,6 @@ { "fieldname": "company", "fieldtype": "Link", - "hidden": 1, "label": "Company", "options": "Company" }, @@ -229,11 +230,20 @@ "options": "Vital Signs", "print_hide": 1, "read_only": 1 + }, + { + "collapsible": 1, + "fieldname": "sb_references", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_28", + "fieldtype": "Column Break" } ], "is_submittable": 1, "links": [], - "modified": "2020-03-04 17:19:29.549889", + "modified": "2020-04-03 23:06:29.786184", "modified_by": "Administrator", "module": "Healthcare", "name": "Vital Signs", From 174dcee155c033fcd01ffa5d93e8cf4f5a20e767 Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 12:09:06 +0530 Subject: [PATCH 3/8] fix: set company while creating encounter, fields rearranged --- .../patient_appointment.js | 3 +- .../patient_appointment.json | 43 +++++++++++++------ .../patient_appointment.py | 3 +- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js index efa6b249b3..de8dc0e90a 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js @@ -193,7 +193,6 @@ let check_and_set_availability = function(frm) { d.hide(); frm.enable_save(); frm.save(); - frm.enable_save(); d.get_primary_btn().attr('disabled', true); } }); @@ -400,6 +399,7 @@ let create_vital_signs = function(frm) { frappe.route_options = { 'patient': frm.doc.patient, 'appointment': frm.doc.name, + 'company': frm.doc.company }; frappe.new_doc('Vital Signs'); }; @@ -432,6 +432,7 @@ frappe.ui.form.on('Patient Appointment', 'practitioner', function(frm) { callback: function (data) { frappe.model.set_value(frm.doctype, frm.docname, 'department', data.message.department); frappe.model.set_value(frm.doctype, frm.docname, 'paid_amount', data.message.op_consulting_charge); + frappe.model.set_value(frm.doctype, frm.docname, 'billing_item', data.message.op_consulting_charge_item); } }); } diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json index 7f9a671d47..81f7597563 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json @@ -14,13 +14,16 @@ "patient_name", "patient_sex", "patient_age", - "inpatient_record", "column_break_1", - "status", - "procedure_template", - "get_procedure_from_encounter", - "procedure_prescription", + "inpatient_record", + "company", "service_unit", + "status", + "section_break_11", + "get_procedure_from_encounter", + "column_break_13", + "procedure_template", + "procedure_prescription", "section_break_12", "practitioner", "department", @@ -32,9 +35,9 @@ "duration", "section_break_16", "mode_of_payment", - "paid_amount", - "company", + "billing_item", "column_break_2", + "paid_amount", "invoiced", "ref_sales_invoice", "section_break_3", @@ -114,7 +117,8 @@ "label": "Procedure Prescription", "no_copy": 1, "options": "Procedure Prescription", - "print_hide": 1 + "print_hide": 1, + "read_only": 1 }, { "fieldname": "service_unit", @@ -140,6 +144,7 @@ "set_only_once": 1 }, { + "fetch_from": "practitioner.department", "fieldname": "department", "fieldtype": "Link", "ignore_user_permissions": 1, @@ -234,12 +239,9 @@ { "fieldname": "company", "fieldtype": "Link", - "hidden": 1, "label": "Company", "no_copy": 1, - "options": "Company", - "print_hide": 1, - "report_hide": 1 + "options": "Company" }, { "collapsible": 1, @@ -282,10 +284,25 @@ "label": "Series", "options": "HLC-APP-.YYYY.-", "set_only_once": 1 + }, + { + "fieldname": "section_break_11", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "fieldname": "billing_item", + "fieldtype": "Link", + "label": "Billing Item", + "options": "Item", + "read_only": 1 } ], "links": [], - "modified": "2020-03-27 11:27:33.773195", + "modified": "2020-04-07 11:16:34.981240", "modified_by": "Administrator", "module": "Healthcare", "name": "Patient Appointment", diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py index a2d9d0240f..3786bf2861 100755 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py @@ -340,7 +340,8 @@ def make_encounter(source_name, target_doc=None): ['medical_department', 'department'], ['patient_sex', 'patient_sex'], ['encounter_date', 'appointment_date'], - ['invoiced', 'invoiced'] + ['invoiced', 'invoiced'], + ['company', 'company'] ] } }, target_doc) From d2224626c7c94c5a579606091efbea1ab52b591b Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 12:11:59 +0530 Subject: [PATCH 4/8] fix: company when creatign procedure, practitioner name added --- .../patient_encounter/patient_encounter.js | 9 ++++--- .../patient_encounter/patient_encounter.json | 24 +++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js index 83c5d2be9c..0e34164d07 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js @@ -110,7 +110,8 @@ frappe.ui.form.on('Patient Encounter', { 'patient':data.message.patient, 'type': data.message.appointment_type, 'practitioner': data.message.practitioner, - 'invoiced': data.message.invoiced + 'invoiced': data.message.invoiced, + 'company': data.message.company }; frm.set_value(values); } @@ -209,7 +210,8 @@ let create_vital_signs = function (frm) { frappe.route_options = { 'patient': frm.doc.patient, 'appointment': frm.doc.appointment, - 'encounter': frm.doc.name + 'encounter': frm.doc.name, + 'company': frm.doc.company }; frappe.new_doc('Vital Signs'); }; @@ -220,7 +222,8 @@ let create_procedure = function (frm) { } frappe.route_options = { 'patient': frm.doc.patient, - 'medical_department': frm.doc.medical_department + 'medical_department': frm.doc.medical_department, + 'company': frm.doc.company }; frappe.new_doc('Clinical Procedure'); }; diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json index d00e7bc7dd..935935e0c0 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json @@ -17,9 +17,9 @@ "patient_name", "patient_sex", "patient_age", - "company", "column_break_6", "practitioner", + "practitioner_name", "medical_department", "encounter_date", "encounter_time", @@ -43,6 +43,8 @@ "sb_procedures", "procedure_prescription", "encounter_comment", + "sb_refs", + "company", "amended_from" ], "fields": [ @@ -80,7 +82,6 @@ "fieldname": "patient", "fieldtype": "Link", "ignore_user_permissions": 1, - "in_list_view": 1, "in_standard_filter": 1, "label": "Patient", "options": "Patient", @@ -110,7 +111,6 @@ { "fieldname": "company", "fieldtype": "Link", - "hidden": 1, "label": "Company", "options": "Company" }, @@ -121,7 +121,6 @@ { "fieldname": "practitioner", "fieldtype": "Link", - "in_list_view": 1, "in_standard_filter": 1, "label": "Healthcare Practitioner", "options": "Healthcare Practitioner", @@ -272,7 +271,6 @@ "fieldname": "medical_department", "fieldtype": "Link", "ignore_user_permissions": 1, - "in_list_view": 1, "in_standard_filter": 1, "label": "Department", "options": "Medical Department", @@ -287,11 +285,23 @@ { "fieldname": "column_break_17", "fieldtype": "Column Break" + }, + { + "fieldname": "sb_refs", + "fieldtype": "Section Break" + }, + { + "fetch_from": "practitioner.practitioner_name", + "fieldname": "practitioner_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Practitioner Name", + "read_only": 1 } ], "is_submittable": 1, "links": [], - "modified": "2020-02-27 12:42:21.751964", + "modified": "2020-04-03 23:06:16.348846", "modified_by": "Administrator", "module": "Healthcare", "name": "Patient Encounter", @@ -318,7 +328,7 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", - "title_field": "patient", + "title_field": "patient_name", "track_changes": 1, "track_seen": 1 } \ No newline at end of file From 5f923fce2de89abfb3f517573c190e5ef071aaff Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 16:30:00 +0530 Subject: [PATCH 5/8] feat: multi company support --- .../healthcare/doctype/lab_test/lab_test.js | 9 ++++---- .../healthcare/doctype/lab_test/lab_test.json | 15 ++++++------- .../healthcare/doctype/lab_test/lab_test.py | 21 +++++++++++-------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.js b/erpnext/healthcare/doctype/lab_test/lab_test.js index 5b3f4c705a..e7e44dcb48 100644 --- a/erpnext/healthcare/doctype/lab_test/lab_test.js +++ b/erpnext/healthcare/doctype/lab_test/lab_test.js @@ -137,7 +137,7 @@ var get_lab_test_prescribed = function(frm){ }); } else{ - frappe.msgprint(__("Please select Patient to get Lab Tests")); + frappe.msgprint(__("Please select a Patient to get Lab Orders")); } }; @@ -180,9 +180,10 @@ var show_lab_tests = function(frm, result){ return false; }); }); - if(!result){ - var msg = "There are no Lab Test prescribed for "+frm.doc.patient; - $(repl('
%(msg)s
', {msg: msg})).appendTo(html_field); + if(!result.length){ + var msg = "No Lab Orders found for patient " + frm.doc.patient_name + ""; + html_field.empty(); + $(repl('
%(msg)s
', {msg: msg})).appendTo(html_field); } d.show(); }; diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.json b/erpnext/healthcare/doctype/lab_test/lab_test.json index ccbc24b3fb..17dc1edd8c 100644 --- a/erpnext/healthcare/doctype/lab_test/lab_test.json +++ b/erpnext/healthcare/doctype/lab_test/lab_test.json @@ -9,18 +9,18 @@ "document_type": "Document", "engine": "InnoDB", "field_order": [ - "inpatient_record", "naming_series", - "invoiced", "patient", "patient_name", "patient_age", "patient_sex", - "practitioner", + "report_preference", "email", "mobile", - "company", + "practitioner", "c_b", + "inpatient_record", + "company", "department", "status", "submitted_date", @@ -31,7 +31,7 @@ "employee_name", "employee_designation", "user", - "report_preference", + "invoiced", "sb_first", "lab_test_name", "column_break_26", @@ -153,7 +153,7 @@ { "fieldname": "company", "fieldtype": "Link", - "hidden": 1, + "in_standard_filter": 1, "label": "Company", "options": "Company", "print_hide": 1, @@ -168,6 +168,7 @@ "fieldname": "department", "fieldtype": "Link", "ignore_user_permissions": 1, + "in_standard_filter": 1, "label": "Department", "options": "Medical Department", "search_index": 1 @@ -427,7 +428,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-03-23 19:37:06.617764", + "modified": "2020-04-04 19:16:29.131168", "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 4e4015d2f0..e49429ea62 100644 --- a/erpnext/healthcare/doctype/lab_test/lab_test.py +++ b/erpnext/healthcare/doctype/lab_test/lab_test.py @@ -69,9 +69,9 @@ def create_multiple(doctype, docname): lab_test_created = create_lab_test_from_encounter(docname) if lab_test_created: - frappe.msgprint(_("Lab Test(s) "+lab_test_created+" created.")) + frappe.msgprint(_("Lab Test(s) " + lab_test_created + " created.")) else: - frappe.msgprint(_("No Lab Test created")) + frappe.msgprint(_("No Lab Tests created")) def create_lab_test_from_encounter(encounter_id): lab_test_created = False @@ -87,7 +87,7 @@ def create_lab_test_from_encounter(encounter_id): for lab_test_id in lab_test_ids: template = get_lab_test_template(lab_test_id[1]) if template: - lab_test = create_lab_test_doc(lab_test_id[2], encounter.practitioner, patient, template) + lab_test = create_lab_test_doc(lab_test_id[2], encounter.practitioner, patient, template, encounter.company) lab_test.save(ignore_permissions = True) frappe.db.set_value("Lab Prescription", lab_test_id[0], "lab_test_created", 1) if not lab_test_created: @@ -111,7 +111,7 @@ def create_lab_test_from_invoice(invoice_name): if lab_test_created != 1: template = get_lab_test_template(item.item_code) if template: - lab_test = create_lab_test_doc(True, invoice.ref_practitioner, patient, template) + lab_test = create_lab_test_doc(True, invoice.ref_practitioner, patient, template, company, invoice.company) if item.reference_dt == "Lab Prescription": lab_test.prescription = item.reference_dn lab_test.save(ignore_permissions = True) @@ -121,7 +121,7 @@ def create_lab_test_from_invoice(invoice_name): if not lab_tests_created: lab_tests_created = lab_test.name else: - lab_tests_created += ", "+lab_test.name + lab_tests_created += ", " + lab_test.name return lab_tests_created def get_lab_test_template(item): @@ -141,7 +141,7 @@ def check_template_exists(item): return template_exists return False -def create_lab_test_doc(invoiced, practitioner, patient, template): +def create_lab_test_doc(invoiced, practitioner, patient, template, company): lab_test = frappe.new_doc("Lab Test") lab_test.invoiced = invoiced lab_test.practitioner = practitioner @@ -150,11 +150,12 @@ def create_lab_test_doc(invoiced, practitioner, patient, template): lab_test.patient_sex = patient.sex lab_test.email = patient.email lab_test.mobile = patient.mobile + lab_test.report_preference = patient.report_preference lab_test.department = template.department lab_test.template = template.name lab_test.lab_test_group = template.lab_test_group lab_test.result_date = getdate() - lab_test.report_preference = patient.report_preference + lab_test.company = company return lab_test def create_normals(template, lab_test): @@ -190,7 +191,7 @@ def create_specials(template, lab_test): special.require_result_value = 1 special.template = template.name -def create_sample_doc(template, patient, invoice): +def create_sample_doc(template, patient, invoice, company = None): if template.sample: sample_exists = frappe.db.exists({ "doctype": "Sample Collection", @@ -221,6 +222,8 @@ def create_sample_doc(template, patient, invoice): sample_collection.sample = template.sample sample_collection.sample_uom = template.sample_uom sample_collection.sample_qty = template.sample_qty + sample_collection.company = company + if(template.sample_details): sample_collection.sample_details = "Test :" + (template.get("lab_test_name") or template.get("template")) +"\n"+"Collection Detials:\n\t"+template.sample_details sample_collection.save(ignore_permissions=True) @@ -229,7 +232,7 @@ def create_sample_doc(template, patient, invoice): def create_sample_collection(lab_test, template, patient, invoice): if(frappe.db.get_value("Healthcare Settings", None, "create_sample_collection_for_lab_test") == "1"): - sample_collection = create_sample_doc(template, patient, invoice) + sample_collection = create_sample_doc(template, patient, invoice, lab_test.company) if(sample_collection): lab_test.sample = sample_collection.name return lab_test From 0686c3d729ab8046c1a79b233bb6b7d9ece78ba7 Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 16:32:35 +0530 Subject: [PATCH 6/8] feat: multi company support --- .../clinical_procedure/clinical_procedure.js | 35 ++++++++--- .../clinical_procedure.json | 58 ++++++++++++++++--- .../clinical_procedure/clinical_procedure.py | 2 +- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js index 5f36bdd95c..213fa3de1f 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js @@ -175,16 +175,37 @@ frappe.ui.form.on('Clinical Procedure', { name: frm.doc.appointment }, callback: function(data) { - frm.set_value('patient', data.message.patient); - frm.set_value('procedure_template', data.message.procedure_template); - frm.set_value('medical_department', data.message.department); - frm.set_value('start_date', data.message.appointment_date); - frm.set_value('start_time', data.message.appointment_time); - frm.set_value('notes', data.message.notes); - frm.set_value('service_unit', data.message.service_unit); + let values = { + 'patient':data.message.patient, + 'procedure_template': data.message.procedure_template, + 'medical_department': data.message.department, + 'start_date': data.message.appointment_date, + 'start_time': data.message.appointment_time, + 'notes': data.message.notes, + 'service_unit': data.message.service_unit, + 'company': data.message.company + } + frm.set_value(values); } }); } + else{ + let values = { + 'patient': '', + 'patient_name': '', + 'patient_sex': '', + 'patient_age': '', + 'medical_department': '', + 'procedure_template': '', + 'start_date': '', + 'start_time': '', + 'notes': '', + 'service_unit': '', + 'inpatient_record': '' + // 'inpatient_status': '' + }; + frm.set_value(values); + } }, procedure_template: function(frm) { diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json index 3c936bbf27..59a87eccde 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json @@ -7,16 +7,18 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "inpatient_record", "naming_series", - "procedure_template", "appointment", + "column_break_30", + "procedure_template", + "section_break_6", "patient", + "patient_name", "patient_sex", "patient_age", - "prescription", "medical_department", "practitioner", + "practitioner_name", "column_break_7", "status", "service_unit", @@ -26,7 +28,6 @@ "sample", "invoiced", "notes", - "company", "consumables_section", "consume_stock", "items", @@ -36,6 +37,11 @@ "consumable_total_amount", "column_break_27", "consumption_details", + "sb_refs", + "inpatient_record", + "company", + "column_break_34", + "prescription", "amended_from" ], "fields": [ @@ -56,7 +62,7 @@ { "fieldname": "appointment", "fieldtype": "Link", - "in_list_view": 1, + "in_standard_filter": 1, "label": "Appointment", "options": "Patient Appointment" }, @@ -64,7 +70,7 @@ "fetch_from": "inpatient_record.patient", "fieldname": "patient", "fieldtype": "Link", - "in_list_view": 1, + "in_standard_filter": 1, "label": "Patient", "options": "Patient", "reqd": 1 @@ -88,17 +94,20 @@ "fieldtype": "Link", "hidden": 1, "label": "Procedure Prescription", - "options": "Procedure Prescription" + "options": "Procedure Prescription", + "read_only": 1 }, { "fieldname": "medical_department", "fieldtype": "Link", + "in_standard_filter": 1, "label": "Medical Department", "options": "Medical Department" }, { "fieldname": "practitioner", "fieldtype": "Link", + "in_standard_filter": 1, "label": "Healthcare Practitioner", "options": "Healthcare Practitioner" }, @@ -237,11 +246,43 @@ { "fieldname": "section_break_24", "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_30", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_6", + "fieldtype": "Section Break" + }, + { + "collapsible": 1, + "fieldname": "sb_refs", + "fieldtype": "Section Break" + }, + { + "fetch_from": "patient.patient_name", + "fieldname": "patient_name", + "fieldtype": "Data", + "label": "Patient Name", + "read_only": 1 + }, + { + "fetch_from": "practitioner.practitioner_name", + "fieldname": "practitioner_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Practitioner Name", + "read_only": 1 + }, + { + "fieldname": "column_break_34", + "fieldtype": "Column Break" } ], "is_submittable": 1, "links": [], - "modified": "2020-03-02 11:44:27.970651", + "modified": "2020-04-03 23:06:04.009856", "modified_by": "Administrator", "module": "Healthcare", "name": "Clinical Procedure", @@ -263,5 +304,6 @@ "restrict_to_domain": "Healthcare", "sort_field": "modified", "sort_order": "DESC", + "title_field": "patient_name", "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py index db3afc8807..56617e5258 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py @@ -37,7 +37,7 @@ class ClinicalProcedure(Document): template = frappe.get_doc('Clinical Procedure Template', self.procedure_template) if template.sample: patient = frappe.get_doc('Patient', self.patient) - sample_collection = create_sample_doc(template, patient, None) + sample_collection = create_sample_doc(template, patient, None, self.company) frappe.db.set_value('Clinical Procedure', self.name, 'sample', sample_collection.name) self.reload() From f90ea8d622c6ffeed1b8d9c02d2cc166f0fc236e Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 16:34:28 +0530 Subject: [PATCH 7/8] company field added --- .../inpatient_record/inpatient_record.json | 1165 ++++------------- 1 file changed, 220 insertions(+), 945 deletions(-) diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json index 92c11fbb4d..c1b516d536 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json @@ -1,980 +1,255 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2018-07-11 17:48:51.404139", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "autoname": "naming_series:", + "creation": "2018-07-11 17:48:51.404139", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "section_break_1", + "naming_series", + "patient", + "patient_name", + "gender", + "blood_group", + "dob", + "mobile", + "email", + "phone", + "column_break_8", + "company", + "status", + "scheduled_date", + "admitted_datetime", + "expected_discharge", + "discharge_date", + "references", + "cb_admission", + "admission_practitioner", + "admission_encounter", + "cb_discharge", + "discharge_practitioner", + "discharge_encounter", + "sb_inpatient_occupancy", + "inpatient_occupancies", + "btn_transfer", + "sb_discharge_note", + "discharge_note" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_1", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_1", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "naming_series", - "fieldtype": "Select", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Series", - "length": 0, - "no_copy": 0, - "options": "HLC-INP-.YYYY.-", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "naming_series", + "fieldtype": "Select", + "hidden": 1, + "label": "Series", + "options": "HLC-INP-.YYYY.-" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "patient", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Patient", - "length": 0, - "no_copy": 0, - "options": "Patient", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "patient", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Patient", + "options": "Patient", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.patient_name", - "fieldname": "patient_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Patient Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "patient.patient_name", + "fieldname": "patient_name", + "fieldtype": "Data", + "label": "Patient Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.sex", - "fieldname": "gender", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Gender", - "length": 0, - "no_copy": 0, - "options": "Gender", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "patient.sex", + "fieldname": "gender", + "fieldtype": "Link", + "label": "Gender", + "options": "Gender", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.blood_group", - "fieldname": "blood_group", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Blood Group", - "length": 0, - "no_copy": 0, - "options": "\nA Positive\nA Negative\nAB Positive\nAB Negative\nB Positive\nB Negative\nO Positive\nO Negative", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "patient.blood_group", + "fieldname": "blood_group", + "fieldtype": "Select", + "label": "Blood Group", + "options": "\nA Positive\nA Negative\nAB Positive\nAB Negative\nB Positive\nB Negative\nO Positive\nO Negative", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "dob", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Date of birth", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "patient.dob", + "fieldname": "dob", + "fieldtype": "Date", + "label": "Date of birth", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.mobile", - "fieldname": "mobile", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mobile", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "patient.mobile", + "fieldname": "mobile", + "fieldtype": "Data", + "label": "Mobile", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.email", - "fieldname": "email", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Email", - "length": 0, - "no_copy": 0, - "options": "Email", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "patient.email", + "fieldname": "email", + "fieldtype": "Data", + "label": "Email", + "options": "Email", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "patient.phone", - "fieldname": "phone", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Phone", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fetch_from": "patient.phone", + "fieldname": "phone", + "fieldtype": "Data", + "label": "Phone", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_8", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Admission Scheduled\nAdmitted\nDischarge Scheduled\nDischarged", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Status", + "options": "Admission Scheduled\nAdmitted\nDischarge Scheduled\nDischarged", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fieldname": "scheduled_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Admission Schedule Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Today", + "fieldname": "scheduled_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Admission Schedule Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fieldname": "admitted_datetime", - "fieldtype": "Datetime", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Admitted Datetime", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Today", + "fieldname": "admitted_datetime", + "fieldtype": "Datetime", + "in_list_view": 1, + "label": "Admitted Datetime" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "expected_discharge", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Expected Discharge", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "expected_discharge", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Expected Discharge" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "discharge_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Discharge Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "discharge_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Discharge Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "references", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "References", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "references", + "fieldtype": "Section Break", + "label": "References" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_admission", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Admission", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_admission", + "fieldtype": "Column Break", + "label": "Admission" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "admission_practitioner", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Healthcare Practitioner", - "length": 0, - "no_copy": 0, - "options": "Healthcare Practitioner", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "admission_practitioner", + "fieldtype": "Link", + "label": "Healthcare Practitioner", + "options": "Healthcare Practitioner", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "admission_encounter", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Patient Encounter", - "length": 0, - "no_copy": 0, - "options": "Patient Encounter", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "admission_encounter", + "fieldtype": "Link", + "label": "Patient Encounter", + "options": "Patient Encounter", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_discharge", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Discharge", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_discharge", + "fieldtype": "Column Break", + "label": "Discharge" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "discharge_practitioner", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Healthcare Practitioner", - "length": 0, - "no_copy": 0, - "options": "Healthcare Practitioner", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "discharge_practitioner", + "fieldtype": "Link", + "label": "Healthcare Practitioner", + "options": "Healthcare Practitioner", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "discharge_encounter", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Patient Encounter", - "length": 0, - "no_copy": 0, - "options": "Patient Encounter", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "discharge_encounter", + "fieldtype": "Link", + "label": "Patient Encounter", + "options": "Patient Encounter", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_inpatient_occupancy", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Inpatient Occupancy", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sb_inpatient_occupancy", + "fieldtype": "Section Break", + "label": "Inpatient Occupancy" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "inpatient_occupancies", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "options": "Inpatient Occupancy", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "inpatient_occupancies", + "fieldtype": "Table", + "options": "Inpatient Occupancy", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "btn_transfer", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Transfer", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "btn_transfer", + "fieldtype": "Button", + "label": "Transfer" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.status != \"Admission Scheduled\"", - "fieldname": "sb_discharge_note", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Discharge Note", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.status != \"Admission Scheduled\"", + "fieldname": "sb_discharge_note", + "fieldtype": "Section Break", + "label": "Discharge Note" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "discharge_note", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "discharge_note", + "fieldtype": "Text Editor" + }, + { + "fetch_from": "admission_encounter.company", + "fieldname": "company", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Company", + "options": "Company" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-08-21 14:44:43.168245", - "modified_by": "Administrator", - "module": "Healthcare", - "name": "Inpatient Record", - "name_case": "", - "owner": "Administrator", + ], + "links": [], + "modified": "2020-04-07 13:13:39.351977", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Inpatient Record", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Healthcare Administrator", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Healthcare Administrator", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "restrict_to_domain": "Healthcare", - "search_fields": "patient", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "patient", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} + ], + "restrict_to_domain": "Healthcare", + "search_fields": "patient", + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "patient", + "track_changes": 1 +} \ No newline at end of file From c01fb2a4d8752b663828513fe722d4d62414b0da Mon Sep 17 00:00:00 2001 From: anoop Date: Mon, 13 Apr 2020 16:42:03 +0530 Subject: [PATCH 8/8] feat: multi-company billing sales onvoice - filter get items based on company utils - company filters in all get item helper methods utils - refactor appointemnt items --- .../doctype/sales_invoice/sales_invoice.js | 7 +- erpnext/healthcare/utils.py | 96 ++++++++++--------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 6f78db2ccc..7741842fca 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -919,7 +919,7 @@ var get_healthcare_services_to_invoice = function(frm) { if(patient && patient!=selected_patient){ selected_patient = patient; var method = "erpnext.healthcare.utils.get_healthcare_services_to_invoice"; - var args = {patient: patient}; + var args = {patient: patient, company: frm.doc.company}; var columns = (["service", "reference_name", "reference_type"]); get_healthcare_items(frm, true, $results, $placeholder, method, args, columns); } @@ -1063,7 +1063,10 @@ var get_drugs_to_invoice = function(frm) { description:'Quantity will be calculated only for items which has "Nos" as UoM. You may change as required for each invoice item.', get_query: function(doc) { return { - filters: { patient: dialog.get_value("patient"), docstatus: 1 } + filters: { patient: dialog.get_value("patient"), + company: frm.doc.company, + docstatus: 1 + } }; } }, diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py index 246242ad84..e9cc597e81 100644 --- a/erpnext/healthcare/utils.py +++ b/erpnext/healthcare/utils.py @@ -3,82 +3,84 @@ # For license information, please see license.txt from __future__ import unicode_literals +import math +import json import frappe from frappe import _ -import math from frappe.utils import time_diff_in_hours, rounded from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple @frappe.whitelist() -def get_healthcare_services_to_invoice(patient): +def get_healthcare_services_to_invoice(patient, company): patient = frappe.get_doc('Patient', patient) + items_to_invoice = [] if patient: validate_customer_created(patient) - items_to_invoice = [] - patient_appointments = frappe.get_list( - 'Patient Appointment', - fields='*', - filters={'patient': patient.name, 'invoiced': 0}, - order_by='appointment_date' - ) - if patient_appointments: - items_to_invoice = get_fee_validity(patient_appointments) + # Customer validated, build a list of billable services + items_to_invoice += get_appointments_to_invoice(patient, company) + items_to_invoice += get_encounters_to_invoice(patient, company) + items_to_invoice += get_lab_tests_to_invoice(patient, company) + items_to_invoice += get_clinical_procedures_to_invoice(patient, company) + items_to_invoice += get_inpatient_services_to_invoice(patient, company) - encounters = get_encounters_to_invoice(patient) - lab_tests = get_lab_tests_to_invoice(patient) - clinical_procedures = get_clinical_procedures_to_invoice(patient) - inpatient_services = get_inpatient_services_to_invoice(patient) - - items_to_invoice += encounters + lab_tests + clinical_procedures + inpatient_services return items_to_invoice + def validate_customer_created(patient): if not frappe.db.get_value('Patient', patient.name, 'customer'): msg = _("Please set a Customer linked to the Patient") msg += " {0}".format(patient.name) frappe.throw(msg, title=_('Customer Not Found')) -def get_fee_validity(patient_appointments): - if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'): - return - items_to_invoice = [] +def get_appointments_to_invoice(patient, company): + appointments_to_invoice = [] + patient_appointments = frappe.get_list( + 'Patient Appointment', + fields = '*', + filters = {'patient': patient.name, 'company': company, 'invoiced': 0}, + order_by = 'appointment_date' + ) + for appointment in patient_appointments: + # Procedure Appointments if appointment.procedure_template: if frappe.db.get_value('Clinical Procedure Template', appointment.procedure_template, 'is_billable'): - items_to_invoice.append({ + appointments_to_invoice.append({ 'reference_type': 'Patient Appointment', 'reference_name': appointment.name, 'service': appointment.procedure_template }) + # Consultation Appointments, should check fee validity else: - fee_validity = frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name}) - if not fee_validity: - practitioner_charge = 0 - income_account = None - service_item = None - if appointment.practitioner: - service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment) - income_account = get_income_account(appointment.practitioner, appointment.company) - items_to_invoice.append({ - 'reference_type': 'Patient Appointment', - 'reference_name': appointment.name, - 'service': service_item, - 'rate': practitioner_charge, - 'income_account': income_account - }) + if frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups') and \ + frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name}): + continue # Skip invoicing, fee validty present + practitioner_charge = 0 + income_account = None + service_item = None + if appointment.practitioner: + service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment) + income_account = get_income_account(appointment.practitioner, appointment.company) + appointments_to_invoice.append({ + 'reference_type': 'Patient Appointment', + 'reference_name': appointment.name, + 'service': service_item, + 'rate': practitioner_charge, + 'income_account': income_account + }) - return items_to_invoice + return appointments_to_invoice -def get_encounters_to_invoice(patient): +def get_encounters_to_invoice(patient, company): encounters_to_invoice = [] encounters = frappe.get_list( 'Patient Encounter', fields=['*'], - filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1} + filters={'patient': patient.name, 'company': company, 'invoiced': False, 'docstatus': 1} ) if encounters: for encounter in encounters: @@ -101,12 +103,12 @@ def get_encounters_to_invoice(patient): return encounters_to_invoice -def get_lab_tests_to_invoice(patient): +def get_lab_tests_to_invoice(patient, company): lab_tests_to_invoice = [] lab_tests = frappe.get_list( 'Lab Test', fields=['name', 'template'], - filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1} + filters={'patient': patient.name, 'company': company, 'invoiced': False, 'docstatus': 1} ) for lab_test in lab_tests: item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.lab_test_code, ['item', 'is_billable']) @@ -142,12 +144,12 @@ def get_lab_tests_to_invoice(patient): return lab_tests_to_invoice -def get_clinical_procedures_to_invoice(patient): +def get_clinical_procedures_to_invoice(patient, company): clinical_procedures_to_invoice = [] procedures = frappe.get_list( 'Clinical Procedure', fields='*', - filters={'patient': patient.name, 'invoiced': False} + filters={'patient': patient.name, 'company': company, 'invoiced': False} ) for procedure in procedures: if not procedure.appointment: @@ -203,7 +205,7 @@ def get_clinical_procedures_to_invoice(patient): return clinical_procedures_to_invoice -def get_inpatient_services_to_invoice(patient): +def get_inpatient_services_to_invoice(patient, company): services_to_invoice = [] inpatient_services = frappe.db.sql( ''' @@ -213,10 +215,11 @@ def get_inpatient_services_to_invoice(patient): `tabInpatient Record` ip, `tabInpatient Occupancy` io WHERE ip.patient=%s + and ip.company=%s and io.parent=ip.name and io.left=1 and io.invoiced=0 - ''', (patient.name), as_dict=1) + ''', (patient.name, company), as_dict=1) for inpatient_occupancy in inpatient_services: service_unit_type = frappe.db.get_value('Healthcare Service Unit', inpatient_occupancy.service_unit, 'service_unit_type') @@ -376,6 +379,7 @@ def check_fee_validity(appointment): def manage_fee_validity(appointment): fee_validity = check_fee_validity(appointment) + if fee_validity: if appointment.status == 'Cancelled' and fee_validity.visited > 0: fee_validity.visited -= 1