From 5ec7b55c3c3f0a4f04c69f6cbe72e4e0ddf4be33 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 2 Mar 2020 10:17:15 +0530 Subject: [PATCH] fix: consumable total amount not set in Clinical Procedure --- .../clinical_procedure/clinical_procedure.js | 37 ++-- .../clinical_procedure/clinical_procedure.py | 166 +++++++++--------- 2 files changed, 108 insertions(+), 95 deletions(-) diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js index 41e7a3f7cf7..1e2cb10989c 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js @@ -22,6 +22,7 @@ frappe.ui.form.on('Clinical Procedure', { } }); }, + refresh: function(frm) { frm.set_query('patient', function () { return { @@ -60,7 +61,7 @@ frappe.ui.form.on('Clinical Procedure', { function(doc) { return (doc.qty<=doc.actual_qty) ? 'green' : 'orange' ; }); } - if (frm.doc.docstatus == 2) { + if (frm.doc.docstatus == 1) { if (frm.doc.status == 'In Progress') { let btn_label = ''; let msg = ''; @@ -77,17 +78,22 @@ frappe.ui.form.on('Clinical Procedure', { msg, function() { frappe.call({ - doc: frm.doc, method: 'complete_procedure', + doc: frm.doc, callback: function(r) { - if (!r.exc) { - cur_frm.reload_doc(); + if (r.message) { + frappe.show_alert({ + message: __('Stock Entry {0} created', + ['' + r.message + '']), + indicator: 'green' + }); + frm.reload_doc(); } } }); } ); - }); + }).addClass("btn-primary"); } else if (frm.doc.status == 'Pending') { frm.add_custom_button(__('Start'), function() { @@ -96,9 +102,11 @@ frappe.ui.form.on('Clinical Procedure', { method: 'start_procedure', callback: function(r) { if (!r.exc) { - if (r.data.message == 'insufficient stock') { + if (r.message == 'insufficient stock') { + let msg = __('Stock quantity to start the Procedure is not available in the Warehouse {0}. Do you want to record a Stock Entry?', + [frm.doc.warehouse.bold()]); frappe.confirm( - __('Stock quantity to start the procedure is not available in the warehouse. Do you want to record a Stock Transfer?'), + msg, function() { frappe.call({ doc: frm.doc, @@ -119,10 +127,9 @@ frappe.ui.form.on('Clinical Procedure', { } } }); - }); + }).addClass("btn-primary"); } } - }, onload: function(frm) { @@ -257,6 +264,7 @@ frappe.ui.form.on('Clinical Procedure Item', { let d = locals[cdt][cdn]; frappe.model.set_value(cdt, cdn, 'transfer_qty', d.qty*d.conversion_factor); }, + uom: function(doc, cdt, cdn) { let d = locals[cdt][cdn]; if (d.uom && d.item_code) { @@ -275,6 +283,7 @@ frappe.ui.form.on('Clinical Procedure Item', { }); } }, + item_code: function(frm, cdt, cdn) { let d = locals[cdt][cdn]; let args = null; @@ -286,14 +295,14 @@ frappe.ui.form.on('Clinical Procedure Item', { 'warehouse': frm.doc.warehouse }; return frappe.call({ - method: 'erpnext.stock.get_item_details.get_item_details', + method: 'erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.get_item_details', args: {args: args}, callback: function(r) { if (r.message) { - frappe.model.set_value(cdt, cdn, 'item_name', r.message.item_name); - frappe.model.set_value(cdt, cdn, 'stock_uom', r.message.stock_uom); - frappe.model.set_value(cdt, cdn, 'conversion_factor', r.message.conversion_factor); - frappe.model.set_value(cdt, cdn, 'actual_qty', r.message.actual_qty); + let d = locals[cdt][cdn]; + $.each(r.message, function(k, v) { + d[k] = v; + }); refresh_field('items'); } } diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py index ea5303020c4..f45ea78e70f 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py @@ -17,7 +17,7 @@ class ClinicalProcedure(Document): self.set_status() if self.consume_stock and not self.status == 'Draft': if not self.warehouse: - frappe.throw(_("Set warehouse for Procedure {0} ").format(self.name)) + frappe.throw(_('Set warehouse for Procedure {0} ').format(self.name)) self.set_actual_qty() if self.items: @@ -28,19 +28,19 @@ class ClinicalProcedure(Document): def before_insert(self): if self.consume_stock: - set_stock_items(self, self.procedure_template, "Clinical Procedure Template") - self.set_actual_qty(); + set_stock_items(self, self.procedure_template, 'Clinical Procedure Template') + self.set_actual_qty() def after_insert(self): if self.prescription: - frappe.db.set_value("Procedure Prescription", self.prescription, "procedure_created", 1) + frappe.db.set_value('Procedure Prescription', self.prescription, 'procedure_created', 1) if self.appointment: - frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed") - template = frappe.get_doc("Clinical Procedure Template", self.procedure_template) + 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) + 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) + frappe.db.set_value('Clinical Procedure', self.name, 'sample', sample_collection.name) self.reload() def set_status(self): @@ -52,52 +52,57 @@ class ClinicalProcedure(Document): elif self.docstatus == 2: self.status = 'Cancelled' - def complete(self): + def complete_procedure(self): if self.consume_stock and self.items: - create_stock_entry(self) - frappe.db.set_value("Clinical Procedure", self.name, "status", 'Completed') + stock_entry = make_stock_entry(self) if self.items: consumable_total_amount = 0 consumption_details = False - for item in self.items: - if item.invoice_separately_as_consumables: - price_list, price_list_currency = frappe.db.get_values("Price List", {"selling": 1}, ['name', 'currency'])[0] - args = { - 'doctype': "Sales Invoice", - 'item_code': item.item_code, - 'company': self.company, - 'warehouse': self.warehouse, - 'customer': frappe.db.get_value("Patient", self.patient, "customer"), - 'selling_price_list': price_list, - 'price_list_currency': price_list_currency, - 'plc_conversion_rate': 1.0, - 'conversion_rate': 1.0 - } - item_details = get_item_details(args) - item_price = item_details.price_list_rate * item.transfer_qty - item_consumption_details = item_details.item_name+"\t"+str(item.qty)+" "+item.uom+"\t"+str(item_price) - consumable_total_amount += item_price - if not consumption_details: - consumption_details = "Clinical Procedure ("+self.name+"):\n\t"+item_consumption_details - else: - consumption_details += "\n\t"+item_consumption_details - if consumable_total_amount > 0: - frappe.db.set_value("Clinical Procedure", self.name, "consumable_total_amount", consumable_total_amount) - frappe.db.set_value("Clinical Procedure", self.name, "consumption_details", consumption_details) + customer = frappe.db.get_value('Patient', self.patient, 'customer') + if customer: + for item in self.items: + if item.invoice_separately_as_consumables: + price_list, price_list_currency = frappe.db.get_values('Price List', {'selling': 1}, ['name', 'currency'])[0] + args = { + 'doctype': 'Sales Invoice', + 'item_code': item.item_code, + 'company': self.company, + 'warehouse': self.warehouse, + 'customer': customer, + 'selling_price_list': price_list, + 'price_list_currency': price_list_currency, + 'plc_conversion_rate': 1.0, + 'conversion_rate': 1.0 + } + item_details = get_item_details(args) + item_price = item_details.price_list_rate * item.qty + item_consumption_details = item_details.item_name + ' ' + str(item.qty) + ' ' + item.uom + ' ' + str(item_price) + consumable_total_amount += item_price + if not consumption_details: + consumption_details = _('Clinical Procedure ({0}):').format(self.name) + consumption_details += '\n\t' + item_consumption_details + if consumable_total_amount > 0: + frappe.db.set_value('Clinical Procedure', self.name, 'consumable_total_amount', consumable_total_amount) + frappe.db.set_value('Clinical Procedure', self.name, 'consumption_details', consumption_details) + else: + frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found')) - def start(self): + frappe.db.set_value('Clinical Procedure', self.name, 'status', 'Completed') + if self.consume_stock and self.items: + return stock_entry.name + + def start_procedure(self): allow_start = self.set_actual_qty() if allow_start: - self.status = 'In Progress' + self.db_set('status', 'In Progress') insert_clinical_procedure_to_medical_record(self) - else: - self.status = 'Pending' - self.save() + return 'success' + return 'insufficient stock' def set_actual_qty(self): - allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")) + allow_negative_stock = cint(frappe.db.get_value('Stock Settings', None, 'allow_negative_stock')) allow_start = True for d in self.get('items'): @@ -109,11 +114,11 @@ class ClinicalProcedure(Document): return allow_start def make_material_transfer(self): - stock_entry = frappe.new_doc("Stock Entry") + stock_entry = frappe.new_doc('Stock Entry') - stock_entry.purpose = "Material Transfer" + stock_entry.stock_entry_type = 'Material Receipt' stock_entry.to_warehouse = self.warehouse - expense_account = get_account(None, "expense_account", "Healthcare Settings", self.company) + 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') @@ -131,69 +136,68 @@ class ClinicalProcedure(Document): se_child.expense_account = expense_account return stock_entry.as_dict() -@frappe.whitelist() + def get_stock_qty(item_code, warehouse): return get_previous_sle({ - "item_code": item_code, - "warehouse": warehouse, - "posting_date": nowdate(), - "posting_time": nowtime() - }).get("qty_after_transaction") or 0 + 'item_code': item_code, + 'warehouse': warehouse, + 'posting_date': nowdate(), + 'posting_time': nowtime() + }).get('qty_after_transaction') or 0 @frappe.whitelist() def set_stock_items(doc, stock_detail_parent, parenttype): - item_dict = get_item_dict("Clinical Procedure Item", 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"]) + 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"] - if parenttype == "Clinical Procedure Template": - se_child.invoice_separately_as_consumables = d["invoice_separately_as_consumables"] + 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'] + if parenttype == 'Clinical Procedure Template': + se_child.invoice_separately_as_consumables = d['invoice_separately_as_consumables'] return doc def get_item_dict(table, parent, parenttype): - query = """select * from `tab{table}` where parent = '{parent}' and parenttype = '{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" +@frappe.whitelist() +def make_stock_entry(doc): + stock_entry = frappe.new_doc('Stock Entry') + stock_entry = set_stock_items(stock_entry, doc.name, 'Clinical Procedure') + stock_entry.stock_entry_type = 'Material Issue' stock_entry.from_warehouse = doc.warehouse stock_entry.company = doc.company - expense_account = get_account(None, "expense_account", "Healthcare Settings", doc.company) + expense_account = get_account(None, 'expense_account', 'Healthcare Settings', doc.company) for item_line in stock_entry.items: cost_center = frappe.get_cached_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.save(ignore_permissions=True) stock_entry.submit() + return stock_entry def make_procedure(source_name, target_doc=None): def set_missing_values(source, target): - consume_stock = frappe.db.get_value("Clinical Procedure Template", source.procedure_template, "consume_stock") + consume_stock = frappe.db.get_value('Clinical Procedure Template', source.procedure_template, 'consume_stock') if consume_stock: target.consume_stock = 1 warehouse = None if source.service_unit: - warehouse = frappe.db.get_value("Healthcare Service Unit", source.service_unit, "warehouse") + warehouse = frappe.db.get_value('Healthcare Service Unit', source.service_unit, 'warehouse') if not warehouse: - warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse") + warehouse = frappe.db.get_value('Stock Settings', None, 'default_warehouse') if warehouse: target.warehouse = warehouse @@ -224,16 +228,16 @@ def make_procedure(source_name, target_doc=None): def insert_clinical_procedure_to_medical_record(doc): subject = cstr(doc.procedure_template) if doc.practitioner: - subject += " "+doc.practitioner + subject += ' '+doc.practitioner if subject and doc.notes: - subject += "
"+doc.notes + subject += '
'+doc.notes - medical_record = frappe.new_doc("Patient Medical Record") + medical_record = frappe.new_doc('Patient Medical Record') medical_record.patient = doc.patient medical_record.subject = subject - medical_record.status = "Open" + medical_record.status = 'Open' medical_record.communication_date = doc.start_date - medical_record.reference_doctype = "Clinical Procedure" + medical_record.reference_doctype = 'Clinical Procedure' medical_record.reference_name = doc.name medical_record.reference_owner = doc.owner medical_record.save(ignore_permissions=True)