diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index daf1bfea4bb..facfa53d985 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -984,7 +984,7 @@ var set_primary_action= function(frm, dialog, $results) { frappe.model.set_value(si_item.doctype, si_item.name, 'reference_dn', checked_values[i]['dn']); frappe.model.set_value(si_item.doctype, si_item.name, 'qty', 1); if(checked_values[i]['qty'] > 1){ - frappe.model.set_value(si_item.doctype, si_item.name, 'qty', checked_values[i]['qty']); + frappe.model.set_value(si_item.doctype, si_item.name, 'qty', parseFloat(checked_values[i]['qty'])); } } frm.refresh_fields(); diff --git a/erpnext/domains/healthcare.py b/erpnext/domains/healthcare.py index 57f30f63010..ee8dc8161b7 100644 --- a/erpnext/domains/healthcare.py +++ b/erpnext/domains/healthcare.py @@ -31,7 +31,7 @@ data = { 'insert_after': 'patient', 'read_only': True }, { - 'fieldname': 'ref_practitioner', 'label': 'Referring Practitioner', 'fieldtype': 'Link', 'options': 'Practitioner', + 'fieldname': 'ref_practitioner', 'label': 'Referring Practitioner', 'fieldtype': 'Link', 'options': 'Healthcare Practitioner', 'insert_after': 'customer' } ], diff --git a/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json b/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json index 2ac498df111..3e101439427 100644 --- a/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json +++ b/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json @@ -140,6 +140,39 @@ "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", + "fieldname": "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": "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 } ], "has_web_view": 0, @@ -152,7 +185,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-07-17 18:26:46.009878", + "modified": "2018-07-18 18:26:46.009878", "modified_by": "Administrator", "module": "Healthcare", "name": "Inpatient Occupancy", @@ -167,4 +200,4 @@ "sort_order": "DESC", "track_changes": 1, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py index 07cd9e467ed..2ed3f8e0656 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py @@ -69,17 +69,20 @@ def schedule_inpatient(patient, encounter_id, practitioner): inpatient_record.save(ignore_permissions = True) @frappe.whitelist() -def schedule_discharge(patient, encounter_id, practitioner): +def schedule_discharge(patient, encounter_id=None, practitioner=None): inpatient_record_id = frappe.db.get_value('Patient', patient, 'inpatient_record') if inpatient_record_id: inpatient_record = frappe.get_doc("Inpatient Record", inpatient_record_id) inpatient_record.discharge_practitioner = practitioner inpatient_record.discharge_encounter = encounter_id inpatient_record.status = "Discharge Scheduled" + + check_out_inpatient(inpatient_record) + inpatient_record.save(ignore_permissions = True) frappe.db.set_value("Patient", patient, "inpatient_status", "Discharge Scheduled") -def discharge_patient(inpatient_record): +def check_out_inpatient(inpatient_record): if inpatient_record.inpatient_occupancies: for inpatient_occupancy in inpatient_record.inpatient_occupancies: if inpatient_occupancy.left != 1: @@ -87,11 +90,54 @@ def discharge_patient(inpatient_record): inpatient_occupancy.check_out = now_datetime() frappe.db.set_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "occupied", False) +def discharge_patient(inpatient_record): + validate_invoiced_inpatient(inpatient_record) inpatient_record.discharge_date = today() inpatient_record.status = "Discharged" inpatient_record.save(ignore_permissions = True) +def validate_invoiced_inpatient(inpatient_record): + pending_invoices = [] + if inpatient_record.inpatient_occupancies: + service_unit_names = False + for inpatient_occupancy in inpatient_record.inpatient_occupancies: + if inpatient_occupancy.invoiced != 1: + if service_unit_names: + service_unit_names += ", " + inpatient_occupancy.service_unit + else: + service_unit_names = inpatient_occupancy.service_unit + if service_unit_names: + pending_invoices.append("Inpatient Occupancy (" + service_unit_names + ")") + + docs = ["Patient Appointment", "Patient Encounter", "Lab Test", "Clinical Procedure"] + + for doc in docs: + doc_name_list = get_inpatient_docs_not_invoiced(doc, inpatient_record) + if doc_name_list: + pending_invoices = get_doc_pendig(doc, doc_name_list, pending_invoices) + + if pending_invoices: + frappe.throw(_("Can not mark Inpatient Record Discharged, there are Unpaid Invoices {0}").format(", " + .join(map(lambda x: """ {0}""".format(x), pending_invoices)))) + +def get_doc_pendig(doc, doc_name_list, pending_invoices): + if doc_name_list: + doc_ids = False + for doc_name in doc_name_list: + if doc_ids: + doc_ids += ", "+doc_name.name + else: + doc_ids = doc_name.name + if doc_ids: + pending_invoices.append(doc + " (" + doc_ids + ")") + + return pending_invoices + +def get_inpatient_docs_not_invoiced(doc, inpatient_record): + return frappe.db.get_list(doc, filters = {"patient": inpatient_record.patient, + "inpatient_record": inpatient_record.name, "invoiced": 0}) + def admit_patient(inpatient_record, service_unit, check_in, expected_discharge=None): inpatient_record.admitted_datetime = check_in inpatient_record.status = "Admitted" diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py index 5a7c7e36800..5145c850764 100644 --- a/erpnext/healthcare/utils.py +++ b/erpnext/healthcare/utils.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import frappe import datetime from frappe import _ +from frappe.utils import date_diff, getdate from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account from erpnext.healthcare.doctype.patient_appointment.patient_appointment import validity_exists from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity, update_fee_validity @@ -118,6 +119,20 @@ def get_healthcare_services_to_invoice(patient): item_to_invoice.append({'reference_type': 'Clinical Procedure Item', 'reference_name': procedure_consumable_obj.name, 'service': procedure_consumable_obj.item_code, 'qty': procedure_consumable_obj.qty}) + inpatient_services = frappe.db.sql("""select io.name, io.parent from `tabInpatient Record` ip, + `tabInpatient Occupancy` io where ip.patient=%s and io.parent=ip.name and + io.left=1 and io.invoiced=0""", (patient.name)) + if inpatient_services: + for inpatient_service in inpatient_services: + inpatient_occupancy = frappe.get_doc("Inpatient Occupancy", inpatient_service[0]) + service_unit_type = frappe.get_doc("Healthcare Service Unit Type", frappe.db.get_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "service_unit_type")) + if service_unit_type and service_unit_type.is_billable == 1: + qty = date_diff(getdate(inpatient_occupancy.check_out), getdate(inpatient_occupancy.check_in)) + if qty < 1: + qty = 1 + item_to_invoice.append({'reference_type': 'Inpatient Occupancy', 'reference_name': inpatient_occupancy.name, + 'service': service_unit_type.item, 'qty': qty}) + return item_to_invoice else: frappe.throw(_("The Patient {0} do not have customer refrence to invoice").format(patient.name))