From 4dd6f0ae9b4135aa6e591b3647eb5c758788b094 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 11 Feb 2020 13:39:18 +0530 Subject: [PATCH] fix: non-empty service unit set as empty after booking appointment --- .../patient_appointment.js | 345 +++++++++--------- .../patient_appointment.json | 45 ++- 2 files changed, 188 insertions(+), 202 deletions(-) diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js index 28c326a9ad..dde720b7d1 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js @@ -1,6 +1,6 @@ // Copyright (c) 2016, ESS LLP and contributors // For license information, please see license.txt -frappe.provide("erpnext.queries"); +frappe.provide('erpnext.queries'); frappe.ui.form.on('Patient Appointment', { setup: function(frm) { frm.custom_make_buttons = { @@ -8,24 +8,32 @@ frappe.ui.form.on('Patient Appointment', { 'Patient Encounter': 'Patient Encounter' }; }, + + onload: function(frm) { + if (frm.is_new()) { + frm.set_value('appointment_time', null); + frm.disable_save(); + } + }, + refresh: function(frm) { - frm.set_query("patient", function () { + frm.set_query('patient', function () { return { - filters: {"status": "Active"} + filters: {'status': 'Active'} }; }); - frm.set_query("practitioner", function() { + frm.set_query('practitioner', function() { return { filters: { 'department': frm.doc.department } }; }); - frm.set_query("service_unit", function(){ + frm.set_query('service_unit', function(){ return { filters: { - "is_group": false, - "allow_appointments": true + 'is_group': 0, + 'allow_appointments': 1 } }; }); @@ -42,127 +50,104 @@ frappe.ui.form.on('Patient Appointment', { frm.page.set_primary_action(__('Save'), () => frm.save()); } - if(frm.doc.patient){ + if (frm.doc.patient) { frm.add_custom_button(__('Patient History'), function() { - frappe.route_options = {"patient": frm.doc.patient}; - frappe.set_route("patient_history"); - },__("View")); + frappe.route_options = {'patient': frm.doc.patient}; + frappe.set_route('patient_history'); + },__('View')); } - if(frm.doc.status == "Open"){ + + if (frm.doc.status == 'Open' || (frm.doc.status == 'Scheduled' && !frm.doc.__islocal)) { frm.add_custom_button(__('Cancel'), function() { - btn_update_status(frm, "Cancelled"); + update_status(frm, 'Cancelled'); }); frm.add_custom_button(__('Reschedule'), function() { check_and_set_availability(frm); }); - if(frm.doc.procedure_template){ - frm.add_custom_button(__("Procedure"),function(){ - btn_create_procedure(frm); - },"Create"); - } - else{ - frm.add_custom_button(__("Patient Encounter"),function(){ - btn_create_encounter(frm); - },"Create"); + + if (frm.doc.procedure_template) { + frm.add_custom_button(__('Procedure'), function(){ + create_procedure(frm); + },'Create'); + } else { + frm.add_custom_button(__('Patient Encounter'), function() { + create_encounter(frm); + },'Create'); } frm.add_custom_button(__('Vital Signs'), function() { - btn_create_vital_signs(frm); - },"Create"); + create_vital_signs(frm); + },'Create'); } - if(frm.doc.status == "Scheduled" && !frm.doc.__islocal){ - frm.add_custom_button(__('Cancel'), function() { - btn_update_status(frm, "Cancelled"); - }); - frm.add_custom_button(__('Reschedule'), function() { - check_and_set_availability(frm); - }); - if(frm.doc.procedure_template){ - frm.add_custom_button(__("Procedure"),function(){ - btn_create_procedure(frm); - },"Create"); - } - else{ - frm.add_custom_button(__("Patient Encounter"),function(){ - btn_create_encounter(frm); - },"Create"); - } - frm.add_custom_button(__('Vital Signs'), function() { - btn_create_vital_signs(frm); - },"Create"); - } - if(frm.doc.status == "Pending"){ + if (frm.doc.status == 'Pending') { frm.add_custom_button(__('Set Open'), function() { - btn_update_status(frm, "Open"); + update_status(frm, 'Open'); }); frm.add_custom_button(__('Cancel'), function() { - btn_update_status(frm, "Cancelled"); + update_status(frm, 'Cancelled'); }); } - frm.set_df_property("get_procedure_from_encounter", "read_only", frm.doc.__islocal ? 0 : 1); - frappe.db.get_value('Healthcare Settings', {name: 'Healthcare Settings'}, 'manage_appointment_invoice_automatically', (r) => { - if(r.manage_appointment_invoice_automatically == 1){ - frm.set_df_property("mode_of_payment", "hidden", 0); - frm.set_df_property("paid_amount", "hidden", 0); - frm.set_df_property("mode_of_payment", "reqd", 1); - frm.set_df_property("paid_amount", "reqd", 1); - } - else{ - frm.set_df_property("mode_of_payment", "hidden", 1); - frm.set_df_property("paid_amount", "hidden", 1); - frm.set_df_property("mode_of_payment", "reqd", 0); - frm.set_df_property("paid_amount", "reqd", 0); + + frappe.db.get_value('Healthcare Settings', {name: 'Healthcare Settings'}, 'manage_appointment_invoice_automatically', (settings) => { + if (settings.manage_appointment_invoice_automatically) { + frm.set_df_property('mode_of_payment', 'hidden', 0); + frm.set_df_property('paid_amount', 'hidden', 0); + frm.set_df_property('mode_of_payment', 'reqd', 1); + frm.set_df_property('paid_amount', 'reqd', 1); + } else { + frm.set_df_property('mode_of_payment', 'hidden', 1); + frm.set_df_property('paid_amount', 'hidden', 1); + frm.set_df_property('mode_of_payment', 'reqd', 0); + frm.set_df_property('paid_amount', 'reqd', 0); } }); }, - onload:function(frm){ - if(frm.is_new()) { - frm.set_value("appointment_time", null); - frm.disable_save(); - } - }, + get_procedure_from_encounter: function(frm) { - get_procedure_prescribed(frm); + get_prescribed_procedure(frm); } }); -var check_and_set_availability = function(frm) { - var selected_slot = null; - var service_unit = null; - var duration = null; +let check_and_set_availability = function(frm) { + let selected_slot = null; + let service_unit = null; + let duration = null; show_availability(); function show_empty_state(practitioner, appointment_date) { frappe.msgprint({ title: __('Not Available'), - message: __("Healthcare Practitioner {0} not available on {1}", [practitioner.bold(), appointment_date.bold()]), + message: __('Healthcare Practitioner {0} not available on {1}', [practitioner.bold(), appointment_date.bold()]), indicator: 'red' }); } function show_availability() { let selected_practitioner = ''; - var d = new frappe.ui.Dialog({ - title: __("Available slots"), + let d = new frappe.ui.Dialog({ + title: __('Available slots'), fields: [ - { fieldtype: 'Link', options: 'Medical Department', reqd:1, fieldname: 'department', label: 'Medical Department'}, + { fieldtype: 'Link', options: 'Medical Department', reqd: 1, fieldname: 'department', label: 'Medical Department'}, { fieldtype: 'Column Break'}, - { fieldtype: 'Link', options: 'Healthcare Practitioner', reqd:1, fieldname: 'practitioner', label: 'Healthcare Practitioner'}, + { fieldtype: 'Link', options: 'Healthcare Practitioner', reqd: 1, fieldname: 'practitioner', label: 'Healthcare Practitioner'}, { fieldtype: 'Column Break'}, - { fieldtype: 'Date', reqd:1, fieldname: 'appointment_date', label: 'Date'}, + { fieldtype: 'Date', reqd: 1, fieldname: 'appointment_date', label: 'Date'}, { fieldtype: 'Section Break'}, { fieldtype: 'HTML', fieldname: 'available_slots'} + ], - primary_action_label: __("Book"), + primary_action_label: __('Book'), primary_action: function() { frm.set_value('appointment_time', selected_slot); - frm.set_value('service_unit', service_unit || ''); frm.set_value('duration', duration); frm.set_value('practitioner', d.get_value('practitioner')); frm.set_value('department', d.get_value('department')); frm.set_value('appointment_date', d.get_value('appointment_date')); + if (service_unit) { + frm.set_value('service_unit', service_unit); + } d.hide(); frm.enable_save(); frm.save(); @@ -177,16 +162,16 @@ var check_and_set_availability = function(frm) { 'appointment_date': frm.doc.appointment_date }); - d.fields_dict["department"].df.onchange = () => { + d.fields_dict['department'].df.onchange = () => { d.set_values({ 'practitioner': '' }); - var department = d.get_value('department'); - if(department){ + let department = d.get_value('department'); + if (department) { d.fields_dict.practitioner.get_query = function() { return { filters: { - "department": department + 'department': department } }; }; @@ -198,13 +183,13 @@ var check_and_set_availability = function(frm) { // Field Change Handler - var fd = d.fields_dict; + let fd = d.fields_dict; - d.fields_dict["appointment_date"].df.onchange = () => { + d.fields_dict['appointment_date'].df.onchange = () => { show_slots(d, fd); }; - d.fields_dict["practitioner"].df.onchange = () => { - if(d.get_value('practitioner') && d.get_value('practitioner') != selected_practitioner){ + d.fields_dict['practitioner'].df.onchange = () => { + if (d.get_value('practitioner') && d.get_value('practitioner') != selected_practitioner) { selected_practitioner = d.get_value('practitioner'); show_slots(d, fd); } @@ -213,8 +198,8 @@ var check_and_set_availability = function(frm) { } function show_slots(d, fd) { - if (d.get_value('appointment_date') && d.get_value('practitioner')){ - fd.available_slots.html(""); + if (d.get_value('appointment_date') && d.get_value('practitioner')) { + fd.available_slots.html(''); frappe.call({ method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_availability_data', args: { @@ -222,13 +207,13 @@ var check_and_set_availability = function(frm) { date: d.get_value('appointment_date') }, callback: (r) => { - var data = r.message; - if(data.slot_details.length > 0) { - var $wrapper = d.fields_dict.available_slots.$wrapper; + let data = r.message; + if (data.slot_details.length > 0) { + let $wrapper = d.fields_dict.available_slots.$wrapper; // make buttons for each slot - var slot_details = data.slot_details; - var slot_html = ""; + let slot_details = data.slot_details; + let slot_html = ''; for (let i = 0; i < slot_details.length; i++) { slot_html = slot_html + ``; slot_html = slot_html + `
` + slot_details[i].avail_slot.map(slot => { @@ -242,14 +227,14 @@ var check_and_set_availability = function(frm) { let booked_moment = moment(booked.appointment_time, 'HH:mm:ss'); let end_time = booked_moment.clone().add(booked.duration, 'minutes'); // Deal with 0 duration appointments - if(booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)){ + if (booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)) { if(booked.duration == 0){ disabled = 'disabled="disabled"'; return false; } } // Check for overlaps considering appointment duration - if(slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)){ + if (slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)) { // There is an overlap disabled = 'disabled="disabled"'; return false; @@ -273,7 +258,7 @@ var check_and_set_availability = function(frm) { // blue button when clicked $wrapper.on('click', 'button', function() { - var $btn = $(this); + let $btn = $(this); $wrapper.find('button').removeClass('btn-primary'); $btn.addClass('btn-primary'); selected_slot = $btn.attr('data-name'); @@ -283,52 +268,57 @@ var check_and_set_availability = function(frm) { d.get_primary_btn().attr('disabled', null); }); - }else { - // fd.available_slots.html("Please select a valid date.".bold()) + } else { + // fd.available_slots.html('Please select a valid date.'.bold()) show_empty_state(d.get_value('practitioner'), d.get_value('appointment_date')); } }, freeze: true, - freeze_message: __("Fetching records......") + freeze_message: __('Fetching records......') }); - }else{ - fd.available_slots.html("Appointment date and Healthcare Practitioner are Mandatory".bold()); + } else { + fd.available_slots.html('Appointment date and Healthcare Practitioner are Mandatory'.bold()); } } }; -var get_procedure_prescribed = function(frm){ - if(frm.doc.patient){ +let get_prescribed_procedure = function(frm) { + if (frm.doc.patient) { frappe.call({ - method:"erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_procedure_prescribed", + method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_procedure_prescribed', args: {patient: frm.doc.patient}, callback: function(r) { if (r.message && r.message.length) { show_procedure_templates(frm, r.message); } else { - frappe.msgprint(__("No Prescribed Procedures found for the selected patient")); + frappe.msgprint({ + title: __('Not Found'), + message: __('No Prescribed Procedures found for the selected Patient') + }); } } }); - } - else{ - frappe.msgprint(__("Please select Patient to get prescribed procedure")); + } else { + frappe.msgprint({ + title: __('Not Allowed'), + message: __('Please select Patient first') + }); } }; -var show_procedure_templates = function(frm, result){ - var d = new frappe.ui.Dialog({ - title: __("Prescribed Procedures"), +let show_procedure_templates = function(frm, result){ + let d = new frappe.ui.Dialog({ + title: __('Prescribed Procedures'), fields: [ { - fieldtype: "HTML", fieldname: "procedure_template" + fieldtype: 'HTML', fieldname: 'procedure_template' } ] }); - var html_field = d.fields_dict.procedure_template.$wrapper; + let html_field = d.fields_dict.procedure_template.$wrapper; html_field.empty(); - $.each(result, function(x, y){ - var row = $(repl('
\ + $.each(result, function(x, y) { + let row = $(repl('
\
%(encounter)s
%(consulting_practitioner)s
%(encounter_date)s
\
%(procedure_template)s
%(practitioner)s
%(date)s
\
\ @@ -340,76 +330,75 @@ var show_procedure_templates = function(frm, result){ encounter:y[2], consulting_practitioner:y[3], encounter_date:y[4], practitioner:y[5]? y[5]:'', date: y[6]? y[6]:'', department: y[7]? y[7]:''})).appendTo(html_field); row.find("a").click(function() { - frm.doc.procedure_template = $(this).attr("data-procedure-template"); - frm.doc.procedure_prescription = $(this).attr("data-name"); - frm.doc.practitioner = $(this).attr("data-practitioner"); - frm.doc.appointment_date = $(this).attr("data-date"); - frm.doc.department = $(this).attr("data-department"); - refresh_field("procedure_template"); - refresh_field("procedure_prescription"); - refresh_field("appointment_date"); - refresh_field("practitioner"); - refresh_field("department"); + frm.doc.procedure_template = $(this).attr('data-procedure-template'); + frm.doc.procedure_prescription = $(this).attr('data-name'); + frm.doc.practitioner = $(this).attr('data-practitioner'); + frm.doc.appointment_date = $(this).attr('data-date'); + frm.doc.department = $(this).attr('data-department'); + refresh_field('procedure_template'); + refresh_field('procedure_prescription'); + refresh_field('appointment_date'); + refresh_field('practitioner'); + refresh_field('department'); d.hide(); return false; }); }); - if(!result){ - var msg = "There are no procedure prescribed for "+frm.doc.patient; + if (!result) { + let msg = 'There are no procedure prescribed for '+frm.doc.patient; $(repl('
%(msg)s
', {msg: msg})).appendTo(html_field); } d.show(); }; -var btn_create_procedure = function(frm){ - var doc = frm.doc; +let create_procedure = function(frm) { + let doc = frm.doc; frappe.call({ - method:"erpnext.healthcare.doctype.clinical_procedure.clinical_procedure.create_procedure", + method: 'erpnext.healthcare.doctype.clinical_procedure.clinical_procedure.create_procedure', args: {appointment: doc.name}, - callback: function(data){ - if(!data.exc){ - var doclist = frappe.model.sync(data.message); - frappe.set_route("Form", doclist[0].doctype, doclist[0].name); + callback: function(data) { + if (!data.exc) { + let doclist = frappe.model.sync(data.message); + frappe.set_route('Form', doclist[0].doctype, doclist[0].name); } } }); }; -var btn_create_encounter = function(frm){ - var doc = frm.doc; +let create_encounter = function(frm) { + let doc = frm.doc; frappe.call({ - method:"erpnext.healthcare.doctype.patient_appointment.patient_appointment.create_encounter", + method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.create_encounter', args: {appointment: doc.name}, callback: function(data){ - if(!data.exc){ - var doclist = frappe.model.sync(data.message); - frappe.set_route("Form", doclist[0].doctype, doclist[0].name); + if (!data.exc) { + let doclist = frappe.model.sync(data.message); + frappe.set_route('Form', doclist[0].doctype, doclist[0].name); } } }); }; -var btn_create_vital_signs = function (frm) { - if(!frm.doc.patient){ - frappe.throw(__("Please select patient")); +let create_vital_signs = function(frm) { + if (!frm.doc.patient) { + frappe.throw(__('Please select patient')); } frappe.route_options = { - "patient": frm.doc.patient, - "appointment": frm.doc.name, + 'patient': frm.doc.patient, + 'appointment': frm.doc.name, }; - frappe.new_doc("Vital Signs"); + frappe.new_doc('Vital Signs'); }; -var btn_update_status = function(frm, status){ - var doc = frm.doc; +let update_status = function(frm, status){ + let doc = frm.doc; frappe.confirm(__('Are you sure you want to cancel this appointment?'), function() { frappe.call({ - method: - "erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status", + method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status', args: {appointment_id: doc.name, status:status}, - callback: function(data){ - if(!data.exc){ + callback: function(data) { + if (!data.exc) { frm.reload_doc(); } } @@ -418,60 +407,60 @@ var btn_update_status = function(frm, status){ ); }; -frappe.ui.form.on("Patient Appointment", "practitioner", function(frm) { - if(frm.doc.practitioner){ +frappe.ui.form.on('Patient Appointment', 'practitioner', function(frm) { + if (frm.doc.practitioner) { frappe.call({ - "method": "frappe.client.get", + method: 'frappe.client.get', args: { - doctype: "Healthcare Practitioner", + doctype: 'Healthcare Practitioner', name: frm.doc.practitioner }, callback: function (data) { - frappe.model.set_value(frm.doctype,frm.docname, "department",data.message.department); - frappe.model.set_value(frm.doctype,frm.docname, "paid_amount",data.message.op_consulting_charge); + frappe.model.set_value(frm.doctype, frm.docname, 'department', data.message.department); + frappe.model.set_value(frm.doctype, frm.docname, 'paid_amount', data.message.op_consulting_charge); } }); } }); -frappe.ui.form.on("Patient Appointment", "patient", function(frm) { - if(frm.doc.patient){ +frappe.ui.form.on('Patient Appointment', 'patient', function(frm) { + if (frm.doc.patient) { frappe.call({ - "method": "frappe.client.get", + method: 'frappe.client.get', args: { - doctype: "Patient", + doctype: 'Patient', name: frm.doc.patient }, callback: function (data) { - var age = null; - if(data.message.dob){ + let age = null; + if (data.message.dob) { age = calculate_age(data.message.dob); } - frappe.model.set_value(frm.doctype,frm.docname, "patient_age", age); + frappe.model.set_value(frm.doctype,frm.docname, 'patient_age', age); } }); } }); -frappe.ui.form.on("Patient Appointment", "appointment_type", function(frm) { - if(frm.doc.appointment_type) { +frappe.ui.form.on('Patient Appointment', 'appointment_type', function(frm) { + if (frm.doc.appointment_type) { frappe.call({ - "method": "frappe.client.get", + method: 'frappe.client.get', args: { - doctype: "Appointment Type", + doctype: 'Appointment Type', name: frm.doc.appointment_type }, - callback: function (data) { - frappe.model.set_value(frm.doctype,frm.docname, "duration",data.message.default_duration); + callback: function(data) { + frappe.model.set_value(frm.doctype,frm.docname, 'duration',data.message.default_duration); } }); } }); -var calculate_age = function(birth) { - var ageMS = Date.parse(Date()) - Date.parse(birth); - var age = new Date(); +let calculate_age = function(birth) { + let ageMS = Date.parse(Date()) - Date.parse(birth); + let age = new Date(); age.setTime(ageMS); - var years = age.getFullYear() - 1970; - return years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)"; + let years = age.getFullYear() - 1970; + return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)'; }; diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json index bfcfbcf201..c2fba688a5 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json @@ -9,10 +9,11 @@ "document_type": "Document", "engine": "InnoDB", "field_order": [ - "inpatient_record", "patient", - "appointment_type", - "duration", + "patient_name", + "patient_sex", + "patient_age", + "inpatient_record", "column_break_1", "status", "procedure_template", @@ -22,20 +23,18 @@ "section_break_12", "practitioner", "department", + "appointment_type", "column_break_17", "appointment_date", "appointment_time", - "section_break_16", - "patient_name", - "patient_sex", - "column_break_21", - "patient_age", - "section_break_1", "appointment_datetime", + "duration", + "section_break_16", + "invoiced", + "ref_sales_invoice", + "column_break_2", "mode_of_payment", "paid_amount", - "column_break_2", - "invoiced", "company", "section_break_3", "notes", @@ -73,11 +72,10 @@ "set_only_once": 1 }, { - "description": "In Minutes", "fieldname": "duration", "fieldtype": "Int", "in_filter": 1, - "label": "Duration" + "label": "Duration (In Minutes)" }, { "fieldname": "column_break_1", @@ -104,9 +102,10 @@ "set_only_once": 1 }, { + "depends_on": "eval:doc.__islocal && doc.patient", "fieldname": "get_procedure_from_encounter", "fieldtype": "Button", - "label": "Get prescribed procedures" + "label": "Get Prescribed Clinical Procedures" }, { "fieldname": "procedure_prescription", @@ -194,21 +193,12 @@ "read_only": 1, "report_hide": 1 }, - { - "fieldname": "column_break_21", - "fieldtype": "Column Break" - }, { "fieldname": "patient_age", "fieldtype": "Data", "label": "Patient Age", "read_only": 1 }, - { - "fieldname": "section_break_1", - "fieldtype": "Section Break", - "set_only_once": 1 - }, { "fieldname": "appointment_datetime", "fieldtype": "Datetime", @@ -279,10 +269,17 @@ "label": "Reminded", "print_hide": 1, "report_hide": 1 + }, + { + "fieldname": "ref_sales_invoice", + "fieldtype": "Link", + "label": "Reference Sales Invoice", + "options": "Sales Invoice", + "read_only": 1 } ], "links": [], - "modified": "2020-02-03 23:38:41.821141", + "modified": "2020-02-10 22:38:55.401247", "modified_by": "Administrator", "module": "Healthcare", "name": "Patient Appointment",