From 1646010059299e6dbfec8a240c161fb18391ba86 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Thu, 26 Jul 2018 20:52:00 +0530 Subject: [PATCH] Clinical Procedure - Consumables Invoice Separately --- .../clinical_procedure/clinical_procedure.js | 21 ++- .../clinical_procedure.json | 133 ++++++++++++++++++ .../clinical_procedure/clinical_procedure.py | 78 +++++----- 3 files changed, 189 insertions(+), 43 deletions(-) diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js index 9fc5b376a5..7f866e1996 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js @@ -264,21 +264,20 @@ frappe.ui.form.on('Clinical Procedure Item', { 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 + 'doctype' : "Clinical Procedure", + 'item_code' : d.item_code, + 'company' : frm.doc.company, + 'warehouse': frm.doc.warehouse }; return frappe.call({ - doc: frm.doc, - method: "get_item_details", - args: args, + method: "erpnext.stock.get_item_details.get_item_details", + args: {args: args}, callback: function(r) { if(r.message) { - var d = locals[cdt][cdn]; - $.each(r.message, function(k, v){ - d[k] = v; - }); + 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); refresh_field("items"); } } diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json index 0856606359..a830c37d96 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json @@ -704,6 +704,139 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "fieldname": "invoice_separately_as_consumables", + "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": "Consumables Invoice Separately", + "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_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "invoice_separately_as_consumables", + "fieldname": "consumable_total_amount", + "fieldtype": "Currency", + "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": "Consumable Total Amount", + "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_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "invoice_separately_as_consumables", + "fieldname": "consumption_details", + "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": "Consumption 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_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "depends_on": "invoice_separately_as_consumables", + "fieldname": "consumption_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": "Consumption 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_in_quick_entry": 0, diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py index d51d062408..4a4bd39153 100644 --- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py +++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py @@ -10,6 +10,7 @@ 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 +from erpnext.stock.get_item_details import get_item_details class ClinicalProcedure(Document): def validate(self): @@ -18,6 +19,12 @@ class ClinicalProcedure(Document): frappe.throw(("Set warehouse for Procedure {0} ").format(self.name)) self.set_actual_qty() + if self.items: + self.invoice_separately_as_consumables = False + for item in self.items: + if item.invoice_separately_as_consumables == 1: + self.invoice_separately_as_consumables = True + def before_insert(self): if self.consume_stock: set_stock_items(self, self.procedure_template, "Clinical Procedure Template") @@ -40,6 +47,36 @@ class ClinicalProcedure(Document): create_stock_entry(self) frappe.db.set_value("Clinical Procedure", self.name, "status", 'Completed') + 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) + + def start(self): allow_start = self.set_actual_qty() if allow_start: @@ -54,16 +91,7 @@ class ClinicalProcedure(Document): 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 - + d.actual_qty = get_stock_qty(d.item_code, self.warehouse) # validate qty if not allow_negative_stock and d.actual_qty < d.qty: allow_start = False @@ -93,28 +121,14 @@ class ClinicalProcedure(Document): 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 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 @frappe.whitelist() def set_stock_items(doc, stock_detail_parent, parenttype):