', {msg: msg})).appendTo(html_field);
}
d.show();
};
-var btn_create_procedure = function(frm){
- var doc = frm.doc;
- frappe.call({
- 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);
+let show_therapy_types = function(frm, result) {
+ var d = new frappe.ui.Dialog({
+ title: __('Prescribed Therapies'),
+ fields: [
+ {
+ fieldtype: 'HTML', fieldname: 'therapy_type'
}
- }
+ ]
});
+ var html_field = d.fields_dict.therapy_type.$wrapper;
+ $.each(result, function(x, y){
+ var row = $(repl('
', {therapy:y[0],
+ name: y[1], encounter:y[2], practitioner:y[3], date:y[4],
+ department:y[6]? y[6]:'', therapy_plan:y[5]})).appendTo(html_field);
+
+ row.find("a").click(function() {
+ frm.doc.therapy_type = $(this).attr("data-therapy");
+ frm.doc.practitioner = $(this).attr("data-practitioner");
+ frm.doc.department = $(this).attr("data-department");
+ frm.doc.therapy_plan = $(this).attr("data-therapy-plan");
+ frm.refresh_field("therapy_type");
+ frm.refresh_field("practitioner");
+ frm.refresh_field("department");
+ frm.refresh_field("therapy-plan");
+ frappe.db.get_value('Therapy Type', frm.doc.therapy_type, 'default_duration', (r) => {
+ if (r.default_duration) {
+ frm.set_value('duration', r.default_duration)
+ }
+ });
+ d.hide();
+ return false;
+ });
+ });
+ d.show();
};
-var btn_create_encounter = function(frm){
- var doc = frm.doc;
- frappe.call({
- 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);
- }
- }
- });
-};
-
-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();
}
}
@@ -404,60 +502,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 ee9f013084b..57e6c479d1e 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
@@ -1,1177 +1,358 @@
{
+ "actions": [],
"allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
- "allow_rename": 0,
- "autoname": "OP-.######",
+ "autoname": "naming_series:",
"beta": 1,
"creation": "2017-05-04 11:52:40.941507",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
- "editable_grid": 0,
"engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "patient",
+ "patient_name",
+ "patient_sex",
+ "patient_age",
+ "inpatient_record",
+ "column_break_1",
+ "status",
+ "procedure_template",
+ "get_procedure_from_encounter",
+ "procedure_prescription",
+ "therapy_type",
+ "get_prescribed_therapies",
+ "therapy_plan",
+ "service_unit",
+ "section_break_12",
+ "practitioner",
+ "department",
+ "appointment_type",
+ "column_break_17",
+ "appointment_date",
+ "appointment_time",
+ "appointment_datetime",
+ "duration",
+ "section_break_16",
+ "mode_of_payment",
+ "paid_amount",
+ "company",
+ "column_break_2",
+ "invoiced",
+ "ref_sales_invoice",
+ "section_break_3",
+ "notes",
+ "referring_practitioner",
+ "reminded"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.inpatient_record",
"fieldname": "inpatient_record",
"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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
"options": "Inpatient Record",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "inpatient_record.patient",
"fieldname": "patient",
"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": "Patient",
- "length": 0,
- "no_copy": 0,
"options": "Patient",
- "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
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment_type",
"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": "Appointment Type",
- "length": 0,
- "no_copy": 0,
"options": "Appointment Type",
- "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,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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": 1,
- "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
+ "label": "Duration (In Minutes)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_1",
"fieldtype": "Column Break",
- "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": "",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Scheduled",
"depends_on": "eval:!doc.__islocal",
"fieldname": "status",
"fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
+ "in_list_view": 1,
"label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "\nScheduled\nOpen\nClosed\nPending\nCancelled",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
+ "options": "\nScheduled\nOpen\nClosed\nCancelled",
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "procedure_template",
"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": "Procedure",
- "length": 0,
- "no_copy": 0,
+ "label": "Clinical Procedure Template",
"options": "Clinical Procedure Template",
- "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,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "depends_on": "eval:doc.__islocal && doc.patient",
"fieldname": "get_procedure_from_encounter",
"fieldtype": "Button",
- "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": "Get prescribed procedures",
- "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
+ "label": "Get Prescribed Clinical Procedures"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "procedure_prescription",
"fieldtype": "Link",
"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": "Procedure Prescription",
- "length": 0,
"no_copy": 1,
"options": "Procedure Prescription",
- "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": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "print_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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": "Healthcare 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": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.__islocal",
- "fieldname": "check_availability",
- "fieldtype": "Button",
- "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": "Check availability",
- "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,
"fieldname": "section_break_12",
- "fieldtype": "Section Break",
- "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,
- "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
+ "fieldtype": "Section Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "practitioner",
"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": 1,
"label": "Healthcare Practitioner",
- "length": 0,
- "no_copy": 0,
"options": "Healthcare Practitioner",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
"search_index": 1,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
"search_index": 1,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_17",
- "fieldtype": "Column Break",
- "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,
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment_date",
"fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Date",
- "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": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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": 1,
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "section_break_16",
- "fieldtype": "Section Break",
- "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,
- "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
+ "fieldtype": "Section Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
"fetch_from": "patient.patient_name",
"fieldname": "patient_name",
"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": "Patient Name",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.sex",
"fieldname": "patient_sex",
- "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,
+ "fieldtype": "Link",
"label": "Gender",
- "length": 0,
"no_copy": 1,
- "options": "",
- "permlevel": 0,
- "precision": "",
+ "options": "Gender",
"print_hide": 1,
- "print_hide_if_no_value": 0,
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_21",
- "fieldtype": "Column Break",
- "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,
- "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,
"fieldname": "patient_age",
"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": "Patient Age",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "section_break_1",
- "fieldtype": "Section Break",
- "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,
- "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,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment_datetime",
"fieldtype": "Datetime",
- "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": "Date TIme",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
+ "label": "Appointment Datetime",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
+ "read_only": 1,
"report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "mode_of_payment",
"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": "Mode of Payment",
- "length": 0,
- "no_copy": 0,
- "options": "Mode of Payment",
- "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
+ "options": "Mode of Payment"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "paid_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": "Paid Amount",
- "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
+ "label": "Paid Amount"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "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,
- "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
+ "fieldtype": "Column Break"
},
{
- "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,
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"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": "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
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
"fieldname": "section_break_3",
"fieldtype": "Section Break",
- "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": "More Info",
- "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
+ "label": "More Info"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "notes",
"fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Notes",
- "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
+ "label": "Notes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "referring_practitioner",
"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": "Referring Practitioner",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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,
- "translatable": 0,
- "unique": 0
+ "options": "Healthcare Practitioner"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0",
"fieldname": "reminded",
"fieldtype": "Check",
"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": "Reminded",
- "length": 0,
- "no_copy": 0,
- "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
+ "report_hide": 1
+ },
+ {
+ "depends_on": "eval:doc.patient;",
+ "fieldname": "therapy_type",
+ "fieldtype": "Link",
+ "label": "Therapy",
+ "options": "Therapy Type",
+ "set_only_once": 1
+ },
+ {
+ "depends_on": "eval:doc.patient && doc.__islocal;",
+ "fieldname": "get_prescribed_therapies",
+ "fieldtype": "Button",
+ "label": "Get Prescribed Therapies"
+ },
+ {
+ "depends_on": "eval: doc.patient && doc.therapy_type",
+ "fieldname": "therapy_plan",
+ "fieldtype": "Link",
+ "label": "Therapy Plan",
+ "mandatory_depends_on": "eval: doc.patient && doc.therapy_type",
+ "options": "Therapy Plan"
+ },
+ {
+ "fieldname": "ref_sales_invoice",
+ "fieldtype": "Link",
+ "label": "Reference Sales Invoice",
+ "options": "Sales Invoice",
+ "read_only": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-APP-.YYYY.-",
+ "set_only_once": 1
}
],
- "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-11-14 13:24:01.529536",
+ "links": [],
+ "modified": "2020-03-31 16:16:32.116865",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Patient Appointment",
- "name_case": "",
"owner": "Administrator",
"permissions": [
{
- "amend": 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": "Healthcare Administrator",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 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": "Physician",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 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,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Healthcare",
"search_fields": "patient, practitioner, department, appointment_date, appointment_time",
"show_name_in_global_search": 1,
@@ -1179,6 +360,5 @@
"sort_order": "DESC",
"title_field": "patient",
"track_changes": 1,
- "track_seen": 1,
- "track_views": 0
-}
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 5f48c9ffe45..512d44ec370 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -6,26 +6,42 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
import json
-from frappe.utils import getdate, add_days, get_time
+from frappe.utils import getdate, get_time
+from frappe.model.mapper import get_mapped_doc
from frappe import _
import datetime
from frappe.core.doctype.sms_settings.sms_settings import send_sms
from erpnext.hr.doctype.employee.employee import is_holiday
-from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account,get_income_account
-from erpnext.healthcare.utils import validity_exists, service_item_and_practitioner_charge
+from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
+from erpnext.healthcare.utils import check_fee_validity, get_service_item_and_practitioner_charge, manage_fee_validity
class PatientAppointment(Document):
- def on_update(self):
- today = datetime.date.today()
+ def validate(self):
+ self.validate_overlaps()
+ self.set_appointment_datetime()
+ self.validate_customer_created()
+ self.set_status()
+
+ def after_insert(self):
+ self.update_prescription_details()
+ invoice_appointment(self)
+ self.update_fee_validity()
+ send_confirmation_msg(self)
+
+ def set_status(self):
+ today = getdate()
appointment_date = getdate(self.appointment_date)
- # If appointment created for today set as open
- if today == appointment_date:
- frappe.db.set_value("Patient Appointment", self.name, "status", "Open")
- self.reload()
+ # If appointment is created for today set status as Open else Scheduled
+ if appointment_date == today:
+ self.status = 'Open'
+ elif appointment_date > today:
+ self.status = 'Scheduled'
+
+ def validate_overlaps(self):
+ end_time = datetime.datetime.combine(getdate(self.appointment_date), get_time(self.appointment_time)) \
+ + datetime.timedelta(minutes=float(self.duration))
- def validate(self):
- end_time = datetime.datetime.combine(getdate(self.appointment_date), get_time(self.appointment_time)) + datetime.timedelta(minutes=float(self.duration))
overlaps = frappe.db.sql("""
select
name, practitioner, patient, appointment_time, duration
@@ -41,135 +57,153 @@ class PatientAppointment(Document):
self.appointment_time, end_time.time(), self.appointment_time, end_time.time(), self.appointment_time))
if overlaps:
- frappe.throw(_("""Appointment overlaps with {0}.
{1} has appointment scheduled
- with {2} at {3} having {4} minute(s) duration.""").format(overlaps[0][0], overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4]))
+ overlapping_details = _('Appointment overlaps with ')
+ overlapping_details += "
{0} ".format(overlaps[0][0])
+ overlapping_details += _('{0} has appointment scheduled with {1} at {2} having {3} minute(s) duration.').format(
+ overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4])
+ frappe.throw(overlapping_details, title=_('Appointments Overlapping'))
- def after_insert(self):
+ def set_appointment_datetime(self):
+ self.appointment_datetime = "%s %s" % (self.appointment_date, self.appointment_time or "00:00:00")
+
+ def validate_customer_created(self):
+ if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
+ if not frappe.db.get_value('Patient', self.patient, 'customer'):
+ msg = _("Please set a Customer linked to the Patient")
+ msg += "
{0} ".format(self.patient)
+ frappe.throw(msg, title=_('Customer Not Found'))
+
+ def update_prescription_details(self):
if self.procedure_prescription:
- frappe.db.set_value("Procedure Prescription", self.procedure_prescription, "appointment_booked", True)
+ frappe.db.set_value('Procedure Prescription', self.procedure_prescription, 'appointment_booked', 1)
if self.procedure_template:
- comments = frappe.db.get_value("Procedure Prescription", self.procedure_prescription, "comments")
+ comments = frappe.db.get_value('Procedure Prescription', self.procedure_prescription, 'comments')
if comments:
- frappe.db.set_value("Patient Appointment", self.name, "notes", comments)
- # Check fee validity exists
- appointment = self
- validity_exist = validity_exists(appointment.practitioner, appointment.patient)
- if validity_exist:
- fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
+ frappe.db.set_value('Patient Appointment', self.name, 'notes', comments)
- # Check if the validity is valid
- appointment_date = getdate(appointment.appointment_date)
- if (fee_validity.valid_till >= appointment_date) and (fee_validity.visited < fee_validity.max_visit):
- visited = fee_validity.visited + 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- if fee_validity.ref_invoice:
- frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", True)
- frappe.msgprint(_("{0} has fee validity till {1}").format(appointment.patient, fee_validity.valid_till))
- confirm_sms(self)
+ def update_fee_validity(self):
+ fee_validity = manage_fee_validity(self)
+ if fee_validity:
+ frappe.msgprint(_('{0} has fee validity till {1}').format(self.patient, fee_validity.valid_till))
- if frappe.db.get_value("Healthcare Settings", None, "manage_appointment_invoice_automatically") == '1' and \
- frappe.db.get_value("Patient Appointment", self.name, "invoiced") != 1:
- invoice_appointment(self)
@frappe.whitelist()
-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", appointment_doc.patient, "customer")
- sales_invoice.appointment = appointment_doc.name
- sales_invoice.due_date = getdate()
- sales_invoice.is_pos = True
- sales_invoice.company = appointment_doc.company
- sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
-
- item_line = sales_invoice.append("items")
- service_item, practitioner_charge = service_item_and_practitioner_charge(appointment_doc)
- item_line.item_code = service_item
- item_line.description = "Consulting Charges: " + appointment_doc.practitioner
- item_line.income_account = get_income_account(appointment_doc.practitioner, appointment_doc.company)
- item_line.rate = practitioner_charge
- item_line.amount = practitioner_charge
- item_line.qty = 1
- item_line.reference_dt = "Patient Appointment"
- item_line.reference_dn = appointment_doc.name
-
- payments_line = sales_invoice.append("payments")
- payments_line.mode_of_payment = appointment_doc.mode_of_payment
- payments_line.amount = appointment_doc.paid_amount
-
- sales_invoice.set_missing_values(for_validate = True)
-
- sales_invoice.save(ignore_permissions=True)
- sales_invoice.submit()
- frappe.msgprint(_("Sales Invoice {0} created as paid").format(sales_invoice.name), alert=True)
-
-def appointment_cancel(appointment_id):
- appointment = frappe.get_doc("Patient Appointment", appointment_id)
- # If invoiced --> fee_validity update with -1 visit
- if appointment.invoiced:
- sales_invoice = exists_sales_invoice(appointment)
- if sales_invoice and cancel_sales_invoice(sales_invoice):
- frappe.msgprint(
- _("Appointment {0} and Sales Invoice {1} cancelled").format(appointment.name, sales_invoice.name)
- )
- else:
- validity = validity_exists(appointment.practitioner, appointment.patient)
- if validity:
- fee_validity = frappe.get_doc("Fee Validity", validity[0][0])
- if appointment_valid_in_fee_validity(appointment, fee_validity.valid_till, True, fee_validity.ref_invoice):
- visited = fee_validity.visited - 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- frappe.msgprint(
- _("Appointment cancelled, Please review and cancel the invoice {0}").format(fee_validity.ref_invoice)
- )
- else:
- frappe.msgprint(_("Appointment cancelled"))
- else:
- frappe.msgprint(_("Appointment cancelled"))
- else:
- frappe.msgprint(_("Appointment cancelled"))
-
-def appointment_valid_in_fee_validity(appointment, valid_end_date, invoiced, ref_invoice):
- valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
- max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
- valid_start_date = add_days(getdate(valid_end_date), -int(valid_days))
-
- # Appointments which has same fee validity range with the appointment
- appointments = frappe.get_list("Patient Appointment",{'patient': appointment.patient, 'invoiced': invoiced,
- 'appointment_date':("<=", getdate(valid_end_date)), 'appointment_date':(">=", getdate(valid_start_date)),
- 'practitioner': appointment.practitioner}, order_by="appointment_date desc", limit=int(max_visit))
-
- if appointments and len(appointments) > 0:
- appointment_obj = appointments[len(appointments)-1]
- sales_invoice = exists_sales_invoice(appointment_obj)
- if sales_invoice.name == ref_invoice:
- return True
+def check_payment_fields_reqd(patient):
+ automate_invoicing = frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing')
+ free_follow_ups = frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups')
+ if automate_invoicing:
+ if free_follow_ups:
+ fee_validity = frappe.db.exists('Fee Validity', {'patient': patient, 'status': 'Pending'})
+ if fee_validity:
+ return {'fee_validity': fee_validity}
+ if check_is_new_patient(patient):
+ return False
+ return True
return False
+def invoice_appointment(appointment_doc):
+ automate_invoicing = frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing')
+ appointment_invoiced = frappe.db.get_value('Patient Appointment', appointment_doc.name, 'invoiced')
+ enable_free_follow_ups = frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups')
+ if enable_free_follow_ups:
+ fee_validity = check_fee_validity(appointment_doc)
+ if fee_validity and fee_validity.status == 'Completed':
+ fee_validity = None
+ elif not fee_validity:
+ if frappe.db.exists('Fee Validity Reference', {'appointment': appointment_doc.name}):
+ return
+ if check_is_new_patient(appointment_doc.patient, appointment_doc.name):
+ return
+ else:
+ fee_validity = None
+
+ if automate_invoicing and not appointment_invoiced and not fee_validity:
+ sales_invoice = frappe.new_doc('Sales Invoice')
+ 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 = 1
+ sales_invoice.company = appointment_doc.company
+ sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
+
+ item = sales_invoice.append('items', {})
+ item = get_appointment_item(appointment_doc, item)
+
+ payment = sales_invoice.append('payments', {})
+ payment.mode_of_payment = appointment_doc.mode_of_payment
+ payment.amount = appointment_doc.paid_amount
+
+ sales_invoice.set_missing_values(for_validate=True)
+ sales_invoice.flags.ignore_mandatory = True
+ sales_invoice.save(ignore_permissions=True)
+ sales_invoice.submit()
+ frappe.msgprint(_('Sales Invoice {0} created as paid'.format(sales_invoice.name)), alert=True)
+ frappe.db.set_value('Patient Appointment', appointment_doc.name, 'invoiced', 1)
+ frappe.db.set_value('Patient Appointment', appointment_doc.name, 'ref_sales_invoice', sales_invoice.name)
+
+
+def check_is_new_patient(patient, name=None):
+ filters = {'patient': patient, 'status': ('!=','Cancelled')}
+ if name:
+ filters['name'] = ('!=', name)
+
+ has_previous_appointment = frappe.db.exists('Patient Appointment', filters)
+ if has_previous_appointment:
+ return False
+ return True
+
+
+def get_appointment_item(appointment_doc, item):
+ service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment_doc)
+ item.item_code = service_item
+ item.description = _('Consulting Charges: {0}').format(appointment_doc.practitioner)
+ item.income_account = get_income_account(appointment_doc.practitioner, appointment_doc.company)
+ item.cost_center = frappe.get_cached_value('Company', appointment_doc.company, 'cost_center')
+ item.rate = practitioner_charge
+ item.amount = practitioner_charge
+ item.qty = 1
+ item.reference_dt = 'Patient Appointment'
+ item.reference_dn = appointment_doc.name
+ return item
+
+
+def cancel_appointment(appointment_id):
+ appointment = frappe.get_doc('Patient Appointment', appointment_id)
+ if appointment.invoiced:
+ sales_invoice = check_sales_invoice_exists(appointment)
+ if sales_invoice and cancel_sales_invoice(sales_invoice):
+ msg = _('Appointment {0} and Sales Invoice {1} cancelled').format(appointment.name, sales_invoice.name)
+ else:
+ msg = _('Appointment Cancelled. Please review and cancel the invoice {0}').format(sales_invoice.name)
+ else:
+ fee_validity = manage_fee_validity(appointment)
+ msg = _('Appointment Cancelled.')
+ if fee_validity:
+ msg += _('Fee Validity {0} updated.').format(fee_validity.name)
+
+ frappe.msgprint(msg)
+
+
def cancel_sales_invoice(sales_invoice):
- if frappe.db.get_value("Healthcare Settings", None, "manage_appointment_invoice_automatically") == '1':
+ if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
if len(sales_invoice.items) == 1:
sales_invoice.cancel()
return True
return False
-def exists_sales_invoice_item(appointment):
- return frappe.db.exists(
- "Sales Invoice Item",
- {
- "reference_dt": "Patient Appointment",
- "reference_dn": appointment.name
- }
- )
-def exists_sales_invoice(appointment):
- sales_item_exist = exists_sales_invoice_item(appointment)
- if sales_item_exist:
- sales_invoice = frappe.get_doc("Sales Invoice", frappe.db.get_value("Sales Invoice Item", sales_item_exist, "parent"))
+def check_sales_invoice_exists(appointment):
+ sales_invoice = frappe.db.get_value('Sales Invoice Item', {
+ 'reference_dt': 'Patient Appointment',
+ 'reference_dn': appointment.name
+ }, 'parent')
+
+ if sales_invoice:
+ sales_invoice = frappe.get_doc('Sales Invoice', sales_invoice)
return sales_invoice
return False
+
@frappe.whitelist()
def get_availability_data(date, practitioner):
"""
@@ -180,169 +214,163 @@ def get_availability_data(date, practitioner):
"""
date = getdate(date)
- weekday = date.strftime("%A")
+ weekday = date.strftime('%A')
- available_slots = []
- slot_details = []
- practitioner_schedule = None
+ practitioner_doc = frappe.get_doc('Healthcare Practitioner', practitioner)
+ check_employee_wise_availability(date, practitioner_doc)
+
+ if practitioner_doc.practitioner_schedules:
+ slot_details = get_available_slots(practitioner_doc, date)
+ else:
+ frappe.throw(_('{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master').format(
+ practitioner), title=_('Practitioner Schedule Not Found'))
+
+
+ if not slot_details:
+ # TODO: return available slots in nearby dates
+ frappe.throw(_('Healthcare Practitioner not available on {0}').format(weekday), title=_('Not Available'))
+
+ return {'slot_details': slot_details}
+
+
+def check_employee_wise_availability(date, practitioner_doc):
employee = None
-
- practitioner_obj = frappe.get_doc("Healthcare Practitioner", practitioner)
-
- # Get practitioner employee relation
- if practitioner_obj.employee:
- employee = practitioner_obj.employee
- elif practitioner_obj.user_id:
- if frappe.db.exists({
- "doctype": "Employee",
- "user_id": practitioner_obj.user_id
- }):
- employee = frappe.get_doc("Employee", {"user_id": practitioner_obj.user_id}).name
+ if practitioner_doc.employee:
+ employee = practitioner_doc.employee
+ elif practitioner_doc.user_id:
+ employee = frappe.db.get_value('Employee', {'user_id': practitioner_doc.user_id}, 'name')
if employee:
- # Check if it is Holiday
+ # check holiday
if is_holiday(employee, date):
- frappe.throw(_("{0} is a company holiday").format(date))
+ frappe.throw(_('{0} is a holiday'.format(date)), title=_('Not Available'))
- # Check if He/She on Leave
+ # check leave status
leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
where employee = %s and %s between from_date and to_date
and docstatus = 1""", (employee, date), as_dict=True)
if leave_record:
if leave_record[0].half_day:
- frappe.throw(_("{0} on Half day Leave on {1}").format(practitioner, date))
+ frappe.throw(_('{0} is on a Half day Leave on {1}').format(practitioner_doc.name, date), title=_('Not Available'))
else:
- frappe.throw(_("{0} on Leave on {1}").format(practitioner, date))
+ frappe.throw(_('{0} is on Leave on {1}').format(practitioner_doc.name, date), title=_('Not Available'))
- # get practitioners schedule
- if practitioner_obj.practitioner_schedules:
- for schedule in practitioner_obj.practitioner_schedules:
- if schedule.schedule:
- practitioner_schedule = frappe.get_doc("Practitioner Schedule", schedule.schedule)
- else:
- frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master").format(practitioner))
- if practitioner_schedule:
- available_slots = []
- for t in practitioner_schedule.time_slots:
- if weekday == t.day:
- available_slots.append(t)
+def get_available_slots(practitioner_doc, date):
+ available_slots = []
+ slot_details = []
+ weekday = date.strftime('%A')
+ practitioner = practitioner_doc.name
- if available_slots:
- appointments = []
+ for schedule_entry in practitioner_doc.practitioner_schedules:
+ if schedule_entry.schedule:
+ practitioner_schedule = frappe.get_doc('Practitioner Schedule', schedule_entry.schedule)
+ else:
+ frappe.throw(_('{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner').format(
+ frappe.bold(practitioner)), title=_('Practitioner Schedule Not Found'))
- if schedule.service_unit:
- slot_name = schedule.schedule+" - "+schedule.service_unit
- allow_overlap = frappe.get_value('Healthcare Service Unit', schedule.service_unit, 'overlap_appointments')
- if allow_overlap:
- # fetch all appointments to practitioner by service unit
- appointments = frappe.get_all(
- "Patient Appointment",
- filters={"practitioner": practitioner, "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 practitioner without service unit
- appointments = frappe.get_all(
- "Patient Appointment",
- filters={"practitioner": practitioner, "service_unit": '', "appointment_date": date, "status": ["not in",["Cancelled"]]},
- fields=["name", "appointment_time", "duration", "status"])
+ if practitioner_schedule:
+ available_slots = []
+ for time_slot in practitioner_schedule.time_slots:
+ if weekday == time_slot.day:
+ available_slots.append(time_slot)
- slot_details.append({"slot_name":slot_name, "service_unit":schedule.service_unit,
- "avail_slot":available_slots, 'appointments': appointments})
+ if available_slots:
+ appointments = []
+ # fetch all appointments to practitioner by service unit
+ filters = {
+ 'practitioner': practitioner,
+ 'service_unit': schedule_entry.service_unit,
+ 'appointment_date': date,
+ 'status': ['not in',['Cancelled']]
+ }
- else:
- frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master").format(practitioner))
+ if schedule_entry.service_unit:
+ slot_name = schedule_entry.schedule + ' - ' + schedule_entry.service_unit
+ allow_overlap = frappe.get_value('Healthcare Service Unit', schedule_entry.service_unit, 'overlap_appointments')
+ if not allow_overlap:
+ # fetch all appointments to service unit
+ filters.pop('practitioner')
+ else:
+ slot_name = schedule_entry.schedule
+ # fetch all appointments to practitioner without service unit
+ filters['practitioner'] = practitioner
+ filters.pop('service_unit')
- if not available_slots and not slot_details:
- # TODO: return available slots in nearby dates
- frappe.throw(_("Healthcare Practitioner not available on {0}").format(weekday))
+ appointments = frappe.get_all(
+ 'Patient Appointment',
+ filters=filters,
+ fields=['name', 'appointment_time', 'duration', 'status'])
- return {
- "slot_details": slot_details
- }
+ slot_details.append({'slot_name':slot_name, 'service_unit':schedule_entry.service_unit,
+ 'avail_slot':available_slots, 'appointments': appointments})
+
+ return slot_details
@frappe.whitelist()
def update_status(appointment_id, status):
- frappe.db.set_value("Patient Appointment", appointment_id, "status", status)
+ frappe.db.set_value('Patient Appointment', appointment_id, 'status', status)
appointment_booked = True
- if status == "Cancelled":
+ if status == 'Cancelled':
appointment_booked = False
- appointment_cancel(appointment_id)
+ cancel_appointment(appointment_id)
- procedure_prescription = frappe.db.get_value("Patient Appointment", appointment_id, "procedure_prescription")
+ procedure_prescription = frappe.db.get_value('Patient Appointment', appointment_id, 'procedure_prescription')
if procedure_prescription:
- frappe.db.set_value("Procedure Prescription", procedure_prescription, "appointment_booked", appointment_booked)
+ frappe.db.set_value('Procedure Prescription', procedure_prescription, 'appointment_booked', appointment_booked)
-@frappe.whitelist()
-def set_open_appointments():
- today = getdate()
- frappe.db.sql(
- "update `tabPatient Appointment` set status='Open' where status = 'Scheduled'"
- " and appointment_date = %s", today)
-
-
-@frappe.whitelist()
-def set_pending_appointments():
- today = getdate()
- frappe.db.sql(
- "update `tabPatient Appointment` set status='Pending' where status in "
- "('Scheduled','Open') and appointment_date < %s", today)
-
-
-def confirm_sms(doc):
- if frappe.db.get_value("Healthcare Settings", None, "app_con") == '1':
- message = frappe.db.get_value("Healthcare Settings", None, "app_con_msg")
+def send_confirmation_msg(doc):
+ if frappe.db.get_single_value('Healthcare Settings', 'send_appointment_confirmation'):
+ message = frappe.db.get_single_value('Healthcare Settings', 'appointment_confirmation_msg')
send_message(doc, message)
+
@frappe.whitelist()
-def create_encounter(appointment):
- appointment = frappe.get_doc("Patient Appointment", appointment)
- encounter = frappe.new_doc("Patient Encounter")
- encounter.appointment = appointment.name
- encounter.patient = appointment.patient
- encounter.practitioner = appointment.practitioner
- encounter.visit_department = appointment.department
- encounter.patient_sex = appointment.patient_sex
- encounter.encounter_date = appointment.appointment_date
- if appointment.invoiced:
- encounter.invoiced = True
- return encounter.as_dict()
+def make_encounter(source_name, target_doc=None):
+ doc = get_mapped_doc('Patient Appointment', source_name, {
+ 'Patient Appointment': {
+ 'doctype': 'Patient Encounter',
+ 'field_map': [
+ ['appointment', 'name'],
+ ['patient', 'patient'],
+ ['practitioner', 'practitioner'],
+ ['medical_department', 'department'],
+ ['patient_sex', 'patient_sex'],
+ ['encounter_date', 'appointment_date'],
+ ['invoiced', 'invoiced']
+ ]
+ }
+ }, target_doc)
+ return doc
-def remind_appointment():
- if frappe.db.get_value("Healthcare Settings", None, "app_rem") == '1':
- rem_before = datetime.datetime.strptime(frappe.get_value("Healthcare Settings", None, "rem_before"), "%H:%M:%S")
- rem_dt = datetime.datetime.now() + datetime.timedelta(
- hours=rem_before.hour, minutes=rem_before.minute, seconds=rem_before.second)
+def send_appointment_reminder():
+ if frappe.db.get_single_value('Healthcare Settings', 'send_appointment_reminder'):
+ remind_before = datetime.datetime.strptime(frappe.db.get_single_value('Healthcare Settings', 'remind_before'), '%H:%M:%S')
+ reminder_dt = datetime.datetime.now() + datetime.timedelta(
+ hours=remind_before.hour, minutes=remind_before.minute, seconds=remind_before.second)
- appointment_list = frappe.db.sql(
- "select name from `tabPatient Appointment` where start_dt between %s and %s and reminded = 0 ",
- (datetime.datetime.now(), rem_dt)
- )
+ appointment_list = frappe.db.get_all('Patient Appointment', {
+ 'appointment_datetime': ['between', (datetime.datetime.now(), reminder_dt)],
+ 'reminded': 0,
+ 'status': ['!=', 'Cancelled']
+ })
- for i in range(0, len(appointment_list)):
- doc = frappe.get_doc("Patient Appointment", appointment_list[i][0])
- message = frappe.db.get_value("Healthcare Settings", None, "app_rem_msg")
+ for appointment in appointment_list:
+ doc = frappe.get_doc('Patient Appointment', appointment.name)
+ message = frappe.db.get_single_value('Healthcare Settings', 'appointment_reminder_msg')
send_message(doc, message)
- frappe.db.set_value("Patient Appointment", doc.name, "reminded",1)
-
+ frappe.db.set_value('Patient Appointment', doc.name, 'reminded', 1)
def send_message(doc, message):
- patient = frappe.get_doc("Patient", doc.patient)
+ patient = frappe.get_doc('Patient', doc.patient)
if patient.mobile:
- context = {"doc": doc, "alert": doc, "comments": None}
- if doc.get("_comments"):
- context["comments"] = json.loads(doc.get("_comments"))
+ context = {'doc': doc, 'alert': doc, 'comments': None}
+ if doc.get('_comments'):
+ context['comments'] = json.loads(doc.get('_comments'))
# jinja to string convertion happens here
message = frappe.render_template(message, context)
@@ -359,7 +387,7 @@ def get_events(start, end, filters=None):
:param filters: Filters (JSON).
"""
from frappe.desk.calendar import get_event_conditions
- conditions = get_event_conditions("Patient Appointment", filters)
+ conditions = get_event_conditions('Patient Appointment', filters)
data = frappe.db.sql("""
select
@@ -381,10 +409,46 @@ def get_events(start, end, filters=None):
return data
+
@frappe.whitelist()
def get_procedure_prescribed(patient):
- return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
- ct.encounter_date, pp.practitioner, pp.date, pp.department
- from `tabPatient Encounter` ct, `tabProcedure Prescription` pp
- where ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
- order by ct.creation desc""", {"patient": patient})
+ return frappe.db.sql(
+ """
+ SELECT
+ pp.name, pp.procedure, pp.parent, ct.practitioner,
+ ct.encounter_date, pp.practitioner, pp.date, pp.department
+ FROM
+ `tabPatient Encounter` ct, `tabProcedure Prescription` pp
+ WHERE
+ ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
+ ORDER BY
+ ct.creation desc
+ """, {'patient': patient}
+ )
+
+
+@frappe.whitelist()
+def get_prescribed_therapies(patient):
+ return frappe.db.sql(
+ """
+ SELECT
+ t.therapy_type, t.name, t.parent, e.practitioner,
+ e.encounter_date, e.therapy_plan, e.visit_department
+ FROM
+ `tabPatient Encounter` e, `tabTherapy Plan Detail` t
+ WHERE
+ e.patient=%(patient)s and t.parent=e.name
+ ORDER BY
+ e.creation desc
+ """, {'patient': patient}
+ )
+
+
+def update_appointment_status():
+ # update the status of appointments daily
+ appointments = frappe.get_all('Patient Appointment', {
+ 'status': ('not in', ['Closed', 'Cancelled'])
+ }, as_dict=1)
+
+ for appointment in appointments:
+ frappe.get_doc('Patient Appointment', appointment.name).set_status()
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js
index 701cb69806e..721887b4593 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_list.js
@@ -3,4 +3,14 @@
*/
frappe.listview_settings['Patient Appointment'] = {
filters: [["status", "=", "Open"]],
+ get_indicator: function(doc) {
+ var colors = {
+ "Open": "orange",
+ "Scheduled": "yellow",
+ "Closed": "green",
+ "Cancelled": "red",
+ "Expired": "grey"
+ };
+ return [__(doc.status), colors[doc.status], "status,=," + doc.status];
+ }
};
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 3536a5f9513..7075af5d00c 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -3,8 +3,144 @@
# See license.txt
from __future__ import unicode_literals
import unittest
-
-# test_records = frappe.get_test_records('Patient Appointment')
+import frappe
+from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status
+from frappe.utils import nowdate, add_days
+from frappe.utils.make_random import get_random
class TestPatientAppointment(unittest.TestCase):
- pass
+ def setUp(self):
+ frappe.db.sql("""delete from `tabPatient Appointment`""")
+ frappe.db.sql("""delete from `tabFee Validity""")
+
+ def test_status(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 0)
+ appointment = create_appointment(patient, practitioner, nowdate())
+ self.assertEquals(appointment.status, 'Open')
+ appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2))
+ self.assertEquals(appointment.status, 'Scheduled')
+ create_encounter(appointment)
+ self.assertEquals(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
+
+ def test_invoicing(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 0)
+ appointment = create_appointment(patient, practitioner, nowdate())
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'invoiced'), 0)
+
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+ appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2), invoice=1)
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'invoiced'), 1)
+ self.assertTrue(frappe.db.get_value('Patient Appointment', appointment.name, 'ref_sales_invoice'))
+
+ def test_appointment_cancel(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 1)
+ appointment = create_appointment(patient, practitioner, nowdate())
+ fee_validity = frappe.db.get_value('Fee Validity Reference', {'appointment': appointment.name}, 'parent')
+ # fee validity created
+ self.assertTrue(fee_validity)
+
+ visited = frappe.db.get_value('Fee Validity', fee_validity, 'visited')
+ update_status(appointment.name, 'Cancelled')
+ # check fee validity updated
+ self.assertEqual(frappe.db.get_value('Fee Validity', fee_validity, 'visited'), visited - 1)
+
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+ appointment = create_appointment(patient, practitioner, nowdate(), invoice=1)
+ update_status(appointment.name, 'Cancelled')
+ # check invoice cancelled
+ sales_invoice = frappe.db.get_value('Patient Appointment', appointment.name, 'ref_sales_invoice')
+ self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice, 'status'), 'Cancelled')
+
+
+def create_healthcare_docs():
+ patient = create_patient()
+ practitioner = frappe.db.exists('Healthcare Practitioner', '_Test Healthcare Practitioner')
+ medical_department = frappe.db.exists('Medical Department', '_Test Medical Department')
+
+ if not medical_department:
+ medical_department = frappe.new_doc('Medical Department')
+ medical_department.department = '_Test Medical Department'
+ medical_department.save(ignore_permissions=True)
+ medical_department = medical_department.name
+
+ if not practitioner:
+ practitioner = frappe.new_doc('Healthcare Practitioner')
+ practitioner.first_name = '_Test Healthcare Practitioner'
+ practitioner.gender = 'Female'
+ practitioner.department = medical_department
+ practitioner.op_consulting_charge = 500
+ practitioner.inpatient_visit_charge = 500
+ practitioner.save(ignore_permissions=True)
+ practitioner = practitioner.name
+
+ return patient, medical_department, practitioner
+
+def create_patient():
+ patient = frappe.db.exists('Patient', '_Test Patient')
+ if not patient:
+ patient = frappe.new_doc('Patient')
+ patient.first_name = '_Test Patient'
+ patient.sex = 'Female'
+ patient.save(ignore_permissions=True)
+ patient = patient.name
+ return patient
+
+def create_encounter(appointment=None):
+ encounter = frappe.new_doc('Patient Encounter')
+ if appointment:
+ encounter.appointment = appointment.name
+ encounter.patient = appointment.patient
+ encounter.practitioner = appointment.practitioner
+ encounter.encounter_date = appointment.appointment_date
+ encounter.encounter_time = appointment.appointment_time
+ encounter.save()
+ encounter.submit()
+ return encounter
+
+def create_appointment(patient, practitioner, appointment_date, invoice=0, procedure_template=0):
+ item = create_healthcare_service_items()
+ frappe.db.set_value('Healthcare Settings', None, 'inpatient_visit_charge_item', item)
+ frappe.db.set_value('Healthcare Settings', None, 'op_consulting_charge_item', item)
+ appointment = frappe.new_doc('Patient Appointment')
+ appointment.patient = patient
+ appointment.practitioner = practitioner
+ appointment.department = '_Test Medical Department'
+ appointment.appointment_date = appointment_date
+ appointment.company = '_Test Company'
+ appointment.duration = 15
+ if invoice:
+ appointment.mode_of_payment = 'Cash'
+ appointment.paid_amount = 500
+ if procedure_template:
+ appointment.procedure_template = create_clinical_procedure_template().get('name')
+ appointment.save(ignore_permissions=True)
+ return appointment
+
+def create_healthcare_service_items():
+ if frappe.db.exists('Item', 'HLC-SI-001'):
+ return 'HLC-SI-001'
+ item = frappe.new_doc('Item')
+ item.item_code = 'HLC-SI-001'
+ item.item_name = 'Consulting Charges'
+ item.item_group = 'Services'
+ item.is_stock_item = 0
+ item.save()
+ return item.name
+
+def create_clinical_procedure_template():
+ if frappe.db.exists('Clinical Procedure Template', 'Knee Surgery and Rehab'):
+ return frappe.get_doc('Clinical Procedure Template', 'Knee Surgery and Rehab')
+ template = frappe.new_doc('Clinical Procedure Template')
+ template.template = 'Knee Surgery and Rehab'
+ template.item_code = 'Knee Surgery and Rehab'
+ template.item_group = 'Services'
+ template.is_billable = 1
+ template.description = 'Knee Surgery and Rehab'
+ template.rate = 50000
+ template.save()
+ return template
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment/__init__.py b/erpnext/healthcare/doctype/patient_assessment/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.js b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.js
new file mode 100644
index 00000000000..c7074e88d5d
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.js
@@ -0,0 +1,86 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Patient Assessment', {
+ refresh: function(frm) {
+ if (frm.doc.assessment_template) {
+ frm.trigger('set_score_range');
+ }
+
+ if (!frm.doc.__islocal) {
+ frm.trigger('show_patient_progress');
+ }
+ },
+
+ assessment_template: function(frm) {
+ if (frm.doc.assessment_template) {
+ frappe.call({
+ 'method': 'frappe.client.get',
+ args: {
+ doctype: 'Patient Assessment Template',
+ name: frm.doc.assessment_template
+ },
+ callback: function(data) {
+ frm.doc.assessment_sheet = [];
+ $.each(data.message.parameters, function(_i, e) {
+ let entry = frm.add_child('assessment_sheet');
+ entry.parameter = e.assessment_parameter;
+ });
+
+ frm.set_value('scale_min', data.message.scale_min);
+ frm.set_value('scale_max', data.message.scale_max);
+ frm.set_value('assessment_description', data.message.assessment_description);
+ frm.set_value('total_score', data.message.scale_max * data.message.parameters.length);
+ frm.trigger('set_score_range');
+ refresh_field('assessment_sheet');
+ }
+ });
+ }
+ },
+
+ set_score_range: function(frm) {
+ let options = [];
+ for(let i = frm.doc.scale_min; i <= frm.doc.scale_max; i++) {
+ options.push(i);
+ }
+ frappe.meta.get_docfield('Patient Assessment Sheet', 'score', frm.doc.name).options = [''].concat(options);
+ },
+
+ calculate_total_score: function(frm, cdt, cdn) {
+ let row = locals[cdt][cdn];
+ let total_score = 0;
+ $.each(frm.doc.assessment_sheet || [], function(_i, item) {
+ if (item.score) {
+ total_score += parseInt(item.score);
+ }
+ });
+
+ frm.set_value('total_score_obtained', total_score);
+ },
+
+ show_patient_progress: function(frm) {
+ let bars = [];
+ let message = '';
+ let added_min = false;
+
+ let title = __('{0} out of {1}', [frm.doc.total_score_obtained, frm.doc.total_score]);
+
+ bars.push({
+ 'title': title,
+ 'width': (frm.doc.total_score_obtained / frm.doc.total_score * 100) + '%',
+ 'progress_class': 'progress-bar-success'
+ });
+ if (bars[0].width == '0%') {
+ bars[0].width = '0.5%';
+ added_min = 0.5;
+ }
+ message = title;
+ frm.dashboard.add_progress(__('Status'), bars, message);
+ },
+});
+
+frappe.ui.form.on('Patient Assessment Sheet', {
+ score: function(frm, cdt, cdn) {
+ frm.events.calculate_total_score(frm, cdt, cdn);
+ }
+});
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json
new file mode 100644
index 00000000000..3952a8153f7
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json
@@ -0,0 +1,172 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2020-04-19 22:45:12.356209",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "therapy_session",
+ "patient",
+ "assessment_template",
+ "column_break_4",
+ "healthcare_practitioner",
+ "assessment_datetime",
+ "assessment_description",
+ "section_break_7",
+ "assessment_sheet",
+ "section_break_9",
+ "total_score_obtained",
+ "column_break_11",
+ "total_score",
+ "scale_min",
+ "scale_max",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fetch_from": "therapy_session.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
+ {
+ "fieldname": "assessment_template",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Assessment Template",
+ "options": "Patient Assessment Template",
+ "reqd": 1
+ },
+ {
+ "fieldname": "therapy_session",
+ "fieldtype": "Link",
+ "label": "Therapy Session",
+ "options": "Therapy Session"
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "therapy_session.practitioner",
+ "fieldname": "healthcare_practitioner",
+ "fieldtype": "Link",
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner"
+ },
+ {
+ "fieldname": "assessment_datetime",
+ "fieldtype": "Datetime",
+ "label": "Assessment Datetime"
+ },
+ {
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "assessment_sheet",
+ "fieldtype": "Table",
+ "label": "Assessment Sheet",
+ "options": "Patient Assessment Sheet"
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "total_score",
+ "fieldtype": "Int",
+ "label": "Total Score",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_score_obtained",
+ "fieldtype": "Int",
+ "label": "Total Score Obtained",
+ "read_only": 1
+ },
+ {
+ "fieldname": "scale_min",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "Scale Min",
+ "read_only": 1
+ },
+ {
+ "fieldname": "scale_max",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "Scale Max",
+ "read_only": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Naming Series",
+ "options": "HLC-PA-.YYYY.-"
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Patient Assessment",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "assessment_description",
+ "fieldtype": "Small Text",
+ "label": "Assessment Description"
+ }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-04-21 13:23:09.815007",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py
new file mode 100644
index 00000000000..3033a3e6ac9
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe.model.mapper import get_mapped_doc
+
+class PatientAssessment(Document):
+ def validate(self):
+ self.set_total_score()
+
+ def set_total_score(self):
+ total_score = 0
+ for entry in self.assessment_sheet:
+ total_score += int(entry.score)
+ self.total_score_obtained = total_score
+
+@frappe.whitelist()
+def create_patient_assessment(source_name, target_doc=None):
+ doc = get_mapped_doc('Therapy Session', source_name, {
+ 'Therapy Session': {
+ 'doctype': 'Patient Assessment',
+ 'field_map': [
+ ['therapy_session', 'name'],
+ ['patient', 'patient'],
+ ['practitioner', 'practitioner']
+ ]
+ }
+ }, target_doc)
+
+ return doc
+
+
+
diff --git a/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py b/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py
new file mode 100644
index 00000000000..3fda8550f6c
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestPatientAssessment(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_detail/__init__.py b/erpnext/healthcare/doctype/patient_assessment_detail/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.json b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.json
new file mode 100644
index 00000000000..179f441044e
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.json
@@ -0,0 +1,32 @@
+{
+ "actions": [],
+ "creation": "2020-04-19 19:33:00.115395",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "assessment_parameter"
+ ],
+ "fields": [
+ {
+ "fieldname": "assessment_parameter",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Assessment Parameter",
+ "options": "Patient Assessment Parameter",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-19 19:33:00.115395",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py
new file mode 100644
index 00000000000..0519599ac0c
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentDetail(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/__init__.py b/erpnext/healthcare/doctype/patient_assessment_parameter/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.js b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.js
new file mode 100644
index 00000000000..2c5d270d575
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Patient Assessment Parameter', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.json b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.json
new file mode 100644
index 00000000000..098bdefea70
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.json
@@ -0,0 +1,45 @@
+{
+ "actions": [],
+ "autoname": "field:assessment_parameter",
+ "creation": "2020-04-15 14:34:46.551042",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "assessment_parameter"
+ ],
+ "fields": [
+ {
+ "fieldname": "assessment_parameter",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Assessment Parameter",
+ "reqd": 1,
+ "unique": 1
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-20 09:22:19.135196",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Parameter",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py
new file mode 100644
index 00000000000..b8e00747171
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentParameter(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py b/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py
new file mode 100644
index 00000000000..e722f9905ec
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestPatientAssessmentParameter(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_sheet/__init__.py b/erpnext/healthcare/doctype/patient_assessment_sheet/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.json b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.json
new file mode 100644
index 00000000000..64e4aef7cf0
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.json
@@ -0,0 +1,57 @@
+{
+ "actions": [],
+ "creation": "2020-04-19 23:07:02.220244",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "parameter",
+ "score",
+ "time",
+ "column_break_4",
+ "comments"
+ ],
+ "fields": [
+ {
+ "fieldname": "parameter",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Parameter",
+ "options": "Patient Assessment Parameter",
+ "reqd": 1
+ },
+ {
+ "fieldname": "score",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Score",
+ "reqd": 1
+ },
+ {
+ "fieldname": "time",
+ "fieldtype": "Time",
+ "label": "Time"
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "comments",
+ "fieldtype": "Small Text",
+ "label": "Comments"
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-20 09:56:28.746619",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Sheet",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py
new file mode 100644
index 00000000000..40da7630132
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentSheet(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/__init__.py b/erpnext/healthcare/doctype/patient_assessment_template/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.js b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.js
new file mode 100644
index 00000000000..40419362a4a
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Patient Assessment Template', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.json b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.json
new file mode 100644
index 00000000000..de006b18056
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.json
@@ -0,0 +1,109 @@
+{
+ "actions": [],
+ "autoname": "field:assessment_name",
+ "creation": "2020-04-19 19:33:13.204707",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "assessment_name",
+ "section_break_2",
+ "parameters",
+ "assessment_scale_details_section",
+ "scale_min",
+ "scale_max",
+ "column_break_8",
+ "assessment_description"
+ ],
+ "fields": [
+ {
+ "fieldname": "parameters",
+ "fieldtype": "Table",
+ "label": "Parameters",
+ "options": "Patient Assessment Detail"
+ },
+ {
+ "fieldname": "assessment_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Assessment Name",
+ "reqd": 1,
+ "unique": 1
+ },
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break",
+ "label": "Assessment Parameters"
+ },
+ {
+ "fieldname": "assessment_scale_details_section",
+ "fieldtype": "Section Break",
+ "label": "Assessment Scale"
+ },
+ {
+ "fieldname": "scale_min",
+ "fieldtype": "Int",
+ "label": "Scale Minimum"
+ },
+ {
+ "fieldname": "scale_max",
+ "fieldtype": "Int",
+ "label": "Scale Maximum"
+ },
+ {
+ "fieldname": "column_break_8",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "assessment_description",
+ "fieldtype": "Small Text",
+ "label": "Assessment Description"
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-21 13:14:19.075167",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Template",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py
new file mode 100644
index 00000000000..083cab5d017
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentTemplate(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py b/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py
new file mode 100644
index 00000000000..86dbd5438cd
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestPatientAssessmentTemplate(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
index 088bc8161b1..78e789d3594 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
@@ -3,6 +3,10 @@
frappe.ui.form.on('Patient Encounter', {
setup: function(frm) {
+ frm.get_field('therapies').grid.editable_fields = [
+ {fieldname: 'therapy_type', columns: 8},
+ {fieldname: 'no_of_sessions', columns: 2}
+ ];
frm.get_field('drug_prescription').grid.editable_fields = [
{fieldname: 'drug_code', columns: 2},
{fieldname: 'drug_name', columns: 2},
@@ -19,297 +23,237 @@ frappe.ui.form.on('Patient Encounter', {
refresh: function(frm) {
refresh_field('drug_prescription');
refresh_field('lab_test_prescription');
- if (!frm.doc.__islocal){
- frappe.call({
- method: 'frappe.client.get_value',
- args: {
- doctype: 'Patient',
- fieldname: 'inpatient_status',
- filters: {name: frm.doc.patient}
- },
- callback: function(data) {
- if(data.message && data.message.inpatient_status == "Admission Scheduled" || data.message.inpatient_status == "Admitted"){
- frm.add_custom_button(__('Schedule Discharge'), function() {
- schedule_discharge(frm);
- });
- }
- else if(data.message.inpatient_status != "Discharge Scheduled"){
- frm.add_custom_button(__('Schedule Admission'), function() {
- schedule_inpatient(frm);
- });
- }
- }
- });
- }
- frm.add_custom_button(__('Patient History'), function() {
- if (frm.doc.patient) {
- frappe.route_options = {"patient": frm.doc.patient};
- frappe.set_route("patient_history");
- } else {
- frappe.msgprint(__("Please select Patient"));
+
+ if (!frm.doc.__islocal) {
+
+ if (frm.doc.inpatient_status == 'Admission Scheduled' || frm.doc.inpatient_status == 'Admitted') {
+ frm.add_custom_button(__('Schedule Discharge'), function() {
+ schedule_discharge(frm);
+ });
+ } else if (frm.doc.inpatient_status != 'Discharge Scheduled') {
+ frm.add_custom_button(__('Schedule Admission'), function() {
+ schedule_inpatient(frm);
+ });
}
- },"View");
- frm.add_custom_button(__('Vital Signs'), function() {
- btn_create_vital_signs(frm);
- },"Create");
- frm.add_custom_button(__('Medical Record'), function() {
- create_medical_record(frm);
- },"Create");
- frm.add_custom_button(__("Procedure"),function(){
- btn_create_procedure(frm);
- },"Create");
+ frm.add_custom_button(__('Patient History'), function() {
+ if (frm.doc.patient) {
+ frappe.route_options = {'patient': frm.doc.patient};
+ frappe.set_route('patient_history');
+ } else {
+ frappe.msgprint(__('Please select Patient'));
+ }
+ },'View');
- frm.set_query("patient", function () {
+ frm.add_custom_button(__('Vital Signs'), function() {
+ create_vital_signs(frm);
+ },'Create');
+
+ frm.add_custom_button(__('Medical Record'), function() {
+ create_medical_record(frm);
+ },'Create');
+
+ frm.add_custom_button(__('Clinical Procedure'), function() {
+ create_procedure(frm);
+ },'Create');
+
+ }
+
+ frm.set_query('patient', function() {
return {
- filters: {"disabled": 0}
+ filters: {'status': 'Active'}
};
});
- frm.set_query("drug_code", "drug_prescription", function() {
+
+ frm.set_query('drug_code', 'drug_prescription', function() {
return {
filters: {
- is_stock_item:'1'
+ is_stock_item: 1
}
};
});
- frm.set_query("lab_test_code", "lab_test_prescription", function() {
+
+ frm.set_query('lab_test_code', 'lab_test_prescription', function() {
return {
filters: {
- is_billable:'1'
+ is_billable: 1
}
};
});
- frm.set_query("medical_code", "codification_table", function() {
- return {
- filters: {
- medical_code_standard: frappe.defaults.get_default("default_medical_code_standard")
- }
- };
- });
- frm.set_query("appointment", function() {
+
+ frm.set_query('appointment', function() {
return {
filters: {
// Scheduled filter for demo ...
- status:['in',["Open","Scheduled"]]
+ status:['in',['Open','Scheduled']]
}
};
});
- frm.set_df_property("appointment", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("patient", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("patient_age", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("patient_sex", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("type", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("practitioner", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("visit_department", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("encounter_date", "read_only", frm.doc.__islocal ? 0:1);
- frm.set_df_property("encounter_time", "read_only", frm.doc.__islocal ? 0:1);
- }
-});
-var schedule_inpatient = function(frm) {
- frappe.call({
- method: "erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_inpatient",
- args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
- callback: function(data) {
- if(!data.exc){
- frm.reload_doc();
- }
- },
- freeze: true,
- freeze_message: "Process Inpatient Scheduling"
- });
-};
+ frm.set_df_property('patient', 'read_only', frm.doc.appointment ? 1 : 0);
+ },
-var schedule_discharge = function(frm) {
- frappe.call({
- method: "erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_discharge",
- args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
- callback: function(data) {
- if(!data.exc){
- frm.reload_doc();
- }
- },
- freeze: true,
- freeze_message: "Process Discharge"
- });
-};
+ appointment: function(frm) {
+ frm.events.set_appointment_fields(frm);
+ },
-var create_medical_record = function (frm) {
- if(!frm.doc.patient){
- frappe.throw(__("Please select patient"));
- }
- frappe.route_options = {
- "patient": frm.doc.patient,
- "status": "Open",
- "reference_doctype": "Patient Medical Record",
- "reference_owner": frm.doc.owner
- };
- frappe.new_doc("Patient Medical Record");
-};
+ patient: function(frm) {
+ frm.events.set_patient_info(frm);
+ },
-var btn_create_vital_signs = function (frm) {
- if(!frm.doc.patient){
- frappe.throw(__("Please select patient"));
- }
- frappe.route_options = {
- "patient": frm.doc.patient,
- "appointment": frm.doc.appointment
- };
- frappe.new_doc("Vital Signs");
-};
-
-var btn_create_procedure = function (frm) {
- if(!frm.doc.patient){
- frappe.throw(__("Please select patient"));
- }
- frappe.route_options = {
- "patient": frm.doc.patient,
- "medical_department": frm.doc.visit_department
- };
- frappe.new_doc("Clinical Procedure");
-};
-
-frappe.ui.form.on("Patient Encounter", "appointment", function(frm){
- if(frm.doc.appointment){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Patient Appointment",
- name: frm.doc.appointment
- },
- callback: function (data) {
- frappe.model.set_value(frm.doctype,frm.docname, "patient", data.message.patient);
- frappe.model.set_value(frm.doctype,frm.docname, "type", data.message.appointment_type);
- frappe.model.set_value(frm.doctype,frm.docname, "practitioner", data.message.practitioner);
- frappe.model.set_value(frm.doctype,frm.docname, "invoiced", data.message.invoiced);
- }
- });
- }
- else{
- frappe.model.set_value(frm.doctype,frm.docname, "patient", "");
- frappe.model.set_value(frm.doctype,frm.docname, "type", "");
- frappe.model.set_value(frm.doctype,frm.docname, "practitioner", "");
- frappe.model.set_value(frm.doctype,frm.docname, "invoiced", 0);
- }
-});
-
-frappe.ui.form.on("Patient Encounter", "practitioner", function(frm) {
- if(frm.doc.practitioner){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Healthcare Practitioner",
- name: frm.doc.practitioner
- },
- callback: function (data) {
- frappe.model.set_value(frm.doctype,frm.docname, "visit_department",data.message.department);
- }
- });
- }
-});
-
-frappe.ui.form.on("Patient Encounter", "symptoms_select", function(frm) {
- if(frm.doc.symptoms_select){
- var symptoms = null;
- if(frm.doc.symptoms)
- symptoms = frm.doc.symptoms + "\n" +frm.doc.symptoms_select;
- else
- symptoms = frm.doc.symptoms_select;
- frappe.model.set_value(frm.doctype,frm.docname, "symptoms", symptoms);
- frappe.model.set_value(frm.doctype,frm.docname, "symptoms_select", null);
- }
-});
-frappe.ui.form.on("Patient Encounter", "diagnosis_select", function(frm) {
- if(frm.doc.diagnosis_select){
- var diagnosis = null;
- if(frm.doc.diagnosis)
- diagnosis = frm.doc.diagnosis + "\n" +frm.doc.diagnosis_select;
- else
- diagnosis = frm.doc.diagnosis_select;
- frappe.model.set_value(frm.doctype,frm.docname, "diagnosis", diagnosis);
- frappe.model.set_value(frm.doctype,frm.docname, "diagnosis_select", null);
- }
-});
-
-frappe.ui.form.on("Patient Encounter", "patient", function(frm) {
- if(frm.doc.patient){
- frappe.call({
- "method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
- args: {
- patient: frm.doc.patient
- },
- callback: function (data) {
- var age = "";
- 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_sex", data.message.sex);
- }
- });
- }
-});
-
-frappe.ui.form.on("Drug Prescription", {
- drug_code: function(frm, cdt, cdn) {
- var child = locals[cdt][cdn];
- if(child.drug_code){
+ set_appointment_fields: function(frm) {
+ if (frm.doc.appointment) {
frappe.call({
- "method": "frappe.client.get",
+ method: 'frappe.client.get',
args: {
- doctype: "Item",
- name: child.drug_code,
+ doctype: 'Patient Appointment',
+ name: frm.doc.appointment
},
- callback: function (data) {
- frappe.model.set_value(cdt, cdn, 'drug_name',data.message.item_name);
+ callback: function(data) {
+ let values = {
+ 'patient':data.message.patient,
+ 'type': data.message.appointment_type,
+ 'practitioner': data.message.practitioner,
+ 'invoiced': data.message.invoiced
+ };
+ frm.set_value(values);
}
});
}
+ else {
+ let values = {
+ 'patient': '',
+ 'patient_name': '',
+ 'type': '',
+ 'practitioner': '',
+ 'invoiced': 0,
+ 'patient_sex': '',
+ 'patient_age': '',
+ 'inpatient_record': '',
+ 'inpatient_status': ''
+ };
+ frm.set_value(values);
+ }
},
+
+ set_patient_info: function(frm) {
+ if (frm.doc.patient) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
+ args: {
+ patient: frm.doc.patient
+ },
+ callback: function(data) {
+ let age = '';
+ 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_sex', data.message.sex);
+ if (data.message.inpatient_record) {
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_record', data.message.inpatient_record);
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_status', data.message.inpatient_status);
+ }
+ }
+ });
+ } else {
+ frappe.model.set_value(frm.doctype, frm.docname, 'patient_sex', '');
+ frappe.model.set_value(frm.doctype, frm.docname, 'patient_age', '');
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_record', '');
+ frappe.model.set_value(frm.doctype, frm.docname, 'inpatient_status', '');
+ }
+ }
+});
+
+let schedule_inpatient = function(frm) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_inpatient',
+ args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
+ callback: function(data) {
+ if (!data.exc) {
+ frm.reload_doc();
+ }
+ },
+ freeze: true,
+ freeze_message: __('Process Inpatient Scheduling')
+ });
+};
+
+let schedule_discharge = function(frm) {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_discharge',
+ args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
+ callback: function(data) {
+ if (!data.exc) {
+ frm.reload_doc();
+ }
+ },
+ freeze: true,
+ freeze_message: 'Process Discharge'
+ });
+};
+
+let create_medical_record = function (frm) {
+ if (!frm.doc.patient) {
+ frappe.throw(__('Please select patient'));
+ }
+ frappe.route_options = {
+ 'patient': frm.doc.patient,
+ 'status': 'Open',
+ 'reference_doctype': 'Patient Medical Record',
+ 'reference_owner': frm.doc.owner
+ };
+ frappe.new_doc('Patient Medical Record');
+};
+
+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.appointment,
+ 'encounter': frm.doc.name
+ };
+ frappe.new_doc('Vital Signs');
+};
+
+let create_procedure = function (frm) {
+ if (!frm.doc.patient) {
+ frappe.throw(__('Please select patient'));
+ }
+ frappe.route_options = {
+ 'patient': frm.doc.patient,
+ 'medical_department': frm.doc.medical_department
+ };
+ frappe.new_doc('Clinical Procedure');
+};
+
+frappe.ui.form.on('Drug Prescription', {
dosage: function(frm, cdt, cdn){
frappe.model.set_value(cdt, cdn, 'update_schedule', 1);
- var child = locals[cdt][cdn];
- if(child.dosage){
- frappe.model.set_value(cdt, cdn, 'in_every', 'Day');
+ let child = locals[cdt][cdn];
+ if (child.dosage) {
+ frappe.model.set_value(cdt, cdn, 'interval_uom', 'Day');
frappe.model.set_value(cdt, cdn, 'interval', 1);
}
},
- period: function(frm, cdt, cdn){
+ period: function(frm, cdt, cdn) {
frappe.model.set_value(cdt, cdn, 'update_schedule', 1);
},
- in_every: function(frm, cdt, cdn){
+ interval_uom: function(frm, cdt, cdn) {
frappe.model.set_value(cdt, cdn, 'update_schedule', 1);
- var child = locals[cdt][cdn];
- if(child.in_every == "Hour"){
+ let child = locals[cdt][cdn];
+ if (child.interval_uom == 'Hour') {
frappe.model.set_value(cdt, cdn, 'dosage', null);
}
}
});
-frappe.ui.form.on("Procedure Prescription", {
- procedure: function(frm, cdt, cdn) {
- var child = locals[cdt][cdn];
- if(child.procedure){
- frappe.call({
- "method": "frappe.client.get_value",
- args: {
- doctype: "Clinical Procedure Template",
- fieldname: "medical_department",
- filters: {name: child.procedure}
- },
- callback: function (data) {
- frappe.model.set_value(cdt, cdn, 'department',data.message.medical_department);
- }
- });
- }
- }
-});
-
-
-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_encounter/patient_encounter.json b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
index 91c9d7bcf2c..5f11039e19b 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
@@ -1,1183 +1,351 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2016-04-21 10:53:44.637684",
- "custom": 0,
- "default_print_format": "",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2016-04-21 10:53:44.637684",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "appointment",
+ "appointment_type",
+ "patient",
+ "patient_name",
+ "patient_sex",
+ "patient_age",
+ "company",
+ "column_break_6",
+ "practitioner",
+ "medical_department",
+ "encounter_date",
+ "encounter_time",
+ "invoiced",
+ "section_break_1",
+ "inpatient_record",
+ "column_break_17",
+ "inpatient_status",
+ "sb_symptoms",
+ "symptoms",
+ "symptoms_in_print",
+ "physical_examination",
+ "diagnosis",
+ "diagnosis_in_print",
+ "codification",
+ "codification_table",
+ "sb_drug_prescription",
+ "drug_prescription",
+ "sb_test_prescription",
+ "lab_test_prescription",
+ "sb_procedures",
+ "procedure_prescription",
+ "rehabilitation_section",
+ "therapy_plan",
+ "therapies",
+ "section_break_33",
+ "encounter_comment",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.inpatient_record",
- "fieldname": "inpatient_record",
- "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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
- "options": "Inpatient Record",
- "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
- },
+ "fieldname": "inpatient_record",
+ "fieldtype": "Link",
+ "label": "Inpatient Record",
+ "options": "Inpatient Record",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_1",
- "fieldtype": "Section Break",
- "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,
- "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
- },
+ "collapsible": 1,
+ "fieldname": "section_break_1",
+ "fieldtype": "Section Break",
+ "label": "Inpatient Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "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": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "HLC-ENC-.YYYY.-",
- "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
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "HLC-ENC-.YYYY.-",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "appointment",
- "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": "Appointment",
- "length": 0,
- "no_copy": 0,
- "options": "Patient Appointment",
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "appointment",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Appointment",
+ "options": "Patient Appointment",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "type",
- "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": "Type",
- "length": 0,
- "no_copy": 1,
- "options": "Appointment Type",
- "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
- },
+ "fetch_from": "inpatient_record.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "inpatient_record.patient",
- "fieldname": "patient",
- "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": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "patient.patient_name",
+ "fieldname": "patient_name",
+ "fieldtype": "Data",
+ "label": "Patient Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_from": "patient.patient_name",
- "fieldname": "patient_name",
- "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": "Patient Name",
- "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
- },
+ "fieldname": "patient_age",
+ "fieldtype": "Data",
+ "label": "Age",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient_age",
- "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": "Age",
- "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": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient_sex",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient_sex",
- "fieldtype": "Select",
- "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": "Gender",
- "length": 0,
- "no_copy": 0,
- "options": "\nMale\nFemale\nOther",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Company",
+ "options": "Company"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "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": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "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
- },
+ "fieldname": "column_break_6",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_6",
- "fieldtype": "Column Break",
- "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,
- "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
- },
+ "fieldname": "practitioner",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "practitioner",
- "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": 1,
- "label": "Healthcare Practitioner",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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
- },
+ "default": "Today",
+ "fieldname": "encounter_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Encounter Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "visit_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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "encounter_time",
+ "fieldtype": "Time",
+ "label": "Encounter Time",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fieldname": "encounter_date",
- "fieldtype": "Date",
- "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": "Encounter Date",
- "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
- },
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "no_copy": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "encounter_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": "Encounter 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "sb_symptoms",
+ "fieldtype": "Section Break",
+ "label": "Encounter Impression"
+ },
{
- "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": 1,
- "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
- },
+ "fieldname": "symptoms",
+ "fieldtype": "Table MultiSelect",
+ "ignore_xss_filter": 1,
+ "label": "Symptoms",
+ "no_copy": 1,
+ "options": "Patient Encounter Symptom"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "sb_symptoms",
- "fieldtype": "Section Break",
- "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": "Encounter Impression",
- "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
- },
+ "default": "0",
+ "depends_on": "eval: doc.symptoms != ''",
+ "fieldname": "symptoms_in_print",
+ "fieldtype": "Check",
+ "label": "In print",
+ "no_copy": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "symptoms_select",
- "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": "Complaints",
- "length": 0,
- "no_copy": 1,
- "options": "Complaint",
- "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
- },
+ "fieldname": "physical_examination",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "symptoms",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "",
- "length": 0,
- "no_copy": 1,
- "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
- },
+ "fieldname": "diagnosis",
+ "fieldtype": "Table MultiSelect",
+ "ignore_xss_filter": 1,
+ "label": "Diagnosis",
+ "no_copy": 1,
+ "options": "Patient Encounter Diagnosis"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "symptoms_in_print",
- "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": "In print",
- "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": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "1",
+ "depends_on": "eval: doc.diagnosis != ''",
+ "fieldname": "diagnosis_in_print",
+ "fieldtype": "Check",
+ "label": "In print",
+ "no_copy": 1,
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "physical_examination",
- "fieldtype": "Column Break",
- "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": "",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "codification",
+ "fieldtype": "Section Break",
+ "label": "Medical Coding"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "diagnosis_select",
- "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": "Diagnosis",
- "length": 0,
- "no_copy": 1,
- "options": "Diagnosis",
- "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
- },
+ "fieldname": "codification_table",
+ "fieldtype": "Table",
+ "label": "Medical Coding",
+ "options": "Codification Table"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "diagnosis",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "",
- "length": 0,
- "no_copy": 1,
- "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
- },
+ "fieldname": "sb_drug_prescription",
+ "fieldtype": "Section Break",
+ "label": "Medication"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "depends_on": "",
- "fieldname": "diagnosis_in_print",
- "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": "In print",
- "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": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "drug_prescription",
+ "fieldtype": "Table",
+ "label": "Drug Prescription",
+ "options": "Drug Prescription"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "codification",
- "fieldtype": "Section Break",
- "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": "Medical Coding",
- "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
- },
+ "fieldname": "sb_test_prescription",
+ "fieldtype": "Section Break",
+ "label": "Investigation"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "codification_table",
- "fieldtype": "Table",
- "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": "Medical Coding",
- "length": 0,
- "no_copy": 0,
- "options": "Codification Table",
- "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
- },
+ "fieldname": "lab_test_prescription",
+ "fieldtype": "Table",
+ "label": "Lab Prescription",
+ "options": "Lab Prescription"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_drug_prescription",
- "fieldtype": "Section Break",
- "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": "Medication",
- "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
- },
+ "fieldname": "sb_procedures",
+ "fieldtype": "Section Break",
+ "label": "Procedures"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "drug_prescription",
- "fieldtype": "Table",
- "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": "Medication",
- "length": 0,
- "no_copy": 0,
- "options": "Drug Prescription",
- "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
- },
+ "fieldname": "procedure_prescription",
+ "fieldtype": "Table",
+ "label": "Procedure Prescription",
+ "no_copy": 1,
+ "options": "Procedure Prescription"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_test_prescription",
- "fieldtype": "Section Break",
- "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": "Investigations",
- "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
- },
+ "fieldname": "encounter_comment",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Review Details",
+ "no_copy": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lab_test_prescription",
- "fieldtype": "Table",
- "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": "Investigations",
- "length": 0,
- "no_copy": 0,
- "options": "Lab Prescription",
- "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
- },
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Patient Encounter",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_procedures",
- "fieldtype": "Section Break",
- "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": "Procedures",
- "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
- },
+ "fieldname": "rehabilitation_section",
+ "fieldtype": "Section Break",
+ "label": "Rehabilitation"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure_prescription",
- "fieldtype": "Table",
- "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": "Procedures",
- "length": 0,
- "no_copy": 1,
- "options": "Procedure Prescription",
- "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
- },
+ "fieldname": "therapies",
+ "fieldtype": "Table",
+ "label": "Therapies",
+ "options": "Therapy Plan Detail"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "encounter_comment",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Review Details",
- "length": 0,
- "no_copy": 1,
- "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
- },
+ "fieldname": "section_break_33",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "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": "Amended From",
- "length": 0,
- "no_copy": 1,
- "options": "Patient Encounter",
- "permlevel": 0,
- "print_hide": 1,
- "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
+ "fieldname": "therapy_plan",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Therapy Plan",
+ "options": "Therapy Plan",
+ "read_only": 1
+ },
+ {
+ "fieldname": "appointment_type",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Appointment Type",
+ "no_copy": 1,
+ "options": "Appointment Type",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
+ {
+ "fetch_from": "practitioner.department",
+ "fieldname": "medical_department",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Department",
+ "options": "Medical Department",
+ "read_only": 1
+ },
+ {
+ "fieldname": "inpatient_status",
+ "fieldtype": "Data",
+ "label": "Inpatient Status",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_17",
+ "fieldtype": "Column Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-09-04 11:50:52.217175",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Patient Encounter",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-04-14 16:18:08.180457",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Encounter",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "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": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "patient, practitioner, visit_department, encounter_date, encounter_time",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "patient",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "patient, practitioner, medical_department, encounter_date, encounter_time",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1,
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
index fe7ac8eb33e..767643bc73a 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
@@ -4,61 +4,84 @@
from __future__ import unicode_literals
import frappe
+from frappe import _
from frappe.model.document import Document
from frappe.utils import cstr
+from frappe import _
class PatientEncounter(Document):
def on_update(self):
- if(self.appointment):
- frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
- update_encounter_to_medical_record(self)
+ if self.appointment:
+ frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
+ update_encounter_medical_record(self)
def after_insert(self):
insert_encounter_to_medical_record(self)
def on_cancel(self):
- if(self.appointment):
- frappe.db.set_value("Patient Appointment", self.appointment, "status", "Open")
+ if self.appointment:
+ frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
delete_medical_record(self)
+ def on_submit(self):
+ create_therapy_plan(self)
+
+def create_therapy_plan(encounter):
+ if len(encounter.therapies):
+ doc = frappe.new_doc('Therapy Plan')
+ doc.patient = encounter.patient
+ doc.start_date = encounter.encounter_date
+ for entry in encounter.therapies:
+ doc.append('therapy_plan_details', {
+ 'therapy_type': entry.therapy_type,
+ 'no_of_sessions': entry.no_of_sessions
+ })
+ doc.save(ignore_permissions=True)
+ if doc.get('name'):
+ encounter.db_set('therapy_plan', doc.name)
+ frappe.msgprint(_('Therapy Plan {0} created successfully.').format(frappe.bold(doc.name)), alert=True)
+
def insert_encounter_to_medical_record(doc):
subject = set_subject_field(doc)
- 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.encounter_date
- medical_record.reference_doctype = "Patient Encounter"
+ medical_record.reference_doctype = 'Patient Encounter'
medical_record.reference_name = doc.name
medical_record.reference_owner = doc.owner
medical_record.save(ignore_permissions=True)
-def update_encounter_to_medical_record(encounter):
- medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s", (encounter.name))
+def update_encounter_medical_record(encounter):
+ medical_record_id = frappe.db.exists('Patient Medical Record', {'reference_name': encounter.name})
+
if medical_record_id and medical_record_id[0][0]:
subject = set_subject_field(encounter)
- frappe.db.set_value("Patient Medical Record", medical_record_id[0][0], "subject", subject)
+ frappe.db.set_value('Patient Medical Record', medical_record_id[0][0], 'subject', subject)
else:
insert_encounter_to_medical_record(encounter)
def delete_medical_record(encounter):
- frappe.db.sql("""delete from `tabPatient Medical Record` where reference_name = %s""", (encounter.name))
+ frappe.db.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
def set_subject_field(encounter):
- subject = encounter.practitioner+"
"
- if(encounter.symptoms):
- subject += "Symptoms: "+ cstr(encounter.symptoms)+".
"
+ subject = encounter.practitioner + '\n'
+ if encounter.symptoms:
+ subject += _('Symptoms: ') + cstr(encounter.symptoms) + '\n'
else:
- subject += "No Symptoms
"
- if(encounter.diagnosis):
- subject += "Diagnosis: "+ cstr(encounter.diagnosis)+".
"
+ subject += _('No Symptoms') + '\n'
+
+ if encounter.diagnosis:
+ subject += _('Diagnosis: ') + cstr(encounter.diagnosis) + '\n'
else:
- subject += "No Diagnosis
"
- if(encounter.drug_prescription):
- subject +="\nDrug(s) Prescribed. "
- if(encounter.lab_test_prescription):
- subject += "\nTest(s) Prescribed."
- if(encounter.procedure_prescription):
- subject += "\nProcedure(s) Prescribed."
+ subject += _('No Diagnosis') + '\n'
+
+ if encounter.drug_prescription:
+ subject += '\n' + _('Drug(s) Prescribed.')
+ if encounter.lab_test_prescription:
+ subject += '\n' + _('Test(s) Prescribed.')
+ if encounter.procedure_prescription:
+ subject += '\n' + _('Procedure(s) Prescribed.')
return subject
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js
index 93c02f60c5c..d8f63bd0fa5 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter_list.js
@@ -2,5 +2,5 @@
(c) ESS 2015-16
*/
frappe.listview_settings['Patient Encounter'] = {
- filters:[["docstatus","!=","1"]]
+ filters:[["docstatus","!=","2"]]
};
diff --git a/erpnext/healthcare/doctype/patient_encounter_diagnosis/__init__.py b/erpnext/healthcare/doctype/patient_encounter_diagnosis/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.json b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.json
new file mode 100644
index 00000000000..00ca309d63e
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.json
@@ -0,0 +1,33 @@
+{
+ "actions": [],
+ "beta": 1,
+ "creation": "2020-02-26 16:48:16.835105",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "diagnosis"
+ ],
+ "fields": [
+ {
+ "fieldname": "diagnosis",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Diagnosis",
+ "options": "Diagnosis",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 16:58:16.480583",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Encounter Diagnosis",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py
new file mode 100644
index 00000000000..34b0cf8a580
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_diagnosis/patient_encounter_diagnosis.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientEncounterDiagnosis(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_encounter_symptom/__init__.py b/erpnext/healthcare/doctype/patient_encounter_symptom/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.json b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.json
new file mode 100644
index 00000000000..bc921458674
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.json
@@ -0,0 +1,33 @@
+{
+ "actions": [],
+ "beta": 1,
+ "creation": "2020-02-26 16:47:00.525657",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "complaint"
+ ],
+ "fields": [
+ {
+ "fieldname": "complaint",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Complaint",
+ "options": "Complaint",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 16:57:37.997481",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Encounter Symptom",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py
new file mode 100644
index 00000000000..bdb7bb218eb
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_encounter_symptom/patient_encounter_symptom.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientEncounterSymptom(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
index c6a6b44ce74..3655e24cb98 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
+++ b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
@@ -1,457 +1,155 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2016-06-09 11:30:44.972056",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2016-06-09 11:30:44.972056",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "patient",
+ "status",
+ "column_break_2",
+ "attach",
+ "section_break_4",
+ "subject",
+ "section_break_8",
+ "communication_date",
+ "reference_doctype",
+ "reference_name",
+ "column_break_9",
+ "reference_owner",
+ "user"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "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": "Series",
- "length": 0,
- "no_copy": 0,
- "options": "HLC-PMR-.YYYY.-",
- "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
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-PMR-.YYYY.-",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient",
- "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": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "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,
- "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
- },
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "attach",
- "fieldtype": "Attach",
- "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,
- "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
- },
+ "fieldname": "attach",
+ "fieldtype": "Attach",
+ "label": "Attach Medical Record"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_4",
- "fieldtype": "Section Break",
- "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,
- "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
- },
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "subject",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Subject",
- "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
- },
+ "fieldname": "subject",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Subject"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "status",
- "fieldtype": "Select",
- "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": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Open\nClose",
- "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": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "options": "Open\nClose",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fieldname": "communication_date",
- "fieldtype": "Date",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Datetime",
- "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
- },
+ "default": "Today",
+ "fieldname": "communication_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Datetime",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "reference_doctype",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Reference DocType",
- "length": 0,
- "no_copy": 0,
- "options": "DocType",
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "reference_doctype",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Reference DocType",
+ "options": "DocType",
+ "read_only": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "reference_name",
- "fieldtype": "Dynamic Link",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Reference Name",
- "length": 0,
- "no_copy": 0,
- "options": "reference_doctype",
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "reference_name",
+ "fieldtype": "Dynamic Link",
+ "in_list_view": 1,
+ "label": "Reference Name",
+ "options": "reference_doctype",
+ "read_only": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "reference_name.owner",
- "fieldname": "reference_owner",
- "fieldtype": "Data",
- "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": "Reference Owner",
- "length": 0,
- "no_copy": 1,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "reference_name.owner",
+ "fieldname": "reference_owner",
+ "fieldtype": "Data",
+ "label": "Reference Owner",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "__user",
- "fieldname": "user",
- "fieldtype": "Link",
- "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": "User",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "default": "__user",
+ "fieldname": "user",
+ "fieldtype": "Link",
+ "label": "User",
+ "options": "User",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
+ {
+ "fieldname": "column_break_9",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_8",
+ "fieldtype": "Section Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 1,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-21 14:44:37.927284",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Patient Medical Record",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "in_create": 1,
+ "links": [],
+ "modified": "2020-03-23 19:26:59.308383",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Medical Record",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 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": "Physician",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "patient, subject, communication_date, reference_doctype, reference_name",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "patient",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
-}
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "patient, subject, communication_date, reference_doctype, reference_name",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
index 460774a7ec8..e5a5e4c010d 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
+++ b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.py
@@ -3,8 +3,86 @@
# See license.txt
from __future__ import unicode_literals
import unittest
-
-# test_records = frappe.get_test_records('Patient Medical Record')
+import frappe
+from frappe.utils import nowdate
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_encounter, create_healthcare_docs, create_appointment
class TestPatientMedicalRecord(unittest.TestCase):
- pass
+ def setUp(self):
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+
+ def test_medical_record(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ appointment = create_appointment(patient, practitioner, nowdate(), invoice=1)
+ encounter = create_encounter(appointment)
+ # check for encounter
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': encounter.name})
+ self.assertTrue(medical_rec)
+
+ vital_signs = create_vital_signs(appointment)
+ # check for vital signs
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': vital_signs.name})
+ self.assertTrue(medical_rec)
+
+ appointment = create_appointment(patient, practitioner, nowdate(), invoice=1, procedure_template=1)
+ procedure = create_procedure(appointment)
+ procedure.start_procedure()
+ procedure.complete_procedure()
+ # check for clinical procedure
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': procedure.name})
+ self.assertTrue(medical_rec)
+
+ template = create_lab_test_template(medical_department)
+ lab_test = create_lab_test(template, patient)
+ # check for lab test
+ medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': lab_test.name})
+ self.assertTrue(medical_rec)
+
+
+def create_procedure(appointment):
+ if appointment:
+ procedure = frappe.new_doc('Clinical Procedure')
+ procedure.procedure_template = appointment.procedure_template
+ procedure.appointment = appointment.name
+ procedure.patient = appointment.patient
+ procedure.practitioner = appointment.practitioner
+ procedure.medical_department = appointment.department
+ procedure.start_dt = appointment.appointment_date
+ procedure.start_time = appointment.appointment_time
+ procedure.save()
+ procedure.submit()
+ return procedure
+
+def create_vital_signs(appointment):
+ vital_signs = frappe.new_doc('Vital Signs')
+ vital_signs.patient = appointment.patient
+ vital_signs.signs_date = appointment.appointment_date
+ vital_signs.signs_time = appointment.appointment_time
+ vital_signs.temperature = 38.5
+ vital_signs.save()
+ vital_signs.submit()
+ return vital_signs
+
+def create_lab_test_template(medical_department):
+ if frappe.db.exists('Lab Test Template', 'Blood Test'):
+ return 'Blood Test'
+
+ template = frappe.new_doc('Lab Test Template')
+ template.lab_test_name = 'Blood Test'
+ template.lab_test_code = 'Blood Test'
+ template.lab_test_group = 'Services'
+ template.department = medical_department
+ template.is_billable = 1
+ template.lab_test_rate = 2000
+ template.save()
+ return template.name
+
+def create_lab_test(template, patient):
+ lab_test = frappe.new_doc('Lab Test')
+ lab_test.patient = patient
+ lab_test.patient_sex = frappe.db.get_value('Patient', patient, 'sex')
+ lab_test.template = template
+ lab_test.save()
+ lab_test.submit()
+ return lab_test
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_relation/patient_relation.json b/erpnext/healthcare/doctype/patient_relation/patient_relation.json
index 209a3746a6e..376f7f76d66 100644
--- a/erpnext/healthcare/doctype/patient_relation/patient_relation.json
+++ b/erpnext/healthcare/doctype/patient_relation/patient_relation.json
@@ -1,134 +1,52 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-04-26 15:40:11.561855",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2017-04-26 15:40:11.561855",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "patient",
+ "relation",
+ "description"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "relation",
- "fieldtype": "Select",
- "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": "Relation",
- "length": 0,
- "no_copy": 0,
- "options": "\nFather\nMother\nSpouse\nSiblings\nFamily",
- "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": 0,
- "unique": 0
- },
+ "fieldname": "relation",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Relation",
+ "options": "\nFather\nMother\nSpouse\nSiblings\nFamily\nOther",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient",
- "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": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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
- },
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Description",
- "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
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "ignore_xss_filter": 1,
+ "label": "Description"
}
- ],
- "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-10-04 16:12:45.485333",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Patient Relation",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-01-29 12:45:40.081899",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Relation",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js
index f247856b92f..7cb7c4b65e6 100644
--- a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js
+++ b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.js
@@ -5,9 +5,9 @@ frappe.ui.form.on('Practitioner Schedule', {
refresh: function(frm) {
cur_frm.fields_dict["time_slots"].grid.wrapper.find('.grid-add-row').hide();
cur_frm.fields_dict["time_slots"].grid.add_custom_button(__('Add Time Slots'), () => {
- var d = new frappe.ui.Dialog({
+ let d = new frappe.ui.Dialog({
fields: [
- {fieldname: 'days', label: __('Select Days'), fieldtype:'MultiSelect',
+ {fieldname: 'days', label: __('Select Days'), fieldtype: 'MultiSelect',
options:[
{value:'Sunday', label:__('Sunday')},
{value:'Monday', label:__('Monday')},
@@ -17,40 +17,41 @@ frappe.ui.form.on('Practitioner Schedule', {
{value:'Friday', label:__('Friday')},
{value:'Saturday', label:__('Saturday')},
], reqd: 1},
- {fieldname: 'from_time', label:__('From'), fieldtype:'Time',
+ {fieldname: 'from_time', label: __('From'), fieldtype: 'Time',
'default': '09:00:00', reqd: 1},
- {fieldname: 'to_time', label:__('To'), fieldtype:'Time',
+ {fieldname: 'to_time', label: __('To'), fieldtype: 'Time',
'default': '12:00:00', reqd: 1},
- {fieldname: 'duration', label:__('Appointment Duration (mins)'),
+ {fieldname: 'duration', label: __('Appointment Duration (mins)'),
fieldtype:'Int', 'default': 15, reqd: 1},
],
primary_action_label: __('Add Timeslots'),
primary_action: () => {
- var values = d.get_values();
- if(values) {
+ let values = d.get_values();
+ if (values) {
let slot_added = false;
values.days.split(',').forEach(function(day){
day = $.trim(day);
- if(['Sunday', 'Monday', 'Tuesday', 'Wednesday',
+ if (['Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday'].includes(day)){
add_slots(day);
}
});
+
function check_overlap_or_add_slot(week_day, cur_time, end_time, add_slots_to_child){
let overlap = false;
- while(cur_time < end_time) {
+ while (cur_time < end_time) {
let add_to_child = true;
let to_time = cur_time.clone().add(values.duration, 'minutes');
- if(to_time <= end_time) {
- if(frm.doc.time_slots){
+ if (to_time <= end_time) {
+ if (frm.doc.time_slots){
frm.doc.time_slots.forEach(function(slot) {
- if(slot.day == week_day){
+ if (slot.day == week_day){
let slot_from_moment = moment(slot.from_time, 'HH:mm:ss');
let slot_to_moment = moment(slot.to_time, 'HH:mm:ss');
- if(cur_time.isSame(slot_from_moment) || cur_time.isBetween(slot_from_moment, slot_to_moment) ||
- to_time.isSame(slot_to_moment) || to_time.isBetween(slot_from_moment, slot_to_moment)){
+ if (cur_time.isSame(slot_from_moment) || cur_time.isBetween(slot_from_moment, slot_to_moment) ||
+ to_time.isSame(slot_to_moment) || to_time.isBetween(slot_from_moment, slot_to_moment)) {
overlap = true;
- if(add_slots_to_child){
+ if (add_slots_to_child) {
frappe.show_alert({
message:__('Time slot skiped, the slot {0} to {1} overlap exisiting slot {2} to {3}',
[cur_time.format('HH:mm:ss'), to_time.format('HH:mm:ss'), slot.from_time, slot.to_time]),
@@ -63,7 +64,7 @@ frappe.ui.form.on('Practitioner Schedule', {
});
}
// add a new timeslot
- if(add_to_child && add_slots_to_child){
+ if (add_to_child && add_slots_to_child) {
frm.add_child('time_slots', {
from_time: cur_time.format('HH:mm:ss'),
to_time: to_time.format('HH:mm:ss'),
@@ -76,10 +77,11 @@ frappe.ui.form.on('Practitioner Schedule', {
}
return overlap;
}
- function add_slots(week_day){
+
+ function add_slots(week_day) {
let cur_time = moment(values.from_time, 'HH:mm:ss');
let end_time = moment(values.to_time, 'HH:mm:ss');
- if(check_overlap_or_add_slot(week_day, cur_time, end_time, false)){
+ if (check_overlap_or_add_slot(week_day, cur_time, end_time, false)) {
frappe.confirm(__('Schedules for {0} overlaps, do you want to proceed after skiping overlaped slots ?', [week_day]),
function() {
// if Yes
@@ -88,21 +90,22 @@ frappe.ui.form.on('Practitioner Schedule', {
function() {
// if No
frappe.show_alert({
- message:__('Slots for {0} are not added to the schedule', [week_day]),
- indicator:'red'
+ message: __('Slots for {0} are not added to the schedule', [week_day]),
+ indicator: 'red'
});
}
);
- }
- else{
+ } else {
check_overlap_or_add_slot(week_day, cur_time, end_time, true);
}
}
+
frm.refresh_field('time_slots');
- if(slot_added){
+
+ if (slot_added) {
frappe.show_alert({
- message:__('Time slots added'),
- indicator:'green'
+ message: __('Time slots added'),
+ indicator: 'green'
});
}
}
diff --git a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json
index 08a1b86969c..cff100cc704 100644
--- a/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json
+++ b/erpnext/healthcare/doctype/practitioner_schedule/practitioner_schedule.json
@@ -1,160 +1,71 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:schedule_name",
- "beta": 1,
- "creation": "2017-05-03 17:28:03.926787",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:schedule_name",
+ "beta": 1,
+ "creation": "2017-05-03 17:28:03.926787",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "disabled",
+ "schedule_details_section",
+ "schedule_name",
+ "time_slots"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "schedule_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Schedule Name",
- "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
- },
+ "fieldname": "schedule_name",
+ "fieldtype": "Data",
+ "ignore_xss_filter": 1,
+ "in_list_view": 1,
+ "label": "Schedule Name",
+ "reqd": 1,
+ "unique": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "time_slots",
- "fieldtype": "Table",
- "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 Slots",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Schedule Time Slot",
- "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
- },
+ "fieldname": "time_slots",
+ "fieldtype": "Table",
+ "label": "Time Slots",
+ "options": "Healthcare Schedule Time Slot"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "disabled",
- "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": "Disabled",
- "length": 0,
- "no_copy": 0,
- "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
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "label": "Disabled",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "schedule_details_section",
+ "fieldtype": "Section Break",
+ "label": "Schedule Details"
}
- ],
- "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-06-29 14:55:34.795995",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Practitioner Schedule",
- "name_case": "",
- "owner": "rmehta@gmail.com",
+ ],
+ "links": [],
+ "modified": "2020-01-31 12:21:45.975488",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Practitioner Schedule",
+ "owner": "rmehta@gmail.com",
"permissions": [
{
- "amend": 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": "Healthcare Administrator",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "restrict_to_domain": "Healthcare",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json b/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json
index 236c2b84023..e4c01d79c10 100644
--- a/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json
+++ b/erpnext/healthcare/doctype/procedure_prescription/procedure_prescription.json
@@ -1,338 +1,99 @@
{
- "allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-11-17 15:52:48.324157",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2017-11-17 15:52:48.324157",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "procedure",
+ "procedure_name",
+ "department",
+ "practitioner",
+ "date",
+ "comments",
+ "appointment_booked",
+ "procedure_created",
+ "invoiced"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure",
- "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": "Procedure",
- "length": 0,
- "no_copy": 0,
- "options": "Clinical Procedure Template",
- "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
- },
+ "fieldname": "procedure",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Clinical Procedure",
+ "options": "Clinical Procedure Template",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "procedure.template",
- "fieldname": "procedure_name",
- "fieldtype": "Data",
- "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": "Procedure Name",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fetch_from": "procedure.template",
+ "fieldname": "procedure_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Procedure Name"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "department",
- "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": "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": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "procedure.medical_department",
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Department",
+ "options": "Medical Department"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "practitioner",
- "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": "Referral",
- "length": 0,
- "no_copy": 0,
- "options": "Healthcare Practitioner",
- "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
- },
+ "fieldname": "practitioner",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Referring Practitioner",
+ "options": "Healthcare Practitioner"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "date",
- "fieldtype": "Date",
- "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": "Date",
- "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
- },
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Date"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "comments",
- "fieldtype": "Data",
- "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": "Comments",
- "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
- },
+ "fieldname": "comments",
+ "fieldtype": "Data",
+ "label": "Comments"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "appointment_booked",
- "fieldtype": "Check",
- "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": "Appointment Booked",
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "appointment_booked",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Appointment Booked",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "procedure_created",
- "fieldtype": "Check",
- "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": "Procedure Created",
- "length": 0,
- "no_copy": 1,
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "procedure_created",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Procedure Created",
+ "no_copy": 1,
+ "search_index": 1
+ },
{
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "read_only": 1,
+ "search_index": 1
}
- ],
- "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": "2018-11-04 03:33:35.939816",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Procedure Prescription",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-02-26 15:42:33.988081",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Procedure Prescription",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.js b/erpnext/healthcare/doctype/sample_collection/sample_collection.js
index 9934ce48451..2f5278b2d53 100644
--- a/erpnext/healthcare/doctype/sample_collection/sample_collection.js
+++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.js
@@ -3,7 +3,7 @@
frappe.ui.form.on('Sample Collection', {
refresh: function(frm) {
- if(frappe.defaults.get_default("require_sample_collection")){
+ if(frappe.defaults.get_default("create_sample_collection_for_lab_test")){
frm.add_custom_button(__("View Lab Tests"), function() {
frappe.route_options = {"sample": frm.doc.name};
frappe.set_route("List", "Lab Test");
diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.json b/erpnext/healthcare/doctype/sample_collection/sample_collection.json
index 783fc3d0440..39cead88621 100644
--- a/erpnext/healthcare/doctype/sample_collection/sample_collection.json
+++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.json
@@ -1,687 +1,199 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 1,
- "creation": "2016-04-05 15:58:18.076977",
- "custom": 0,
- "default_print_format": "",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 0,
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "beta": 1,
+ "creation": "2016-04-05 15:58:18.076977",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+ "inpatient_record",
+ "naming_series",
+ "invoiced",
+ "patient",
+ "column_break_4",
+ "patient_age",
+ "patient_sex",
+ "company",
+ "section_break_6",
+ "sample",
+ "sample_uom",
+ "sample_qty",
+ "column_break_10",
+ "collected_by",
+ "collected_time",
+ "num_print",
+ "amended_from",
+ "section_break_15",
+ "sample_details"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.inpatient_record",
- "fieldname": "inpatient_record",
- "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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
- "options": "Inpatient Record",
- "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
- },
+ "fetch_from": "patient.inpatient_record",
+ "fieldname": "inpatient_record",
+ "fieldtype": "Link",
+ "label": "Inpatient Record",
+ "options": "Inpatient Record",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "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": "Series",
- "length": 0,
- "no_copy": 1,
- "options": "HLC-SC-.YYYY.-",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "bold": 1,
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "HLC-SC-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 1,
- "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": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "no_copy": 1,
+ "read_only": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "inpatient_record.patient",
- "fieldname": "patient",
- "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": 1,
- "label": "Patient",
- "length": 0,
- "no_copy": 0,
- "options": "Patient",
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "inpatient_record.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_standard_filter": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_4",
- "fieldtype": "Column Break",
- "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,
- "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
- },
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "patient_age",
- "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": "Age",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fieldname": "patient_age",
+ "fieldtype": "Data",
+ "label": "Age"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "patient.sex",
- "fieldname": "patient_sex",
- "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": "Gender",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fetch_from": "patient.sex",
+ "fieldname": "patient_sex",
+ "fieldtype": "Data",
+ "label": "Gender"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "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": "Company",
- "length": 0,
- "no_copy": 0,
- "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
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Company",
+ "options": "Company",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_6",
- "fieldtype": "Section Break",
- "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,
- "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
- },
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample",
- "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": "Sample",
- "length": 0,
- "no_copy": 0,
- "options": "Lab Test Sample",
- "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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "sample",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Sample",
+ "options": "Lab Test Sample",
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "sample.sample_uom",
- "fieldname": "sample_uom",
- "fieldtype": "Data",
- "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": "UOM",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fetch_from": "sample.sample_uom",
+ "fieldname": "sample_uom",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "UOM"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "sample_quantity",
- "fieldtype": "Float",
- "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": "Quantity",
- "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
- },
+ "fieldname": "column_break_10",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_10",
- "fieldtype": "Column Break",
- "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,
- "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
- },
+ "fieldname": "collected_by",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Collected By",
+ "options": "User"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "collected_by",
- "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": "Collected By",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "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
- },
+ "fieldname": "collected_time",
+ "fieldtype": "Datetime",
+ "label": "Collected Time"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "collected_time",
- "fieldtype": "Datetime",
- "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": "Collected 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": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "1",
+ "fieldname": "num_print",
+ "fieldtype": "Int",
+ "label": "No. of print",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fieldname": "num_print",
- "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": "No. of print",
- "length": 0,
- "no_copy": 0,
- "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
- },
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Sample Collection",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "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": "Amended From",
- "length": 0,
- "no_copy": 1,
- "options": "Sample Collection",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "section_break_15",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_15",
- "fieldtype": "Section Break",
- "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,
- "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
- },
+ "default": "0",
+ "fieldname": "sample_qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Quantity"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sample_collection_details",
- "fieldtype": "Long Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Collection 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
+ "fieldname": "sample_details",
+ "fieldtype": "Long Text",
+ "ignore_xss_filter": 1,
+ "label": "Collection Details"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-21 14:44:39.128989",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Sample Collection",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-03-25 16:55:52.376834",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Sample Collection",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Laboratory User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Laboratory User",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Healthcare",
- "search_fields": "patient, sample",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "patient",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
-}
+ ],
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "patient, sample",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan/__init__.py b/erpnext/healthcare/doctype/therapy_plan/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
new file mode 100644
index 00000000000..526bb95b70e
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.utils import getdate
+from erpnext.healthcare.doctype.therapy_type.test_therapy_type import create_therapy_type
+from erpnext.healthcare.doctype.therapy_plan.therapy_plan import make_therapy_session
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_patient
+
+class TestTherapyPlan(unittest.TestCase):
+ def test_creation_on_encounter_submission(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ encounter = create_encounter(patient, medical_department, practitioner)
+ self.assertTrue(frappe.db.exists('Therapy Plan', encounter.therapy_plan))
+
+ def test_status(self):
+ plan = create_therapy_plan()
+ self.assertEquals(plan.status, 'Not Started')
+
+ session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab')
+ frappe.get_doc(session).submit()
+ self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'In Progress')
+
+ session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab')
+ frappe.get_doc(session).submit()
+ self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
+
+
+def create_therapy_plan():
+ patient = create_patient()
+ therapy_type = create_therapy_type()
+ plan = frappe.new_doc('Therapy Plan')
+ plan.patient = patient
+ plan.start_date = getdate()
+ plan.append('therapy_plan_details', {
+ 'therapy_type': therapy_type.name,
+ 'no_of_sessions': 2
+ })
+ plan.save()
+ return plan
+
+def create_encounter(patient, medical_department, practitioner):
+ encounter = frappe.new_doc('Patient Encounter')
+ encounter.patient = patient
+ encounter.practitioner = practitioner
+ encounter.medical_department = medical_department
+ therapy_type = create_therapy_type()
+ encounter.append('therapies', {
+ 'therapy_type': therapy_type.name,
+ 'no_of_sessions': 2
+ })
+ encounter.save()
+ encounter.submit()
+ return encounter
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.js b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.js
new file mode 100644
index 00000000000..dea0cfeb849
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.js
@@ -0,0 +1,90 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Therapy Plan', {
+ setup: function(frm) {
+ frm.get_field('therapy_plan_details').grid.editable_fields = [
+ {fieldname: 'therapy_type', columns: 6},
+ {fieldname: 'no_of_sessions', columns: 2},
+ {fieldname: 'sessions_completed', columns: 2}
+ ];
+ },
+
+ refresh: function(frm) {
+ if (!frm.doc.__islocal) {
+ frm.trigger('show_progress_for_therapies');
+ }
+
+ if (!frm.doc.__islocal && frm.doc.status != 'Completed') {
+ let therapy_types = (frm.doc.therapy_plan_details || []).map(function(d){ return d.therapy_type });
+ const fields = [{
+ fieldtype: 'Link',
+ label: __('Therapy Type'),
+ fieldname: 'therapy_type',
+ options: 'Therapy Type',
+ reqd: 1,
+ get_query: function() {
+ return {
+ filters: { 'therapy_type': ['in', therapy_types]}
+ }
+ }
+ }];
+
+ frm.add_custom_button(__('Therapy Session'), function() {
+ frappe.prompt(fields, data => {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.therapy_plan.therapy_plan.make_therapy_session',
+ args: {
+ therapy_plan: frm.doc.name,
+ patient: frm.doc.patient,
+ therapy_type: data.therapy_type
+ },
+ freeze: true,
+ callback: function(r) {
+ if (r.message) {
+ frappe.model.sync(r.message);
+ frappe.set_route('Form', r.message.doctype, r.message.name);
+ }
+ }
+ });
+ }, __('Select Therapy Type'), __('Create'));
+ }, __('Create'));
+ }
+ },
+
+ show_progress_for_therapies: function(frm) {
+ let bars = [];
+ let message = '';
+ let added_min = false;
+
+ // completed sessions
+ let title = __('{0} sessions completed', [frm.doc.total_sessions_completed]);
+ if (frm.doc.total_sessions_completed === 1) {
+ title = __('{0} session completed', [frm.doc.total_sessions_completed]);
+ }
+ title += __(' out of {0}', [frm.doc.total_sessions]);
+
+ bars.push({
+ 'title': title,
+ 'width': (frm.doc.total_sessions_completed / frm.doc.total_sessions * 100) + '%',
+ 'progress_class': 'progress-bar-success'
+ });
+ if (bars[0].width == '0%') {
+ bars[0].width = '0.5%';
+ added_min = 0.5;
+ }
+ message = title;
+ frm.dashboard.add_progress(__('Status'), bars, message);
+ },
+});
+
+frappe.ui.form.on('Therapy Plan Detail', {
+ no_of_sessions: function(frm) {
+ let total = 0;
+ $.each(frm.doc.therapy_plan_details, function(_i, e) {
+ total += e.no_of_sessions;
+ });
+ frm.set_value('total_sessions', total);
+ refresh_field('total_sessions');
+ }
+});
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json
new file mode 100644
index 00000000000..ca78b6618ec
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json
@@ -0,0 +1,151 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2020-03-29 20:56:49.758602",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "patient",
+ "patient_name",
+ "column_break_4",
+ "status",
+ "start_date",
+ "section_break_3",
+ "therapy_plan_details",
+ "title",
+ "section_break_9",
+ "total_sessions",
+ "column_break_11",
+ "total_sessions_completed"
+ ],
+ "fields": [
+ {
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
+ {
+ "fieldname": "start_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Start Date",
+ "reqd": 1
+ },
+ {
+ "fieldname": "section_break_3",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "therapy_plan_details",
+ "fieldtype": "Table",
+ "label": "Therapy Plan Details",
+ "options": "Therapy Plan Detail",
+ "reqd": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Naming Series",
+ "options": "HLC-THP-.YYYY.-"
+ },
+ {
+ "fetch_from": "patient.patient_name",
+ "fieldname": "patient_name",
+ "fieldtype": "Data",
+ "label": "Patient Name",
+ "read_only": 1
+ },
+ {
+ "default": "{patient_name}",
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Title",
+ "no_copy": 1
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "total_sessions",
+ "fieldtype": "Int",
+ "label": "Total Sessions",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_sessions_completed",
+ "fieldtype": "Int",
+ "label": "Total Sessions Completed",
+ "read_only": 1
+ },
+ {
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "options": "Not Started\nIn Progress\nCompleted\nCancelled",
+ "read_only": 1
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-21 13:13:43.956014",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Plan",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "search_fields": "patient",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
new file mode 100644
index 00000000000..201264f8294
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class TherapyPlan(Document):
+ def validate(self):
+ self.set_totals()
+ self.set_status()
+
+ def set_status(self):
+ if not self.total_sessions_completed:
+ self.status = 'Not Started'
+ else:
+ if self.total_sessions_completed < self.total_sessions:
+ self.status = 'In Progress'
+ elif self.total_sessions_completed == self.total_sessions:
+ self.status = 'Completed'
+
+ def set_totals(self):
+ total_sessions = sum([int(d.no_of_sessions) for d in self.get('therapy_plan_details')])
+ total_sessions_completed = sum([int(d.sessions_completed) for d in self.get('therapy_plan_details')])
+ self.db_set('total_sessions', total_sessions)
+ self.db_set('total_sessions_completed', total_sessions_completed)
+
+
+@frappe.whitelist()
+def make_therapy_session(therapy_plan, patient, therapy_type):
+ therapy_type = frappe.get_doc('Therapy Type', therapy_type)
+
+ therapy_session = frappe.new_doc('Therapy Session')
+ therapy_session.therapy_plan = therapy_plan
+ therapy_session.patient = patient
+ therapy_session.therapy_type = therapy_type.name
+ therapy_session.duration = therapy_type.default_duration
+ therapy_session.rate = therapy_type.rate
+ therapy_session.exercises = therapy_type.exercises
+
+ return therapy_session.as_dict()
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py
new file mode 100644
index 00000000000..df647829dbc
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'therapy_plan',
+ 'transactions': [
+ {
+ 'label': _('Therapy Sessions'),
+ 'items': ['Therapy Session']
+ }
+ ]
+ }
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan_list.js b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_list.js
new file mode 100644
index 00000000000..63967aff33b
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_list.js
@@ -0,0 +1,11 @@
+frappe.listview_settings['Therapy Plan'] = {
+ get_indicator: function(doc) {
+ var colors = {
+ 'Completed': 'green',
+ 'In Progress': 'orange',
+ 'Not Started': 'red',
+ 'Cancelled': 'grey'
+ };
+ return [__(doc.status), colors[doc.status], 'status,=,' + doc.status];
+ }
+};
diff --git a/erpnext/healthcare/doctype/therapy_plan_detail/__init__.py b/erpnext/healthcare/doctype/therapy_plan_detail/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.json b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.json
new file mode 100644
index 00000000000..9eb20e2ef3b
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.json
@@ -0,0 +1,48 @@
+{
+ "actions": [],
+ "creation": "2020-03-29 20:52:57.068731",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "therapy_type",
+ "no_of_sessions",
+ "sessions_completed"
+ ],
+ "fields": [
+ {
+ "fieldname": "therapy_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Therapy Type",
+ "options": "Therapy Type",
+ "reqd": 1
+ },
+ {
+ "fieldname": "no_of_sessions",
+ "fieldtype": "Int",
+ "in_list_view": 1,
+ "label": "No of Sessions"
+ },
+ {
+ "default": "0",
+ "depends_on": "eval:doc.parenttype=='Therapy Plan';",
+ "fieldname": "sessions_completed",
+ "fieldtype": "Int",
+ "label": "Sessions Completed",
+ "read_only": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-30 22:02:01.740109",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Plan Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py
new file mode 100644
index 00000000000..44211f32e3a
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class TherapyPlanDetail(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/therapy_session/__init__.py b/erpnext/healthcare/doctype/therapy_session/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py b/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py
new file mode 100644
index 00000000000..75bb8df1963
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestTherapySession(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.js b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
new file mode 100644
index 00000000000..bb675752bbc
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
@@ -0,0 +1,60 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Therapy Session', {
+ setup: function(frm) {
+ frm.get_field('exercises').grid.editable_fields = [
+ {fieldname: 'exercise_type', columns: 7},
+ {fieldname: 'counts_target', columns: 1},
+ {fieldname: 'counts_completed', columns: 1},
+ {fieldname: 'assistance_level', columns: 1}
+ ];
+ },
+
+ refresh: function(frm) {
+ if (!frm.doc.__islocal) {
+ let target = 0;
+ let completed = 0;
+ $.each(frm.doc.exercises, function(_i, e) {
+ target += e.counts_target;
+ completed += e.counts_completed;
+ });
+ frm.dashboard.add_indicator(__('Counts Targetted: {0}', [target]), 'blue');
+ frm.dashboard.add_indicator(__('Counts Completed: {0}', [completed]), (completed < target) ? 'orange' : 'green');
+ }
+
+ if (frm.doc.docstatus === 1) {
+ frm.add_custom_button(__('Patient Assessment'),function() {
+ frappe.model.open_mapped_doc({
+ method: 'erpnext.healthcare.doctype.patient_assessment.patient_assessment.create_patient_assessment',
+ frm: frm,
+ })
+ }, 'Create');
+ }
+ },
+
+ therapy_type: function(frm) {
+ if (frm.doc.therapy_type) {
+ frappe.call({
+ 'method': 'frappe.client.get',
+ args: {
+ doctype: 'Therapy Type',
+ name: frm.doc.therapy_type
+ },
+ callback: function(data) {
+ frm.set_value('duration', data.message.default_duration);
+ frm.set_value('rate', data.message.rate);
+ frm.doc.exercises = [];
+ $.each(data.message.exercises, function(_i, e) {
+ let exercise = frm.add_child('exercises');
+ exercise.exercise_type = e.exercise_type;
+ exercise.difficulty_level = e.difficulty_level;
+ exercise.counts_target = e.counts_target;
+ exercise.assistance_level = e.assistance_level;
+ });
+ refresh_field('exercises');
+ }
+ });
+ }
+ }
+});
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.json b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
new file mode 100644
index 00000000000..5ff719672fb
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
@@ -0,0 +1,218 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2020-03-11 08:57:40.669857",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "appointment",
+ "patient",
+ "patient_age",
+ "gender",
+ "column_break_5",
+ "therapy_plan",
+ "therapy_type",
+ "practitioner",
+ "department",
+ "details_section",
+ "duration",
+ "rate",
+ "location",
+ "company",
+ "column_break_12",
+ "service_unit",
+ "start_date",
+ "start_time",
+ "invoiced",
+ "exercises_section",
+ "exercises",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-THP-.YYYY.-"
+ },
+ {
+ "fieldname": "appointment",
+ "fieldtype": "Link",
+ "label": "Appointment",
+ "options": "Patient Appointment"
+ },
+ {
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
+ {
+ "fetch_from": "patient.sex",
+ "fieldname": "gender",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "practitioner",
+ "fieldtype": "Link",
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner"
+ },
+ {
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Medical Department",
+ "options": "Medical Department"
+ },
+ {
+ "fieldname": "details_section",
+ "fieldtype": "Section Break",
+ "label": "Details"
+ },
+ {
+ "fetch_from": "therapy_template.default_duration",
+ "fieldname": "duration",
+ "fieldtype": "Int",
+ "label": "Duration"
+ },
+ {
+ "fieldname": "location",
+ "fieldtype": "Select",
+ "label": "Location",
+ "options": "\nCenter\nHome\nTele"
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "therapy_template.rate",
+ "fieldname": "rate",
+ "fieldtype": "Currency",
+ "label": "Rate"
+ },
+ {
+ "fieldname": "exercises_section",
+ "fieldtype": "Section Break",
+ "label": "Exercises"
+ },
+ {
+ "fieldname": "exercises",
+ "fieldtype": "Table",
+ "label": "Exercises",
+ "options": "Exercise"
+ },
+ {
+ "depends_on": "eval: doc.therapy_plan",
+ "fieldname": "therapy_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Therapy Type",
+ "options": "Therapy Type",
+ "reqd": 1
+ },
+ {
+ "fieldname": "therapy_plan",
+ "fieldtype": "Link",
+ "label": "Therapy Plan",
+ "options": "Therapy Plan",
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Therapy Session",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "service_unit",
+ "fieldtype": "Link",
+ "label": "Healthcare Service Unit",
+ "options": "Healthcare Service Unit"
+ },
+ {
+ "fieldname": "start_date",
+ "fieldtype": "Date",
+ "label": "Start Date"
+ },
+ {
+ "fieldname": "start_time",
+ "fieldtype": "Time",
+ "label": "Start Time"
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company"
+ },
+ {
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "read_only": 1
+ },
+ {
+ "fieldname": "patient_age",
+ "fieldtype": "Data",
+ "label": "Patient Age",
+ "read_only": 1
+ }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-04-21 13:16:46.378798",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Session",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "search_fields": "patient,appointment,therapy_plan,therapy_type",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.py b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
new file mode 100644
index 00000000000..45d2ee60e61
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe.model.mapper import get_mapped_doc
+
+class TherapySession(Document):
+ def on_submit(self):
+ self.update_sessions_count_in_therapy_plan()
+
+ def on_cancel(self):
+ self.update_sessions_count_in_therapy_plan(on_cancel=True)
+
+ def update_sessions_count_in_therapy_plan(self, on_cancel=False):
+ therapy_plan = frappe.get_doc('Therapy Plan', self.therapy_plan)
+ for entry in therapy_plan.therapy_plan_details:
+ if entry.therapy_type == self.therapy_type:
+ if on_cancel:
+ entry.sessions_completed -= 1
+ else:
+ entry.sessions_completed += 1
+ therapy_plan.save()
+
+
+@frappe.whitelist()
+def create_therapy_session(source_name, target_doc=None):
+ def set_missing_values(source, target):
+ therapy_type = frappe.get_doc('Therapy Type', source.therapy_type)
+ target.exercises = therapy_type.exercises
+
+ doc = get_mapped_doc('Patient Appointment', source_name, {
+ 'Patient Appointment': {
+ 'doctype': 'Therapy Session',
+ 'field_map': [
+ ['appointment', 'name'],
+ ['patient', 'patient'],
+ ['patient_age', 'patient_age'],
+ ['gender', 'patient_sex'],
+ ['therapy_type', 'therapy_type'],
+ ['therapy_plan', 'therapy_plan'],
+ ['practitioner', 'practitioner'],
+ ['department', 'department'],
+ ['start_date', 'appointment_date'],
+ ['start_time', 'appointment_time'],
+ ['service_unit', 'service_unit'],
+ ['company', 'company'],
+ ['invoiced', 'invoiced']
+ ]
+ }
+ }, target_doc, set_missing_values)
+
+ return doc
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py b/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py
new file mode 100644
index 00000000000..9de7e293238
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'therapy_session',
+ 'transactions': [
+ {
+ 'label': _('Assessments'),
+ 'items': ['Patient Assessment']
+ }
+ ]
+ }
diff --git a/erpnext/healthcare/doctype/therapy_type/__init__.py b/erpnext/healthcare/doctype/therapy_type/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py
new file mode 100644
index 00000000000..03a1be8a4e7
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestTherapyType(unittest.TestCase):
+ def test_therapy_type_item(self):
+ therapy_type = create_therapy_type()
+ self.assertTrue(frappe.db.exists('Item', therapy_type.item))
+
+ therapy_type.disabled = 1
+ therapy_type.save()
+ self.assertEquals(frappe.db.get_value('Item', therapy_type.item, 'disabled'), 1)
+
+def create_therapy_type():
+ exercise = create_exercise_type()
+ therapy_type = frappe.db.exists('Therapy Type', 'Basic Rehab')
+ if not therapy_type:
+ therapy_type = frappe.new_doc('Therapy Type')
+ therapy_type.therapy_type = 'Basic Rehab'
+ therapy_type.default_duration = 30
+ therapy_type.is_billable = 1
+ therapy_type.rate = 5000
+ therapy_type.item_code = 'Basic Rehab'
+ therapy_type.item_name = 'Basic Rehab'
+ therapy_type.item_group = 'Services'
+ therapy_type.append('exercises', {
+ 'exercise_type': exercise.name,
+ 'counts_target': 10,
+ 'assistance_level': 'Passive'
+ })
+ therapy_type.save()
+ else:
+ therapy_type = frappe.get_doc('Therapy Type', 'Basic Rehab')
+ return therapy_type
+
+def create_exercise_type():
+ exercise_type = frappe.db.exists('Exercise Type', 'Sit to Stand')
+ if not exercise_type:
+ exercise_type = frappe.new_doc('Exercise Type')
+ exercise_type.exercise_name = 'Sit to Stand'
+ exercise_type.append('steps_table', {
+ 'title': 'Step 1',
+ 'description': 'Squat and Rise'
+ })
+ exercise_type.save()
+ return exercise_type
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.js b/erpnext/healthcare/doctype/therapy_type/therapy_type.js
new file mode 100644
index 00000000000..7a61b0def03
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.js
@@ -0,0 +1,93 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Therapy Type', {
+ setup: function(frm) {
+ frm.get_field('exercises').grid.editable_fields = [
+ {fieldname: 'exercise_type', columns: 7},
+ {fieldname: 'difficulty_level', columns: 1},
+ {fieldname: 'counts_target', columns: 1},
+ {fieldname: 'assistance_level', columns: 1}
+ ];
+ },
+
+ refresh: function(frm) {
+ if (!frm.doc.__islocal) {
+ cur_frm.add_custom_button(__('Change Item Code'), function() {
+ change_template_code(frm.doc);
+ });
+ }
+ },
+
+ therapy_type: function(frm) {
+ if (!frm.doc.item_code)
+ frm.set_value('item_code', frm.doc.therapy_type);
+ if (!frm.doc.description)
+ frm.set_value('description', frm.doc.therapy_type);
+ mark_change_in_item(frm);
+ },
+
+ rate: function(frm) {
+ mark_change_in_item(frm);
+ },
+
+ is_billable: function (frm) {
+ mark_change_in_item(frm);
+ },
+
+ item_group: function(frm) {
+ mark_change_in_item(frm);
+ },
+
+ description: function(frm) {
+ mark_change_in_item(frm);
+ },
+
+ medical_department: function(frm) {
+ mark_change_in_item(frm);
+ }
+});
+
+let mark_change_in_item = function(frm) {
+ if (!frm.doc.__islocal) {
+ frm.doc.change_in_item = 1;
+ }
+};
+
+let change_template_code = function(doc) {
+ let d = new frappe.ui.Dialog({
+ title:__('Change Item Code'),
+ fields:[
+ {
+ 'fieldtype': 'Data',
+ 'label': 'Item Code',
+ 'fieldname': 'item_code',
+ reqd: 1
+ }
+ ],
+ primary_action: function() {
+ let values = d.get_values();
+
+ if (values) {
+ frappe.call({
+ 'method': 'erpnext.healthcare.doctype.therapy_type.therapy_type.change_item_code_from_therapy',
+ 'args': {item_code: values.item_code, doc: doc},
+ callback: function () {
+ cur_frm.reload_doc();
+ frappe.show_alert({
+ message: 'Item Code renamed successfully',
+ indicator: 'green'
+ });
+ }
+ });
+ }
+ d.hide();
+ },
+ primary_action_label: __('Change Item Code')
+ });
+ d.show();
+
+ d.set_values({
+ 'item_code': doc.item_code
+ });
+};
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.json b/erpnext/healthcare/doctype/therapy_type/therapy_type.json
new file mode 100644
index 00000000000..0b3c3caeaab
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.json
@@ -0,0 +1,211 @@
+{
+ "actions": [],
+ "autoname": "field:therapy_type",
+ "creation": "2020-03-29 20:48:31.715063",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "disabled",
+ "section_break_2",
+ "therapy_type",
+ "default_duration",
+ "medical_department",
+ "column_break_3",
+ "is_billable",
+ "rate",
+ "healthcare_service_unit",
+ "item_details_section",
+ "item",
+ "item_code",
+ "item_name",
+ "item_group",
+ "column_break_12",
+ "description",
+ "section_break_18",
+ "therapy_for",
+ "add_exercises",
+ "section_break_6",
+ "exercises",
+ "change_in_item"
+ ],
+ "fields": [
+ {
+ "fieldname": "therapy_type",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Therapy Type",
+ "reqd": 1,
+ "unique": 1
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_billable",
+ "fieldtype": "Check",
+ "label": "Is Billable"
+ },
+ {
+ "depends_on": "eval:doc.is_billable;",
+ "fieldname": "rate",
+ "fieldtype": "Currency",
+ "label": "Rate",
+ "mandatory_depends_on": "eval:doc.is_billable;"
+ },
+ {
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break",
+ "label": "Exercises"
+ },
+ {
+ "fieldname": "exercises",
+ "fieldtype": "Table",
+ "label": "Exercises",
+ "options": "Exercise"
+ },
+ {
+ "fieldname": "default_duration",
+ "fieldtype": "Int",
+ "label": "Default Duration (In Minutes)"
+ },
+ {
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "label": "Disabled"
+ },
+ {
+ "fieldname": "item_details_section",
+ "fieldtype": "Section Break",
+ "label": "Item Details"
+ },
+ {
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "label": "Item",
+ "options": "Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "item_code",
+ "fieldtype": "Data",
+ "label": "Item Code",
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "label": "Item Group",
+ "options": "Item Group",
+ "reqd": 1
+ },
+ {
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description"
+ },
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "medical_department",
+ "fieldtype": "Link",
+ "label": "Medical Department",
+ "options": "Medical Department"
+ },
+ {
+ "default": "0",
+ "fieldname": "change_in_item",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Change In Item",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
+ {
+ "fieldname": "therapy_for",
+ "fieldtype": "Table MultiSelect",
+ "label": "Therapy For",
+ "options": "Body Part Link"
+ },
+ {
+ "fieldname": "healthcare_service_unit",
+ "fieldtype": "Link",
+ "label": "Healthcare Service Unit",
+ "options": "Healthcare Service Unit"
+ },
+ {
+ "depends_on": "eval: doc.therapy_for",
+ "fieldname": "add_exercises",
+ "fieldtype": "Button",
+ "label": "Add Exercises",
+ "options": "add_exercises"
+ },
+ {
+ "fieldname": "section_break_18",
+ "fieldtype": "Section Break"
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-21 13:09:04.006289",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Type",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.py b/erpnext/healthcare/doctype/therapy_type/therapy_type.py
new file mode 100644
index 00000000000..ea3d84e7c5d
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.py
@@ -0,0 +1,122 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import json
+from frappe import _
+from frappe.utils import cint
+from frappe.model.document import Document
+from frappe.model.rename_doc import rename_doc
+
+class TherapyType(Document):
+ def validate(self):
+ self.enable_disable_item()
+
+ def after_insert(self):
+ create_item_from_therapy(self)
+
+ def on_update(self):
+ if self.change_in_item:
+ self.update_item_and_item_price()
+
+ def enable_disable_item(self):
+ if self.is_billable:
+ if self.disabled:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
+ else:
+ frappe.db.set_value('Item', self.item, 'disabled', 0)
+
+ def update_item_and_item_price(self):
+ if self.is_billable and self.item:
+ item_doc = frappe.get_doc('Item', {'item_code': self.item})
+ item_doc.item_name = self.item_name
+ item_doc.item_group = self.item_group
+ item_doc.description = self.description
+ item_doc.disabled = 0
+ item_doc.ignore_mandatory = True
+ item_doc.save(ignore_permissions=True)
+
+ if self.rate:
+ item_price = frappe.get_doc('Item Price', {'item_code': self.item})
+ item_price.item_name = self.item_name
+ item_price.price_list_name = self.rate
+ item_price.ignore_mandatory = True
+ item_price.save()
+
+ elif not self.is_billable and self.item:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
+
+ self.db_set('change_in_item', 0)
+
+ def add_exercises(self):
+ exercises = self.get_exercises_for_body_parts()
+ last_idx = max([cint(d.idx) for d in self.get('exercises')] or [0,])
+ for i, d in enumerate(exercises):
+ ch = self.append('exercises', {})
+ ch.exercise_type = d.parent
+ ch.idx = last_idx + i + 1
+
+ def get_exercises_for_body_parts(self):
+ body_parts = [entry.body_part for entry in self.therapy_for]
+
+ exercises = frappe.db.sql(
+ """
+ SELECT DISTINCT
+ b.parent, e.name, e.difficulty_level
+ FROM
+ `tabExercise Type` e, `tabBody Part Link` b
+ WHERE
+ b.body_part IN %(body_parts)s AND b.parent=e.name
+ """, {'body_parts': body_parts}, as_dict=1)
+
+ return exercises
+
+
+def create_item_from_therapy(doc):
+ disabled = doc.disabled
+ if doc.is_billable and not doc.disabled:
+ disabled = 0
+
+ uom = frappe.db.exists('UOM', 'Unit') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
+
+ item = frappe.get_doc({
+ 'doctype': 'Item',
+ 'item_code': doc.item_code,
+ 'item_name': doc.item_name,
+ 'item_group': doc.item_group,
+ 'description': doc.description,
+ 'is_sales_item': 1,
+ 'is_service_item': 1,
+ 'is_purchase_item': 0,
+ 'is_stock_item': 0,
+ 'show_in_website': 0,
+ 'is_pro_applicable': 0,
+ 'disabled': disabled,
+ 'stock_uom': uom
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
+
+ make_item_price(item.name, doc.rate)
+ doc.db_set('item', item.name)
+
+
+def make_item_price(item, item_price):
+ price_list_name = frappe.db.get_value('Price List', {'selling': 1})
+ frappe.get_doc({
+ 'doctype': 'Item Price',
+ 'price_list': price_list_name,
+ 'item_code': item,
+ 'price_list_rate': item_price
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
+
+@frappe.whitelist()
+def change_item_code_from_therapy(item_code, doc):
+ doc = frappe._dict(json.loads(doc))
+
+ if frappe.db.exists('Item', {'item_code': item_code}):
+ frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
+ else:
+ rename_doc('Item', doc.item, item_code, ignore_permissions=True)
+ frappe.db.set_value('Therapy Type', doc.name, 'item_code', item_code)
+ return
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.js b/erpnext/healthcare/doctype/vital_signs/vital_signs.js
index a5f9d612952..78509e0323c 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.js
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.js
@@ -1,49 +1,52 @@
// Copyright (c) 2016, ESS LLP and contributors
// For license information, please see license.txt
-frappe.ui.form.on("Vital Signs", "height", function(frm) {
- if(frm.doc.height && frm.doc.weight){
- calculate_bmi(frm);
+frappe.ui.form.on('Vital Signs', {
+ height: function(frm) {
+ if (frm.doc.height && frm.doc.weight) {
+ calculate_bmi(frm);
+ }
+ },
+
+ weight: function(frm) {
+ if (frm.doc.height && frm.doc.weight) {
+ calculate_bmi(frm);
+ }
+ },
+
+ bp_systolic: function(frm) {
+ if (frm.doc.bp_systolic && frm.doc.bp_diastolic) {
+ set_bp(frm);
+ }
+ },
+
+ bp_diastolic: function(frm) {
+ if (frm.doc.bp_systolic && frm.doc.bp_diastolic) {
+ set_bp(frm);
+ }
}
});
-frappe.ui.form.on("Vital Signs", "weight", function(frm) {
- if(frm.doc.height && frm.doc.weight){
- calculate_bmi(frm);
- }
-});
-
-var calculate_bmi = function(frm){
+let calculate_bmi = function(frm){
// Reference https://en.wikipedia.org/wiki/Body_mass_index
// bmi = weight (in Kg) / height * height (in Meter)
- var bmi = (frm.doc.weight/(frm.doc.height*frm.doc.height)).toFixed(2);
- var bmi_note = null;
- if(bmi<18.5){
- bmi_note = "Underweight";
- }else if(bmi>=18.5 && bmi<25){
- bmi_note = "Normal";
- }else if(bmi>=25 && bmi<30){
- bmi_note = "Overweight";
- }else if(bmi>=30){
- bmi_note = "Obese";
+ let bmi = (frm.doc.weight / (frm.doc.height * frm.doc.height)).toFixed(2);
+ let bmi_note = null;
+
+ if (bmi<18.5) {
+ bmi_note = 'Underweight';
+ } else if (bmi>=18.5 && bmi<25) {
+ bmi_note = 'Normal';
+ } else if (bmi>=25 && bmi<30) {
+ bmi_note = 'Overweight';
+ } else if (bmi>=30) {
+ bmi_note = 'Obese';
}
- frappe.model.set_value(frm.doctype,frm.docname, "bmi", bmi);
- frappe.model.set_value(frm.doctype,frm.docname, "nutrition_note", bmi_note);
+ frappe.model.set_value(frm.doctype,frm.docname, 'bmi', bmi);
+ frappe.model.set_value(frm.doctype,frm.docname, 'nutrition_note', bmi_note);
};
-frappe.ui.form.on("Vital Signs", "bp_systolic", function(frm) {
- if(frm.doc.bp_systolic && frm.doc.bp_diastolic){
- set_bp(frm);
- }
-});
-
-frappe.ui.form.on("Vital Signs", "bp_diastolic", function(frm) {
- if(frm.doc.bp_systolic && frm.doc.bp_diastolic){
- set_bp(frm);
- }
-});
-
-var set_bp = function(frm){
- var bp = frm.doc.bp_systolic+"/"+frm.doc.bp_diastolic+" mmHg";
- frappe.model.set_value(frm.doctype,frm.docname, "bp", bp);
+let set_bp = function(frm){
+ let bp = frm.doc.bp_systolic+ '/' + frm.doc.bp_diastolic + ' mmHg';
+ frappe.model.set_value(frm.doctype,frm.docname, 'bp', bp);
};
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.json b/erpnext/healthcare/doctype/vital_signs/vital_signs.json
index 1503f835a47..75726dbe070 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.json
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.json
@@ -1,991 +1,273 @@
{
+ "actions": [],
"allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
- "allow_rename": 0,
"beta": 1,
"creation": "2017-02-02 11:00:24.853005",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
+ "field_order": [
+ "inpatient_record",
+ "patient",
+ "patient_name",
+ "appointment",
+ "encounter",
+ "column_break_2",
+ "signs_date",
+ "signs_time",
+ "sb_vs",
+ "temperature",
+ "pulse",
+ "respiratory_rate",
+ "tongue",
+ "abdomen",
+ "column_break_8",
+ "reflexes",
+ "bp_systolic",
+ "bp_diastolic",
+ "bp",
+ "vital_signs_note",
+ "sb_nutrition_values",
+ "height",
+ "weight",
+ "bmi",
+ "column_break_14",
+ "nutrition_note",
+ "company",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.inpatient_record",
"fieldname": "inpatient_record",
"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": "Inpatient Record",
- "length": 0,
- "no_copy": 0,
"options": "Inpatient Record",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "inpatient_record.patient",
"fieldname": "patient",
"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": "Patient",
- "length": 0,
- "no_copy": 0,
"options": "Patient",
- "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "patient.patient_name",
"fieldname": "patient_name",
"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": "Patient Name",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "appointment",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Appointment",
- "length": 0,
- "no_copy": 1,
"options": "Patient Appointment",
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "encounter",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
"in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Patient Encounter",
- "length": 0,
"no_copy": 1,
"options": "Patient Encounter",
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "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,
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "Today",
"fieldname": "signs_date",
"fieldtype": "Date",
- "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": "Date",
- "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
"fieldname": "signs_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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "sb_vs",
"fieldtype": "Section Break",
- "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": "Vital Signs",
- "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
+ "label": "Vital Signs"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Presence of a fever (temp > 38.5 \u00b0C/101.3 \u00b0F or sustained temp > 38 \u00b0C/100.4 \u00b0F)",
"fieldname": "temperature",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Body Temperature",
- "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
+ "label": "Body Temperature"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Adults' pulse rate is anywhere between 50 and 80 beats per minute.",
"fieldname": "pulse",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Heart Rate / Pulse",
- "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
+ "label": "Heart Rate / Pulse"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Normal reference range for an adult is 16\u201320 breaths/minute (RCP 2012)",
"fieldname": "respiratory_rate",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Respiratory rate",
- "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
+ "label": "Respiratory rate"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "tongue",
"fieldtype": "Select",
- "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": "Tongue",
- "length": 0,
- "no_copy": 0,
- "options": "\nCoated\nVery Coated\nNormal\nFurry\nCuts",
- "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
+ "options": "\nCoated\nVery Coated\nNormal\nFurry\nCuts"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "abdomen",
"fieldtype": "Select",
- "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": "Abdomen",
- "length": 0,
- "no_copy": 0,
- "options": "\nNormal\nBloated\nFull\nFluid\nConstipated",
- "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
+ "options": "\nNormal\nBloated\nFull\nFluid\nConstipated"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_8",
- "fieldtype": "Column Break",
- "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,
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "reflexes",
"fieldtype": "Select",
- "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": "Reflexes",
- "length": 0,
- "no_copy": 0,
- "options": "\nNormal\nHyper\nVery Hyper\nOne Sided",
- "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
+ "options": "\nNormal\nHyper\nVery Hyper\nOne Sided"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "bp_systolic",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Blood Pressure (systolic)",
- "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
+ "label": "Blood Pressure (systolic)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
"fieldname": "bp_diastolic",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Blood Pressure (diastolic)",
- "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
+ "label": "Blood Pressure (diastolic)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Normal resting blood pressure in an adult is approximately 120 mmHg systolic, and 80 mmHg diastolic, abbreviated \"120/80 mmHg\"",
"fieldname": "bp",
"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": "Blood Pressure",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "vital_signs_note",
"fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Notes",
- "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
+ "label": "Notes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "sb_nutrition_values",
"fieldtype": "Section Break",
- "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": "Nutrition Values",
- "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
+ "label": "Nutrition Values"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "height",
"fieldtype": "Float",
- "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": "Height (In Meter)",
- "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
+ "label": "Height (In Meter)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "weight",
"fieldtype": "Float",
- "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": "Weight (In Kilogram)",
- "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
+ "label": "Weight (In Kilogram)"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0.00",
"fieldname": "bmi",
"fieldtype": "Float",
- "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": "BMI",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_14",
- "fieldtype": "Column Break",
- "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,
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "nutrition_note",
"fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
"ignore_xss_filter": 1,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Notes",
- "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
+ "label": "Notes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"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": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "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
+ "options": "Company"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "amended_from",
"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": "Amended From",
- "length": 0,
"no_copy": 1,
"options": "Vital Signs",
- "permlevel": 0,
"print_hide": 1,
- "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
+ "read_only": 1
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
"is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-11-23 14:14:05.933292",
+ "links": [],
+ "modified": "2020-03-04 17:19:29.549889",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Vital Signs",
- "name_case": "",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"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": 1,
"write": 1
},
{
- "amend": 0,
"cancel": 1,
"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": 1,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"restrict_to_domain": "Healthcare",
"search_fields": "patient, signs_date",
"show_name_in_global_search": 1,
@@ -993,6 +275,5 @@
"sort_order": "DESC",
"title_field": "patient",
"track_changes": 1,
- "track_seen": 1,
- "track_views": 0
+ "track_seen": 1
}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.py b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
index bf4dace22b3..959e8504c47 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.py
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.utils import cstr
+from frappe import _
class VitalSigns(Document):
def on_submit(self):
@@ -16,34 +17,35 @@ class VitalSigns(Document):
def insert_vital_signs_to_medical_record(doc):
subject = set_subject_field(doc)
- 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.signs_date
- medical_record.reference_doctype = "Vital Signs"
+ medical_record.reference_doctype = 'Vital Signs'
medical_record.reference_name = doc.name
medical_record.reference_owner = doc.owner
+ medical_record.flags.ignore_mandatory = True
medical_record.save(ignore_permissions=True)
def delete_vital_signs_from_medical_record(doc):
- medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s",(doc.name))
- if medical_record_id and medical_record_id[0][0]:
- frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
+ medical_record = frappe.db.get_value('Patient Medical Record', {'reference_name': doc.name})
+ if medical_record:
+ frappe.delete_doc('Patient Medical Record', medical_record)
def set_subject_field(doc):
- subject = ""
+ subject = ''
if(doc.temperature):
- subject += "Temperature: \n"+ cstr(doc.temperature)+". "
+ subject += _('Temperature: ') + '\n'+ cstr(doc.temperature) + '. '
if(doc.pulse):
- subject += "Pulse: \n"+ cstr(doc.pulse)+". "
+ subject += _('Pulse: ') + '\n' + cstr(doc.pulse) + '. '
if(doc.respiratory_rate):
- subject += "Respiratory Rate: \n"+ cstr(doc.respiratory_rate)+". "
+ subject += _('Respiratory Rate: ') + '\n' + cstr(doc.respiratory_rate) + '. '
if(doc.bp):
- subject += "BP: \n"+ cstr(doc.bp)+". "
+ subject += _('BP: ') + '\n' + cstr(doc.bp) + '. '
if(doc.bmi):
- subject += "BMI: \n"+ cstr(doc.bmi)+". "
+ subject += _('BMI: ') + '\n' + cstr(doc.bmi) + '. '
if(doc.nutrition_note):
- subject += "Note: \n"+ cstr(doc.nutrition_note)+". "
+ subject += _('Note: ') + '\n' + cstr(doc.nutrition_note) + '. '
return subject
diff --git a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.js b/erpnext/healthcare/page/appointment_analytic/appointment_analytic.js
deleted file mode 100644
index 9f2e552efcb..00000000000
--- a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.js
+++ /dev/null
@@ -1,205 +0,0 @@
-frappe.pages['appointment-analytic'].on_page_load = function(wrapper) {
- frappe.ui.make_app_page({
- parent: wrapper,
- title: 'Appointment Analytics',
- single_column: true
- });
- new erpnext.AppointmentAnalytics(wrapper);
- frappe.breadcrumbs.add("Medical");
-};
-
-erpnext.AppointmentAnalytics = frappe.views.TreeGridReport.extend({
- init: function(wrapper) {
- this._super({
- title: __("Appointment Analytics"),
- parent: $(wrapper).find('.layout-main'),
- page: wrapper.page,
- doctypes: ["Patient Appointment", "Healthcare Practitioner", "Medical Department", "Appointment Type", "Patient"],
- tree_grid: { show: true }
- });
-
- this.tree_grids = {
- "Medical Department": {
- label: __("Department"),
- show: true,
- item_key: "practitioner",
- parent_field: "department",
- formatter: function(item) {
- return item.name;
- }
- },
- "Healthcare Practitioner": {
- label: __("Healthcare Practitioner"),
- show: true,
- item_key: "practitioner",
- formatter: function(item) {
- return item.name;
- }
- },
- };
- },
- setup_columns: function() {
- this.tree_grid = this.tree_grids[this.tree_type];
-
- var std_columns = [
- {id: "name", name: this.tree_grid.label, field: "name", width: 300},
- {id: "total", name: "Total", field: "total", plot: false,
- formatter: this.currency_formatter}
- ];
-
- this.make_date_range_columns();
- this.columns = std_columns.concat(this.columns);
- },
- filters: [
- {fieldtype:"Select", label: __("Tree Type"), fieldname: "tree_type",
- options:["Healthcare Practitioner", "Medical Department"], filter: function(val, item, opts, me) {
- return me.apply_zero_filter(val, item, opts, me);}},
- {fieldtype:"Select", label: __("Status"), fieldname: "status",
- options:[
- {label: __("Select Status"), value: "Select Status..."},
- {label: __("Open"), value: "Open"},
- {label: __("Closed"), value: "Closed"},
- {label: __("Pending"), value: "Pending"},
- {label: __("Scheduled"), value: "Scheduled"},
- {label: __("Cancelled"), value: "Cancelled"}]},
- {fieldtype:"Select", label: __("Type"), link:"Appointment Type", fieldname: "type",
- default_value: __("Select Type...")},
- {fieldtype:"Select", label: __("Healthcare Practitioner"), link:"Healthcare Practitioner", fieldname: "practitioner",
- default_value: __("Select Healthcare Practitioner..."), filter: function(val, item, opts) {
- return val == opts.default_value || item.name == val || item._show;
- }, link_formatter: {filter_input: "practitioner"}},
- {fieldtype:"Select", label: __("Department"), link:"Medical Department", fieldname: "department",
- default_value: __("Select Department..."), filter: function(val, item, opts) {
- return val == opts.default_value || item.department == val || item._show;
- }, link_formatter: {filter_input: "department"}},
- {fieldtype:"Date", label: __("From Date"), fieldname: "from_date"},
- {fieldtype:"Date", label: __("To Date"), fieldname: "to_date"},
- {fieldtype:"Select", label: __("Range"), fieldname: "range",
- options:[{label: __("Daily"), value: "Daily"}, {label: __("Weekly"), value: "Weekly"},
- {label: __("Monthly"), value: "Monthly"}, {label: __("Quarterly"), value: "Quarterly"},
- {label: __("Yearly"), value: "Yearly"}]}
- ],
- setup_filters: function() {
- this._super();
- this.trigger_refresh_on_change(["tree_type", "practitioner", "department", "status", "type"]);
-
- // this.show_zero_check()
- },
- init_filter_values: function() {
- this._super();
- this.filter_inputs.range.val('Quarterly');
- },
- prepare_data: function() {
- var me = this;
- if (!this.tl) {
- this.tl = frappe.report_dump.data["Patient Appointment"];
- }
- if(!this.data || me.item_type != me.tree_type) {
- var items = null;
- if(me.tree_type=='Healthcare Practitioner') {
- items = frappe.report_dump.data["Healthcare Practitioner"];
- } if(me.tree_type=='Medical Department') {
- items = this.prepare_tree("Healthcare Practitioner", "Medical Department");
- }
- me.item_type = me.tree_type;
- me.parent_map = {};
- me.item_by_name = {};
- me.data = [];
-
- $.each(items, function(i, v) {
- var d = copy_dict(v);
-
- me.data.push(d);
- me.item_by_name[d.name] = d;
- if(d[me.tree_grid.parent_field]) {
- me.parent_map[d.name] = d[me.tree_grid.parent_field];
- }
- me.reset_item_values(d);
- });
-
- this.set_indent();
-
-
- } else {
- // otherwise, only reset values
- $.each(this.data, function(i, d) {
- me.reset_item_values(d);
- });
- }
- this.prepare_balances();
- if(me.tree_grid.show) {
- this.set_totals(false);
- this.update_groups();
- } else {
- this.set_totals(true);
- }
-
-
- },
- prepare_balances: function() {
- var me = this;
- var from_date = frappe.datetime.str_to_obj(this.from_date);
- var status = this.status;
- var type = this.type;
- var to_date = frappe.datetime.str_to_obj(this.to_date);
- $.each(this.tl, function(i, tl) {
- if (me.is_default('company') ? true : tl.company === me.company) {
-
- var date = frappe.datetime.str_to_obj(tl.appointment_date);
- if (date >= from_date && date <= to_date) {
- var item = me.item_by_name[tl[me.tree_grid.item_key]] ||
- me.item_by_name['Not Set'];
-
- var d = tl.appointment_date.split(" ")[0];
- if(status == "Select Status..." && type=="Select Type...")
- {
- item[me.column_map[d].field] += 1;
-
- }else if (status !== "Select Status..." && type == "Select Type..."){
- if(status === tl.status){item[me.column_map[d].field] += 1;}
- }else if (status == "Select Status..." && type !== "Select Type..."){
- if(type === tl.appointment_type){item[me.column_map[d].field] += 1;}
- }else {
- if(type === tl.appointment_type && status === tl.status){item[me.column_map[d].field] += 1;}
- }
- }
- }
- });
- },
- update_groups: function() {
- var me = this;
-
- $.each(this.data, function(i, item) {
- var parent = me.parent_map[item.name];
- while(parent) {
- var parent_group = me.item_by_name[parent];
-
- $.each(me.columns, function(c, col) {
- if (col.formatter == me.currency_formatter) {
- parent_group[col.field] =
- flt(parent_group[col.field])
- + flt(item[col.field]);
- }
- });
- parent = me.parent_map[parent];
- }
- });
- },
- set_totals: function(sort) {
- var me = this;
- $.each(this.data, function(i, d) {
- d.total = 0.0;
- $.each(me.columns, function(i, col) {
- if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total")
- d.total += d[col.field];
- });
- });
-
- if(sort)this.data = this.data.sort(function(a, b) { return b.total - a.total; });
-
- if(!this.checked) {
- this.data[0].checked = true;
- }
- }
-
-});
diff --git a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.json b/erpnext/healthcare/page/appointment_analytic/appointment_analytic.json
deleted file mode 100644
index ac5ca1a266e..00000000000
--- a/erpnext/healthcare/page/appointment_analytic/appointment_analytic.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "content": null,
- "creation": "2016-08-18 12:29:52.497819",
- "docstatus": 0,
- "doctype": "Page",
- "idx": 0,
- "modified": "2018-08-06 11:40:53.082863",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "appointment-analytic",
- "owner": "Administrator",
- "page_name": "Appointment Analytics",
- "restrict_to_domain": "Healthcare",
- "roles": [
- {
- "role": "Physician"
- }
- ],
- "script": null,
- "standard": "Yes",
- "style": null,
- "system_page": 0,
- "title": "Appointment Analytics"
-}
\ No newline at end of file
diff --git a/erpnext/healthcare/print_format/encounter_print/encounter_print.json b/erpnext/healthcare/print_format/encounter_print/encounter_print.json
index 20e44b79049..ec1e0f202a2 100644
--- a/erpnext/healthcare/print_format/encounter_print/encounter_print.json
+++ b/erpnext/healthcare/print_format/encounter_print/encounter_print.json
@@ -1,22 +1,22 @@
{
- "align_labels_right": 0,
- "creation": "2017-04-10 14:05:53.355863",
- "custom_format": 1,
- "disabled": 0,
- "doc_type": "Patient Encounter",
- "docstatus": 0,
- "doctype": "Print Format",
- "font": "Default",
- "html": "
\n {% if letter_head and not no_letterhead -%}\n
{{ letter_head }}
\n
\n {% else %}\n
\n
{{doc.name}} \n \n {%- endif %}\n
\n
\n {% if doc.appointment %}\n\t
\n\t\t\t
\n\t\t\tAppointment \n\t\t\t
\n\t\t\t
\n\t\t\t: {{doc.appointment}}\n\t\t\t
\n\t\t
\n\t\t{%- endif -%}\n\n
\n\t\t
\n\t\t\t Patient \n\t\t
\n {% if doc.patient %}\n\t\t
\n\t\t\t : {{doc.patient}}\n\t\t
\n {% else %}\n
\n\t\t\t : Patient Name \n\t\t
\n {%- endif -%}\n\t\t
\n\t
\n\t\t\t
\n\t\t\t\tAge \n\t\t\t
\n\t\t\t
\n\t\t\t : {{doc.patient_age}}\n\t\t\t
\n\t\t
\n\n
\n
\n\t\t\t\tGender \n\t\t\t
\n\t\t\t
\n\t\t\t : {{doc.patient_sex}}\n\t\t\t
\n
\n\n
\n
\n\n
\n\t
\n\t\t Healthcare Practitioner \n\t
\n {% if doc.practitioner %}\n\t
\n\t\t\t: {{doc.practitioner}}\n\t
\n {%- endif -%}\n\t
\n\n {% if doc.encounter_date %}\n\t
\n\t\t
\n\t\tDate \n\t\t
\n\t\t
\n\t\t: {{doc.encounter_date}}\n\t\t
\n
\n\t {%- endif -%}\n {% if doc.encounter_time %}\n\t
\n\t\t
\n\t\tTime \n\t\t
\n\t\t
\n\t\t: {{doc.encounter_time}}\n\t\t
\n
\n\t {%- endif -%}\n {% if doc.visit_department %}\n\t
\n\t\t
\n\t\tDepartment \n\t\t
\n\t\t
\n\t\t: {{doc.visit_department}}\n\t\t
\n
\n {%- endif -%}\n
\n\n
\n\n
\n
\n
\n {% if doc.symptoms_in_print%}\n {% if doc.symptoms %}\n Complaints:\n {{doc.symptoms}} \n \t \n {%- endif -%}\n {%- endif -%}\n\n {% if doc.diagnosis_in_print%}\n {% if doc.diagnosis %}\n \t Diagnosis:\n {{doc.diagnosis}} \n \n {%- endif -%}\n {%- endif -%}\n\n\n\n
\n {% if doc.drug_prescription %}\n
\n Rx,\n
\n \n \n\n {%- for row in doc.drug_prescription -%}\n \n \n {%- if row.drug_name -%}{{ row.drug_name }} {%- endif -%}\n \n \t\n {%- if row.dosage -%}{{ row.dosage }}{%- endif -%}\n \n \t\n {%- if row.period -%}{{ row.period }}{%- endif -%}\n\t\t \n \n\t\t\t \n {%- if row.comment -%}{{ row.comment }}{%- endif -%}\n
\n\t\t \n \n\t {%- endfor -%}\n \n
\n\n\n {%- endif -%}\n
\n\n\n
\n {% if doc.lab_test_prescription %}\n Investigations,\n
\n \n \n\n {%- for row in doc.lab_test_prescription -%}\n \n \n {%- if row.lab_test_name -%}{{ row.lab_test_name }} {%- endif -%}\n \n \n\t\t\t \n {%- if row.lab_test_comment -%}{{ row.lab_test_comment }}{%- endif -%}\n
\n\t\t \n \n\n\t {%- endfor -%}\n \n
\n\n\n {%- endif -%}\n
\n
\n {% if doc.encounter_comment %}\n \n {{doc.encounter_comment}}\n {%- endif -%}\n
\n",
- "idx": 0,
- "line_breaks": 0,
- "modified": "2018-09-04 11:52:54.473702",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Encounter Print",
- "owner": "Administrator",
- "print_format_builder": 0,
- "print_format_type": "Server",
- "show_section_headings": 0,
+ "align_labels_right": 0,
+ "creation": "2017-04-10 14:05:53.355863",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "Patient Encounter",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "
\n {% if letter_head and not no_letterhead -%}\n
{{ letter_head }}
\n
\n {% else %}\n
\n
{{doc.name}} \n \n {%- endif %}\n
\n
\n {% if doc.appointment %}\n\t
\n\t\t\t
\n\t\t\tAppointment \n\t\t\t
\n\t\t\t
\n\t\t\t: {{doc.appointment}}\n\t\t\t
\n\t\t
\n\t\t{%- endif -%}\n\n
\n\t\t
\n\t\t\t Patient \n\t\t
\n {% if doc.patient %}\n\t\t
\n\t\t\t : {{doc.patient}}\n\t\t
\n {% else %}\n
\n\t\t\t : Patient Name \n\t\t
\n {%- endif -%}\n\t\t
\n\t
\n\t\t\t
\n\t\t\t\tAge \n\t\t\t
\n\t\t\t
\n\t\t\t : {{doc.patient_age}}\n\t\t\t
\n\t\t
\n\n
\n
\n\t\t\t\tGender \n\t\t\t
\n\t\t\t
\n\t\t\t : {{doc.patient_sex}}\n\t\t\t
\n
\n\n
\n
\n\n
\n\t
\n\t\t Healthcare Practitioner \n\t
\n {% if doc.practitioner %}\n\t
\n\t\t\t: {{doc.practitioner}}\n\t
\n {%- endif -%}\n\t
\n\n {% if doc.encounter_date %}\n\t
\n\t\t
\n\t\tDate \n\t\t
\n\t\t
\n\t\t: {{doc.encounter_date}}\n\t\t
\n
\n\t {%- endif -%}\n {% if doc.encounter_time %}\n\t
\n\t\t
\n\t\tTime \n\t\t
\n\t\t
\n\t\t: {{doc.encounter_time}}\n\t\t
\n
\n\t {%- endif -%}\n {% if doc.medical_department %}\n\t
\n\t\t
\n\t\tDepartment \n\t\t
\n\t\t
\n\t\t: {{doc.visit_department}}\n\t\t
\n
\n {%- endif -%}\n
\n\n
\n\n
\n
\n
\n {% if doc.symptoms_in_print%}\n {% if doc.symptoms %}\n Complaints:\n {{doc.symptoms}} \n \t \n {%- endif -%}\n {%- endif -%}\n\n {% if doc.diagnosis_in_print%}\n {% if doc.diagnosis %}\n \t Diagnosis:\n {{doc.diagnosis}} \n \n {%- endif -%}\n {%- endif -%}\n\n\n\n
\n {% if doc.drug_prescription %}\n
\n Rx,\n
\n \n \n\n {%- for row in doc.drug_prescription -%}\n \n \n {%- if row.drug_name -%}{{ row.drug_name }} {%- endif -%}\n \n \t\n {%- if row.dosage -%}{{ row.dosage }}{%- endif -%}\n \n \t\n {%- if row.period -%}{{ row.period }}{%- endif -%}\n\t\t \n \n\t\t\t \n {%- if row.comment -%}{{ row.comment }}{%- endif -%}\n
\n\t\t \n \n\t {%- endfor -%}\n \n
\n\n\n {%- endif -%}\n
\n\n\n
\n {% if doc.lab_test_prescription %}\n Investigations,\n
\n \n \n\n {%- for row in doc.lab_test_prescription -%}\n \n \n {%- if row.lab_test_name -%}{{ row.lab_test_name }} {%- endif -%}\n \n \n\t\t\t \n {%- if row.lab_test_comment -%}{{ row.lab_test_comment }}{%- endif -%}\n
\n\t\t \n \n\n\t {%- endfor -%}\n \n
\n\n\n {%- endif -%}\n
\n
\n {% if doc.encounter_comment %}\n \n {{doc.encounter_comment}}\n {%- endif -%}\n
\n",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2018-09-04 11:52:54.473702",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Encounter Print",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Server",
+ "show_section_headings": 0,
"standard": "Yes"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json b/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
index 6badc6f82dc..e8e95d8439c 100644
--- a/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
+++ b/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
@@ -1,22 +1,22 @@
{
- "align_labels_right": 0,
- "creation": "2017-04-24 15:38:45.332473",
- "custom_format": 1,
- "disabled": 0,
- "doc_type": "Lab Test",
- "docstatus": 0,
- "doctype": "Print Format",
- "font": "Default",
- "html": "
\n {% if letter_head and not no_letterhead -%}\n
{{ letter_head }}
\n
\n {%- endif %}\n\n {% if (doc.docstatus != 1) %}\n
Lab Tests have to be Submitted for Print .. ! \n {% elif (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"require_test_result_approval\") == '1' and doc.approval_status != \"Approved\") %}\n
Lab Tests have to be Approved for Print .. ! \n {%- else -%}\n
\n
\n\n
\n
\n Patient \n
\n {% if doc.patient %}\n
\n : {{doc.patient}}\n
\n {% else %}\n
\n : Patient Name \n
\n {%- endif -%}\n
\n\n
\n
\n Age \n
\n
\n : {{doc.patient_age}}\n
\n
\n\n
\n
\n Gender \n
\n
\n : {{doc.patient_sex}}\n
\n
\n\n
\n\n
\n\n
\n
\n Practitioner \n
\n {% if doc.practitioner %}\n
\n : {{doc.practitioner}}\n
\n {%- endif -%}\n
\n\n {% if doc.sample_date %}\n
\n
\n Sample Date \n
\n
\n : {{doc.sample_date}}\n
\n
\n {%- endif -%}\n\n {% if doc.result_date %}\n
\n
\n Result Date \n
\n
\n : {{doc.result_date}}\n
\n
\n {%- endif -%}\n\n
\n\n
\n\n
\n
Department of {{doc.department}} \n \n\n
\n \n {%- if doc.normal_test_items -%}\n \n Name of Test \n Result \n Normal Range \n \n\n {%- if doc.normal_test_items|length > 1 %}\n {{ doc.lab_test_name }} \n {%- endif -%}\n\n {%- for row in doc.normal_test_items -%}\n \n \n {%- if doc.normal_test_items|length > 1 %} {%- endif -%}\n {%- if row.lab_test_name -%}{{ row.lab_test_name }} \n {%- else -%} {%- endif -%}\n {%- if row.lab_test_event -%} {{ row.lab_test_event }}{%- endif -%}\n \n\n \n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%} \n {%- if row.lab_test_uom -%}{{ row.lab_test_uom }}{%- endif -%}\n \n\n \n \n {%- if row.normal_range -%}{{ row.normal_range }}{%- endif -%}\n
\n \n \n\n {%- endfor -%}\n {%- endif -%}\n \n
\n\n
\n \n {%- if doc.special_test_items -%}\n \n Name of Test \n Result \n \n {{ doc.lab_test_name }} \n {%- for row in doc.special_test_items -%}\n \n {{ row.lab_test_particulars }} \n \n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%}\n \n \n\n {%- endfor -%}\n {%- endif -%}\n\n {%- if doc.sensitivity_test_items -%}\n \n Antibiotic \n Sensitivity \n \n {%- for row in doc.sensitivity_test_items -%}\n \n {{ row.antibiotic }} \n {{ row.antibiotic_sensitivity }} \n \n\n {%- endfor -%}\n {%- endif -%}\n\n \n
\n {%- endif -%}\n\n
\n {%- if (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"employee_name_and_designation_in_print\") == '1') -%}\n
{{doc.employee_name}} \n {{doc.employee_designation}} \n {%- else -%}\n {{frappe.db.get_value(\"Healthcare Settings\", \"None\", \"custom_signature_in_print\") }} \n {%- endif -%}\n \n
\n",
- "idx": 0,
- "line_breaks": 0,
- "modified": "2018-09-04 12:03:47.066918",
- "modified_by": "Administrator",
- "module": "Healthcare",
- "name": "Lab Test Print",
- "owner": "Administrator",
- "print_format_builder": 0,
- "print_format_type": "Server",
- "show_section_headings": 0,
+ "align_labels_right": 0,
+ "creation": "2017-04-24 15:38:45.332473",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "Lab Test",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "
\n {% if letter_head and not no_letterhead -%}\n
{{ letter_head }}
\n
\n {%- endif %}\n\n {% if (doc.docstatus != 1) %}\n
Lab Tests have to be Submitted for Print .. ! \n {% elif (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"lab_test_approval_required\") == '1' and doc.approval_status != \"Approved\") %}\n
Lab Tests have to be Approved for Print .. ! \n {%- else -%}\n
\n
\n\n
\n
\n Patient \n
\n {% if doc.patient %}\n
\n : {{doc.patient}}\n
\n {% else %}\n
\n : Patient Name \n
\n {%- endif -%}\n
\n\n
\n
\n Age \n
\n
\n : {{doc.patient_age}}\n
\n
\n\n
\n
\n Gender \n
\n
\n : {{doc.patient_sex}}\n
\n
\n\n
\n\n
\n\n
\n
\n Practitioner \n
\n {% if doc.practitioner %}\n
\n : {{doc.practitioner}}\n
\n {%- endif -%}\n
\n\n {% if doc.sample_date %}\n
\n
\n Sample Date \n
\n
\n : {{doc.sample_date}}\n
\n
\n {%- endif -%}\n\n {% if doc.result_date %}\n
\n
\n Result Date \n
\n
\n : {{doc.result_date}}\n
\n
\n {%- endif -%}\n\n
\n\n
\n\n
\n
Department of {{doc.department}} \n \n\n
\n \n {%- if doc.normal_test_items -%}\n \n Name of Test \n Result \n Normal Range \n \n\n {%- if doc.normal_test_items|length > 1 %}\n {{ doc.lab_test_name }} \n {%- endif -%}\n\n {%- for row in doc.normal_test_items -%}\n \n \n {%- if doc.normal_test_items|length > 1 %} {%- endif -%}\n {%- if row.lab_test_name -%}{{ row.lab_test_name }} \n {%- else -%} {%- endif -%}\n {%- if row.lab_test_event -%} {{ row.lab_test_event }}{%- endif -%}\n \n\n \n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%} \n {%- if row.lab_test_uom -%}{{ row.lab_test_uom }}{%- endif -%}\n \n\n \n \n {%- if row.normal_range -%}{{ row.normal_range }}{%- endif -%}\n
\n \n \n\n {%- endfor -%}\n {%- endif -%}\n \n
\n\n
\n \n {%- if doc.special_test_items -%}\n \n Name of Test \n Result \n \n {{ doc.lab_test_name }} \n {%- for row in doc.special_test_items -%}\n \n {{ row.lab_test_particulars }} \n \n {%- if row.result_value -%}{{ row.result_value }}{%- endif -%}\n \n \n\n {%- endfor -%}\n {%- endif -%}\n\n {%- if doc.sensitivity_test_items -%}\n \n Antibiotic \n Sensitivity \n \n {%- for row in doc.sensitivity_test_items -%}\n \n {{ row.antibiotic }} \n {{ row.antibiotic_sensitivity }} \n \n\n {%- endfor -%}\n {%- endif -%}\n\n \n
\n {%- endif -%}\n\n
\n {%- if (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"employee_name_and_designation_in_print\") == '1') -%}\n
{{doc.employee_name}} \n {{doc.employee_designation}} \n {%- else -%}\n {{frappe.db.get_value(\"Healthcare Settings\", \"None\", \"custom_signature_in_print\") }} \n {%- endif -%}\n \n
\n",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2018-09-04 12:03:47.066918",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Lab Test Print",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Server",
+ "show_section_headings": 0,
"standard": "Yes"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/report/patient_appointment_analytics/__init__.py b/erpnext/healthcare/report/patient_appointment_analytics/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.js b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.js
new file mode 100644
index 00000000000..18d252ede13
--- /dev/null
+++ b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.js
@@ -0,0 +1,128 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports['Patient Appointment Analytics'] = {
+ "filters": [
+ {
+ fieldname: 'tree_type',
+ label: __('Tree Type'),
+ fieldtype: 'Select',
+ options: ['Healthcare Practitioner', 'Medical Department'],
+ default: 'Healthcare Practitioner',
+ reqd: 1
+ },
+ {
+ fieldname: 'status',
+ label: __('Appointment Status'),
+ fieldtype: 'Select',
+ options:[
+ {label: __('Scheduled'), value: 'Scheduled'},
+ {label: __('Open'), value: 'Open'},
+ {label: __('Closed'), value: 'Closed'},
+ {label: __('Expired'), value: 'Expired'},
+ {label: __('Cancelled'), value: 'Cancelled'}
+ ]
+ },
+ {
+ fieldname: 'appointment_type',
+ label: __('Appointment Type'),
+ fieldtype: 'Link',
+ options: 'Appointment Type'
+ },
+ {
+ fieldname: 'practitioner',
+ label: __('Healthcare Practitioner'),
+ fieldtype: 'Link',
+ options: 'Healthcare Practitioner'
+ },
+ {
+ fieldname: 'department',
+ label: __('Medical Department'),
+ fieldtype: 'Link',
+ options: 'Medical Department'
+ },
+ {
+ fieldname: 'from_date',
+ label: __('From Date'),
+ fieldtype: 'Date',
+ default: frappe.defaults.get_user_default('year_start_date'),
+ reqd: 1
+ },
+ {
+ fieldname: 'to_date',
+ label: __('To Date'),
+ fieldtype: 'Date',
+ default: frappe.defaults.get_user_default('year_end_date'),
+ reqd: 1
+ },
+ {
+ fieldname: 'range',
+ label: __('Range'),
+ fieldtype: 'Select',
+ options:[
+ {label: __('Weekly'), value: 'Weekly'},
+ {label: __('Monthly'), value: 'Monthly'},
+ {label: __('Quarterly'), value: 'Quarterly'},
+ {label: __('Yearly'), value: 'Yearly'}
+ ],
+ default: 'Monthly',
+ reqd: 1
+ }
+ ],
+ after_datatable_render: function(datatable_obj) {
+ $(datatable_obj.wrapper).find(".dt-row-0").find('input[type=checkbox]').click();
+ },
+ get_datatable_options(options) {
+ return Object.assign(options, {
+ checkboxColumn: true,
+ events: {
+ onCheckRow: function(data) {
+ row_name = data[2].content;
+ length = data.length;
+
+ row_values = data.slice(3,length-1).map(function (column) {
+ return column.content;
+ })
+
+ entry = {
+ 'name': row_name,
+ 'values': row_values
+ }
+
+ let raw_data = frappe.query_report.chart.data;
+ let new_datasets = raw_data.datasets;
+
+ let found = false;
+ for (let i=0; i < new_datasets.length;i++) {
+ if (new_datasets[i].name == row_name) {
+ found = true;
+ new_datasets.splice(i,1);
+ break;
+ }
+ }
+
+ if (!found) {
+ new_datasets.push(entry);
+ }
+
+ let new_data = {
+ labels: raw_data.labels,
+ datasets: new_datasets
+ }
+
+ setTimeout(() => {
+ frappe.query_report.chart.update(new_data)
+ }, 500)
+
+
+ setTimeout(() => {
+ frappe.query_report.chart.draw(true);
+ }, 1000)
+
+ frappe.query_report.raw_chart_data = new_data;
+ },
+ }
+ })
+ },
+};
diff --git a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.json b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.json
new file mode 100644
index 00000000000..64750c012f1
--- /dev/null
+++ b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.json
@@ -0,0 +1,36 @@
+{
+ "add_total_row": 1,
+ "creation": "2020-03-02 15:13:16.273493",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-03-02 15:13:16.273493",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Appointment Analytics",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Patient Appointment",
+ "report_name": "Patient Appointment Analytics",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Healthcare Administrator"
+ },
+ {
+ "role": "LabTest Approver"
+ },
+ {
+ "role": "Physician"
+ },
+ {
+ "role": "Nursing User"
+ },
+ {
+ "role": "Laboratory User"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py
new file mode 100644
index 00000000000..9c35dbb3ea5
--- /dev/null
+++ b/erpnext/healthcare/report/patient_appointment_analytics/patient_appointment_analytics.py
@@ -0,0 +1,194 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import getdate, flt, add_to_date, add_days
+from frappe import _ , scrub
+from six import iteritems
+from erpnext.accounts.utils import get_fiscal_year
+
+def execute(filters=None):
+ return Analytics(filters).run()
+
+class Analytics(object):
+ def __init__(self, filters=None):
+ """Patient Appointment Analytics Report."""
+ self.filters = frappe._dict(filters or {})
+ self.months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+ self.get_period_date_ranges()
+
+ def run(self):
+ self.get_columns()
+ self.get_data()
+ self.get_chart_data()
+
+ return self.columns, self.data, None, self.chart
+
+ def get_period_date_ranges(self):
+ from dateutil.relativedelta import relativedelta, MO
+ from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date)
+
+ increment = {
+ 'Monthly': 1,
+ 'Quarterly': 3,
+ 'Half-Yearly': 6,
+ 'Yearly': 12
+ }.get(self.filters.range, 1)
+
+ if self.filters.range in ['Monthly', 'Quarterly']:
+ from_date = from_date.replace(day=1)
+ elif self.filters.range == 'Yearly':
+ from_date = get_fiscal_year(from_date)[1]
+ else:
+ from_date = from_date + relativedelta(from_date, weekday=MO(-1))
+
+ self.periodic_daterange = []
+ for dummy in range(1, 53):
+ if self.filters.range == 'Weekly':
+ period_end_date = add_days(from_date, 6)
+ else:
+ period_end_date = add_to_date(from_date, months=increment, days=-1)
+
+ if period_end_date > to_date:
+ period_end_date = to_date
+
+ self.periodic_daterange.append(period_end_date)
+
+ from_date = add_days(period_end_date, 1)
+ if period_end_date == to_date:
+ break
+
+ def get_columns(self):
+ self.columns = []
+
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ self.columns.append({
+ 'label': _('Healthcare Practitioner'),
+ 'options': 'Healthcare Practitioner',
+ 'fieldname': 'practitioner',
+ 'fieldtype': 'Link',
+ 'width': 200
+ })
+
+ elif self.filters.tree_type == 'Medical Department':
+ self.columns.append({
+ 'label': _('Medical Department'),
+ 'fieldname': 'department',
+ 'fieldtype': 'Link',
+ 'options': 'Medical Department',
+ 'width': 150
+ })
+
+ for end_date in self.periodic_daterange:
+ period = self.get_period(end_date)
+ self.columns.append({
+ 'label': _(period),
+ 'fieldname': scrub(period),
+ 'fieldtype': 'Int',
+ 'width': 120
+ })
+
+ self.columns.append({
+ 'label': _('Total'),
+ 'fieldname': 'total',
+ 'fieldtype': 'Int',
+ 'width': 120
+ })
+
+ def get_data(self):
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ self.get_appointments_based_on_healthcare_practitioner()
+ self.get_rows()
+
+ elif self.filters.tree_type == 'Medical Department':
+ self.get_appointments_based_on_medical_department()
+ self.get_rows()
+
+ def get_period(self, appointment_date):
+ if self.filters.range == 'Weekly':
+ period = 'Week ' + str(appointment_date.isocalendar()[1])
+ elif self.filters.range == 'Monthly':
+ period = str(self.months[appointment_date.month - 1])
+ elif self.filters.range == 'Quarterly':
+ period = 'Quarter ' + str(((appointment_date.month - 1) // 3) + 1)
+ else:
+ year = get_fiscal_year(appointment_date, company=self.filters.company)
+ period = str(year[0])
+
+ if getdate(self.filters.from_date).year != getdate(self.filters.to_date).year:
+ period += ' ' + str(appointment_date.year)
+
+ return period
+
+ def get_appointments_based_on_healthcare_practitioner(self):
+ filters = self.get_common_filters()
+
+ self.entries = frappe.db.get_all('Patient Appointment',
+ fields=['appointment_date', 'name', 'patient', 'practitioner'],
+ filters=filters
+ )
+
+ def get_appointments_based_on_medical_department(self):
+ filters = self.get_common_filters()
+ if not filters.get('department'):
+ filters['department'] = ('!=', '')
+
+ self.entries = frappe.db.get_all('Patient Appointment',
+ fields=['appointment_date', 'name', 'patient', 'practitioner', 'department'],
+ filters=filters
+ )
+
+ def get_common_filters(self):
+ filters = {}
+ filters['appointment_date'] = ('between', [self.filters.from_date, self.filters.to_date])
+ for entry in ['appointment_type', 'practitioner', 'department', 'status']:
+ if self.filters.get(entry):
+ filters[entry] = self.filters.get(entry)
+
+ return filters
+
+ def get_rows(self):
+ self.data = []
+ self.get_periodic_data()
+
+ for entity, period_data in iteritems(self.appointment_periodic_data):
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ row = {'practitioner': entity}
+ elif self.filters.tree_type == 'Medical Department':
+ row = {'department': entity}
+
+ total = 0
+ for end_date in self.periodic_daterange:
+ period = self.get_period(end_date)
+ amount = flt(period_data.get(period, 0.0))
+ row[scrub(period)] = amount
+ total += amount
+
+ row['total'] = total
+
+ self.data.append(row)
+
+ def get_periodic_data(self):
+ self.appointment_periodic_data = frappe._dict()
+
+ for d in self.entries:
+ period = self.get_period(d.get('appointment_date'))
+ if self.filters.tree_type == 'Healthcare Practitioner':
+ self.appointment_periodic_data.setdefault(d.practitioner, frappe._dict()).setdefault(period, 0.0)
+ self.appointment_periodic_data[d.practitioner][period] += 1
+
+ elif self.filters.tree_type == 'Medical Department':
+ self.appointment_periodic_data.setdefault(d.department, frappe._dict()).setdefault(period, 0.0)
+ self.appointment_periodic_data[d.department][period] += 1
+
+ def get_chart_data(self):
+ length = len(self.columns)
+ labels = [d.get("label") for d in self.columns[1:length - 1]]
+ self.chart = {
+ "data": {
+ 'labels': labels,
+ 'datasets': []
+ },
+ "type": "line"
+ }
\ No newline at end of file
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index 97bb98f6779..a7565323585 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -4,417 +4,491 @@
from __future__ import unicode_literals
import frappe
-import datetime
from frappe import _
import math
-from frappe.utils import time_diff_in_hours, rounded, getdate, add_days
+from frappe.utils import time_diff_in_hours, rounded
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account
-from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity, update_fee_validity
+from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
@frappe.whitelist()
def get_healthcare_services_to_invoice(patient):
- patient = frappe.get_doc("Patient", patient)
+ patient = frappe.get_doc('Patient', patient)
if patient:
- if patient.customer:
- item_to_invoice = []
- patient_appointments = frappe.get_list("Patient Appointment",{'patient': patient.name, 'invoiced': False},
- order_by="appointment_date")
- if patient_appointments:
- fee_validity_details = []
- valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
- max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
- for patient_appointment in patient_appointments:
- patient_appointment_obj = frappe.get_doc("Patient Appointment", patient_appointment['name'])
+ validate_customer_created(patient)
+ items_to_invoice = []
+ patient_appointments = frappe.get_list(
+ 'Patient Appointment',
+ fields='*',
+ filters={'patient': patient.name, 'invoiced': 0},
+ order_by='appointment_date'
+ )
+ if patient_appointments:
+ items_to_invoice = get_fee_validity(patient_appointments)
- if patient_appointment_obj.procedure_template:
- if frappe.db.get_value("Clinical Procedure Template", patient_appointment_obj.procedure_template, "is_billable") == 1:
- item_to_invoice.append({'reference_type': 'Patient Appointment', 'reference_name': patient_appointment_obj.name, 'service': patient_appointment_obj.procedure_template})
- else:
- practitioner_exist_in_list = False
- skip_invoice = False
- if fee_validity_details:
- for validity in fee_validity_details:
- if validity['practitioner'] == patient_appointment_obj.practitioner:
- practitioner_exist_in_list = True
- if validity['valid_till'] >= patient_appointment_obj.appointment_date:
- validity['visits'] = validity['visits']+1
- if int(max_visit) > validity['visits']:
- skip_invoice = True
- if not skip_invoice:
- validity['visits'] = 1
- validity['valid_till'] = patient_appointment_obj.appointment_date + datetime.timedelta(days=int(valid_days))
- if not practitioner_exist_in_list:
- valid_till = patient_appointment_obj.appointment_date + datetime.timedelta(days=int(valid_days))
- visits = 0
- validity_exist = validity_exists(patient_appointment_obj.practitioner, patient_appointment_obj.patient)
- if validity_exist:
- fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
- valid_till = fee_validity.valid_till
- visits = fee_validity.visited
- fee_validity_details.append({'practitioner': patient_appointment_obj.practitioner,
- 'valid_till': valid_till, 'visits': visits})
+ encounters = get_encounters_to_invoice(patient)
+ lab_tests = get_lab_tests_to_invoice(patient)
+ clinical_procedures = get_clinical_procedures_to_invoice(patient)
+ inpatient_services = get_inpatient_services_to_invoice(patient)
+ therapy_sessions = get_therapy_sessions_to_invoice(patient)
- if not skip_invoice:
- practitioner_charge = 0
- income_account = None
- service_item = None
- if patient_appointment_obj.practitioner:
- service_item, practitioner_charge = service_item_and_practitioner_charge(patient_appointment_obj)
- income_account = get_income_account(patient_appointment_obj.practitioner, patient_appointment_obj.company)
- item_to_invoice.append({'reference_type': 'Patient Appointment', 'reference_name': patient_appointment_obj.name,
- 'service': service_item, 'rate': practitioner_charge,
- 'income_account': income_account})
+ items_to_invoice += encounters + lab_tests + clinical_procedures + inpatient_services + therapy_sessions
+ return items_to_invoice
- encounters = frappe.get_list("Patient Encounter", {'patient': patient.name, 'invoiced': False, 'docstatus': 1})
- if encounters:
- for encounter in encounters:
- encounter_obj = frappe.get_doc("Patient Encounter", encounter['name'])
- if not encounter_obj.appointment:
- practitioner_charge = 0
- income_account = None
- service_item = None
- if encounter_obj.practitioner:
- service_item, practitioner_charge = service_item_and_practitioner_charge(encounter_obj)
- income_account = get_income_account(encounter_obj.practitioner, encounter_obj.company)
+def validate_customer_created(patient):
+ if not frappe.db.get_value('Patient', patient.name, 'customer'):
+ msg = _("Please set a Customer linked to the Patient")
+ msg += "
{0} ".format(patient.name)
+ frappe.throw(msg, title=_('Customer Not Found'))
- item_to_invoice.append({'reference_type': 'Patient Encounter', 'reference_name': encounter_obj.name,
- 'service': service_item, 'rate': practitioner_charge,
- 'income_account': income_account})
+def get_fee_validity(patient_appointments):
+ if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
+ return []
- lab_tests = frappe.get_list("Lab Test", {'patient': patient.name, 'invoiced': False, 'docstatus': 1})
- if lab_tests:
- for lab_test in lab_tests:
- lab_test_obj = frappe.get_doc("Lab Test", lab_test['name'])
- if frappe.db.get_value("Lab Test Template", lab_test_obj.template, "is_billable") == 1:
- item_to_invoice.append({'reference_type': 'Lab Test', 'reference_name': lab_test_obj.name,
- 'service': frappe.db.get_value("Lab Test Template", lab_test_obj.template, "item")})
-
- lab_rxs = frappe.db.sql("""select lp.name from `tabPatient Encounter` et, `tabLab Prescription` lp
- where et.patient=%s and lp.parent=et.name and lp.lab_test_created=0 and lp.invoiced=0""", (patient.name))
- if lab_rxs:
- for lab_rx in lab_rxs:
- rx_obj = frappe.get_doc("Lab Prescription", lab_rx[0])
- if rx_obj.lab_test_code and (frappe.db.get_value("Lab Test Template", rx_obj.lab_test_code, "is_billable") == 1):
- item_to_invoice.append({'reference_type': 'Lab Prescription', 'reference_name': rx_obj.name,
- 'service': frappe.db.get_value("Lab Test Template", rx_obj.lab_test_code, "item")})
-
- procedures = frappe.get_list("Clinical Procedure", {'patient': patient.name, 'invoiced': False})
- if procedures:
- for procedure in procedures:
- procedure_obj = frappe.get_doc("Clinical Procedure", procedure['name'])
- if not procedure_obj.appointment:
- if procedure_obj.procedure_template and (frappe.db.get_value("Clinical Procedure Template", procedure_obj.procedure_template, "is_billable") == 1):
- item_to_invoice.append({'reference_type': 'Clinical Procedure', 'reference_name': procedure_obj.name,
- 'service': frappe.db.get_value("Clinical Procedure Template", procedure_obj.procedure_template, "item")})
-
- procedure_rxs = frappe.db.sql("""select pp.name from `tabPatient Encounter` et,
- `tabProcedure Prescription` pp where et.patient=%s and pp.parent=et.name and
- pp.procedure_created=0 and pp.invoiced=0 and pp.appointment_booked=0""", (patient.name))
- if procedure_rxs:
- for procedure_rx in procedure_rxs:
- rx_obj = frappe.get_doc("Procedure Prescription", procedure_rx[0])
- if frappe.db.get_value("Clinical Procedure Template", rx_obj.procedure, "is_billable") == 1:
- item_to_invoice.append({'reference_type': 'Procedure Prescription', 'reference_name': rx_obj.name,
- 'service': frappe.db.get_value("Clinical Procedure Template", rx_obj.procedure, "item")})
-
- procedures = frappe.get_list("Clinical Procedure",
- {'patient': patient.name, 'invoice_separately_as_consumables': True, 'consumption_invoiced': False,
- 'consume_stock': True, 'status': 'Completed'})
- if procedures:
- service_item = get_healthcare_service_item('clinical_procedure_consumable_item')
- if not service_item:
- msg = _(("Please Configure {0} in ").format("Clinical Procedure Consumable Item") \
- + """
Healthcare Settings """)
- frappe.throw(msg)
- for procedure in procedures:
- procedure_obj = frappe.get_doc("Clinical Procedure", procedure['name'])
- item_to_invoice.append({'reference_type': 'Clinical Procedure', 'reference_name': procedure_obj.name,
- 'service': service_item, 'rate': procedure_obj.consumable_total_amount, 'description': procedure_obj.consumption_details})
-
- 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:
- hours_occupied = time_diff_in_hours(inpatient_occupancy.check_out, inpatient_occupancy.check_in)
- qty = 0.5
- if hours_occupied > 0:
- actual_qty = hours_occupied / service_unit_type.no_of_hours
- floor = math.floor(actual_qty)
- decimal_part = actual_qty - floor
- if decimal_part > 0.5:
- qty = rounded(floor + 1, 1)
- elif decimal_part < 0.5 and decimal_part > 0:
- qty = rounded(floor + 0.5, 1)
- if qty <= 0:
- qty = 0.5
- item_to_invoice.append({'reference_type': 'Inpatient Occupancy', 'reference_name': inpatient_occupancy.name,
- 'service': service_unit_type.item, 'qty': qty})
-
- return item_to_invoice
+ items_to_invoice = []
+ for appointment in patient_appointments:
+ if appointment.procedure_template:
+ if frappe.db.get_value('Clinical Procedure Template', appointment.procedure_template, 'is_billable'):
+ items_to_invoice.append({
+ 'reference_type': 'Patient Appointment',
+ 'reference_name': appointment.name,
+ 'service': appointment.procedure_template
+ })
else:
- frappe.throw(_("The Patient {0} do not have customer refrence to invoice").format(patient.name))
+ fee_validity = frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name})
+ if not fee_validity:
+ practitioner_charge = 0
+ income_account = None
+ service_item = None
+ if appointment.practitioner:
+ service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment)
+ income_account = get_income_account(appointment.practitioner, appointment.company)
+ items_to_invoice.append({
+ 'reference_type': 'Patient Appointment',
+ 'reference_name': appointment.name,
+ 'service': service_item,
+ 'rate': practitioner_charge,
+ 'income_account': income_account
+ })
-def service_item_and_practitioner_charge(doc):
- is_ip = doc_is_ip(doc)
- if is_ip:
- service_item = get_practitioner_service_item(doc.practitioner, "inpatient_visit_charge_item")
+ return items_to_invoice
+
+
+def get_encounters_to_invoice(patient):
+ encounters_to_invoice = []
+ encounters = frappe.get_list(
+ 'Patient Encounter',
+ fields=['*'],
+ filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
+ )
+ if encounters:
+ for encounter in encounters:
+ if not encounter.appointment:
+ practitioner_charge = 0
+ income_account = None
+ service_item = None
+ if encounter.practitioner:
+ service_item, practitioner_charge = get_service_item_and_practitioner_charge(encounter)
+ income_account = get_income_account(encounter.practitioner, encounter.company)
+
+ encounters_to_invoice.append({
+ 'reference_type': 'Patient Encounter',
+ 'reference_name': encounter.name,
+ 'service': service_item,
+ 'rate': practitioner_charge,
+ 'income_account': income_account
+ })
+
+ return encounters_to_invoice
+
+
+def get_lab_tests_to_invoice(patient):
+ lab_tests_to_invoice = []
+ lab_tests = frappe.get_list(
+ 'Lab Test',
+ fields=['name', 'template'],
+ filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
+ )
+ for lab_test in lab_tests:
+ item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.template, ['item', 'is_billable'])
+ if is_billable:
+ lab_tests_to_invoice.append({
+ 'reference_type': 'Lab Test',
+ 'reference_name': lab_test.name,
+ 'service': item
+ })
+
+ lab_prescriptions = frappe.db.sql(
+ '''
+ SELECT
+ lp.name, lp.lab_test_code
+ FROM
+ `tabPatient Encounter` et, `tabLab Prescription` lp
+ WHERE
+ et.patient=%s
+ and lp.parent=et.name
+ and lp.lab_test_created=0
+ and lp.invoiced=0
+ ''', (patient.name), as_dict=1)
+
+ for prescription in lab_prescriptions:
+ item, is_billable = frappe.get_cached_value('Lab Test Template', prescription.lab_test_code, ['item', 'is_billable'])
+ if prescription.lab_test_code and is_billable:
+ lab_tests_to_invoice.append({
+ 'reference_type': 'Lab Prescription',
+ 'reference_name': prescription.name,
+ 'service': item
+ })
+
+ return lab_tests_to_invoice
+
+
+def get_clinical_procedures_to_invoice(patient):
+ clinical_procedures_to_invoice = []
+ procedures = frappe.get_list(
+ 'Clinical Procedure',
+ fields='*',
+ filters={'patient': patient.name, 'invoiced': False}
+ )
+ for procedure in procedures:
+ if not procedure.appointment:
+ item, is_billable = frappe.get_cached_value('Clinical Procedure Template', procedure.procedure_template, ['item', 'is_billable'])
+ if procedure.procedure_template and is_billable:
+ clinical_procedures_to_invoice.append({
+ 'reference_type': 'Clinical Procedure',
+ 'reference_name': procedure.name,
+ 'service': item
+ })
+
+ # consumables
+ if procedure.invoice_separately_as_consumables and procedure.consume_stock \
+ and procedure.status == 'Completed' and not procedure.consumption_invoiced:
+
+ service_item = get_healthcare_service_item('clinical_procedure_consumable_item')
+ if not service_item:
+ msg = _('Please Configure Clinical Procedure Consumable Item in ')
+ msg += '''
Healthcare Settings '''
+ frappe.throw(msg, title=_('Missing Configuration'))
+
+ clinical_procedures_to_invoice.append({
+ 'reference_type': 'Clinical Procedure',
+ 'reference_name': procedure.name,
+ 'service': service_item,
+ 'rate': procedure.consumable_total_amount,
+ 'description': procedure.consumption_details
+ })
+
+ procedure_prescriptions = frappe.db.sql(
+ '''
+ SELECT
+ pp.name, pp.procedure
+ FROM
+ `tabPatient Encounter` et, `tabProcedure Prescription` pp
+ WHERE
+ et.patient=%s
+ and pp.parent=et.name
+ and pp.procedure_created=0
+ and pp.invoiced=0
+ and pp.appointment_booked=0
+ ''', (patient.name), as_dict=1)
+
+ for prescription in procedure_prescriptions:
+ item, is_billable = frappe.get_cached_value('Clinical Procedure Template', prescription.procedure, ['item', 'is_billable'])
+ if is_billable:
+ clinical_procedures_to_invoice.append({
+ 'reference_type': 'Procedure Prescription',
+ 'reference_name': prescription.name,
+ 'service': item
+ })
+
+ return clinical_procedures_to_invoice
+
+
+def get_inpatient_services_to_invoice(patient):
+ services_to_invoice = []
+ inpatient_services = frappe.db.sql(
+ '''
+ SELECT
+ io.*
+ 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), as_dict=1)
+
+ for inpatient_occupancy in inpatient_services:
+ service_unit_type = frappe.db.get_value('Healthcare Service Unit', inpatient_occupancy.service_unit, 'service_unit_type')
+ service_unit_type = frappe.get_cached_doc('Healthcare Service Unit Type', service_unit_type)
+ if service_unit_type and service_unit_type.is_billable:
+ hours_occupied = time_diff_in_hours(inpatient_occupancy.check_out, inpatient_occupancy.check_in)
+ qty = 0.5
+ if hours_occupied > 0:
+ actual_qty = hours_occupied / service_unit_type.no_of_hours
+ floor = math.floor(actual_qty)
+ decimal_part = actual_qty - floor
+ if decimal_part > 0.5:
+ qty = rounded(floor + 1, 1)
+ elif decimal_part < 0.5 and decimal_part > 0:
+ qty = rounded(floor + 0.5, 1)
+ if qty <= 0:
+ qty = 0.5
+ services_to_invoice.append({
+ 'reference_type': 'Inpatient Occupancy',
+ 'reference_name': inpatient_occupancy.name,
+ 'service': service_unit_type.item, 'qty': qty
+ })
+
+ return services_to_invoice
+
+
+def get_therapy_sessions_to_invoice(patient):
+ therapy_sessions_to_invoice = []
+ therapy_sessions = frappe.get_list(
+ 'Therapy Session',
+ fields='*',
+ filters={'patient': patient.name, 'invoiced': False}
+ )
+ for therapy in therapy_sessions:
+ if not therapy.appointment:
+ if therapy.therapy_type and frappe.db.get_value('Therapy Type', therapy.therapy_type, 'is_billable'):
+ therapy_sessions_to_invoice.append({
+ 'reference_type': 'Therapy Session',
+ 'reference_name': therapy.name,
+ 'service': frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
+ })
+
+ return therapy_sessions_to_invoice
+
+
+def get_service_item_and_practitioner_charge(doc):
+ is_inpatient = doc.inpatient_record
+ if is_inpatient:
+ service_item = get_practitioner_service_item(doc.practitioner, 'inpatient_visit_charge_item')
if not service_item:
- service_item = get_healthcare_service_item("inpatient_visit_charge_item")
+ service_item = get_healthcare_service_item('inpatient_visit_charge_item')
else:
- service_item = get_practitioner_service_item(doc.practitioner, "op_consulting_charge_item")
+ service_item = get_practitioner_service_item(doc.practitioner, 'op_consulting_charge_item')
if not service_item:
- service_item = get_healthcare_service_item("op_consulting_charge_item")
+ service_item = get_healthcare_service_item('op_consulting_charge_item')
if not service_item:
- throw_config_service_item(is_ip)
+ throw_config_service_item(is_inpatient)
- practitioner_charge = get_practitioner_charge(doc.practitioner, is_ip)
+ practitioner_charge = get_practitioner_charge(doc.practitioner, is_inpatient)
if not practitioner_charge:
- throw_config_practitioner_charge(is_ip, doc.practitioner)
+ throw_config_practitioner_charge(is_inpatient, doc.practitioner)
return service_item, practitioner_charge
-def throw_config_service_item(is_ip):
- service_item_lable = "Out Patient Consulting Charge Item"
- if is_ip:
- service_item_lable = "Inpatient Visit Charge Item"
- msg = _(("Please Configure {0} in ").format(service_item_lable) \
- + """
Healthcare Settings """)
- frappe.throw(msg)
+def throw_config_service_item(is_inpatient):
+ service_item_label = _('Out Patient Consulting Charge Item')
+ if is_inpatient:
+ service_item_label = _('Inpatient Visit Charge Item')
-def throw_config_practitioner_charge(is_ip, practitioner):
- charge_name = "OP Consulting Charge"
- if is_ip:
- charge_name = "Inpatient Visit Charge"
+ msg = _(('Please Configure {0} in ').format(service_item_label) \
+ + '''
Healthcare Settings ''')
+ frappe.throw(msg, title=_('Missing Configuration'))
+
+
+def throw_config_practitioner_charge(is_inpatient, practitioner):
+ charge_name = _('OP Consulting Charge')
+ if is_inpatient:
+ charge_name = _('Inpatient Visit Charge')
+
+ msg = _(('Please Configure {0} for Healthcare Practitioner').format(charge_name) \
+ + '''
{0} '''.format(practitioner))
+ frappe.throw(msg, title=_('Missing Configuration'))
- msg = _(("Please Configure {0} for Healthcare Practitioner").format(charge_name) \
- + """
{0} """.format(practitioner))
- frappe.throw(msg)
def get_practitioner_service_item(practitioner, service_item_field):
- return frappe.db.get_value("Healthcare Practitioner", practitioner, service_item_field)
+ return frappe.db.get_value('Healthcare Practitioner', practitioner, service_item_field)
+
def get_healthcare_service_item(service_item_field):
- return frappe.db.get_value("Healthcare Settings", None, service_item_field)
+ return frappe.db.get_single_value('Healthcare Settings', service_item_field)
-def doc_is_ip(doc):
- is_ip = False
- if doc.inpatient_record:
- is_ip = True
- return is_ip
-def get_practitioner_charge(practitioner, is_ip):
- if is_ip:
- practitioner_charge = frappe.db.get_value("Healthcare Practitioner", practitioner, "inpatient_visit_charge")
+def get_practitioner_charge(practitioner, is_inpatient):
+ if is_inpatient:
+ practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'inpatient_visit_charge')
else:
- practitioner_charge = frappe.db.get_value("Healthcare Practitioner", practitioner, "op_consulting_charge")
+ practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'op_consulting_charge')
if practitioner_charge:
return practitioner_charge
return False
+
def manage_invoice_submit_cancel(doc, method):
if doc.items:
for item in doc.items:
- if item.get("reference_dt") and item.get("reference_dn"):
- if frappe.get_meta(item.reference_dt).has_field("invoiced"):
+ if item.get('reference_dt') and item.get('reference_dn'):
+ if frappe.get_meta(item.reference_dt).has_field('invoiced'):
set_invoiced(item, method, doc.name)
- if method=="on_submit" and frappe.db.get_value("Healthcare Settings", None, "create_test_on_si_submit") == '1':
- create_multiple("Sales Invoice", doc.name)
+ if method=='on_submit' and frappe.db.get_single_value('Healthcare Settings', 'create_lab_test_on_si_submit'):
+ create_multiple('Sales Invoice', doc.name)
+
def set_invoiced(item, method, ref_invoice=None):
invoiced = False
- if(method=="on_submit"):
+ if method=='on_submit':
validate_invoiced_on_submit(item)
invoiced = True
if item.reference_dt == 'Clinical Procedure':
if get_healthcare_service_item('clinical_procedure_consumable_item') == item.item_code:
- frappe.db.set_value(item.reference_dt, item.reference_dn, "consumption_invoiced", invoiced)
+ frappe.db.set_value(item.reference_dt, item.reference_dn, 'consumption_invoiced', invoiced)
else:
- frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
+ frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)
else:
- frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
+ frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)
if item.reference_dt == 'Patient Appointment':
if frappe.db.get_value('Patient Appointment', item.reference_dn, 'procedure_template'):
- dt_from_appointment = "Clinical Procedure"
+ dt_from_appointment = 'Clinical Procedure'
else:
- manage_fee_validity(item.reference_dn, method, ref_invoice)
- dt_from_appointment = "Patient Encounter"
- manage_doc_for_appoitnment(dt_from_appointment, item.reference_dn, invoiced)
+ dt_from_appointment = 'Patient Encounter'
+ manage_doc_for_appointment(dt_from_appointment, item.reference_dn, invoiced)
elif item.reference_dt == 'Lab Prescription':
- manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, "Lab Test", "lab_test_created")
+ manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Lab Test', 'lab_test_created')
elif item.reference_dt == 'Procedure Prescription':
- manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, "Clinical Procedure", "procedure_created")
+ manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Clinical Procedure', 'procedure_created')
+
def validate_invoiced_on_submit(item):
if item.reference_dt == 'Clinical Procedure' and get_healthcare_service_item('clinical_procedure_consumable_item') == item.item_code:
- is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "consumption_invoiced")
+ is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'consumption_invoiced')
else:
- is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "invoiced")
- if is_invoiced == 1:
- frappe.throw(_("The item referenced by {0} - {1} is already invoiced"\
+ is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'invoiced')
+ if is_invoiced:
+ frappe.throw(_('The item referenced by {0} - {1} is already invoiced'\
).format(item.reference_dt, item.reference_dn))
+
def manage_prescriptions(invoiced, ref_dt, ref_dn, dt, created_check_field):
created = frappe.db.get_value(ref_dt, ref_dn, created_check_field)
- if created == 1:
+ if created:
# Fetch the doc created for the prescription
doc_created = frappe.db.get_value(dt, {'prescription': ref_dn})
frappe.db.set_value(dt, doc_created, 'invoiced', invoiced)
-def validity_exists(practitioner, patient):
- return frappe.db.exists({
- "doctype": "Fee Validity",
- "practitioner": practitioner,
- "patient": patient})
-def manage_fee_validity(appointment_name, method, ref_invoice=None):
- appointment_doc = frappe.get_doc("Patient Appointment", appointment_name)
- validity_exist = validity_exists(appointment_doc.practitioner, appointment_doc.patient)
- do_not_update = False
- visited = 0
- if validity_exist:
- fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
- # Check if the validity is valid
- if (fee_validity.valid_till >= appointment_doc.appointment_date):
- if (method == "on_cancel" and appointment_doc.status != "Closed"):
- if ref_invoice == fee_validity.ref_invoice:
- visited = fee_validity.visited - 1
- if visited < 0:
- visited = 0
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- do_not_update = True
- elif (method == "on_submit" and fee_validity.visited < fee_validity.max_visit):
- visited = fee_validity.visited + 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- do_not_update = True
- else:
- do_not_update = False
+def check_fee_validity(appointment):
+ if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
+ return
- if not do_not_update:
- fee_validity = update_fee_validity(fee_validity, appointment_doc.appointment_date, ref_invoice)
- visited = fee_validity.visited
+ validity = frappe.db.exists('Fee Validity', {
+ 'practitioner': appointment.practitioner,
+ 'patient': appointment.patient,
+ 'valid_till': ('>=', appointment.appointment_date)
+ })
+ if not validity:
+ return
+
+ validity = frappe.get_doc('Fee Validity', validity)
+ return validity
+
+
+def manage_fee_validity(appointment):
+ fee_validity = check_fee_validity(appointment)
+ if fee_validity:
+ if appointment.status == 'Cancelled' and fee_validity.visited > 0:
+ fee_validity.visited -= 1
+ frappe.db.delete('Fee Validity Reference', {'appointment': appointment.name})
+ elif fee_validity.status == 'Completed':
+ return
+ else:
+ fee_validity.visited += 1
+ fee_validity.append('ref_appointments', {
+ 'appointment': appointment.name
+ })
+ fee_validity.save(ignore_permissions=True)
else:
- fee_validity = create_fee_validity(appointment_doc.practitioner, appointment_doc.patient, appointment_doc.appointment_date, ref_invoice)
- visited = fee_validity.visited
+ fee_validity = create_fee_validity(appointment)
+ return fee_validity
- # Mark All Patient Appointment invoiced = True in the validity range do not cross the max visit
- if (method == "on_cancel"):
- invoiced = True
- else:
- invoiced = False
- patient_appointments = appointments_valid_in_fee_validity(appointment_doc, invoiced)
- if patient_appointments and fee_validity:
- visit = visited
- for appointment in patient_appointments:
- if (method == "on_cancel" and appointment.status != "Closed"):
- if ref_invoice == fee_validity.ref_invoice:
- visited = visited - 1
- if visited < 0:
- visited = 0
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", False)
- manage_doc_for_appoitnment("Patient Encounter", appointment.name, False)
- elif method == "on_submit" and int(fee_validity.max_visit) > visit:
- if ref_invoice == fee_validity.ref_invoice:
- visited = visited + 1
- frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
- frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", True)
- manage_doc_for_appoitnment("Patient Encounter", appointment.name, True)
- if ref_invoice == fee_validity.ref_invoice:
- visit = visit + 1
-
- if method == "on_cancel":
- ref_invoice_in_fee_validity = frappe.db.get_value("Fee Validity", fee_validity.name, 'ref_invoice')
- if ref_invoice_in_fee_validity == ref_invoice:
- frappe.delete_doc("Fee Validity", fee_validity.name)
-
-def appointments_valid_in_fee_validity(appointment, invoiced):
- valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
- max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
- if int(max_visit) < 1:
- max_visit = 1
- valid_days_date = add_days(getdate(appointment.appointment_date), int(valid_days))
- return frappe.get_list("Patient Appointment",{'patient': appointment.patient, 'invoiced': invoiced,
- 'appointment_date':("<=", valid_days_date), 'appointment_date':(">=", getdate(appointment.appointment_date)),
- 'practitioner': appointment.practitioner}, order_by="appointment_date", limit=int(max_visit)-1)
-
-def manage_doc_for_appoitnment(dt_from_appointment, appointment, invoiced):
- dn_from_appointment = frappe.db.exists(
+def manage_doc_for_appointment(dt_from_appointment, appointment, invoiced):
+ dn_from_appointment = frappe.db.get_value(
dt_from_appointment,
- {
- "appointment": appointment
- }
+ filters={'appointment': appointment}
)
if dn_from_appointment:
- frappe.db.set_value(dt_from_appointment, dn_from_appointment, "invoiced", invoiced)
+ frappe.db.set_value(dt_from_appointment, dn_from_appointment, 'invoiced', invoiced)
+
@frappe.whitelist()
def get_drugs_to_invoice(encounter):
- encounter = frappe.get_doc("Patient Encounter", encounter)
+ encounter = frappe.get_doc('Patient Encounter', encounter)
if encounter:
- patient = frappe.get_doc("Patient", encounter.patient)
- if patient and patient.customer:
- item_to_invoice = []
+ patient = frappe.get_doc('Patient', encounter.patient)
+ if patient:
+ if patient.customer:
+ items_to_invoice = []
for drug_line in encounter.drug_prescription:
if drug_line.drug_code:
qty = 1
- if frappe.db.get_value("Item", drug_line.drug_code, "stock_uom") == "Nos":
+ if frappe.db.get_value('Item', drug_line.drug_code, 'stock_uom') == 'Nos':
qty = drug_line.get_quantity()
- description = False
- if drug_line.dosage:
- description = drug_line.dosage
- if description and drug_line.period:
- description += " for "+drug_line.period
- if not description:
- description = ""
- item_to_invoice.append({'drug_code': drug_line.drug_code, 'quantity': qty,
- 'description': description})
- return item_to_invoice
+
+ description = ''
+ if drug_line.dosage and drug_line.period:
+ description = _('{0} for {1}').format(drug_line.dosage, drug_line.period)
+
+ items_to_invoice.append({
+ 'drug_code': drug_line.drug_code,
+ 'quantity': qty,
+ 'description': description
+ })
+ return items_to_invoice
+ else:
+ validate_customer_created(patient)
+
@frappe.whitelist()
def get_children(doctype, parent, company, is_root=False):
- parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
+ parent_fieldname = "parent_" + doctype.lower().replace(" ", "_")
fields = [
- 'name as value',
- 'is_group as expandable',
- 'lft',
- 'rgt'
+ "name as value",
+ "is_group as expandable",
+ "lft",
+ "rgt"
]
- # fields = [ 'name', 'is_group', 'lft', 'rgt' ]
- filters = [['ifnull(`{0}`,"")'.format(parent_fieldname), '=', '' if is_root else parent]]
+ # fields = [ "name", "is_group", "lft", "rgt" ]
+ filters = [["ifnull(`{0}`,'')".format(parent_fieldname), "=", "" if is_root else parent]]
if is_root:
- fields += ['service_unit_type'] if doctype == 'Healthcare Service Unit' else []
- filters.append(['company', '=', company])
+ fields += ["service_unit_type"] if doctype == "Healthcare Service Unit" else []
+ filters.append(["company", "=", company])
else:
- fields += ['service_unit_type', 'allow_appointments', 'inpatient_occupancy', 'occupancy_status'] if doctype == 'Healthcare Service Unit' else []
- fields += [parent_fieldname + ' as parent']
+ fields += ["service_unit_type", "allow_appointments", "inpatient_occupancy", "occupancy_status"] if doctype == "Healthcare Service Unit" else []
+ fields += [parent_fieldname + " as parent"]
hc_service_units = frappe.get_list(doctype, fields=fields, filters=filters)
- if doctype == 'Healthcare Service Unit':
+ if doctype == "Healthcare Service Unit":
for each in hc_service_units:
occupancy_msg = ""
- if each['expandable'] == 1:
+ if each["expandable"] == 1:
occupied = False
vacant = False
- child_list = frappe.db.sql("""
- select name, occupancy_status from `tabHealthcare Service Unit`
- where inpatient_occupancy = 1 and
- lft > %s and rgt < %s""",
- (each['lft'], each['rgt']))
+ child_list = frappe.db.sql(
+ '''
+ SELECT
+ name, occupancy_status
+ FROM
+ `tabHealthcare Service Unit`
+ WHERE
+ inpatient_occupancy = 1
+ and lft > %s and rgt < %s
+ ''', (each['lft'], each['rgt']))
+
for child in child_list:
if not occupied:
occupied = 0
@@ -425,39 +499,44 @@ def get_children(doctype, parent, company, is_root=False):
if child[1] == "Vacant":
vacant += 1
if vacant and occupied:
- occupancy_total = vacant+occupied
+ occupancy_total = vacant + occupied
occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
each["occupied_out_of_vacant"] = occupancy_msg
return hc_service_units
+
@frappe.whitelist()
def get_patient_vitals(patient, from_date=None, to_date=None):
if not patient: return
- vitals = frappe.db.sql("""select * from `tabVital Signs` where \
- docstatus=1 and patient=%s order by signs_date, signs_time""", \
- (patient), as_dict=1)
- if vitals and vitals[0]:
+
+ vitals = frappe.db.get_all('Vital Signs', {
+ 'docstatus': 1,
+ 'patient': patient
+ }, order_by='signs_date, signs_time')
+
+ if len(vitals):
return vitals
- else:
- return False
+ return False
+
@frappe.whitelist()
def render_docs_as_html(docs):
# docs key value pair {doctype: docname}
docs_html = "
"
for doc in docs:
- docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + "
"
+ docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + '
'
return {'html': docs_html}
+
@frappe.whitelist()
def render_doc_as_html(doctype, docname, exclude_fields = []):
#render document as html, three column layout will break
doc = frappe.get_doc(doctype, docname)
meta = frappe.get_meta(doctype)
doc_html = "
"
- section_html = ""
- section_label = ""
- html = ""
+ section_html = ''
+ section_label = ''
+ html = ''
sec_on = False
col_on = 0
has_data = False
@@ -476,8 +555,8 @@ def render_doc_as_html(doctype, docname, exclude_fields = []):
sec_on = True
has_data= False
col_on = 0
- section_html = ""
- html = ""
+ section_html = ''
+ html = ''
if df.label:
section_label = df.label
continue
@@ -493,19 +572,19 @@ def render_doc_as_html(doctype, docname, exclude_fields = []):
d-6 col-sm-6'>" + html + "
"
elif sec_on and not col_on:
section_html += "
"
- html = ""
+ html = ''
col_on += 1
if df.label:
html += '
' + df.label
continue
#on table iterate in items and create table based on in_list_view, append to section html or doc html
- if df.fieldtype == "Table":
+ if df.fieldtype == 'Table':
items = doc.get(df.fieldname)
if not items: continue
child_meta = frappe.get_meta(df.options)
if not has_data : has_data = True
- table_head = ""
- table_row = ""
+ table_head = ''
+ table_row = ''
create_head = True
for item in items:
table_row += '
'
@@ -521,24 +600,24 @@ def render_doc_as_html(doctype, docname, exclude_fields = []):
create_head = False
table_row += ' '
if sec_on:
- section_html += '
' + table_head + table_row + '
'
+ section_html += "
" + table_head + table_row + '
'
else:
- html += '
' \
- + table_head + table_row + '
'
+ html += "
" \
+ + table_head + table_row + "
"
continue
#on other field types add label and value to html
if not df.hidden and not df.print_hide and doc.get(df.fieldname) and df.fieldname not in exclude_fields:
- html += "
{0} : {1}".format(df.label or df.fieldname, \
+ html += '
{0} : {1}'.format(df.label or df.fieldname, \
doc.get(df.fieldname))
if not has_data : has_data = True
if sec_on and col_on and has_data:
- doc_html += section_html + html + "
"
+ doc_html += section_html + html + '