Healthcare - Patient Appointment - Service unit based scheduling and booking (#13211)
* New Document - Patient Service Unit * Physician - schedule based on patient service unit * Consultation - Remove validation on submit * Consultation - Label changed from Drug Prescription to Medication * Availability check and book appointment based on service unit, appointment invoice creation optimized * patch fixes * Patient Service Unit - field - overlap_appointments * Patient Appointment - Service Unit based scheduling and booking * Patient Appointment - issue fixed #13016 Healthcare Patient Appointment Save Button Issue - remove validation on save and enable save on book appointment * Codacy fixes on PR #13211 * Codacy fixes on PR #13211 * Fee validity test -fixes * Fee Validity - test - fixes
This commit is contained in:
parent
11241044b2
commit
665b48773f
@ -86,6 +86,11 @@ def get_data():
|
||||
"type": "doctype",
|
||||
"name": "Medical Code",
|
||||
"label": _("Medical Code"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Patient Service Unit",
|
||||
"label": _("Patient Service Unit")
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -767,7 +767,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Drug Prescription",
|
||||
"label": "Medication",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -797,7 +797,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Drug Prescription",
|
||||
"label": "Medication",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Drug Prescription",
|
||||
@ -945,7 +945,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-28 11:25:35.256848",
|
||||
"modified": "2018-02-19 11:35:13.826577",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Consultation",
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import getdate
|
||||
import json
|
||||
@ -19,10 +18,6 @@ class Consultation(Document):
|
||||
def after_insert(self):
|
||||
insert_consultation_to_medical_record(self)
|
||||
|
||||
def on_submit(self):
|
||||
if not self.diagnosis or not self.symptoms:
|
||||
frappe.throw(_("Diagnosis and Complaints cannot be left blank"))
|
||||
|
||||
def on_cancel(self):
|
||||
if(self.appointment):
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Open")
|
||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import create_invoice
|
||||
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import invoice_appointment
|
||||
from frappe.utils.make_random import get_random
|
||||
from frappe.utils import nowdate, add_days
|
||||
# test_records = frappe.get_test_records('Fee Validity')
|
||||
@ -14,6 +14,7 @@ class TestFeeValidity(unittest.TestCase):
|
||||
def test_fee_validity(self):
|
||||
patient = get_random("Patient")
|
||||
physician = get_random("Physician")
|
||||
department = get_random("Medical Department")
|
||||
|
||||
if not patient:
|
||||
patient = frappe.new_doc("Patient")
|
||||
@ -22,33 +23,43 @@ class TestFeeValidity(unittest.TestCase):
|
||||
patient.save(ignore_permissions=True)
|
||||
patient = patient.name
|
||||
|
||||
if not department:
|
||||
medical_department = frappe.new_doc("Medical Department")
|
||||
medical_department.department = "Test Medical Department"
|
||||
medical_department.save(ignore_permissions=True)
|
||||
department = medical_department.name
|
||||
|
||||
if not physician:
|
||||
physician = frappe.new_doc("Physician")
|
||||
physician.first_name = "Amit Jain"
|
||||
physician.department = department
|
||||
physician.save(ignore_permissions=True)
|
||||
physician = physician.name
|
||||
|
||||
|
||||
|
||||
frappe.db.set_value("Healthcare Settings", None, "max_visit", 2)
|
||||
frappe.db.set_value("Healthcare Settings", None, "valid_days", 7)
|
||||
|
||||
appointment = create_appointment(patient, physician, nowdate())
|
||||
appointment = create_appointment(patient, physician, nowdate(), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertEqual(invoice, None)
|
||||
create_invoice(frappe.defaults.get_global_default("company"), physician, patient, appointment.name, appointment.appointment_date)
|
||||
appointment = create_appointment(patient, physician, add_days(nowdate(), 4))
|
||||
invoice_appointment(appointment)
|
||||
appointment = create_appointment(patient, physician, add_days(nowdate(), 4), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertTrue(invoice)
|
||||
appointment = create_appointment(patient, physician, add_days(nowdate(), 5))
|
||||
appointment = create_appointment(patient, physician, add_days(nowdate(), 5), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertEqual(invoice, None)
|
||||
appointment = create_appointment(patient, physician, add_days(nowdate(), 10))
|
||||
appointment = create_appointment(patient, physician, add_days(nowdate(), 10), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertEqual(invoice, None)
|
||||
|
||||
def create_appointment(patient, physician, appointment_date):
|
||||
def create_appointment(patient, physician, appointment_date, department):
|
||||
appointment = frappe.new_doc("Patient Appointment")
|
||||
appointment.patient = patient
|
||||
appointment.physician = physician
|
||||
appointment.department = department
|
||||
appointment.appointment_date = appointment_date
|
||||
appointment.save(ignore_permissions=True)
|
||||
return appointment
|
||||
|
@ -15,6 +15,20 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
filters: {"disabled": 0}
|
||||
};
|
||||
});
|
||||
frm.set_query("physician", function() {
|
||||
return {
|
||||
filters: {
|
||||
'department': frm.doc.department
|
||||
}
|
||||
};
|
||||
});
|
||||
frm.set_query("service_unit", function(){
|
||||
return {
|
||||
filters: {
|
||||
"is_group": false,
|
||||
}
|
||||
};
|
||||
});
|
||||
if(frm.doc.patient){
|
||||
frm.add_custom_button(__('Medical Record'), function() {
|
||||
frappe.route_options = {"patient": frm.doc.patient};
|
||||
@ -83,11 +97,10 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
date: appointment_date
|
||||
},
|
||||
callback: (r) => {
|
||||
// console.log(r);
|
||||
var data = r.message;
|
||||
if(data.available_slots.length > 0) {
|
||||
if(data.slot_details.length > 0){
|
||||
show_availability(data);
|
||||
} else {
|
||||
}else{
|
||||
show_empty_state();
|
||||
}
|
||||
}
|
||||
@ -108,48 +121,71 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
primary_action_label: __("Book"),
|
||||
primary_action: function() {
|
||||
// book slot
|
||||
frm.set_value('appointment_time', selected_slot);
|
||||
frm.set_value('duration', data.time_per_appointment);
|
||||
var btn_selected = $wrapper.find('button.btn-selected-slot');
|
||||
frm.set_value('appointment_time', btn_selected.attr('data-name'));
|
||||
frm.set_value('service_unit', btn_selected.attr('data-service-unit') || '');
|
||||
frm.set_value('duration', btn_selected.attr('data-duration'));
|
||||
d.hide();
|
||||
frm.save();
|
||||
frm.enable_save();
|
||||
}
|
||||
});
|
||||
var $wrapper = d.fields_dict.available_slots.$wrapper;
|
||||
var selected_slot = null;
|
||||
|
||||
// disable dialog action initially
|
||||
d.get_primary_btn().attr('disabled', true);
|
||||
|
||||
// make buttons for each slot
|
||||
var slot_html = data.available_slots.map(slot => {
|
||||
var slot_details = data.slot_details;
|
||||
var slot_html = "";
|
||||
$.each(slot_details, function(i, slot_detail){
|
||||
slot_html = slot_html + `<label>${slot_detail['slot_name']}</label>`;
|
||||
slot_html = slot_html + `<br/>` + slot_detail['avail_slot'].map(slot => {
|
||||
let disabled = '';
|
||||
let start_str = slot.from_time;
|
||||
let start_time = moment(slot.from_time, 'HH:mm:ss');
|
||||
let to_time = moment(slot.to_time, 'HH:mm:ss');
|
||||
let interval = (to_time - start_time)/60000 | 0;
|
||||
// iterate in all booked appointments, update the start time and duration
|
||||
slot_detail['appointments'].forEach(function(booked) {
|
||||
let booked_moment = moment(booked.appointment_time, 'HH:mm:ss');
|
||||
if(booked_moment.isSame(start_time) || booked_moment.isBetween(start_time, to_time)){
|
||||
if(booked.duration == 0){
|
||||
disabled = 'disabled="disabled"';
|
||||
return false;
|
||||
}
|
||||
start_time = booked_moment;
|
||||
let end_time = booked_moment.add(booked.duration, 'minutes');
|
||||
if(end_time.isSameOrAfter(to_time)){
|
||||
disabled = 'disabled="disabled"';
|
||||
return false;
|
||||
}else{
|
||||
start_str = end_time.format('HH:mm:ss');
|
||||
}
|
||||
}
|
||||
});
|
||||
return `<button class="btn btn-default"
|
||||
data-name=${slot.from_time}
|
||||
style="margin: 0 10px 10px 0; width: 72px">
|
||||
${slot.from_time.substring(0, slot.from_time.length - 3)}
|
||||
data-name=${start_str}
|
||||
data-duration=${interval}
|
||||
data-service-unit="${slot_detail['service_unit'] || ''}"
|
||||
style="margin: 0 10px 10px 0; width: 72px;" ${disabled}>
|
||||
${start_str.substring(0, start_str.length - 3)}
|
||||
</button>`;
|
||||
}).join("");
|
||||
slot_html = slot_html + `<br/>`;
|
||||
});
|
||||
|
||||
$wrapper
|
||||
.css('margin-bottom', 0)
|
||||
.addClass('text-center')
|
||||
.html(slot_html);
|
||||
|
||||
// disable buttons for which appointments are booked
|
||||
data.appointments.map(slot => {
|
||||
if(slot.status == "Scheduled" || slot.status == "Open" || slot.status == "Closed"){
|
||||
$wrapper
|
||||
.find(`button[data-name="${slot.appointment_time}"]`)
|
||||
.attr('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
// blue button when clicked
|
||||
$wrapper.on('click', 'button', function() {
|
||||
var $btn = $(this);
|
||||
$wrapper.find('button').removeClass('btn-primary');
|
||||
$wrapper.find('button').removeClass('btn-selected-slot');
|
||||
$btn.addClass('btn-primary');
|
||||
selected_slot = $btn.attr('data-name');
|
||||
|
||||
$btn.addClass('btn-selected-slot');
|
||||
// enable dialog action
|
||||
d.get_primary_btn().attr('disabled', null);
|
||||
});
|
||||
@ -209,12 +245,9 @@ var btn_update_status = function(frm, status){
|
||||
};
|
||||
|
||||
var btn_invoice_consultation = function(frm){
|
||||
var doc = frm.doc;
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.healthcare.doctype.patient_appointment.patient_appointment.create_invoice",
|
||||
args: {company: doc.company, physician:doc.physician, patient: doc.patient,
|
||||
appointment_id: doc.name, appointment_date:doc.appointment_date },
|
||||
doc: frm.doc,
|
||||
method:"create_invoice",
|
||||
callback: function(data){
|
||||
if(!data.exc){
|
||||
if(data.message){
|
||||
|
@ -42,6 +42,39 @@
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "department",
|
||||
"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": "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": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -73,6 +106,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -103,6 +137,71 @@
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "appointment_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,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"description": "In Minutes",
|
||||
"fieldname": "duration",
|
||||
"fieldtype": "Int",
|
||||
"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": "Duration",
|
||||
"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
|
||||
},
|
||||
{
|
||||
@ -134,6 +233,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -151,8 +251,42 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"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": "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": "Patient Service Unit",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -162,7 +296,8 @@
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -195,6 +330,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -226,6 +362,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -257,6 +394,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -271,7 +409,7 @@
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
@ -289,6 +427,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -319,7 +458,8 @@
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -349,68 +489,8 @@
|
||||
"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": "appointment_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": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "In Minutes",
|
||||
"fieldname": "duration",
|
||||
"fieldtype": "Int",
|
||||
"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": "Duration",
|
||||
"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
|
||||
},
|
||||
{
|
||||
@ -441,6 +521,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -470,37 +551,7 @@
|
||||
"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": "department",
|
||||
"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": "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": 1,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -532,6 +583,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -563,6 +615,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -593,6 +646,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -623,6 +677,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -654,6 +709,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -685,6 +741,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -698,7 +755,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-28 11:26:20.262978",
|
||||
"modified": "2018-02-26 12:44:33.756124",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient Appointment",
|
||||
@ -744,6 +801,26 @@
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 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,
|
||||
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
import json
|
||||
from frappe.utils import getdate, cint
|
||||
from frappe.utils import getdate
|
||||
from frappe import _
|
||||
import datetime
|
||||
from frappe.core.doctype.sms_settings.sms_settings import send_sms
|
||||
@ -40,13 +40,8 @@ class PatientAppointment(Document):
|
||||
frappe.msgprint(_("{0} has fee validity till {1}").format(appointment.patient, fee_validity.valid_till))
|
||||
confirm_sms(self)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# duration is the only changeable field in the document
|
||||
if not self.is_new():
|
||||
self.db_set('duration', cint(self.duration))
|
||||
else:
|
||||
super(PatientAppointment, self).save(*args, **kwargs)
|
||||
|
||||
def create_invoice(self):
|
||||
return invoice_appointment(self)
|
||||
|
||||
def appointment_cancel(appointment_id):
|
||||
appointment = frappe.get_doc("Patient Appointment", appointment_id)
|
||||
@ -79,9 +74,9 @@ def get_availability_data(date, physician):
|
||||
weekday = date.strftime("%A")
|
||||
|
||||
available_slots = []
|
||||
physician_schedule_name = None
|
||||
slot_details = []
|
||||
physician_schedule = None
|
||||
time_per_appointment = None
|
||||
|
||||
employee = None
|
||||
|
||||
physician_obj = frappe.get_doc("Physician", physician)
|
||||
@ -112,43 +107,56 @@ def get_availability_data(date, physician):
|
||||
frappe.throw(_("Dr {0} on Leave on {1}").format(physician, date))
|
||||
|
||||
# get physicians schedule
|
||||
physician_schedule_name = frappe.db.get_value("Physician", physician, "physician_schedule")
|
||||
if physician_schedule_name:
|
||||
physician_schedule = frappe.get_doc("Physician Schedule", physician_schedule_name)
|
||||
time_per_appointment = frappe.db.get_value("Physician", physician, "time_per_appointment")
|
||||
if physician_obj.physician_schedules:
|
||||
for schedule in physician_obj.physician_schedules:
|
||||
if schedule.schedule:
|
||||
physician_schedule = frappe.get_doc("Physician Schedule", schedule.schedule)
|
||||
else:
|
||||
frappe.throw(_("Dr {0} does not have a Physician Schedule. Add it in Physician master".format(physician)))
|
||||
|
||||
if physician_schedule:
|
||||
available_slots = []
|
||||
for t in physician_schedule.time_slots:
|
||||
if weekday == t.day:
|
||||
available_slots.append(t)
|
||||
|
||||
# `time_per_appointment` should never be None since validation in `Patient` is supposed to prevent
|
||||
# that. However, it isn't impossible so we'll prepare for that.
|
||||
if not time_per_appointment:
|
||||
frappe.throw(_('"Time Per Appointment" hasn"t been set for Dr {0}. Add it in Physician master.').format(physician))
|
||||
if available_slots:
|
||||
appointments = []
|
||||
if schedule.service_unit:
|
||||
slot_name = schedule.schedule+" - "+schedule.service_unit
|
||||
allow_overlap = frappe.get_value('Patient Service Unit', schedule.service_unit, 'overlap_appointments')
|
||||
if allow_overlap:
|
||||
# fetch all appointments to physician by service unit
|
||||
appointments = frappe.get_all(
|
||||
"Patient Appointment",
|
||||
filters={"physician": physician, "service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
|
||||
fields=["name", "appointment_time", "duration", "status"])
|
||||
else:
|
||||
# fetch all appointments to service unit
|
||||
appointments = frappe.get_all(
|
||||
"Patient Appointment",
|
||||
filters={"service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
|
||||
fields=["name", "appointment_time", "duration", "status"])
|
||||
else:
|
||||
slot_name = schedule.schedule
|
||||
# fetch all appointments to physician without service unit
|
||||
appointments = frappe.get_all(
|
||||
"Patient Appointment",
|
||||
filters={"physician": physician, "service_unit": '', "appointment_date": date, "status": ["not in",["Cancelled"]]},
|
||||
fields=["name", "appointment_time", "duration", "status"])
|
||||
|
||||
# if physician not available return
|
||||
if not available_slots:
|
||||
slot_details.append({"slot_name":slot_name, "service_unit":schedule.service_unit,
|
||||
"avail_slot":available_slots, 'appointments': appointments})
|
||||
|
||||
else:
|
||||
frappe.throw(_("Dr {0} does not have a Physician Schedule. Add it in Physician master".format(physician)))
|
||||
|
||||
if not available_slots and not slot_details:
|
||||
# TODO: return available slots in nearby dates
|
||||
frappe.throw(_("Physician not available on {0}").format(weekday))
|
||||
|
||||
# if physician on leave return
|
||||
|
||||
# if holiday return
|
||||
# if is_holiday(weekday):
|
||||
|
||||
# get appointments on that day for physician
|
||||
appointments = frappe.get_all(
|
||||
"Patient Appointment",
|
||||
filters={"physician": physician, "appointment_date": date},
|
||||
fields=["name", "appointment_time", "duration", "status"])
|
||||
|
||||
return {
|
||||
"available_slots": available_slots,
|
||||
"appointments": appointments,
|
||||
"time_per_appointment": time_per_appointment
|
||||
"slot_details": slot_details
|
||||
}
|
||||
|
||||
|
||||
@ -182,25 +190,25 @@ def confirm_sms(doc):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_invoice(company, physician, patient, appointment_id, appointment_date):
|
||||
if not appointment_id:
|
||||
def invoice_appointment(appointment_doc):
|
||||
if not appointment_doc.name:
|
||||
return False
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.customer = frappe.get_value("Patient", patient, "customer")
|
||||
sales_invoice.appointment = appointment_id
|
||||
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
|
||||
sales_invoice.appointment = appointment_doc.name
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.is_pos = '0'
|
||||
sales_invoice.debit_to = get_receivable_account(company)
|
||||
sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
|
||||
|
||||
fee_validity = get_fee_validity(physician, patient, appointment_date)
|
||||
create_invoice_items(appointment_id, physician, company, sales_invoice)
|
||||
fee_validity = get_fee_validity(appointment_doc.physician, appointment_doc.patient, appointment_doc.appointment_date)
|
||||
create_invoice_items(appointment_doc.physician, appointment_doc.company, sales_invoice)
|
||||
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
frappe.db.sql("""update `tabPatient Appointment` set sales_invoice=%s where name=%s""", (sales_invoice.name, appointment_id))
|
||||
frappe.db.sql("""update `tabPatient Appointment` set sales_invoice=%s where name=%s""", (sales_invoice.name, appointment_doc.name))
|
||||
frappe.db.set_value("Fee Validity", fee_validity.name, "ref_invoice", sales_invoice.name)
|
||||
consultation = frappe.db.exists({
|
||||
"doctype": "Consultation",
|
||||
"appointment": appointment_id})
|
||||
"appointment": appointment_doc.name})
|
||||
if consultation:
|
||||
frappe.db.set_value("Consultation", consultation[0][0], "invoice", sales_invoice.name)
|
||||
return sales_invoice.name
|
||||
@ -247,7 +255,7 @@ def create_fee_validity(physician, patient, date):
|
||||
return fee_validity
|
||||
|
||||
|
||||
def create_invoice_items(appointment_id, physician, company, invoice):
|
||||
def create_invoice_items(physician, company, invoice):
|
||||
item_line = invoice.append("items")
|
||||
item_line.item_name = "Consulting Charges"
|
||||
item_line.description = "Consulting Charges: " + physician
|
||||
|
@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2017, earthians and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Patient Service Unit', {
|
||||
});
|
||||
|
||||
// get query select patient service unit
|
||||
cur_frm.fields_dict['parent_patient_service_unit'].get_query = function(doc) {
|
||||
return{
|
||||
filters:[
|
||||
['Patient Service Unit', 'is_group', '=', 1],
|
||||
['Patient Service Unit', 'name', '!=', doc.patient_service_unit_name]
|
||||
]
|
||||
};
|
||||
};
|
@ -0,0 +1,358 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:patient_service_unit_name",
|
||||
"beta": 1,
|
||||
"creation": "2016-09-21 13:48:14.731437",
|
||||
"custom": 0,
|
||||
"description": "Patinet Service Unit",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "patient_service_unit_name",
|
||||
"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": "Service Unit",
|
||||
"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": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "parent_patient_service_unit",
|
||||
"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": 0,
|
||||
"label": "Parent Service Unit",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Patient 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": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_group",
|
||||
"fieldtype": "Check",
|
||||
"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": "Is Group",
|
||||
"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,
|
||||
"fieldname": "overlap_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 Overlap",
|
||||
"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": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 1,
|
||||
"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": 1,
|
||||
"options": "Company",
|
||||
"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": "lft",
|
||||
"fieldtype": "Int",
|
||||
"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": "lft",
|
||||
"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": 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,
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"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": "rgt",
|
||||
"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": 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,
|
||||
"fieldname": "old_parent",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 1,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Old Parent",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Patient Service Unit",
|
||||
"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-03-07 13:25:51.163029",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient Service Unit",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"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,
|
||||
"user_permission_doctypes": "[\"Service Unit\"]",
|
||||
"write": 0
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 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,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"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": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"search_fields": "patient_service_unit_name",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "patient_service_unit_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, earthians and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
|
||||
class PatientServiceUnit(NestedSet):
|
||||
nsm_parent_field = 'parent_patient_service_unit'
|
||||
|
||||
def on_update(self):
|
||||
super(PatientServiceUnit, self).on_update()
|
||||
self.validate_one_root()
|
@ -0,0 +1,3 @@
|
||||
frappe.treeview_settings["Patient Service Unit"] = {
|
||||
ignore_fields:["parent_patient_service_unit"]
|
||||
};
|
@ -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: Patient Service Unit", 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', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, earthians and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
|
||||
class TestPatientServiceUnit(unittest.TestCase):
|
||||
pass
|
@ -19,6 +19,13 @@ frappe.ui.form.on('Physician', {
|
||||
if(!frm.is_new()) {
|
||||
frappe.contacts.render_address_and_contact(frm);
|
||||
}
|
||||
frm.set_query("service_unit", "physician_schedules", function(){
|
||||
return {
|
||||
filters: {
|
||||
"is_group": false,
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -435,45 +435,14 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "physician_schedule",
|
||||
"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": "Physician Schedule",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Physician Schedule",
|
||||
"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": "column_break_17",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "physician_schedules",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -481,39 +450,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Physician Schedules",
|
||||
"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,
|
||||
"description": "In minutes",
|
||||
"fieldname": "time_per_appointment",
|
||||
"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": "Time per Appointment",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Physician Service Unit Schedule",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -811,7 +751,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-01-19 15:25:43.166877",
|
||||
"modified_by": "jams@hcf.com",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Physician",
|
||||
"name_case": "",
|
||||
|
@ -20,7 +20,6 @@ class Physician(Document):
|
||||
[cstr(self.get(f)).strip() for f in ["first_name","middle_name","last_name"]]))
|
||||
|
||||
def validate(self):
|
||||
self.validate_schedule_and_time()
|
||||
validate_party_accounts(self)
|
||||
|
||||
if self.user_id:
|
||||
@ -37,15 +36,6 @@ class Physician(Document):
|
||||
frappe.permissions.remove_user_permission(
|
||||
"Physician", self.name, existing_user_id)
|
||||
|
||||
def validate_schedule_and_time(self):
|
||||
if (self.physician_schedule or self.time_per_appointment) and \
|
||||
not (self.physician_schedule and self.time_per_appointment):
|
||||
frappe.msgprint(
|
||||
_('Both "Physician Schedule" and Time Per Appointment" must be set for Dr {0}').format(
|
||||
self.first_name),
|
||||
title='Error', raise_exception=1, indicator='red'
|
||||
)
|
||||
|
||||
def on_update(self):
|
||||
if self.user_id:
|
||||
frappe.permissions.add_user_permission("Physician", self.name, self.user_id)
|
||||
|
@ -12,23 +12,6 @@ class TestPhysician(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
frappe.delete_doc_if_exists('Physician', '_Testdoctor2', force=1)
|
||||
|
||||
def test_schedule_and_time(self):
|
||||
physician = frappe.new_doc('Physician')
|
||||
physician.first_name = '_Testdoctor2'
|
||||
physician.physician_schedule = '_Testdoctor2 Schedule'
|
||||
|
||||
self.assertRaises(frappe.ValidationError, physician.insert)
|
||||
|
||||
physician.physician_schedule = ''
|
||||
physician.time_per_appointment = 15
|
||||
|
||||
self.assertRaises(frappe.ValidationError, physician.insert)
|
||||
|
||||
physician.physician_schedule = '_Testdoctor2 Schedule'
|
||||
physician.time_per_appointment = 15
|
||||
|
||||
physician.insert()
|
||||
|
||||
def test_new_physician_without_schedule(self):
|
||||
physician = frappe.new_doc('Physician')
|
||||
physician.first_name = '_Testdoctor2'
|
||||
|
@ -0,0 +1,103 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2017-11-16 12:19:17.163786",
|
||||
"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": "schedule",
|
||||
"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": "Schedule",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Physician Schedule",
|
||||
"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,
|
||||
"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": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Service Unit",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Patient 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": 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": "2017-12-27 10:57:42.301295",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Physician Service Unit Schedule",
|
||||
"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
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PhysicianServiceUnitSchedule(Document):
|
||||
pass
|
@ -504,6 +504,7 @@ execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=
|
||||
erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_group
|
||||
erpnext.patches.v10_0.add_default_cash_flow_mappers
|
||||
erpnext.patches.v11_0.make_quality_inspection_template
|
||||
erpnext.patches.v10_0.remove_and_copy_fields_in_physician
|
||||
erpnext.patches.v10_0.update_status_for_multiple_source_in_po
|
||||
erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
|
||||
erpnext.patches.v10_0.update_territory_and_customer_group
|
||||
|
12
erpnext/patches/v10_0/remove_and_copy_fields_in_physician.py
Normal file
12
erpnext/patches/v10_0/remove_and_copy_fields_in_physician.py
Normal file
@ -0,0 +1,12 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
if frappe.db.exists("DocType", "Physician"):
|
||||
frappe.reload_doc("healthcare", "doctype", "physician")
|
||||
frappe.reload_doc("healthcare", "doctype", "physician_service_unit_schedule")
|
||||
if frappe.db.has_column('Physician', 'physician_schedule'):
|
||||
for doc in frappe.get_all('Physician'):
|
||||
_doc = frappe.get_doc('Physician', doc.name)
|
||||
if _doc.physician_schedule:
|
||||
_doc.append('physician_schedules', {'schedule': _doc.physician_schedule})
|
||||
_doc.save()
|
Loading…
x
Reference in New Issue
Block a user