diff --git a/erpnext/config/healthcare.py b/erpnext/config/healthcare.py index 4e8bb483a29..f1339a7b113 100644 --- a/erpnext/config/healthcare.py +++ b/erpnext/config/healthcare.py @@ -33,6 +33,11 @@ def get_data(): "type": "page", "name": "appointment-analytic", "label": _("Appointment Analytics"), + }, + { + "type": "doctype", + "name": "Clinical Procedure", + "label": _("Clinical Procedure"), } ] }, @@ -89,8 +94,8 @@ def get_data(): }, { "type": "doctype", - "name": "Patient Service Unit", - "label": _("Patient Service Unit") + "name": "Healthcare Service Unit", + "label": _("Healthcare Service Unit") } ] }, @@ -157,6 +162,11 @@ def get_data(): "type": "doctype", "name": "Lab Test Template", "label": _("Lab Test Template") + }, + { + "type": "doctype", + "name": "Clinical Procedure Template", + "label": _("Clinical Procedure Template"), } ] } diff --git a/erpnext/healthcare/doctype/patient_service_unit/__init__.py b/erpnext/healthcare/doctype/clinical_procedure/__init__.py similarity index 100% rename from erpnext/healthcare/doctype/patient_service_unit/__init__.py rename to erpnext/healthcare/doctype/clinical_procedure/__init__.py diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js new file mode 100644 index 00000000000..9fc5b376a54 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js @@ -0,0 +1,305 @@ +// Copyright (c) 2017, ESS LLP and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Clinical Procedure', { + setup: function(frm) { + frm.set_query('batch_no', 'items', function(doc, cdt, cdn) { + var item = locals[cdt][cdn]; + if(!item.item_code) { + frappe.throw(__("Please enter Item Code to get Batch Number")); + } else { + if (frm.doc.status == 'In Progress') { + var filters = { + 'item_code': item.item_code, + 'posting_date': frm.doc.start_date || frappe.datetime.nowdate() + }; + if(frm.doc.warehouse) filters["warehouse"] = frm.doc.warehouse; + } else { + filters = { + 'item_code': item.item_code + }; + } + return { + query : "erpnext.controllers.queries.get_batch_no", + filters: filters + }; + } + }); + }, + refresh: function(frm) { + frm.set_query("patient", function () { + return { + filters: {"disabled": 0} + }; + }); + frm.set_query("appointment", function () { + return { + filters: { + "procedure_template": ["not in", null], + "status": ['in', 'Open, Scheduled'] + } + }; + }); + frm.set_query("service_unit", function(){ + return { + filters: { + "is_group": false, + "allow_appointments": true + } + }; + }); + if(frm.doc.consume_stock){ + frm.set_indicator_formatter('item_code', + function(doc) { return (doc.qty<=doc.actual_qty) ? "green" : "orange" ; }); + } + + if (!frm.doc.__islocal && frm.doc.status == 'In Progress'){ + + if(frm.doc.consume_stock){ + var btn_label = 'Complete and Consume'; + var msg = 'Complete '+frm.doc.name+' and Consume Stock?'; + }else{ + btn_label = 'Complete'; + msg = 'Complete '+frm.doc.name+'?'; + } + + frm.add_custom_button(__(btn_label), function () { + frappe.confirm( + __(msg), + function(){ + frappe.call({ + doc: frm.doc, + method: "complete", + callback: function(r) { + if(!r.exc){ + cur_frm.reload_doc(); + } + } + }); + } + ); + }); + }else if (frm.doc.status == 'Draft') { + frm.add_custom_button(__("Start"), function () { + frappe.call({ + doc: frm.doc, + method: "start", + callback: function(r) { + if(!r.exc){ + if(frm.doc.status == 'Draft'){ + frappe.confirm( + __("Stock quantity to start procedure is not available in the warehouse. Do you want to record a Stock Transfer"), + function(){ + frappe.call({ + doc: frm.doc, + method: "make_material_transfer", + callback: function(r) { + if(!r.exc){ + cur_frm.reload_doc(); + var doclist = frappe.model.sync(r.message); + frappe.set_route("Form", doclist[0].doctype, doclist[0].name); + } + } + }); + } + ); + }else{ + cur_frm.reload_doc(); + } + } + } + }); + }); + } + if (frm.doc.__islocal){ + frm.set_df_property("consumables", "hidden", 1); + }else{ + frm.set_df_property("consumables", "hidden", 0); + } + }, + onload: function(frm){ + if(frm.doc.status == 'Completed'){ + frm.set_df_property("items", "read_only", 1); + } + if(frm.is_new()) { + frm.add_fetch("procedure_template", "medical_department", "medical_department"); + frm.set_value("start_time", null); + } + }, + patient: function(frm) { + if(frm.doc.patient){ + frappe.call({ + "method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail", + args: { + patient: frm.doc.patient + }, + callback: function (data) { + let age = ""; + if(data.message.dob){ + age = calculate_age(data.message.dob); + }else if (data.message.age){ + age = data.message.age; + if(data.message.age_as_on){ + age = age+" as on "+data.message.age_as_on; + } + } + frm.set_value("patient_age", age); + frm.set_value("patient_sex", data.message.sex); + } + }); + }else{ + frm.set_value("patient_age", ""); + frm.set_value("patient_sex", ""); + } + }, + appointment: function(frm) { + if(frm.doc.appointment){ + frappe.call({ + "method": "frappe.client.get", + args: { + doctype: "Patient Appointment", + 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); + } + }); + } + }, + procedure_template: function(frm) { + if(frm.doc.procedure_template){ + frappe.call({ + "method": "frappe.client.get", + args: { + doctype: "Clinical Procedure Template", + name: frm.doc.procedure_template + }, + callback: function (data) { + frm.set_value("medical_department", data.message.medical_department); + frm.set_value("consume_stock", data.message.consume_stock); + if(!frm.doc.warehouse){ + frappe.call({ + method: "frappe.client.get_value", + args: { + doctype: "Stock Settings", + fieldname: "default_warehouse" + }, + callback: function (data) { + frm.set_value("warehouse", data.message.default_warehouse); + } + }); + } + } + }); + }else{ + frm.set_value("consume_stock", 0); + } + }, + service_unit: function(frm) { + if(frm.doc.service_unit){ + frappe.call({ + method: "frappe.client.get_value", + args:{ + fieldname: "warehouse", + doctype: "Healthcare Service Unit", + filters:{name: frm.doc.service_unit}, + }, + callback: function(data) { + if(data.message){ + frm.set_value("warehouse", data.message.warehouse); + } + } + }); + } + } +}); + +cur_frm.set_query("procedure_template", function(doc) { + return { + filters: { + 'medical_department': doc.medical_department + } + }; +}); + +cur_frm.set_query("appointment", function() { + return { + filters: { + status:['in',["Open"]] + } + }; +}); + +frappe.ui.form.on('Clinical Procedure Item', { + qty: function(frm, cdt, cdn){ + var d = locals[cdt][cdn]; + frappe.model.set_value(cdt, cdn, "transfer_qty", d.qty*d.conversion_factor); + }, + uom: function(doc, cdt, cdn){ + var d = locals[cdt][cdn]; + if(d.uom && d.item_code){ + return frappe.call({ + method: "erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details", + args: { + item_code: d.item_code, + uom: d.uom, + qty: d.qty + }, + callback: function(r) { + if(r.message) { + frappe.model.set_value(cdt, cdn, r.message); + } + } + }); + } + }, + item_code: function(frm, cdt, cdn) { + var d = locals[cdt][cdn]; + let args = null; + if(d.item_code) { + args = { + 'item_code' : d.item_code, + 'transfer_qty' : d.transfer_qty, + 'company' : frm.doc.company, + 'quantity' : d.qty + }; + return frappe.call({ + doc: frm.doc, + method: "get_item_details", + args: args, + callback: function(r) { + if(r.message) { + var d = locals[cdt][cdn]; + $.each(r.message, function(k, v){ + d[k] = v; + }); + refresh_field("items"); + } + } + }); + } + } +}); + +var calculate_age = function(birth) { + var ageMS = Date.parse(Date()) - Date.parse(birth); + var age = new Date(); + age.setTime(ageMS); + var years = age.getFullYear() - 1970; + return years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)"; +}; + +// List Stock items +cur_frm.set_query("item_code", "items", function() { + return { + filters: { + is_stock_item:1 + } + }; +}); diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json new file mode 100644 index 00000000000..c687393b329 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json @@ -0,0 +1,697 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "naming_series:", + "beta": 1, + "creation": "2017-04-07 12:52:43.542429", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "naming_series", + "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": "Series", + "length": 0, + "no_copy": 0, + "options": "PRO-", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "appointment", + "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": "Appointment", + "length": 0, + "no_copy": 0, + "options": "Patient Appointment", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "patient_age", + "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": "Age", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "patient_sex", + "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": "Gender", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "procedure_template", + "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": "Procedure Template", + "length": 0, + "no_copy": 0, + "options": "Clinical Procedure Template", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "medical_department", + "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": "Medical Department", + "length": 0, + "no_copy": 0, + "options": "Medical Department", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_7", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "service_unit", + "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": "Service Unit", + "length": 0, + "no_copy": 0, + "options": "Healthcare Service Unit", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "warehouse", + "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": "Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Today", + "fieldname": "start_date", + "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": "Start 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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "start_time", + "fieldtype": "Time", + "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": "Time", + "length": 0, + "no_copy": 0, + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sample", + "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": "Sample", + "length": 0, + "no_copy": 0, + "options": "Sample Collection", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_invoiced", + "fieldtype": "Check", + "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": "Is Invoiced", + "length": 0, + "no_copy": 0, + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "notes", + "fieldtype": "Small Text", + "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": "Notes", + "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": 1, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "company", + "fieldtype": "Link", + "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": "Company", + "length": 0, + "no_copy": 0, + "options": "Company", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "fieldname": "consume_stock", + "fieldtype": "Check", + "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": "Consume Stock", + "length": 0, + "no_copy": 0, + "options": "", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.consume_stock == 1", + "fieldname": "consumables", + "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": "Consumables", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "items", + "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, + "label": "Consumables", + "length": 0, + "no_copy": 0, + "options": "Clinical Procedure Item", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "", + "fieldname": "status", + "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": "Status", + "length": 0, + "no_copy": 0, + "options": "Draft\nIn Progress\nCompleted\nPending\nCancelled", + "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 + } + ], + "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-05-04 11:23:32.884076", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Clinical Procedure", + "name_case": "", + "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": "Nursing User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 +} \ 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 new file mode 100644 index 00000000000..6346f1f2df8 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, ESS LLP and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.utils import cint, flt, nowdate, nowtime +from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account +from erpnext.healthcare.doctype.lab_test.lab_test import create_sample_doc +from erpnext.stock.stock_ledger import get_previous_sle + +class ClinicalProcedure(Document): + def validate(self): + if self.consume_stock and not self.status == 'Draft': + if not self.warehouse: + frappe.throw(("Set warehouse for Procedure {0} ").format(self.name)) + self.set_actual_qty() + + def before_insert(self): + if self.consume_stock: + set_stock_items(self, self.procedure_template, "Clinical Procedure Template") + self.set_actual_qty(); + + def after_insert(self): + if self.appointment: + frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed") + 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) + frappe.db.set_value("Clinical Procedure", self.name, "sample", sample_collection.name) + self.reload() + + def complete(self): + if self.consume_stock: + create_stock_entry(self) + frappe.db.set_value("Clinical Procedure", self.name, "status", 'Completed') + + def start(self): + allow_start = self.set_actual_qty() + if allow_start: + self.status = 'In Progress' + else: + self.status = 'Draft' + + self.save() + + def set_actual_qty(self): + allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")) + + allow_start = True + for d in self.get('items'): + previous_sle = get_previous_sle({ + "item_code": d.item_code, + "warehouse": self.warehouse, + "posting_date": nowdate(), + "posting_time": nowtime() + }) + + # get actual stock at source warehouse + d.actual_qty = previous_sle.get("qty_after_transaction") or 0 + + # validate qty + if not allow_negative_stock and d.actual_qty < d.qty: + allow_start = False + + return allow_start + + def make_material_transfer(self): + stock_entry = frappe.new_doc("Stock Entry") + + stock_entry.purpose = "Material Transfer" + stock_entry.to_warehouse = self.warehouse + expense_account = get_account(None, "expense_account", "Healthcare Settings", self.company) + for item in self.items: + if item.qty > item.actual_qty: + se_child = stock_entry.append('items') + se_child.item_code = item.item_code + se_child.item_name = item.item_name + se_child.uom = item.uom + se_child.stock_uom = item.stock_uom + se_child.qty = flt(item.qty-item.actual_qty) + se_child.t_warehouse = self.warehouse + # in stock uom + se_child.transfer_qty = flt(item.transfer_qty) + se_child.conversion_factor = flt(item.conversion_factor) + cost_center = frappe.db.get_value('Company', self.company, 'cost_center') + se_child.cost_center = cost_center + se_child.expense_account = expense_account + return stock_entry.as_dict() + + def get_item_details(self, args=None): + item = frappe.db.sql("""select stock_uom, description, image, item_name, + expense_account, buying_cost_center, item_group from `tabItem` + where name = %s + and disabled=0 + and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""", + (args.get('item_code'), nowdate()), as_dict = 1) + if not item: + frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get('item_code'))) + + item = item[0] + + ret = { + 'uom' : item.stock_uom, + 'stock_uom' : item.stock_uom, + 'item_name' : item.item_name, + 'quantity' : 0, + 'transfer_qty' : 0, + 'conversion_factor' : 1 + } + return ret + + +@frappe.whitelist() +def set_stock_items(doc, stock_detail_parent, parenttype): + item_dict = get_item_dict("Clinical Procedure Item", stock_detail_parent, parenttype) + + for d in item_dict: + se_child = doc.append('items') + se_child.item_code = d["item_code"] + se_child.item_name = d["item_name"] + se_child.uom = d["uom"] + se_child.stock_uom = d["stock_uom"] + se_child.qty = flt(d["qty"]) + # in stock uom + se_child.transfer_qty = flt(d["transfer_qty"]) + se_child.conversion_factor = flt(d["conversion_factor"]) + if d["batch_no"]: + se_child.batch_no = d["batch_no"] + return doc + +def get_item_dict(table, parent, parenttype): + query = """select * from `tab{table}` where parent = '{parent}' and parenttype = '{parenttype}' """ + + return frappe.db.sql(query.format(table=table, parent=parent, parenttype=parenttype), as_dict=True) + +def create_stock_entry(doc): + stock_entry = frappe.new_doc("Stock Entry") + stock_entry = set_stock_items(stock_entry, doc.name, "Clinical Procedure") + stock_entry.purpose = "Material Issue" + stock_entry.from_warehouse = doc.warehouse + stock_entry.company = doc.company + expense_account = get_account(None, "expense_account", "Healthcare Settings", doc.company) + + for item_line in stock_entry.items: + cost_center = frappe.db.get_value('Company', doc.company, 'cost_center') + #item_line.s_warehouse = warehouse #deaful source warehouse set, stock entry to copy to lines + item_line.cost_center = cost_center + #if not expense_account: + # expense_account = frappe.db.get_value("Item", item_line.item_code, "expense_account") + item_line.expense_account = expense_account + + stock_entry.insert(ignore_permissions = True) + stock_entry.submit() + +@frappe.whitelist() +def create_procedure(appointment): + appointment = frappe.get_doc("Patient Appointment",appointment) + procedure = frappe.new_doc("Clinical Procedure") + procedure.appointment = appointment.name + procedure.patient = appointment.patient + procedure.patient_age = appointment.patient_age + procedure.patient_sex = appointment.patient_sex + procedure.procedure_template = appointment.procedure_template + procedure.medical_department = appointment.department + procedure.start_date = appointment.appointment_date + procedure.start_time = appointment.appointment_time + procedure.notes = appointment.notes + procedure.service_unit = appointment.service_unit + consume_stock = frappe.db.get_value("Clinical Procedure Template", appointment.procedure_template, "consume_stock") + if consume_stock == 1: + procedure.consume_stock = True + warehouse = False + if appointment.service_unit: + warehouse = frappe.db.get_value("Healthcare Service Unit", appointment.service_unit, "warehouse") + if not warehouse: + warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse") + if warehouse: + procedure.warehouse = warehouse + return procedure.as_dict() diff --git a/erpnext/healthcare/doctype/patient_service_unit/test_patient_service_unit.js b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.js similarity index 69% rename from erpnext/healthcare/doctype/patient_service_unit/test_patient_service_unit.js rename to erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.js index 320388a1fde..80ef3d55f2a 100644 --- a/erpnext/healthcare/doctype/patient_service_unit/test_patient_service_unit.js +++ b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.js @@ -2,15 +2,15 @@ // rename this file from _test_[name] to test_[name] to activate // and remove above this line -QUnit.test("test: Patient Service Unit", function (assert) { +QUnit.test("test: Clinical Procedure", function (assert) { let done = assert.async(); // number of asserts assert.expect(1); frappe.run_serially([ - // insert a new Patient Service Unit - () => frappe.tests.make('Patient Service Unit', [ + // insert a new Clinical Procedure + () => frappe.tests.make('Clinical Procedure', [ // values to be set {key: 'value'} ]), diff --git a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py new file mode 100644 index 00000000000..09059e1bb46 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, ESS LLP and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestClinicalProcedure(unittest.TestCase): + pass diff --git a/erpnext/healthcare/doctype/clinical_procedure_item/__init__.py b/erpnext/healthcare/doctype/clinical_procedure_item/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.json b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.json new file mode 100644 index 00000000000..c0a3247993d --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.json @@ -0,0 +1,385 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 1, + "creation": "2017-10-05 16:15:10.876952", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 3, + "fieldname": "item_code", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Item", + "length": 0, + "no_copy": 0, + "options": "Item", + "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": 1, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "barcode", + "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": "Barcode", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_name", + "fieldtype": "Data", + "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": "Item 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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "qty", + "fieldtype": "Float", + "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": "Quantity", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "uom", + "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": "UOM", + "length": 0, + "no_copy": 0, + "options": "UOM", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_5", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "batch_no", + "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": "Batch", + "length": 0, + "no_copy": 0, + "options": "Batch", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "conversion_factor", + "fieldtype": "Float", + "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": "Conversion Factor", + "length": 0, + "no_copy": 0, + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "stock_uom", + "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": "Stock UOM", + "length": 0, + "no_copy": 0, + "options": "UOM", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "transfer_qty", + "fieldtype": "Float", + "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 Qty", + "length": 0, + "no_copy": 0, + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "actual_qty", + "fieldtype": "Float", + "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": "Actual Qty (at source/target)", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2018-03-28 14:34:03.796229", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Clinical Procedure Item", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.py b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.py new file mode 100644 index 00000000000..d59e5175972 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure_item/clinical_procedure_item.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, earthians and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe.model.document import Document + +class ClinicalProcedureItem(Document): + pass diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/__init__.py b/erpnext/healthcare/doctype/clinical_procedure_template/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js new file mode 100644 index 00000000000..583728dd185 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js @@ -0,0 +1,175 @@ +// Copyright (c) 2017, earthians and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Clinical Procedure Template', { + template: function(frm) { + if(!frm.doc.item_code) + frm.set_value("item_code", frm.doc.template); + if(!frm.doc.description) + frm.set_value("description", frm.doc.template); + mark_change_in_item(frm); + }, + rate: function(frm) { + mark_change_in_item(frm); + }, + is_billable: function (frm) { + mark_change_in_item(frm); + }, + item_group: function(frm) { + mark_change_in_item(frm); + }, + description: function(frm) { + mark_change_in_item(frm); + }, + medical_department: function(frm) { + mark_change_in_item(frm); + }, + refresh: function(frm) { + frm.fields_dict["items"].grid.set_column_disp("barcode", false); + frm.fields_dict["items"].grid.set_column_disp("batch_no", false); + cur_frm.set_df_property("item_code", "read_only", frm.doc.__islocal ? 0 : 1); + if(!frm.doc.__islocal) { + cur_frm.add_custom_button(__('Change Item Code'), function() { + change_template_code(frm.doc); + } ); + if(frm.doc.disabled == 1){ + cur_frm.add_custom_button(__('Enable Template'), function() { + enable_template(frm.doc); + } ); + } + else{ + cur_frm.add_custom_button(__('Disable Template'), function() { + disable_template(frm.doc); + } ); + } + } + } +}); + +var mark_change_in_item = function(frm) { + if(!frm.doc.__islocal){ + frm.doc.change_in_item = 1; + } +}; + +var disable_template = function(doc){ + frappe.call({ + method: "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.disable_enable_template", + args: {status: 1, name: doc.name, item_code: doc.item_code, is_billable: doc.is_billable}, + callback: function(){ + cur_frm.reload_doc(); + } + }); +}; + +var enable_template = function(doc){ + frappe.call({ + method: "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.disable_enable_template", + args: {status: 0, name: doc.name, item_code: doc.item_code, is_billable: doc.is_billable}, + callback: function(){ + cur_frm.reload_doc(); + } + }); +}; + + +var change_template_code = function(doc){ + var d = new frappe.ui.Dialog({ + title:__("Change Template Code"), + fields:[ + { + "fieldtype": "Data", + "label": "Template Code", + "fieldname": "Item Code", + reqd:1 + }, + { + "fieldtype": "Button", + "label": __("Change Code"), + click: function() { + var values = d.get_values(); + if(!values) + return; + change_item_code_from_template(values["Item Code"], doc); + d.hide(); + } + } + ] + }); + d.show(); + d.set_values({ + 'Item Code': doc.item_code + }); +}; + +var change_item_code_from_template = function(item_code, doc){ + frappe.call({ + "method": "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.change_item_code_from_template", + "args": {item_code: item_code, doc: doc}, + callback: function () { + cur_frm.reload_doc(); + frappe.show_alert({ + message: "Item Code renamed successfully", + indicator: "green" + }); + } + }); +}; + +frappe.ui.form.on('Clinical Procedure Item', { + qty: function(frm, cdt, cdn){ + var d = locals[cdt][cdn]; + frappe.model.set_value(cdt, cdn, "transfer_qty", d.qty*d.conversion_factor); + }, + uom: function(doc, cdt, cdn){ + var d = locals[cdt][cdn]; + if(d.uom && d.item_code){ + return frappe.call({ + method: "erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details", + args: { + item_code: d.item_code, + uom: d.uom, + qty: d.qty + }, + callback: function(r) { + if(r.message) { + frappe.model.set_value(cdt, cdn, r.message); + } + } + }); + } + }, + item_code: function(frm, cdt, cdn) { + var d = locals[cdt][cdn]; + if(d.item_code) { + let args = { + 'item_code' : d.item_code, + 'transfer_qty' : d.transfer_qty, + 'company' : frm.doc.company, + 'quantity' : d.qty + }; + return frappe.call({ + doc: frm.doc, + method: "get_item_details", + args: args, + callback: function(r) { + if(r.message) { + var d = locals[cdt][cdn]; + $.each(r.message, function(k, v){ + d[k] = v; + }); + refresh_field("items"); + } + } + }); + } + } +}); +// List Stock items +cur_frm.set_query("item_code", "items", function() { + return { + filters: { + is_stock_item:1 + } + }; +}); diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json new file mode 100644 index 00000000000..af430dae123 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json @@ -0,0 +1,783 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 1, + "autoname": "field:template", + "beta": 1, + "creation": "2017-10-05 14:59:55.438359", + "custom": 0, + "description": "Procedure Template", + "docstatus": 0, + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "template", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Template Name", + "length": 0, + "no_copy": 0, + "options": "", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_code", + "fieldtype": "Read Only", + "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": "Item Code", + "length": 0, + "no_copy": 1, + "options": "Item", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_group", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Item Group", + "length": 0, + "no_copy": 0, + "options": "Item Group", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "medical_department", + "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": "Medical Department", + "length": 0, + "no_copy": 0, + "options": "Medical Department", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_5", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_billable", + "fieldtype": "Check", + "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": "Is Billable", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "is_billable", + "fieldname": "rate", + "fieldtype": "Float", + "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": "Rate", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "description", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 1, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Description", + "length": 0, + "no_copy": 1, + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fieldname": "section_break_9", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "consume_stock", + "fieldtype": "Check", + "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": "Allow Stock Consumption", + "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": 1, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.consume_stock == 1", + "fieldname": "consumables", + "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": "Consumables", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "items", + "fieldtype": "Table", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Items", + "length": 0, + "no_copy": 0, + "options": "Clinical Procedure Item", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "columns": 0, + "depends_on": "", + "fieldname": "sample_collection", + "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": "Sample Collection", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sample", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Sample", + "length": 0, + "no_copy": 0, + "options": "Lab Test Sample", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sample_uom", + "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": "UOM", + "length": 0, + "no_copy": 0, + "options": "sample.sample_uom", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sample_qty", + "fieldtype": "Float", + "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": "Quantity", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_21", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sample_details", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 1, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Collection Details", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "change_in_item", + "fieldtype": "Check", + "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": "Change In Item", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "disabled", + "fieldtype": "Check", + "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": "Disabled", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item", + "fieldtype": "Link", + "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": "Item", + "length": 0, + "no_copy": 1, + "options": "Item", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + } + ], + "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-04-27 18:04:32.209983", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Clinical Procedure Template", + "name_case": "", + "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": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "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": "Medical Administrator", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Nursing User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Physician", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "restrict_to_domain": "Healthcare", + "search_fields": "template", + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "template", + "track_changes": 1, + "track_seen": 1 +} \ No newline at end of file diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py new file mode 100644 index 00000000000..565fe9021d8 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, earthians and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe, json +from frappe import _ +from frappe.model.document import Document +from frappe.utils import nowdate + +class ClinicalProcedureTemplate(Document): + def on_update(self): + #Item and Price List update --> if (change_in_item) + if(self.change_in_item and self.is_billable == 1 and self.item): + updating_item(self) + if(self.rate != 0.0): + updating_rate(self) + elif(self.is_billable == 0 and self.item): + frappe.db.set_value("Item",self.item,"disabled",1) + + frappe.db.set_value(self.doctype,self.name,"change_in_item",0) + self.reload() + + def after_insert(self): + create_item_from_template(self) + + #Call before delete the template + def on_trash(self): + if(self.item): + try: + frappe.delete_doc("Item",self.item) + except Exception: + frappe.throw("""Not permitted. Please disable the Procedure Template""") + + def get_item_details(self, args=None): + item = frappe.db.sql("""select stock_uom, description, image, item_name, + expense_account, buying_cost_center, item_group from `tabItem` + where name = %s + and disabled=0 + and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""", + (args.get('item_code'), nowdate()), as_dict = 1) + if not item: + frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get('item_code'))) + + item = item[0] + + ret = { + 'uom' : item.stock_uom, + 'stock_uom' : item.stock_uom, + 'item_name' : item.item_name, + 'quantity' : 0, + 'transfer_qty' : 0, + 'conversion_factor' : 1 + } + return ret + +def updating_item(self): + frappe.db.sql("""update `tabItem` set item_name=%s, item_group=%s, disabled=0, + description=%s, modified=NOW() where item_code=%s""", + (self.template, self.item_group , self.description, self.item)) +def updating_rate(self): + frappe.db.sql("""update `tabItem Price` set item_name=%s, price_list_rate=%s, modified=NOW() where + item_code=%s""",(self.template, self.rate, self.item)) + +def create_item_from_template(doc): + if(doc.is_billable == 1): + disabled = 0 + else: + disabled = 1 + #insert item + item = frappe.get_doc({ + "doctype": "Item", + "item_code": doc.template, + "item_name":doc.template, + "item_group": doc.item_group, + "description":doc.description, + "is_sales_item": 1, + "is_service_item": 1, + "is_purchase_item": 0, + "is_stock_item": 0, + "show_in_website": 0, + "is_pro_applicable": 0, + "disabled": disabled, + "stock_uom": "Unit" + }).insert(ignore_permissions=True) + + #insert item price + #get item price list to insert item price + if(doc.rate != 0.0): + price_list_name = frappe.db.get_value("Price List", {"selling": 1}) + if(doc.rate): + make_item_price(item.name, price_list_name, doc.rate) + else: + make_item_price(item.name, price_list_name, 0.0) + #Set item to the template + frappe.db.set_value("Clinical Procedure Template", doc.name, "item", item.name) + + doc.reload() #refresh the doc after insert. + +def make_item_price(item, price_list_name, item_price): + frappe.get_doc({ + "doctype": "Item Price", + "price_list": price_list_name, + "item_code": item, + "price_list_rate": item_price + }).insert(ignore_permissions=True) + +@frappe.whitelist() +def change_item_code_from_template(item_code, doc): + args = json.loads(doc) + doc = frappe._dict(args) + + if(frappe.db.exists({ + "doctype": "Item", + "item_code": item_code})): + frappe.throw(_("Code {0} already exist").format(item_code)) + else: + frappe.rename_doc("Item", doc.item_code, item_code, ignore_permissions = True) + frappe.db.set_value("Clinical Procedure Template", doc.name, "item_code", item_code) + return + +@frappe.whitelist() +def disable_enable_template(status, name, item_code): + frappe.db.set_value("Clinical Procedure Template", name, "disabled", status) + if (frappe.db.exists({ #set Item's disabled field to status + "doctype": "Item", + "item_code": item_code})): + frappe.db.set_value("Item", item_code, "disabled", status) + + return diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.js b/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.js new file mode 100644 index 00000000000..1dde8b5d867 --- /dev/null +++ b/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Clinical Procedure Template", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Clinical Procedure Template + () => frappe.tests.make('Clinical Procedure Template', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/healthcare/doctype/patient_service_unit/test_patient_service_unit.py b/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.py similarity index 73% rename from erpnext/healthcare/doctype/patient_service_unit/test_patient_service_unit.py rename to erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.py index ceb49fd4c66..62e138b8ed2 100644 --- a/erpnext/healthcare/doctype/patient_service_unit/test_patient_service_unit.py +++ b/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.py @@ -4,5 +4,5 @@ from __future__ import unicode_literals import unittest -class TestPatientServiceUnit(unittest.TestCase): +class TestClinicalProcedureTemplate(unittest.TestCase): pass diff --git a/erpnext/healthcare/doctype/consultation/consultation.js b/erpnext/healthcare/doctype/consultation/consultation.js index dc4870fc633..727d1754088 100644 --- a/erpnext/healthcare/doctype/consultation/consultation.js +++ b/erpnext/healthcare/doctype/consultation/consultation.js @@ -35,6 +35,10 @@ frappe.ui.form.on('Consultation', { create_medical_record(frm); },"Create"); + frm.add_custom_button(__("Procedure"),function(){ + btn_create_procedure(frm); + },"Create"); + frm.set_query("patient", function () { return { filters: {"disabled": 0} @@ -127,6 +131,17 @@ var btn_create_vital_signs = function (frm) { frappe.new_doc("Vital Signs"); }; +var btn_create_procedure = function (frm) { + if(!frm.doc.patient){ + frappe.throw("Please select patient"); + } + frappe.route_options = { + "patient": frm.doc.patient, + "medical_department": frm.doc.visit_department + }; + frappe.new_doc("Clinical Procedure"); +}; + frappe.ui.form.on("Consultation", "appointment", function(frm){ if(frm.doc.appointment){ frappe.call({ @@ -238,6 +253,25 @@ frappe.ui.form.on("Drug Prescription", { } }); +frappe.ui.form.on("Procedure Prescription", { + procedure: function(frm, cdt, cdn) { + var child = locals[cdt][cdn]; + if(child.procedure){ + frappe.call({ + "method": "frappe.client.get_value", + args: { + doctype: "Clinical Procedure Template", + fieldname: "medical_department", + filters: {name: child.procedure} + }, + callback: function (data) { + frappe.model.set_value(cdt, cdn, 'department',data.message.medical_department); + } + }); + } + } +}); + var calculate_age = function(birth) { var ageMS = Date.parse(Date()) - Date.parse(birth); diff --git a/erpnext/healthcare/doctype/consultation/consultation.json b/erpnext/healthcare/doctype/consultation/consultation.json index c1bd37a3d22..2f6de0cb4a9 100644 --- a/erpnext/healthcare/doctype/consultation/consultation.json +++ b/erpnext/healthcare/doctype/consultation/consultation.json @@ -874,6 +874,67 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sb_procedures", + "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": "Procedures", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "procedure_prescription", + "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, + "label": "Procedures", + "length": 0, + "no_copy": 1, + "options": "Procedure Prescription", + "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, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -945,7 +1006,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-02-19 11:35:13.826577", + "modified": "2018-03-19 11:35:13.826577", "modified_by": "Administrator", "module": "Healthcare", "name": "Consultation", diff --git a/erpnext/healthcare/doctype/consultation/consultation.py b/erpnext/healthcare/doctype/consultation/consultation.py index 472a2f2946f..b647c2e6e2d 100755 --- a/erpnext/healthcare/doctype/consultation/consultation.py +++ b/erpnext/healthcare/doctype/consultation/consultation.py @@ -125,5 +125,7 @@ def set_subject_field(consultation): subject +="\nDrug(s) Prescribed. " if(consultation.test_prescription): subject += "\nTest(s) Prescribed." + if(consultation.procedure_prescription): + subject += "\nProcedure(s) Prescribed." return subject diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/__init__.py b/erpnext/healthcare/doctype/healthcare_service_unit/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.js b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.js new file mode 100644 index 00000000000..e9665151d6f --- /dev/null +++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.js @@ -0,0 +1,42 @@ +// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Healthcare Service Unit', { + onload: function(frm) { + frm.list_route = "Tree/Healthcare Service Unit"; + + // get query select healthcare service unit + frm.fields_dict['parent_healthcare_service_unit'].get_query = function(doc) { + return{ + filters:[ + ['Healthcare Service Unit', 'is_group', '=', 1], + ['Healthcare Service Unit', 'name', '!=', doc.healthcare_service_unit_name] + ] + }; + }; + }, + refresh: function(frm) { + frm.trigger("set_root_readonly"); + frm.add_custom_button(__("Healthcare Service Unit Tree"), function() { + frappe.set_route("Tree", "Healthcare Service Unit"); + }); + }, + set_root_readonly: function(frm) { + // read-only for root healthcare service unit + frm.set_intro(""); + if(!frm.doc.parent_healthcare_service_unit) { + frm.set_read_only(); + frm.set_intro(__("This is a root healthcare service unit and cannot be edited."), true); + } + }, + allow_appointments: function(frm) { + if(!frm.doc.allow_appointments){ + frm.set_value("overlap_appointments", false); + } + }, + is_group: function(frm) { + if(frm.doc.is_group){ + frm.set_value("allow_appointments", false); + } + } +}); diff --git a/erpnext/healthcare/doctype/patient_service_unit/patient_service_unit.json b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json similarity index 77% rename from erpnext/healthcare/doctype/patient_service_unit/patient_service_unit.json rename to erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json index 0ca1a53e761..d11ecdc0535 100644 --- a/erpnext/healthcare/doctype/patient_service_unit/patient_service_unit.json +++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json @@ -3,11 +3,11 @@ "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 1, - "autoname": "field:patient_service_unit_name", + "autoname": "field:healthcare_service_unit_name", "beta": 1, "creation": "2016-09-21 13:48:14.731437", "custom": 0, - "description": "Patinet Service Unit", + "description": "Healthcare Service Unit", "docstatus": 0, "doctype": "DocType", "document_type": "Setup", @@ -19,7 +19,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "patient_service_unit_name", + "fieldname": "healthcare_service_unit_name", "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, @@ -50,7 +50,7 @@ "bold": 1, "collapsible": 0, "columns": 0, - "fieldname": "parent_patient_service_unit", + "fieldname": "parent_healthcare_service_unit", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 1, @@ -62,7 +62,7 @@ "label": "Parent Service Unit", "length": 0, "no_copy": 0, - "options": "Patient Service Unit", + "options": "Healthcare Service Unit", "permlevel": 0, "precision": "", "print_hide": 0, @@ -113,6 +113,39 @@ "bold": 1, "collapsible": 0, "columns": 0, + "depends_on": "eval:doc.is_group != 1", + "fieldname": "allow_appointments", + "fieldtype": "Check", + "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": "Allow Appointments", + "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 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.is_group != 1 && doc.allow_appointments == 1", "fieldname": "overlap_appointments", "fieldtype": "Check", "hidden": 0, @@ -138,6 +171,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.is_group != 1", + "fieldname": "warehouse", + "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": "Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "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 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -250,7 +316,7 @@ "label": "Old Parent", "length": 0, "no_copy": 1, - "options": "Patient Service Unit", + "options": "Healthcare Service Unit", "permlevel": 0, "precision": "", "print_hide": 1, @@ -275,16 +341,15 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-03-07 13:25:51.163029", + "modified": "2018-05-04 11:20:16.942603", "modified_by": "Administrator", "module": "Healthcare", - "name": "Patient Service Unit", + "name": "Healthcare Service Unit", "name_case": "", "owner": "Administrator", "permissions": [ { "amend": 0, - "apply_user_permissions": 1, "cancel": 0, "create": 0, "delete": 0, @@ -300,12 +365,10 @@ "set_user_permissions": 0, "share": 1, "submit": 0, - "user_permission_doctypes": "[\"Service Unit\"]", "write": 0 }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -325,7 +388,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 0, @@ -348,11 +410,11 @@ "read_only": 0, "read_only_onload": 0, "restrict_to_domain": "Healthcare", - "search_fields": "patient_service_unit_name", + "search_fields": "healthcare_service_unit_name", "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", - "title_field": "patient_service_unit_name", + "title_field": "healthcare_service_unit_name", "track_changes": 1, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py new file mode 100644 index 00000000000..21b0e6e7278 --- /dev/null +++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals + +from frappe.utils.nestedset import NestedSet + +class HealthcareServiceUnit(NestedSet): + nsm_parent_field = 'parent_healthcare_service_unit' + + def on_update(self): + super(HealthcareServiceUnit, self).on_update() + self.validate_one_root() + + def validate(self): + if self.is_group: + self.allow_appointments = False + self.overlap_appointments = False + elif not self.allow_appointments: + self.overlap_appointments = False diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit_tree.js b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit_tree.js new file mode 100644 index 00000000000..4eb9475a33f --- /dev/null +++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit_tree.js @@ -0,0 +1,3 @@ +frappe.treeview_settings["Healthcare Service Unit"] = { + ignore_fields:["parent_healthcare_service_unit"] +}; diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.js b/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.js new file mode 100644 index 00000000000..a67a4117073 --- /dev/null +++ b/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Healthcare Service Unit", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Healthcare Service Unit + () => frappe.tests.make('Healthcare Service Unit', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.py b/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.py new file mode 100644 index 00000000000..bced2fe1f63 --- /dev/null +++ b/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestHealthcareServiceUnit(unittest.TestCase): + pass diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js index 41974a6976d..7d5ed8dd666 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js @@ -26,6 +26,7 @@ frappe.ui.form.on('Patient Appointment', { return { filters: { "is_group": false, + "allow_appointments": true } }; }); @@ -40,9 +41,16 @@ frappe.ui.form.on('Patient Appointment', { btn_update_status(frm, "Cancelled"); }); - frm.add_custom_button(__("Consultation"),function(){ - btn_create_consultation(frm); - },"Create"); + if(frm.doc.procedure_template){ + frm.add_custom_button(__("Procedure"),function(){ + btn_create_procedure(frm); + },"Create"); + } + else{ + frm.add_custom_button(__("Consultation"),function(){ + btn_create_consultation(frm); + },"Create"); + } frm.add_custom_button(__('Vital Signs'), function() { btn_create_vital_signs(frm); @@ -53,9 +61,16 @@ frappe.ui.form.on('Patient Appointment', { btn_update_status(frm, "Cancelled"); }); - frm.add_custom_button(__("Consultation"),function(){ - btn_create_consultation(frm); - },"Create"); + if(frm.doc.procedure_template){ + frm.add_custom_button(__("Procedure"),function(){ + btn_create_procedure(frm); + },"Create"); + } + else{ + frm.add_custom_button(__("Consultation"),function(){ + btn_create_consultation(frm); + },"Create"); + } frm.add_custom_button(__('Vital Signs'), function() { btn_create_vital_signs(frm); @@ -201,8 +216,85 @@ frappe.ui.form.on('Patient Appointment', { frm.disable_save(); } }, + get_procedure_from_consultation: function(frm) { + get_procedure_prescribed(frm); + } }); +var get_procedure_prescribed = function(frm){ + if(frm.doc.patient){ + frappe.call({ + method:"erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_procedure_prescribed", + args: {patient: frm.doc.patient}, + callback: function(r){ + show_procedure_templates(frm, r.message); + } + }); + } + else{ + frappe.msgprint("Please select Patient to get prescribed procedure"); + } +}; + +var show_procedure_templates = function(frm, result){ + var d = new frappe.ui.Dialog({ + title: __("Prescribed Procedures"), + fields: [ + { + fieldtype: "HTML", fieldname: "procedure_template" + } + ] + }); + var html_field = d.fields_dict.procedure_template.$wrapper; + html_field.empty(); + $.each(result, function(x, y){ + var row = $(repl('