Merge branch 'develop' of https://github.com/frappe/erpnext into razorpay-subscription
This commit is contained in:
commit
8e91553d4b
@ -164,7 +164,7 @@ def build_forest(data):
|
||||
error_messages = []
|
||||
|
||||
for i in data:
|
||||
account_name, _, account_number, is_group, account_type, root_type = i
|
||||
account_name, dummy, account_number, is_group, account_type, root_type = i
|
||||
|
||||
if not account_name:
|
||||
error_messages.append("Row {0}: Please enter Account Name".format(line_no))
|
||||
|
||||
@ -794,7 +794,7 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if (frappe.boot.active_domains.includes("Healthcare")){
|
||||
if (frappe.boot.active_domains.includes("Healthcare")) {
|
||||
frm.set_df_property("patient", "hidden", 0);
|
||||
frm.set_df_property("patient_name", "hidden", 0);
|
||||
frm.set_df_property("ref_practitioner", "hidden", 0);
|
||||
@ -807,7 +807,7 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
},"Get items from");
|
||||
}
|
||||
}
|
||||
else{
|
||||
else {
|
||||
frm.set_df_property("patient", "hidden", 1);
|
||||
frm.set_df_property("patient_name", "hidden", 1);
|
||||
frm.set_df_property("ref_practitioner", "hidden", 1);
|
||||
|
||||
@ -162,8 +162,9 @@ def get_default_price_list(party):
|
||||
def set_price_list(party_details, party, party_type, given_price_list, pos=None):
|
||||
# price list
|
||||
price_list = get_permitted_documents('Price List')
|
||||
|
||||
if price_list:
|
||||
|
||||
# if there is only one permitted document based on user permissions, set it
|
||||
if price_list and len(price_list) == 1:
|
||||
price_list = price_list[0]
|
||||
elif pos and party_type == 'Customer':
|
||||
customer_price_list = frappe.get_value('Customer', party.name, 'default_price_list')
|
||||
@ -635,4 +636,4 @@ def get_default_contact(doctype, name):
|
||||
except:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
|
||||
@ -2,131 +2,68 @@ from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
|
||||
return [
|
||||
{
|
||||
"label": _("Consultation"),
|
||||
"icon": "icon-star",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Patient Appointment",
|
||||
"label": _("Patient Appointment"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Patient Encounter",
|
||||
"label": _("Patient Encounter"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Vital Signs",
|
||||
"label": _("Vital Signs"),
|
||||
"description": _("Record Patient Vitals"),
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "patient_history",
|
||||
"label": _("Patient History"),
|
||||
},
|
||||
{
|
||||
"type": "page",
|
||||
"name": "appointment-analytic",
|
||||
"label": _("Appointment Analytics"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Clinical Procedure",
|
||||
"label": _("Clinical Procedure"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Inpatient Record",
|
||||
"label": _("Inpatient Record"),
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Laboratory"),
|
||||
"icon": "icon-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test",
|
||||
"label": _("Lab Test"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Sample Collection",
|
||||
"label": _("Sample Collection"),
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Lab Test Report",
|
||||
"is_query_report": True,
|
||||
"label": _("Lab Test Report"),
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Masters"),
|
||||
"icon": "icon-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Patient",
|
||||
"label": _("Patient"),
|
||||
"onboard": 1,
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Healthcare Practitioner",
|
||||
"label": _("Healthcare Practitioner"),
|
||||
"onboard": 1,
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Practitioner Schedule",
|
||||
"label": _("Practitioner Schedule"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Medical Code Standard",
|
||||
"label": _("Medical Code Standard"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Medical Code",
|
||||
"label": _("Medical Code"),
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Healthcare Service Unit",
|
||||
"label": _("Healthcare Service Unit")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"icon": "icon-cog",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Healthcare Settings",
|
||||
"label": _("Healthcare Settings"),
|
||||
"onboard": 1,
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Medical Department",
|
||||
"label": _("Medical Department"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Healthcare Service Unit Type",
|
||||
"label": _("Healthcare Service Unit Type")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Healthcare Service Unit",
|
||||
"label": _("Healthcare Service Unit")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Medical Code Standard",
|
||||
"label": _("Medical Code Standard")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Medical Code",
|
||||
"label": _("Medical Code")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Consultation Setup"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Appointment Type",
|
||||
"label": _("Appointment Type"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Clinical Procedure Template",
|
||||
"label": _("Clinical Procedure Template")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Prescription Dosage",
|
||||
@ -137,6 +74,36 @@ def get_data():
|
||||
"name": "Prescription Duration",
|
||||
"label": _("Prescription Duration")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Antibiotic",
|
||||
"label": _("Antibiotic")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Consultation"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Patient Appointment",
|
||||
"label": _("Patient Appointment")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Clinical Procedure",
|
||||
"label": _("Clinical Procedure")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Patient Encounter",
|
||||
"label": _("Patient Encounter")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Vital Signs",
|
||||
"label": _("Vital Signs")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Complaint",
|
||||
@ -147,40 +114,104 @@ def get_data():
|
||||
"name": "Diagnosis",
|
||||
"label": _("Diagnosis")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Fee Validity",
|
||||
"label": _("Fee Validity")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Healthcare Settings",
|
||||
"label": _("Healthcare Settings"),
|
||||
"onboard": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Laboratory Setup"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test Template",
|
||||
"label": _("Lab Test Template")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test Sample",
|
||||
"label": _("Lab Test Sample"),
|
||||
"label": _("Lab Test Sample")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test UOM",
|
||||
"label": _("Lab Test UOM")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Antibiotic",
|
||||
"label": _("Antibiotic")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Sensitivity",
|
||||
"label": _("Sensitivity")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Laboratory"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test",
|
||||
"label": _("Lab Test")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test Template",
|
||||
"label": _("Lab Test Template")
|
||||
"name": "Sample Collection",
|
||||
"label": _("Sample Collection")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Clinical Procedure Template",
|
||||
"label": _("Clinical Procedure Template"),
|
||||
"name": "Dosage Form",
|
||||
"label": _("Dosage Form")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Records and History"),
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "patient_history",
|
||||
"label": _("Patient History"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Healthcare Service Unit Type",
|
||||
"label": _("Healthcare Service Unit Type")
|
||||
"name": "Patient Medical Record",
|
||||
"label": _("Patient Medical Record")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Inpatient Record",
|
||||
"label": _("Inpatient Record")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Reports"),
|
||||
"items": [
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Patient Appointment Analytics",
|
||||
"doctype": "Patient Appointment"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Lab Test Report",
|
||||
"doctype": "Lab Test",
|
||||
"label": _("Lab Test Report")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,28 +1,49 @@
|
||||
{
|
||||
"cards": [
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Settings",
|
||||
"links": "[\n {\n \"label\": \"Healthcare Settings\",\n \"name\": \"Healthcare Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Department\",\n \"name\": \"Medical Department\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Appointment Type\",\n \"name\": \"Appointment Type\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Prescription Dosage\",\n \"name\": \"Prescription Dosage\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Prescription Duration\",\n \"name\": \"Prescription Duration\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Complaint\",\n \"name\": \"Complaint\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Diagnosis\",\n \"name\": \"Diagnosis\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test Sample\",\n \"name\": \"Lab Test Sample\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test UOM\",\n \"name\": \"Lab Test UOM\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Antibiotic\",\n \"name\": \"Antibiotic\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Sensitivity\",\n \"name\": \"Sensitivity\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Lab Test Template\",\n \"name\": \"Lab Test Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Clinical Procedure Template\",\n \"name\": \"Clinical Procedure Template\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Service Unit Type\",\n \"name\": \"Healthcare Service Unit Type\",\n \"type\": \"doctype\"\n }\n]"
|
||||
"icon": "",
|
||||
"links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient\",\n\t\t\"label\": \"Patient\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Practitioner\",\n\t\t\"label\":\"Healthcare Practitioner\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Practitioner Schedule\",\n\t\t\"label\": \"Practitioner Schedule\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Department\",\n\t\t\"label\": \"Medical Department\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Service Unit Type\",\n\t\t\"label\": \"Healthcare Service Unit Type\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Service Unit\",\n\t\t\"label\": \"Healthcare Service Unit\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Code Standard\",\n\t\t\"label\": \"Medical Code Standard\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Code\",\n\t\t\"label\": \"Medical Code\"\n\t}\n]",
|
||||
"title": "Masters"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Laboratory",
|
||||
"links": "[\n {\n \"label\": \"Lab Test\",\n \"name\": \"Lab Test\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Sample Collection\",\n \"name\": \"Sample Collection\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Lab Test Report\",\n \"name\": \"Lab Test Report\",\n \"type\": \"report\"\n }\n]"
|
||||
"icon": "",
|
||||
"links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Appointment Type\",\n\t\t\"label\": \"Appointment Type\"\n },\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Clinical Procedure Template\",\n\t\t\"label\": \"Clinical Procedure Template\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Prescription Dosage\",\n\t\t\"label\": \"Prescription Dosage\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Prescription Duration\",\n\t\t\"label\": \"Prescription Duration\"\n\t},\n\t{\n\t \"type\": \"doctype\",\n\t\t\"name\": \"Antibiotic\",\n\t\t\"label\": \"Antibiotic\"\n\t}\n]",
|
||||
"title": "Consultation Setup"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Masters",
|
||||
"links": "[\n {\n \"label\": \"Patient\",\n \"name\": \"Patient\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Practitioner\",\n \"name\": \"Healthcare Practitioner\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Practitioner Schedule\",\n \"name\": \"Practitioner Schedule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Code Standard\",\n \"name\": \"Medical Code Standard\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Medical Code\",\n \"name\": \"Medical Code\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Healthcare Service Unit\",\n \"name\": \"Healthcare Service Unit\",\n \"type\": \"doctype\"\n }\n]"
|
||||
"icon": "icon-star",
|
||||
"links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Appointment\",\n\t\t\"label\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Clinical Procedure\",\n\t\t\"label\": \"Clinical Procedure\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Encounter\",\n\t\t\"label\": \"Patient Encounter\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Vital Signs\",\n\t\t\"label\": \"Vital Signs\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Complaint\",\n\t\t\"label\": \"Complaint\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Diagnosis\",\n\t\t\"label\": \"Diagnosis\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Fee Validity\",\n\t\t\"label\": \"Fee Validity\"\n\t}\n]",
|
||||
"title": "Consultation"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Consultation",
|
||||
"links": "[\n {\n \"label\": \"Patient Appointment\",\n \"name\": \"Patient Appointment\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Patient Encounter\",\n \"name\": \"Patient Encounter\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Record Patient Vitals\",\n \"label\": \"Vital Signs\",\n \"name\": \"Vital Signs\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Patient History\",\n \"name\": \"patient_history\",\n \"type\": \"page\"\n },\n {\n \"label\": \"Appointment Analytics\",\n \"name\": \"appointment-analytic\",\n \"type\": \"page\"\n },\n {\n \"label\": \"Clinical Procedure\",\n \"name\": \"Clinical Procedure\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Inpatient Record\",\n \"name\": \"Inpatient Record\",\n \"type\": \"doctype\"\n }\n]"
|
||||
"links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Settings\",\n\t\t\"label\": \"Healthcare Settings\",\n\t\t\"onboard\": 1\n\t}\n]",
|
||||
"title": "Settings"
|
||||
},
|
||||
{
|
||||
"links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test Template\",\n\t\t\"label\": \"Lab Test Template\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test Sample\",\n\t\t\"label\": \"Lab Test Sample\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test UOM\",\n\t\t\"label\": \"Lab Test UOM\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Sensitivity\",\n\t\t\"label\": \"Sensitivity\"\n\t}\n]",
|
||||
"title": "Laboratory Setup"
|
||||
},
|
||||
{
|
||||
"links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test\",\n\t\t\"label\": \"Lab Test\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Sample Collection\",\n\t\t\"label\": \"Sample Collection\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Dosage Form\",\n\t\t\"label\": \"Dosage Form\"\n\t}\n]",
|
||||
"title": "Laboratory"
|
||||
},
|
||||
{
|
||||
"links": "[\n\t{\n\t\t\"type\": \"page\",\n\t\t\"name\": \"patient_history\",\n\t\t\"label\": \"Patient History\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Medical Record\",\n\t\t\"label\": \"Patient Medical Record\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Inpatient Record\",\n\t\t\"label\": \"Inpatient Record\"\n\t}\n]",
|
||||
"title": "Records and History"
|
||||
},
|
||||
{
|
||||
"links": "[\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Patient Appointment Analytics\",\n\t\t\"doctype\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Lab Test Report\",\n\t\t\"doctype\": \"Lab Test\",\n\t\t\"label\": \"Lab Test Report\"\n\t}\n]",
|
||||
"title": "Reports"
|
||||
}
|
||||
],
|
||||
"category": "Domains",
|
||||
"charts": [],
|
||||
"charts": [
|
||||
{
|
||||
"chart_name": "Patient Appointments",
|
||||
"label": "Patient Appointments"
|
||||
}
|
||||
],
|
||||
"charts_label": "",
|
||||
"creation": "2020-03-02 17:23:17.919682",
|
||||
"developer_mode_only": 0,
|
||||
"disable_user_customization": 0,
|
||||
@ -32,7 +53,7 @@
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Healthcare",
|
||||
"modified": "2020-04-01 11:28:50.996366",
|
||||
"modified": "2020-03-26 16:10:44.629795",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare",
|
||||
@ -40,5 +61,37 @@
|
||||
"pin_to_bottom": 0,
|
||||
"pin_to_top": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"shortcuts": []
|
||||
"shortcuts": [
|
||||
{
|
||||
"format": "{} Open",
|
||||
"is_query_report": 0,
|
||||
"link_to": "Patient Appointment",
|
||||
"stats_filter": "{\n \"status\": \"Open\"\n}",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"format": "{} Active",
|
||||
"is_query_report": 0,
|
||||
"link_to": "Patient",
|
||||
"stats_filter": "{\n \"status\": \"Active\"\n}",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"format": "{} Vacant",
|
||||
"is_query_report": 0,
|
||||
"link_to": "Healthcare Service Unit",
|
||||
"stats_filter": "{\n \"occupancy_status\": \"Vacant\",\n \"is_group\": 0\n}",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"is_query_report": 0,
|
||||
"link_to": "Healthcare Practitioner",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"is_query_report": 0,
|
||||
"link_to": "patient_history",
|
||||
"type": "Page"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,213 +1,94 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:appointment_type",
|
||||
"beta": 1,
|
||||
"creation": "2016-07-22 11:52:34.953019",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:appointment_type",
|
||||
"beta": 1,
|
||||
"creation": "2016-07-22 11:52:34.953019",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"appointment_type",
|
||||
"ip",
|
||||
"default_duration",
|
||||
"color"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "appointment_type",
|
||||
"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": "Type",
|
||||
"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": 1,
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "appointment_type",
|
||||
"fieldtype": "Data",
|
||||
"ignore_xss_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
"reqd": 1,
|
||||
"translatable": 1,
|
||||
"unique": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "ip",
|
||||
"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": "Is Inpatient",
|
||||
"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
|
||||
},
|
||||
"bold": 1,
|
||||
"default": "0",
|
||||
"fieldname": "ip",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Inpatient",
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "In Minutes",
|
||||
"fieldname": "default_duration",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Default 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
|
||||
},
|
||||
"allow_in_quick_entry": 1,
|
||||
"bold": 1,
|
||||
"fieldname": "default_duration",
|
||||
"fieldtype": "Int",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Default Duration (In Minutes)"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "color",
|
||||
"fieldtype": "Color",
|
||||
"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": "Color",
|
||||
"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": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "color",
|
||||
"fieldtype": "Color",
|
||||
"in_list_view": 1,
|
||||
"label": "Color",
|
||||
"no_copy": 1,
|
||||
"report_hide": 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-08-08 12:57:54.544216",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Appointment Type",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-02-03 21:06:05.833050",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Appointment Type",
|
||||
"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,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Healthcare Administrator",
|
||||
"share": 1,
|
||||
"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,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Physician",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"search_fields": "appointment_type",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"search_fields": "appointment_type",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'appointment_type',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Patient Appointments'),
|
||||
'items': ['Patient Appointment']
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -4,244 +4,285 @@
|
||||
frappe.ui.form.on('Clinical Procedure', {
|
||||
setup: function(frm) {
|
||||
frm.set_query('batch_no', 'items', function(doc, cdt, cdn) {
|
||||
var item = locals[cdt][cdn];
|
||||
if(!item.item_code) {
|
||||
frappe.throw(__("Please enter Item Code to get Batch Number"));
|
||||
let item = locals[cdt][cdn];
|
||||
if (!item.item_code) {
|
||||
frappe.throw(__('Please enter Item Code to get Batch Number'));
|
||||
} else {
|
||||
let filters = {'item_code': item.item_code};
|
||||
|
||||
if (frm.doc.status == 'In Progress') {
|
||||
var filters = {
|
||||
'item_code': item.item_code,
|
||||
'posting_date': frm.doc.start_date || frappe.datetime.nowdate()
|
||||
};
|
||||
if(frm.doc.warehouse) filters["warehouse"] = frm.doc.warehouse;
|
||||
} else {
|
||||
filters = {
|
||||
'item_code': item.item_code
|
||||
};
|
||||
filters['posting_date'] = frm.doc.start_date || frappe.datetime.nowdate();
|
||||
if (frm.doc.warehouse) filters['warehouse'] = frm.doc.warehouse;
|
||||
}
|
||||
|
||||
return {
|
||||
query : "erpnext.controllers.queries.get_batch_no",
|
||||
query : 'erpnext.controllers.queries.get_batch_no',
|
||||
filters: filters
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.set_query("patient", function () {
|
||||
frm.set_query('patient', function () {
|
||||
return {
|
||||
filters: {"disabled": 0}
|
||||
filters: {'status': ['!=', 'Disabled']}
|
||||
};
|
||||
});
|
||||
frm.set_query("appointment", function () {
|
||||
|
||||
frm.set_query('appointment', function () {
|
||||
return {
|
||||
filters: {
|
||||
"procedure_template": ["not in", null],
|
||||
"status": ['in', 'Open, Scheduled']
|
||||
'procedure_template': ['not in', null],
|
||||
'status': ['in', 'Open, Scheduled']
|
||||
}
|
||||
};
|
||||
});
|
||||
frm.set_query("service_unit", function(){
|
||||
|
||||
frm.set_query('service_unit', function() {
|
||||
return {
|
||||
filters: {
|
||||
"is_group": false,
|
||||
"allow_appointments": true
|
||||
'is_group': false,
|
||||
'allow_appointments': true
|
||||
}
|
||||
};
|
||||
});
|
||||
frm.set_query("practitioner", function() {
|
||||
|
||||
frm.set_query('practitioner', function() {
|
||||
return {
|
||||
filters: {
|
||||
'department': frm.doc.medical_department
|
||||
}
|
||||
};
|
||||
});
|
||||
if(frm.doc.consume_stock){
|
||||
|
||||
if (frm.doc.consume_stock) {
|
||||
frm.set_indicator_formatter('item_code',
|
||||
function(doc) { return (doc.qty<=doc.actual_qty) ? "green" : "orange" ; });
|
||||
function(doc) { return (doc.qty<=doc.actual_qty) ? 'green' : 'orange' ; });
|
||||
}
|
||||
|
||||
if (!frm.doc.__islocal && frm.doc.status == 'In Progress'){
|
||||
if (frm.doc.docstatus == 1) {
|
||||
if (frm.doc.status == 'In Progress') {
|
||||
let btn_label = '';
|
||||
let msg = '';
|
||||
if (frm.doc.consume_stock) {
|
||||
btn_label = __('Complete and Consume');
|
||||
msg = __('Complete {0} and Consume Stock?', [frm.doc.name]);
|
||||
} else {
|
||||
btn_label = 'Complete';
|
||||
msg = __('Complete {0}?', [frm.doc.name]);
|
||||
}
|
||||
|
||||
if(frm.doc.consume_stock){
|
||||
var btn_label = 'Complete and Consume';
|
||||
var msg = 'Complete '+frm.doc.name+' and Consume Stock?';
|
||||
}else{
|
||||
btn_label = 'Complete';
|
||||
msg = 'Complete '+frm.doc.name+'?';
|
||||
}
|
||||
frm.add_custom_button(__(btn_label), function () {
|
||||
frappe.confirm(
|
||||
msg,
|
||||
function() {
|
||||
frappe.call({
|
||||
method: 'complete_procedure',
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
frappe.show_alert({
|
||||
message: __('Stock Entry {0} created',
|
||||
['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
|
||||
indicator: 'green'
|
||||
});
|
||||
frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}).addClass("btn-primary");
|
||||
|
||||
frm.add_custom_button(__(btn_label), function () {
|
||||
frappe.confirm(
|
||||
__(msg),
|
||||
function(){
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "complete",
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
} else if (frm.doc.status == 'Pending') {
|
||||
frm.add_custom_button(__('Start'), function() {
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: 'start_procedure',
|
||||
callback: function(r) {
|
||||
if (!r.exc) {
|
||||
if (r.message == 'insufficient stock') {
|
||||
let msg = __('Stock quantity to start the Procedure is not available in the Warehouse {0}. Do you want to record a Stock Entry?',
|
||||
[frm.doc.warehouse.bold()]);
|
||||
frappe.confirm(
|
||||
msg,
|
||||
function() {
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: 'make_material_receipt',
|
||||
callback: function(r) {
|
||||
if (!r.exc) {
|
||||
cur_frm.reload_doc();
|
||||
let doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}else if (frm.doc.status == 'Draft') {
|
||||
frm.add_custom_button(__("Start"), function () {
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "start",
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
if(frm.doc.status == 'Draft'){
|
||||
frappe.confirm(
|
||||
__("Stock quantity to start procedure is not available in the warehouse. Do you want to record a Stock Transfer"),
|
||||
function(){
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "make_material_transfer",
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
cur_frm.reload_doc();
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}else{
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (frm.doc.__islocal){
|
||||
frm.set_df_property("consumables", "hidden", 1);
|
||||
}else{
|
||||
frm.set_df_property("consumables", "hidden", 0);
|
||||
});
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
}
|
||||
},
|
||||
onload: function(frm){
|
||||
if(frm.doc.status == 'Completed'){
|
||||
frm.set_df_property("items", "read_only", 1);
|
||||
}
|
||||
if(frm.is_new()) {
|
||||
frm.add_fetch("procedure_template", "medical_department", "medical_department");
|
||||
frm.set_value("start_time", null);
|
||||
|
||||
onload: function(frm) {
|
||||
if (frm.is_new()) {
|
||||
frm.add_fetch('procedure_template', 'medical_department', 'medical_department');
|
||||
frm.set_value('start_time', null);
|
||||
}
|
||||
},
|
||||
|
||||
patient: function(frm) {
|
||||
if(frm.doc.patient){
|
||||
if (frm.doc.patient) {
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
|
||||
'method': 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
|
||||
args: {
|
||||
patient: frm.doc.patient
|
||||
},
|
||||
callback: function (data) {
|
||||
let age = "";
|
||||
if(data.message.dob){
|
||||
let age = '';
|
||||
if (data.message.dob) {
|
||||
age = calculate_age(data.message.dob);
|
||||
}else if (data.message.age){
|
||||
} else if (data.message.age) {
|
||||
age = data.message.age;
|
||||
if(data.message.age_as_on){
|
||||
age = age+" as on "+data.message.age_as_on;
|
||||
if (data.message.age_as_on) {
|
||||
age = __('{0} as on {1}', [age, data.message.age_as_on]);
|
||||
}
|
||||
}
|
||||
frm.set_value("patient_age", age);
|
||||
frm.set_value("patient_sex", data.message.sex);
|
||||
frm.set_value('patient_age', age);
|
||||
frm.set_value('patient_sex', data.message.sex);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
frm.set_value("patient_age", "");
|
||||
frm.set_value("patient_sex", "");
|
||||
} else {
|
||||
frm.set_value('patient_age', '');
|
||||
frm.set_value('patient_sex', '');
|
||||
}
|
||||
},
|
||||
|
||||
appointment: function(frm) {
|
||||
if(frm.doc.appointment){
|
||||
if (frm.doc.appointment) {
|
||||
frappe.call({
|
||||
"method": "frappe.client.get",
|
||||
'method': 'frappe.client.get',
|
||||
args: {
|
||||
doctype: "Patient Appointment",
|
||||
doctype: 'Patient Appointment',
|
||||
name: frm.doc.appointment
|
||||
},
|
||||
callback: function (data) {
|
||||
frm.set_value("patient", data.message.patient);
|
||||
frm.set_value("procedure_template", data.message.procedure_template);
|
||||
frm.set_value("medical_department", data.message.department);
|
||||
frm.set_value("start_date", data.message.appointment_date);
|
||||
frm.set_value("start_time", data.message.appointment_time);
|
||||
frm.set_value("notes", data.message.notes);
|
||||
frm.set_value("service_unit", data.message.service_unit);
|
||||
callback: function(data) {
|
||||
frm.set_value('patient', data.message.patient);
|
||||
frm.set_value('procedure_template', data.message.procedure_template);
|
||||
frm.set_value('medical_department', data.message.department);
|
||||
frm.set_value('start_date', data.message.appointment_date);
|
||||
frm.set_value('start_time', data.message.appointment_time);
|
||||
frm.set_value('notes', data.message.notes);
|
||||
frm.set_value('service_unit', data.message.service_unit);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
procedure_template: function(frm) {
|
||||
if(frm.doc.procedure_template){
|
||||
if (frm.doc.procedure_template) {
|
||||
frappe.call({
|
||||
"method": "frappe.client.get",
|
||||
'method': 'frappe.client.get',
|
||||
args: {
|
||||
doctype: "Clinical Procedure Template",
|
||||
doctype: 'Clinical Procedure Template',
|
||||
name: frm.doc.procedure_template
|
||||
},
|
||||
callback: function (data) {
|
||||
frm.set_value("medical_department", data.message.medical_department);
|
||||
frm.set_value("consume_stock", data.message.consume_stock);
|
||||
if(!frm.doc.warehouse){
|
||||
frappe.call({
|
||||
method: "frappe.client.get_value",
|
||||
args: {
|
||||
doctype: "Stock Settings",
|
||||
fieldname: "default_warehouse"
|
||||
},
|
||||
callback: function (data) {
|
||||
frm.set_value("warehouse", data.message.default_warehouse);
|
||||
}
|
||||
});
|
||||
}
|
||||
frm.set_value('medical_department', data.message.medical_department);
|
||||
frm.set_value('consume_stock', data.message.consume_stock);
|
||||
frm.events.set_warehouse(frm);
|
||||
frm.events.set_procedure_consumables(frm);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
frm.set_value("consume_stock", 0);
|
||||
}
|
||||
},
|
||||
|
||||
service_unit: function(frm) {
|
||||
if(frm.doc.service_unit){
|
||||
if (frm.doc.service_unit) {
|
||||
frappe.call({
|
||||
method: "frappe.client.get_value",
|
||||
method: 'frappe.client.get_value',
|
||||
args:{
|
||||
fieldname: "warehouse",
|
||||
doctype: "Healthcare Service Unit",
|
||||
fieldname: 'warehouse',
|
||||
doctype: 'Healthcare Service Unit',
|
||||
filters:{name: frm.doc.service_unit},
|
||||
},
|
||||
callback: function(data) {
|
||||
if(data.message){
|
||||
frm.set_value("warehouse", data.message.warehouse);
|
||||
if (data.message) {
|
||||
frm.set_value('warehouse', data.message.warehouse);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
practitioner: function(frm) {
|
||||
if(frm.doc.practitioner){
|
||||
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, "medical_department",data.message.department);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'medical_department',data.message.department);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
set_warehouse: function(frm) {
|
||||
if (!frm.doc.warehouse) {
|
||||
frappe.call({
|
||||
method: 'frappe.client.get_value',
|
||||
args: {
|
||||
doctype: 'Stock Settings',
|
||||
fieldname: 'default_warehouse'
|
||||
},
|
||||
callback: function (data) {
|
||||
frm.set_value('warehouse', data.message.default_warehouse);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
set_procedure_consumables: function(frm) {
|
||||
frappe.call({
|
||||
method: 'erpnext.healthcare.doctype.clinical_procedure.clinical_procedure.get_procedure_consumables',
|
||||
args: {
|
||||
procedure_template: frm.doc.procedure_template
|
||||
},
|
||||
callback: function(data) {
|
||||
if (data.message) {
|
||||
frm.doc.items = [];
|
||||
$.each(data.message, function(i, v) {
|
||||
let item = frm.add_child('items');
|
||||
item.item_code = v.item_code;
|
||||
item.item_name = v.item_name;
|
||||
item.uom = v.uom;
|
||||
item.stock_uom = v.stock_uom;
|
||||
item.qty = flt(v.qty);
|
||||
item.transfer_qty = v.transfer_qty;
|
||||
item.conversion_factor = v.conversion_factor;
|
||||
item.invoice_separately_as_consumables = v.invoice_separately_as_consumables;
|
||||
item.batch_no = v.batch_no;
|
||||
});
|
||||
refresh_field('items');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
cur_frm.set_query("procedure_template", function(doc) {
|
||||
cur_frm.set_query('procedure_template', function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
'medical_department': doc.medical_department
|
||||
@ -249,57 +290,51 @@ cur_frm.set_query("procedure_template", function(doc) {
|
||||
};
|
||||
});
|
||||
|
||||
cur_frm.set_query("appointment", function() {
|
||||
return {
|
||||
filters: {
|
||||
status:['in',["Open"]]
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Clinical Procedure Item', {
|
||||
qty: function(frm, cdt, cdn){
|
||||
var d = locals[cdt][cdn];
|
||||
frappe.model.set_value(cdt, cdn, "transfer_qty", d.qty*d.conversion_factor);
|
||||
qty: function(frm, cdt, cdn) {
|
||||
let d = locals[cdt][cdn];
|
||||
frappe.model.set_value(cdt, cdn, 'transfer_qty', d.qty*d.conversion_factor);
|
||||
},
|
||||
uom: function(doc, cdt, cdn){
|
||||
var d = locals[cdt][cdn];
|
||||
if(d.uom && d.item_code){
|
||||
|
||||
uom: function(doc, cdt, cdn) {
|
||||
let d = locals[cdt][cdn];
|
||||
if (d.uom && d.item_code) {
|
||||
return frappe.call({
|
||||
method: "erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details",
|
||||
method: 'erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details',
|
||||
args: {
|
||||
item_code: d.item_code,
|
||||
uom: d.uom,
|
||||
qty: d.qty
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
if (r.message) {
|
||||
frappe.model.set_value(cdt, cdn, r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
item_code: function(frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
let d = locals[cdt][cdn];
|
||||
let args = null;
|
||||
if(d.item_code) {
|
||||
if (d.item_code) {
|
||||
args = {
|
||||
'doctype' : "Clinical Procedure",
|
||||
'doctype' : 'Clinical Procedure',
|
||||
'item_code' : d.item_code,
|
||||
'company' : frm.doc.company,
|
||||
'warehouse': frm.doc.warehouse
|
||||
};
|
||||
return frappe.call({
|
||||
method: "erpnext.stock.get_item_details.get_item_details",
|
||||
method: 'erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.get_item_details',
|
||||
args: {args: args},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
frappe.model.set_value(cdt, cdn, "item_name", r.message.item_name);
|
||||
frappe.model.set_value(cdt, cdn, "stock_uom", r.message.stock_uom);
|
||||
frappe.model.set_value(cdt, cdn, "conversion_factor", r.message.conversion_factor);
|
||||
frappe.model.set_value(cdt, cdn, "actual_qty", r.message.actual_qty);
|
||||
refresh_field("items");
|
||||
if (r.message) {
|
||||
let d = locals[cdt][cdn];
|
||||
$.each(r.message, function(k, v) {
|
||||
d[k] = v;
|
||||
});
|
||||
refresh_field('items');
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -307,16 +342,16 @@ frappe.ui.form.on('Clinical Procedure Item', {
|
||||
}
|
||||
});
|
||||
|
||||
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)';
|
||||
};
|
||||
|
||||
// List Stock items
|
||||
cur_frm.set_query("item_code", "items", function() {
|
||||
cur_frm.set_query('item_code', 'items', function() {
|
||||
return {
|
||||
filters: {
|
||||
is_stock_item:1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -6,88 +6,101 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, flt, nowdate, nowtime, cstr
|
||||
from frappe.utils import flt, nowdate, nowtime, cstr
|
||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account
|
||||
from erpnext.healthcare.doctype.lab_test.lab_test import create_sample_doc
|
||||
from erpnext.stock.stock_ledger import get_previous_sle
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
class ClinicalProcedure(Document):
|
||||
def validate(self):
|
||||
if self.consume_stock and not self.status == 'Draft':
|
||||
if not self.warehouse:
|
||||
frappe.throw(_("Set warehouse for Procedure {0} ").format(self.name))
|
||||
self.set_status()
|
||||
if self.consume_stock:
|
||||
self.set_actual_qty()
|
||||
|
||||
if self.items:
|
||||
self.invoice_separately_as_consumables = False
|
||||
for item in self.items:
|
||||
if item.invoice_separately_as_consumables == 1:
|
||||
if item.invoice_separately_as_consumables:
|
||||
self.invoice_separately_as_consumables = True
|
||||
|
||||
def before_insert(self):
|
||||
if self.consume_stock:
|
||||
set_stock_items(self, self.procedure_template, "Clinical Procedure Template")
|
||||
self.set_actual_qty();
|
||||
self.set_actual_qty()
|
||||
|
||||
def after_insert(self):
|
||||
if self.prescription:
|
||||
frappe.db.set_value("Procedure Prescription", self.prescription, "procedure_created", 1)
|
||||
frappe.db.set_value('Procedure Prescription', self.prescription, 'procedure_created', 1)
|
||||
if self.appointment:
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
|
||||
template = frappe.get_doc("Clinical Procedure Template", self.procedure_template)
|
||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
|
||||
template = frappe.get_doc('Clinical Procedure Template', self.procedure_template)
|
||||
if template.sample:
|
||||
patient = frappe.get_doc("Patient", self.patient)
|
||||
patient = frappe.get_doc('Patient', self.patient)
|
||||
sample_collection = create_sample_doc(template, patient, None)
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "sample", sample_collection.name)
|
||||
frappe.db.set_value('Clinical Procedure', self.name, 'sample', sample_collection.name)
|
||||
self.reload()
|
||||
|
||||
def complete(self):
|
||||
def set_status(self):
|
||||
if self.docstatus == 0:
|
||||
self.status = 'Draft'
|
||||
elif self.docstatus == 1:
|
||||
if self.status not in ['In Progress', 'Completed']:
|
||||
self.status = 'Pending'
|
||||
elif self.docstatus == 2:
|
||||
self.status = 'Cancelled'
|
||||
|
||||
def complete_procedure(self):
|
||||
if self.consume_stock and self.items:
|
||||
create_stock_entry(self)
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "status", 'Completed')
|
||||
stock_entry = make_stock_entry(self)
|
||||
|
||||
if self.items:
|
||||
consumable_total_amount = 0
|
||||
consumption_details = False
|
||||
for item in self.items:
|
||||
if item.invoice_separately_as_consumables:
|
||||
price_list, price_list_currency = frappe.db.get_values("Price List", {"selling": 1}, ['name', 'currency'])[0]
|
||||
args = {
|
||||
'doctype': "Sales Invoice",
|
||||
'item_code': item.item_code,
|
||||
'company': self.company,
|
||||
'warehouse': self.warehouse,
|
||||
'customer': frappe.db.get_value("Patient", self.patient, "customer"),
|
||||
'selling_price_list': price_list,
|
||||
'price_list_currency': price_list_currency,
|
||||
'plc_conversion_rate': 1.0,
|
||||
'conversion_rate': 1.0
|
||||
}
|
||||
item_details = get_item_details(args)
|
||||
item_price = item_details.price_list_rate * item.transfer_qty
|
||||
item_consumption_details = item_details.item_name+"\t"+str(item.qty)+" "+item.uom+"\t"+str(item_price)
|
||||
consumable_total_amount += item_price
|
||||
if not consumption_details:
|
||||
consumption_details = "Clinical Procedure ("+self.name+"):\n\t"+item_consumption_details
|
||||
else:
|
||||
consumption_details += "\n\t"+item_consumption_details
|
||||
if consumable_total_amount > 0:
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "consumable_total_amount", consumable_total_amount)
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "consumption_details", consumption_details)
|
||||
customer = frappe.db.get_value('Patient', self.patient, 'customer')
|
||||
if customer:
|
||||
for item in self.items:
|
||||
if item.invoice_separately_as_consumables:
|
||||
price_list, price_list_currency = frappe.db.get_values('Price List', {'selling': 1}, ['name', 'currency'])[0]
|
||||
args = {
|
||||
'doctype': 'Sales Invoice',
|
||||
'item_code': item.item_code,
|
||||
'company': self.company,
|
||||
'warehouse': self.warehouse,
|
||||
'customer': customer,
|
||||
'selling_price_list': price_list,
|
||||
'price_list_currency': price_list_currency,
|
||||
'plc_conversion_rate': 1.0,
|
||||
'conversion_rate': 1.0
|
||||
}
|
||||
item_details = get_item_details(args)
|
||||
item_price = item_details.price_list_rate * item.qty
|
||||
item_consumption_details = item_details.item_name + ' ' + str(item.qty) + ' ' + item.uom + ' ' + str(item_price)
|
||||
consumable_total_amount += item_price
|
||||
if not consumption_details:
|
||||
consumption_details = _('Clinical Procedure ({0}):').format(self.name)
|
||||
consumption_details += '\n\t' + item_consumption_details
|
||||
|
||||
if consumable_total_amount > 0:
|
||||
frappe.db.set_value('Clinical Procedure', self.name, 'consumable_total_amount', consumable_total_amount)
|
||||
frappe.db.set_value('Clinical Procedure', self.name, 'consumption_details', consumption_details)
|
||||
else:
|
||||
frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
|
||||
|
||||
def start(self):
|
||||
frappe.db.set_value('Clinical Procedure', self.name, 'status', 'Completed')
|
||||
if self.consume_stock and self.items:
|
||||
return stock_entry
|
||||
|
||||
def start_procedure(self):
|
||||
allow_start = self.set_actual_qty()
|
||||
if allow_start:
|
||||
self.status = 'In Progress'
|
||||
self.db_set('status', 'In Progress')
|
||||
insert_clinical_procedure_to_medical_record(self)
|
||||
else:
|
||||
self.status = 'Draft'
|
||||
self.save()
|
||||
return 'success'
|
||||
return 'insufficient stock'
|
||||
|
||||
def set_actual_qty(self):
|
||||
allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
|
||||
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
||||
|
||||
allow_start = True
|
||||
for d in self.get('items'):
|
||||
@ -95,15 +108,16 @@ class ClinicalProcedure(Document):
|
||||
# validate qty
|
||||
if not allow_negative_stock and d.actual_qty < d.qty:
|
||||
allow_start = False
|
||||
break
|
||||
|
||||
return allow_start
|
||||
|
||||
def make_material_transfer(self):
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
def make_material_receipt(self, submit=False):
|
||||
stock_entry = frappe.new_doc('Stock Entry')
|
||||
|
||||
stock_entry.purpose = "Material Transfer"
|
||||
stock_entry.stock_entry_type = 'Material Receipt'
|
||||
stock_entry.to_warehouse = self.warehouse
|
||||
expense_account = get_account(None, "expense_account", "Healthcare Settings", self.company)
|
||||
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', self.company)
|
||||
for item in self.items:
|
||||
if item.qty > item.actual_qty:
|
||||
se_child = stock_entry.append('items')
|
||||
@ -111,7 +125,7 @@ class ClinicalProcedure(Document):
|
||||
se_child.item_name = item.item_name
|
||||
se_child.uom = item.uom
|
||||
se_child.stock_uom = item.stock_uom
|
||||
se_child.qty = flt(item.qty-item.actual_qty)
|
||||
se_child.qty = flt(item.qty - item.actual_qty)
|
||||
se_child.t_warehouse = self.warehouse
|
||||
# in stock uom
|
||||
se_child.transfer_qty = flt(item.transfer_qty)
|
||||
@ -119,104 +133,130 @@ class ClinicalProcedure(Document):
|
||||
cost_center = frappe.get_cached_value('Company', self.company, 'cost_center')
|
||||
se_child.cost_center = cost_center
|
||||
se_child.expense_account = expense_account
|
||||
if submit:
|
||||
stock_entry.submit()
|
||||
return stock_entry
|
||||
return stock_entry.as_dict()
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
def get_stock_qty(item_code, warehouse):
|
||||
return get_previous_sle({
|
||||
"item_code": item_code,
|
||||
"warehouse": warehouse,
|
||||
"posting_date": nowdate(),
|
||||
"posting_time": nowtime()
|
||||
}).get("qty_after_transaction") or 0
|
||||
'item_code': item_code,
|
||||
'warehouse': warehouse,
|
||||
'posting_date': nowdate(),
|
||||
'posting_time': nowtime()
|
||||
}).get('qty_after_transaction') or 0
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_procedure_consumables(procedure_template):
|
||||
return get_items('Clinical Procedure Item', procedure_template, 'Clinical Procedure Template')
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_stock_items(doc, stock_detail_parent, parenttype):
|
||||
item_dict = get_item_dict("Clinical Procedure Item", stock_detail_parent, parenttype)
|
||||
items = get_items('Clinical Procedure Item', stock_detail_parent, parenttype)
|
||||
|
||||
for d in item_dict:
|
||||
for item in items:
|
||||
se_child = doc.append('items')
|
||||
se_child.item_code = d["item_code"]
|
||||
se_child.item_name = d["item_name"]
|
||||
se_child.uom = d["uom"]
|
||||
se_child.stock_uom = d["stock_uom"]
|
||||
se_child.qty = flt(d["qty"])
|
||||
se_child.item_code = item.item_code
|
||||
se_child.item_name = item.item_name
|
||||
se_child.uom = item.uom
|
||||
se_child.stock_uom = item.stock_uom
|
||||
se_child.qty = flt(item.qty)
|
||||
# in stock uom
|
||||
se_child.transfer_qty = flt(d["transfer_qty"])
|
||||
se_child.conversion_factor = flt(d["conversion_factor"])
|
||||
if d["batch_no"]:
|
||||
se_child.batch_no = d["batch_no"]
|
||||
if parenttype == "Clinical Procedure Template":
|
||||
se_child.invoice_separately_as_consumables = d["invoice_separately_as_consumables"]
|
||||
se_child.transfer_qty = flt(item.transfer_qty)
|
||||
se_child.conversion_factor = flt(item.conversion_factor)
|
||||
if item.batch_no:
|
||||
se_child.batch_no = item.batch_no
|
||||
if parenttype == 'Clinical Procedure Template':
|
||||
se_child.invoice_separately_as_consumables = item.invoice_separately_as_consumables
|
||||
|
||||
return doc
|
||||
|
||||
def get_item_dict(table, parent, parenttype):
|
||||
query = """select * from `tab{table}` where parent = '{parent}' and parenttype = '{parenttype}' """
|
||||
|
||||
return frappe.db.sql(query.format(table=table, parent=parent, parenttype=parenttype), as_dict=True)
|
||||
def get_items(table, parent, parenttype):
|
||||
items = frappe.db.get_all(table, filters={
|
||||
'parent': parent,
|
||||
'parenttype': parenttype
|
||||
}, fields=['*'])
|
||||
|
||||
def create_stock_entry(doc):
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry = set_stock_items(stock_entry, doc.name, "Clinical Procedure")
|
||||
stock_entry.purpose = "Material Issue"
|
||||
return items
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_stock_entry(doc):
|
||||
stock_entry = frappe.new_doc('Stock Entry')
|
||||
stock_entry = set_stock_items(stock_entry, doc.name, 'Clinical Procedure')
|
||||
stock_entry.stock_entry_type = 'Material Issue'
|
||||
stock_entry.from_warehouse = doc.warehouse
|
||||
stock_entry.company = doc.company
|
||||
expense_account = get_account(None, "expense_account", "Healthcare Settings", doc.company)
|
||||
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', doc.company)
|
||||
|
||||
for item_line in stock_entry.items:
|
||||
cost_center = frappe.get_cached_value('Company', doc.company, 'cost_center')
|
||||
#item_line.s_warehouse = warehouse #deaful source warehouse set, stock entry to copy to lines
|
||||
item_line.cost_center = cost_center
|
||||
#if not expense_account:
|
||||
# expense_account = frappe.db.get_value("Item", item_line.item_code, "expense_account")
|
||||
item_line.expense_account = expense_account
|
||||
|
||||
stock_entry.insert(ignore_permissions = True)
|
||||
stock_entry.save(ignore_permissions=True)
|
||||
stock_entry.submit()
|
||||
return stock_entry.name
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_procedure(appointment):
|
||||
appointment = frappe.get_doc("Patient Appointment",appointment)
|
||||
procedure = frappe.new_doc("Clinical Procedure")
|
||||
procedure.appointment = appointment.name
|
||||
procedure.patient = appointment.patient
|
||||
procedure.patient_age = appointment.patient_age
|
||||
procedure.patient_sex = appointment.patient_sex
|
||||
procedure.procedure_template = appointment.procedure_template
|
||||
procedure.prescription = appointment.procedure_prescription
|
||||
procedure.practitioner = appointment.practitioner
|
||||
procedure.invoiced = appointment.invoiced
|
||||
procedure.medical_department = appointment.department
|
||||
procedure.start_date = appointment.appointment_date
|
||||
procedure.start_time = appointment.appointment_time
|
||||
procedure.notes = appointment.notes
|
||||
procedure.service_unit = appointment.service_unit
|
||||
procedure.company = appointment.company
|
||||
consume_stock = frappe.db.get_value("Clinical Procedure Template", appointment.procedure_template, "consume_stock")
|
||||
if consume_stock == 1:
|
||||
procedure.consume_stock = True
|
||||
warehouse = False
|
||||
if appointment.service_unit:
|
||||
warehouse = frappe.db.get_value("Healthcare Service Unit", appointment.service_unit, "warehouse")
|
||||
if not warehouse:
|
||||
warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse")
|
||||
if warehouse:
|
||||
procedure.warehouse = warehouse
|
||||
return procedure.as_dict()
|
||||
def make_procedure(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
consume_stock = frappe.db.get_value('Clinical Procedure Template', source.procedure_template, 'consume_stock')
|
||||
if consume_stock:
|
||||
target.consume_stock = 1
|
||||
warehouse = None
|
||||
if source.service_unit:
|
||||
warehouse = frappe.db.get_value('Healthcare Service Unit', source.service_unit, 'warehouse')
|
||||
if not warehouse:
|
||||
warehouse = frappe.db.get_value('Stock Settings', None, 'default_warehouse')
|
||||
if warehouse:
|
||||
target.warehouse = warehouse
|
||||
|
||||
set_stock_items(target, source.procedure_template, 'Clinical Procedure Template')
|
||||
|
||||
doc = get_mapped_doc('Patient Appointment', source_name, {
|
||||
'Patient Appointment': {
|
||||
'doctype': 'Clinical Procedure',
|
||||
'field_map': [
|
||||
['appointment', 'name'],
|
||||
['patient', 'patient'],
|
||||
['patient_age', 'patient_age'],
|
||||
['patient_sex', 'patient_sex'],
|
||||
['procedure_template', 'procedure_template'],
|
||||
['prescription', 'procedure_prescription'],
|
||||
['practitioner', 'practitioner'],
|
||||
['medical_department', 'department'],
|
||||
['start_date', 'appointment_date'],
|
||||
['start_time', 'appointment_time'],
|
||||
['notes', 'notes'],
|
||||
['service_unit', 'service_unit'],
|
||||
['company', 'company'],
|
||||
['invoiced', 'invoiced']
|
||||
]
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def insert_clinical_procedure_to_medical_record(doc):
|
||||
subject = cstr(doc.procedure_template)
|
||||
if doc.practitioner:
|
||||
subject += " "+doc.practitioner
|
||||
subject += ' ' + doc.practitioner
|
||||
if subject and doc.notes:
|
||||
subject += "<br/>"+doc.notes
|
||||
subject += '<br/>' + doc.notes
|
||||
|
||||
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.start_date
|
||||
medical_record.reference_doctype = "Clinical Procedure"
|
||||
medical_record.reference_doctype = 'Clinical Procedure'
|
||||
medical_record.reference_name = doc.name
|
||||
medical_record.reference_owner = doc.owner
|
||||
medical_record.save(ignore_permissions=True)
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
frappe.listview_settings['Clinical Procedure'] = {
|
||||
get_indicator: function(doc) {
|
||||
var colors = {
|
||||
'Completed': 'green',
|
||||
'In Progress': 'orange',
|
||||
'Pending': 'orange',
|
||||
'Cancelled': 'grey'
|
||||
};
|
||||
return [__(doc.status), colors[doc.status], 'status,=,' + doc.status];
|
||||
}
|
||||
};
|
||||
@ -4,6 +4,60 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
import frappe
|
||||
from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_clinical_procedure_template
|
||||
|
||||
class TestClinicalProcedure(unittest.TestCase):
|
||||
pass
|
||||
def test_procedure_template_item(self):
|
||||
patient, medical_department, practitioner = create_healthcare_docs()
|
||||
procedure_template = create_clinical_procedure_template()
|
||||
self.assertTrue(frappe.db.exists('Item', procedure_template.item))
|
||||
|
||||
procedure_template.disabled = 1
|
||||
procedure_template.save()
|
||||
self.assertEquals(frappe.db.get_value('Item', procedure_template.item, 'disabled'), 1)
|
||||
|
||||
def test_consumables(self):
|
||||
patient, medical_department, practitioner = create_healthcare_docs()
|
||||
procedure_template = create_clinical_procedure_template()
|
||||
procedure_template.allow_stock_consumption = 1
|
||||
consumable = create_consumable()
|
||||
procedure_template.append('items', {
|
||||
'item_code': consumable.item_code,
|
||||
'qty': 1,
|
||||
'uom': consumable.stock_uom,
|
||||
'stock_uom': consumable.stock_uom
|
||||
})
|
||||
procedure_template.save()
|
||||
procedure = create_procedure(procedure_template, patient, practitioner)
|
||||
result = procedure.start_procedure()
|
||||
if result == 'insufficient stock':
|
||||
procedure.make_material_receipt(submit=True)
|
||||
result = procedure.start_procedure()
|
||||
self.assertEqual(procedure.status, 'In Progress')
|
||||
result = procedure.complete_procedure()
|
||||
# check consumption
|
||||
self.assertTrue(frappe.db.exists('Stock Entry', result))
|
||||
|
||||
|
||||
def create_consumable():
|
||||
if frappe.db.exists('Item', 'Syringe'):
|
||||
return frappe.get_doc('Item', 'Syringe')
|
||||
consumable = frappe.new_doc('Item')
|
||||
consumable.item_code = 'Syringe'
|
||||
consumable.item_group = '_Test Item Group'
|
||||
consumable.stock_uom = 'Nos'
|
||||
consumable.valuation_rate = 5.00
|
||||
consumable.save()
|
||||
return consumable
|
||||
|
||||
def create_procedure(procedure_template, patient, practitioner):
|
||||
procedure = frappe.new_doc('Clinical Procedure')
|
||||
procedure.procedure_template = procedure_template.name
|
||||
procedure.patient = patient
|
||||
procedure.practitioner = practitioner
|
||||
procedure.consume_stock = procedure_template.allow_stock_consumption
|
||||
procedure.items = procedure_template.items
|
||||
procedure.warehouse = frappe.db.get_single_value('Stock Settings', 'default_warehouse')
|
||||
procedure.submit()
|
||||
return procedure
|
||||
@ -1,431 +1,123 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2017-10-05 16:15:10.876952",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"beta": 1,
|
||||
"creation": "2017-10-05 16:15:10.876952",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"item_code",
|
||||
"item_name",
|
||||
"qty",
|
||||
"barcode",
|
||||
"uom",
|
||||
"invoice_separately_as_consumables",
|
||||
"column_break_5",
|
||||
"batch_no",
|
||||
"conversion_factor",
|
||||
"stock_uom",
|
||||
"transfer_qty",
|
||||
"actual_qty"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 3,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 1,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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
|
||||
},
|
||||
"bold": 1,
|
||||
"columns": 3,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item",
|
||||
"options": "Item",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "barcode",
|
||||
"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": "Barcode",
|
||||
"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": "barcode",
|
||||
"fieldtype": "Data",
|
||||
"label": "Barcode"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_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": "Item 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": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Item Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "qty",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Quantity",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "uom",
|
||||
"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": "UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "UOM",
|
||||
"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": "uom",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "UOM",
|
||||
"options": "UOM",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoice_separately_as_consumables",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Invoice Separately as Consumables",
|
||||
"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": "invoice_separately_as_consumables",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Separately as Consumables"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"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_5",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "batch_no",
|
||||
"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": "Batch",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Batch",
|
||||
"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": "batch_no",
|
||||
"fieldtype": "Link",
|
||||
"label": "Batch",
|
||||
"options": "Batch"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "conversion_factor",
|
||||
"fieldtype": "Float",
|
||||
"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": "Conversion Factor",
|
||||
"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": "conversion_factor",
|
||||
"fieldtype": "Float",
|
||||
"label": "Conversion Factor",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "stock_uom",
|
||||
"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": "Stock UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "UOM",
|
||||
"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": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Stock UOM",
|
||||
"options": "UOM",
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "transfer_qty",
|
||||
"fieldtype": "Float",
|
||||
"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": "Transfer Qty",
|
||||
"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": "transfer_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Transfer Qty",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "actual_qty",
|
||||
"fieldtype": "Float",
|
||||
"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": "Actual Qty (at source/target)",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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
|
||||
"fieldname": "actual_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Actual Qty (at source/target)",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"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:16.833884",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Clinical Procedure Item",
|
||||
"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,
|
||||
"track_views": 0
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-01 15:34:54.226722",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Clinical Procedure Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@ -3,170 +3,141 @@
|
||||
|
||||
frappe.ui.form.on('Clinical Procedure Template', {
|
||||
template: function(frm) {
|
||||
if(!frm.doc.item_code)
|
||||
frm.set_value("item_code", frm.doc.template);
|
||||
if(!frm.doc.description)
|
||||
frm.set_value("description", frm.doc.template);
|
||||
if (!frm.doc.item_code)
|
||||
frm.set_value('item_code', frm.doc.template);
|
||||
if (!frm.doc.description)
|
||||
frm.set_value('description', frm.doc.template);
|
||||
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);
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.fields_dict["items"].grid.set_column_disp("barcode", false);
|
||||
frm.fields_dict["items"].grid.set_column_disp("batch_no", false);
|
||||
cur_frm.set_df_property("item_code", "read_only", frm.doc.__islocal ? 0 : 1);
|
||||
if(!frm.doc.__islocal) {
|
||||
frm.fields_dict['items'].grid.set_column_disp('barcode', false);
|
||||
frm.fields_dict['items'].grid.set_column_disp('batch_no', false);
|
||||
|
||||
if (!frm.doc.__islocal) {
|
||||
cur_frm.add_custom_button(__('Change Item Code'), function() {
|
||||
change_template_code(frm.doc);
|
||||
} );
|
||||
if(frm.doc.disabled == 1){
|
||||
cur_frm.add_custom_button(__('Enable Template'), function() {
|
||||
enable_template(frm.doc);
|
||||
} );
|
||||
}
|
||||
else{
|
||||
cur_frm.add_custom_button(__('Disable Template'), function() {
|
||||
disable_template(frm.doc);
|
||||
} );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var mark_change_in_item = function(frm) {
|
||||
if(!frm.doc.__islocal){
|
||||
let mark_change_in_item = function(frm) {
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.doc.change_in_item = 1;
|
||||
}
|
||||
};
|
||||
|
||||
var disable_template = function(doc){
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.disable_enable_template",
|
||||
args: {status: 1, name: doc.name, item_code: doc.item_code, is_billable: doc.is_billable},
|
||||
callback: function(){
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var enable_template = function(doc){
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.disable_enable_template",
|
||||
args: {status: 0, name: doc.name, item_code: doc.item_code, is_billable: doc.is_billable},
|
||||
callback: function(){
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var change_template_code = function(doc){
|
||||
var d = new frappe.ui.Dialog({
|
||||
title:__("Change Template Code"),
|
||||
let change_template_code = function(doc) {
|
||||
let d = new frappe.ui.Dialog({
|
||||
title:__('Change Item Code'),
|
||||
fields:[
|
||||
{
|
||||
"fieldtype": "Data",
|
||||
"label": "Template Code",
|
||||
"fieldname": "Item Code",
|
||||
reqd:1
|
||||
},
|
||||
{
|
||||
"fieldtype": "Button",
|
||||
"label": __("Change Code"),
|
||||
click: function() {
|
||||
var values = d.get_values();
|
||||
if(!values)
|
||||
return;
|
||||
change_item_code_from_template(values["Item Code"], doc);
|
||||
d.hide();
|
||||
}
|
||||
'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.clinical_procedure_template.clinical_procedure_template.change_item_code_from_template',
|
||||
'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
|
||||
});
|
||||
};
|
||||
|
||||
var change_item_code_from_template = function(item_code, doc){
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.change_item_code_from_template",
|
||||
"args": {item_code: item_code, doc: doc},
|
||||
callback: function () {
|
||||
cur_frm.reload_doc();
|
||||
frappe.show_alert({
|
||||
message: "Item Code renamed successfully",
|
||||
indicator: "green"
|
||||
});
|
||||
}
|
||||
d.set_values({
|
||||
'item_code': doc.item_code
|
||||
});
|
||||
};
|
||||
|
||||
frappe.ui.form.on('Clinical Procedure Item', {
|
||||
qty: function(frm, cdt, cdn){
|
||||
var d = locals[cdt][cdn];
|
||||
frappe.model.set_value(cdt, cdn, "transfer_qty", d.qty*d.conversion_factor);
|
||||
qty: function(frm, cdt, cdn) {
|
||||
let d = locals[cdt][cdn];
|
||||
frappe.model.set_value(cdt, cdn, 'transfer_qty', d.qty * d.conversion_factor);
|
||||
},
|
||||
|
||||
uom: function(doc, cdt, cdn){
|
||||
var d = locals[cdt][cdn];
|
||||
if(d.uom && d.item_code){
|
||||
let d = locals[cdt][cdn];
|
||||
if (d.uom && d.item_code) {
|
||||
return frappe.call({
|
||||
method: "erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details",
|
||||
method: 'erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details',
|
||||
args: {
|
||||
item_code: d.item_code,
|
||||
uom: d.uom,
|
||||
qty: d.qty
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
if (r.message) {
|
||||
frappe.model.set_value(cdt, cdn, r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
item_code: function(frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
if(d.item_code) {
|
||||
let d = locals[cdt][cdn];
|
||||
if (d.item_code) {
|
||||
let args = {
|
||||
'item_code' : d.item_code,
|
||||
'transfer_qty' : d.transfer_qty,
|
||||
'company' : frm.doc.company,
|
||||
'quantity' : d.qty
|
||||
'quantity' : d.qty
|
||||
};
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "get_item_details",
|
||||
args: args,
|
||||
method: 'erpnext.healthcare.doctype.clinical_procedure_template.clinical_procedure_template.get_item_details',
|
||||
args: {args: args},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
var d = locals[cdt][cdn];
|
||||
$.each(r.message, function(k, v){
|
||||
if (r.message) {
|
||||
let d = locals[cdt][cdn];
|
||||
$.each(r.message, function(k, v) {
|
||||
d[k] = v;
|
||||
});
|
||||
refresh_field("items");
|
||||
refresh_field('items');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// List Stock items
|
||||
cur_frm.set_query("item_code", "items", function() {
|
||||
cur_frm.set_query('item_code', 'items', function() {
|
||||
return {
|
||||
filters: {
|
||||
is_stock_item:1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -7,126 +7,114 @@ import frappe, json
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.rename_doc import rename_doc
|
||||
from frappe.utils import nowdate
|
||||
|
||||
class ClinicalProcedureTemplate(Document):
|
||||
def on_update(self):
|
||||
#Item and Price List update --> if (change_in_item)
|
||||
if(self.change_in_item and self.is_billable == 1 and self.item):
|
||||
updating_item(self)
|
||||
if(self.rate != 0.0):
|
||||
updating_rate(self)
|
||||
elif(self.is_billable == 0 and self.item):
|
||||
frappe.db.set_value("Item",self.item,"disabled",1)
|
||||
|
||||
frappe.db.set_value(self.doctype,self.name,"change_in_item",0)
|
||||
self.reload()
|
||||
def validate(self):
|
||||
self.enable_disable_item()
|
||||
|
||||
def after_insert(self):
|
||||
create_item_from_template(self)
|
||||
|
||||
#Call before delete the template
|
||||
def on_trash(self):
|
||||
if(self.item):
|
||||
try:
|
||||
frappe.delete_doc("Item",self.item)
|
||||
except Exception:
|
||||
frappe.throw(_("""Not permitted. Please disable the Procedure Template"""))
|
||||
def on_update(self):
|
||||
if self.change_in_item:
|
||||
self.update_item_and_item_price()
|
||||
|
||||
def get_item_details(self, args=None):
|
||||
item = frappe.db.sql("""select stock_uom, item_name
|
||||
from `tabItem`
|
||||
where name = %s
|
||||
and disabled=0
|
||||
and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""",
|
||||
(args.get('item_code'), nowdate()), as_dict = 1)
|
||||
if not item:
|
||||
frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get('item_code')))
|
||||
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)
|
||||
|
||||
item = item[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.template
|
||||
item_doc.item_group = self.item_group
|
||||
item_doc.description = self.description
|
||||
item_doc.disabled = 0
|
||||
item_doc.save(ignore_permissions=True)
|
||||
|
||||
ret = {
|
||||
'uom' : item.stock_uom,
|
||||
'stock_uom' : item.stock_uom,
|
||||
'item_name' : item.item_name,
|
||||
'quantity' : 0,
|
||||
'transfer_qty' : 0,
|
||||
'conversion_factor' : 1
|
||||
}
|
||||
return ret
|
||||
if self.rate:
|
||||
item_price = frappe.get_doc('Item Price', {'item_code': self.item})
|
||||
item_price.item_name = self.template
|
||||
item_price.price_list_rate = self.rate
|
||||
item_price.save()
|
||||
|
||||
def updating_item(self):
|
||||
frappe.db.sql("""update `tabItem` set item_name=%s, item_group=%s, disabled=0,
|
||||
description=%s, modified=NOW() where item_code=%s""",
|
||||
(self.template, self.item_group , self.description, self.item))
|
||||
def updating_rate(self):
|
||||
frappe.db.sql("""update `tabItem Price` set item_name=%s, price_list_rate=%s, modified=NOW() where
|
||||
item_code=%s""",(self.template, self.rate, self.item))
|
||||
elif not self.is_billable and self.item:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
|
||||
self.db_set('change_in_item', 0)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(args=None):
|
||||
if not isinstance(args, dict):
|
||||
args = json.loads(args)
|
||||
|
||||
item = frappe.db.get_all('Item',
|
||||
filters={
|
||||
'disabled': 0,
|
||||
'name': args.get('item_code')
|
||||
},
|
||||
fields=['stock_uom', 'item_name']
|
||||
)
|
||||
|
||||
if not item:
|
||||
frappe.throw(_('Item {0} is not active').format(args.get('item_code')))
|
||||
|
||||
item = item[0]
|
||||
ret = {
|
||||
'uom': item.stock_uom,
|
||||
'stock_uom': item.stock_uom,
|
||||
'item_name': item.item_name,
|
||||
'qty': 1,
|
||||
'transfer_qty': 0,
|
||||
'conversion_factor': 1
|
||||
}
|
||||
return ret
|
||||
|
||||
def create_item_from_template(doc):
|
||||
disabled = 1
|
||||
|
||||
if(doc.is_billable == 1):
|
||||
disabled = doc.disabled
|
||||
if doc.is_billable and not doc.disabled:
|
||||
disabled = 0
|
||||
|
||||
#insert item
|
||||
item = frappe.get_doc({
|
||||
"doctype": "Item",
|
||||
"item_code": doc.template,
|
||||
"item_name":doc.template,
|
||||
"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": "Unit"
|
||||
}).insert(ignore_permissions=True)
|
||||
item = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': doc.template,
|
||||
'item_name':doc.template,
|
||||
'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': 'Unit'
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
#insert item price
|
||||
#get item price list to insert item price
|
||||
if(doc.rate != 0.0):
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if(doc.rate):
|
||||
make_item_price(item.name, price_list_name, doc.rate)
|
||||
else:
|
||||
make_item_price(item.name, price_list_name, 0.0)
|
||||
#Set item to the template
|
||||
frappe.db.set_value("Clinical Procedure Template", doc.name, "item", item.name)
|
||||
make_item_price(item.name, doc.rate)
|
||||
doc.db_set('item', item.name)
|
||||
|
||||
doc.reload() #refresh the doc after insert.
|
||||
|
||||
def make_item_price(item, price_list_name, item_price):
|
||||
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)
|
||||
'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_template(item_code, doc):
|
||||
args = json.loads(doc)
|
||||
doc = frappe._dict(args)
|
||||
doc = frappe._dict(json.loads(doc))
|
||||
|
||||
if(frappe.db.exists({
|
||||
"doctype": "Item",
|
||||
"item_code": item_code})):
|
||||
frappe.throw(_("Code {0} already exist").format(item_code))
|
||||
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_code, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value("Clinical Procedure Template", doc.name, "item_code", item_code)
|
||||
rename_doc('Item', doc.item_code, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value('Clinical Procedure Template', doc.name, 'item_code', item_code)
|
||||
return
|
||||
|
||||
@frappe.whitelist()
|
||||
def disable_enable_template(status, name, item_code):
|
||||
frappe.db.set_value("Clinical Procedure Template", name, "disabled", status)
|
||||
if (frappe.db.exists({ #set Item's disabled field to status
|
||||
"doctype": "Item",
|
||||
"item_code": item_code})):
|
||||
frappe.db.set_value("Item", item_code, "disabled", status)
|
||||
|
||||
return
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'procedure_template',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Consultations'),
|
||||
'items': ['Clinical Procedure']
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,140 +1,56 @@
|
||||
{
|
||||
"allow_copy": 1,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2017-06-22 13:09:23.159579",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"beta": 1,
|
||||
"creation": "2017-06-22 13:09:23.159579",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"medical_code",
|
||||
"code",
|
||||
"description"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "medical_code",
|
||||
"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": "Medical Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Medical Code",
|
||||
"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": "medical_code",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Medical Code",
|
||||
"options": "Medical Code",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "medical_code.code",
|
||||
"fieldname": "code",
|
||||
"fieldtype": "Read Only",
|
||||
"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": "Code",
|
||||
"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": "code",
|
||||
"fieldtype": "Data",
|
||||
"ignore_xss_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Code",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "medical_code.description",
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Read Only",
|
||||
"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": "Description",
|
||||
"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": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"read_only": 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-05-16 22:43:27.047479",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Codification Table",
|
||||
"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-02-26 13:17:49.016293",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Codification Table",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@ -1,381 +1,116 @@
|
||||
{
|
||||
"allow_copy": 1,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2016-09-16 16:41:45.533374",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"beta": 1,
|
||||
"creation": "2016-09-16 16:41:45.533374",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"drug_code",
|
||||
"drug_name",
|
||||
"dosage",
|
||||
"period",
|
||||
"dosage_form",
|
||||
"column_break_7",
|
||||
"comment",
|
||||
"usage_interval",
|
||||
"interval",
|
||||
"interval_uom",
|
||||
"update_schedule"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "drug_code",
|
||||
"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": "Drug Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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": "drug_code",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Drug",
|
||||
"options": "Item",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "drug_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": "Description/Strength",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fetch_from": "drug_code.item_name",
|
||||
"fieldname": "drug_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Drug Name / Description"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "dosage",
|
||||
"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": "Dosage",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Prescription Dosage",
|
||||
"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": "dosage",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Dosage",
|
||||
"options": "Prescription Dosage"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "period",
|
||||
"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": "Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Prescription Duration",
|
||||
"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": "period",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Period",
|
||||
"options": "Prescription Duration"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "dosage_form",
|
||||
"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": "Dosage Form",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Dosage Form",
|
||||
"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": "dosage_form",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Dosage Form",
|
||||
"options": "Dosage Form"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_7",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "comment",
|
||||
"fieldtype": "Small Text",
|
||||
"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": "Comment",
|
||||
"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": "comment",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Comment"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "use_interval",
|
||||
"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": "Dosage by time interval",
|
||||
"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
|
||||
},
|
||||
"depends_on": "use_interval",
|
||||
"fieldname": "interval",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Interval"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "use_interval",
|
||||
"fieldname": "interval",
|
||||
"fieldtype": "Int",
|
||||
"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": "Interval",
|
||||
"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
|
||||
},
|
||||
"default": "1",
|
||||
"fieldname": "update_schedule",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Update Schedule",
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "use_interval",
|
||||
"fieldname": "in_every",
|
||||
"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": "Interval UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nHour\nDay",
|
||||
"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
|
||||
},
|
||||
"depends_on": "use_interval",
|
||||
"fieldname": "interval_uom",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Interval UOM",
|
||||
"options": "\nHour\nDay"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "update_schedule",
|
||||
"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": "Update Schedule",
|
||||
"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,
|
||||
"unique": 0
|
||||
"default": "0",
|
||||
"fieldname": "usage_interval",
|
||||
"fieldtype": "Check",
|
||||
"label": "Dosage by Time Interval"
|
||||
}
|
||||
],
|
||||
"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 17:09:54.998517",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Drug 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": 0,
|
||||
"track_seen": 0
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-02-26 17:02:42.741338",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Drug Prescription",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@ -12,21 +12,21 @@ class DrugPrescription(Document):
|
||||
dosage = None
|
||||
period = None
|
||||
|
||||
if(self.dosage):
|
||||
dosage = frappe.get_doc("Prescription Dosage",self.dosage)
|
||||
if self.dosage:
|
||||
dosage = frappe.get_doc('Prescription Dosage', self.dosage)
|
||||
for item in dosage.dosage_strength:
|
||||
quantity += item.strength
|
||||
if(self.period and self.interval):
|
||||
period = frappe.get_doc("Prescription Duration",self.period)
|
||||
if(self.interval < period.get_days()):
|
||||
quantity = quantity*(period.get_days()/self.interval)
|
||||
if self.period and self.interval:
|
||||
period = frappe.get_doc('Prescription Duration', self.period)
|
||||
if self.interval < period.get_days():
|
||||
quantity = quantity * (period.get_days()/self.interval)
|
||||
|
||||
elif(self.interval and self.in_every and self.period):
|
||||
period = frappe.get_doc("Prescription Duration",self.period)
|
||||
interval_in = self.in_every
|
||||
if(interval_in == 'Day' and (self.interval < period.get_days())):
|
||||
elif self.interval and self.interval_uom and self.period:
|
||||
period = frappe.get_doc('Prescription Duration', self.period)
|
||||
interval_in = self.interval_uom
|
||||
if interval_in == 'Day' and self.interval < period.get_days():
|
||||
quantity = period.get_days()/self.interval
|
||||
elif(interval_in == 'Hour' and (self.interval < period.get_hours())):
|
||||
elif interval_in == 'Hour' and self.interval < period.get_hours():
|
||||
quantity = period.get_hours()/self.interval
|
||||
if quantity > 0:
|
||||
return quantity
|
||||
|
||||
@ -1,259 +1,134 @@
|
||||
{
|
||||
"allow_copy": 1,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2017-01-05 10:56:29.564806",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"allow_import": 1,
|
||||
"beta": 1,
|
||||
"creation": "2017-01-05 10:56:29.564806",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"practitioner",
|
||||
"patient",
|
||||
"column_break_3",
|
||||
"status",
|
||||
"section_break_5",
|
||||
"section_break_3",
|
||||
"max_visits",
|
||||
"visited",
|
||||
"ref_appointments",
|
||||
"column_break_6",
|
||||
"start_date",
|
||||
"valid_till"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"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": 0,
|
||||
"in_standard_filter": 0,
|
||||
"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": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "practitioner",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Healthcare Practitioner",
|
||||
"options": "Healthcare Practitioner",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"search_index": 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": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"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",
|
||||
"in_list_view": 1,
|
||||
"label": "Patient",
|
||||
"options": "Patient",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "max_visit",
|
||||
"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": "Max number of visit",
|
||||
"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": "visited",
|
||||
"fieldtype": "Int",
|
||||
"label": "Visited yet",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "visited",
|
||||
"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": "Visited yet",
|
||||
"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": "valid_till",
|
||||
"fieldtype": "Date",
|
||||
"label": "Valid till",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "valid_till",
|
||||
"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": "Valid till",
|
||||
"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_3",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Validity",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "ref_invoice",
|
||||
"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": "Reference Inv",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"fieldname": "max_visits",
|
||||
"fieldtype": "Int",
|
||||
"label": "Max number of visit",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Status",
|
||||
"options": "Completed\nPending",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "ref_appointment.appointment_date",
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Start Date",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "ref_appointments",
|
||||
"fieldtype": "Table MultiSelect",
|
||||
"label": "Reference Appointments",
|
||||
"options": "Fee Validity Reference",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break"
|
||||
}
|
||||
],
|
||||
"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-07-16 12:43:45.635230",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Fee Validity",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"in_create": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-17 20:25:06.487418",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Fee Validity",
|
||||
"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,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Healthcare Administrator",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"search_fields": "practitioner, patient",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "practitioner",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"search_fields": "practitioner, patient",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "practitioner"
|
||||
}
|
||||
@ -9,28 +9,55 @@ from frappe.utils import getdate
|
||||
import datetime
|
||||
|
||||
class FeeValidity(Document):
|
||||
pass
|
||||
def validate(self):
|
||||
self.update_status()
|
||||
self.set_start_date()
|
||||
|
||||
def update_fee_validity(fee_validity, date, ref_invoice=None):
|
||||
max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
|
||||
valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
|
||||
if not valid_days:
|
||||
valid_days = 1
|
||||
if not max_visit:
|
||||
max_visit = 1
|
||||
date = getdate(date)
|
||||
valid_till = date + datetime.timedelta(days=int(valid_days))
|
||||
fee_validity.max_visit = max_visit
|
||||
def update_status(self):
|
||||
if self.visited >= self.max_visits:
|
||||
self.status = 'Completed'
|
||||
else:
|
||||
self.status = 'Pending'
|
||||
|
||||
def set_start_date(self):
|
||||
self.start_date = getdate()
|
||||
for appointment in self.ref_appointments:
|
||||
appointment_date = frappe.db.get_value('Patient Appointment', appointment.appointment, 'appointment_date')
|
||||
if getdate(appointment_date) < self.start_date:
|
||||
self.start_date = getdate(appointment_date)
|
||||
|
||||
|
||||
def create_fee_validity(appointment):
|
||||
if not check_is_new_patient(appointment):
|
||||
return
|
||||
|
||||
fee_validity = frappe.new_doc('Fee Validity')
|
||||
fee_validity.practitioner = appointment.practitioner
|
||||
fee_validity.patient = appointment.patient
|
||||
fee_validity.max_visits = frappe.db.get_single_value('Healthcare Settings', 'max_visits') or 1
|
||||
valid_days = frappe.db.get_single_value('Healthcare Settings', 'valid_days') or 1
|
||||
fee_validity.visited = 1
|
||||
fee_validity.valid_till = valid_till
|
||||
fee_validity.ref_invoice = ref_invoice
|
||||
fee_validity.valid_till = getdate(appointment.appointment_date) + datetime.timedelta(days=int(valid_days))
|
||||
fee_validity.append('ref_appointments', {
|
||||
'appointment': appointment.name
|
||||
})
|
||||
fee_validity.save(ignore_permissions=True)
|
||||
return fee_validity
|
||||
|
||||
def check_is_new_patient(appointment):
|
||||
validity_exists = frappe.db.exists('Fee Validity', {
|
||||
'practitioner': appointment.practitioner,
|
||||
'patient': appointment.patient
|
||||
})
|
||||
if validity_exists:
|
||||
return False
|
||||
|
||||
def create_fee_validity(practitioner, patient, date, ref_invoice=None):
|
||||
fee_validity = frappe.new_doc("Fee Validity")
|
||||
fee_validity.practitioner = practitioner
|
||||
fee_validity.patient = patient
|
||||
fee_validity = update_fee_validity(fee_validity, date, ref_invoice)
|
||||
return fee_validity
|
||||
appointment_exists = frappe.db.get_all('Patient Appointment', {
|
||||
'name': ('!=', appointment.name),
|
||||
'status': ('!=', 'Cancelled'),
|
||||
'patient': appointment.patient,
|
||||
'practitioner': appointment.practitioner
|
||||
})
|
||||
if len(appointment_exists) and appointment_exists[0]:
|
||||
return False
|
||||
return True
|
||||
@ -5,100 +5,44 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from frappe.utils.make_random import get_random
|
||||
from frappe.utils import nowdate, add_days, getdate
|
||||
from frappe.utils import nowdate, add_days
|
||||
from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_appointment, create_healthcare_service_items
|
||||
|
||||
test_dependencies = ["Company"]
|
||||
|
||||
class TestFeeValidity(unittest.TestCase):
|
||||
def test_fee_validity(self):
|
||||
def setUp(self):
|
||||
frappe.db.sql("""delete from `tabPatient Appointment`""")
|
||||
frappe.db.sql("""delete from `tabFee Validity`""")
|
||||
patient = get_random("Patient")
|
||||
practitioner = get_random("Healthcare Practitioner")
|
||||
department = get_random("Medical Department")
|
||||
frappe.db.sql("""delete from `tabPatient`""")
|
||||
|
||||
if not patient:
|
||||
patient = frappe.new_doc("Patient")
|
||||
patient.patient_name = "_Test Patient"
|
||||
patient.sex = "Male"
|
||||
patient.save(ignore_permissions=True)
|
||||
patient = patient.name
|
||||
def test_fee_validity(self):
|
||||
item = create_healthcare_service_items()
|
||||
healthcare_settings = frappe.get_single("Healthcare Settings")
|
||||
healthcare_settings.enable_free_follow_ups = 1
|
||||
healthcare_settings.max_visits = 2
|
||||
healthcare_settings.valid_days = 7
|
||||
healthcare_settings.automate_appointment_invoicing = 1
|
||||
healthcare_settings.op_consulting_charge_item = item
|
||||
healthcare_settings.save(ignore_permissions=True)
|
||||
patient, medical_department, practitioner = create_healthcare_docs()
|
||||
|
||||
if not department:
|
||||
medical_department = frappe.new_doc("Medical Department")
|
||||
medical_department.department = "_Test Medical Department"
|
||||
medical_department.save(ignore_permissions=True)
|
||||
department = medical_department.name
|
||||
|
||||
if not practitioner:
|
||||
practitioner = frappe.new_doc("Healthcare Practitioner")
|
||||
practitioner.first_name = "_Test Healthcare Practitioner"
|
||||
practitioner.department = department
|
||||
practitioner.save(ignore_permissions=True)
|
||||
practitioner = practitioner.name
|
||||
|
||||
|
||||
|
||||
frappe.db.set_value("Healthcare Settings", None, "max_visit", 2)
|
||||
frappe.db.set_value("Healthcare Settings", None, "valid_days", 7)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), department)
|
||||
# appointment should not be invoiced. Check Fee Validity created for new patient
|
||||
appointment = create_appointment(patient, practitioner, nowdate())
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertEqual(invoiced, 0)
|
||||
|
||||
invoice_appointment(appointment)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4), department)
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertTrue(invoiced)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 5), department)
|
||||
# appointment should not be invoiced as it is within fee validity
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4))
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertEqual(invoiced, 0)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 10), department)
|
||||
# appointment should be invoiced as it is within fee validity but the max_visits are exceeded
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 5), invoice=1)
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertEqual(invoiced, 0)
|
||||
self.assertEqual(invoiced, 1)
|
||||
|
||||
def create_appointment(patient, practitioner, appointment_date, department):
|
||||
appointment = frappe.new_doc("Patient Appointment")
|
||||
appointment.patient = patient
|
||||
appointment.practitioner = practitioner
|
||||
appointment.department = department
|
||||
appointment.appointment_date = appointment_date
|
||||
appointment.company = "_Test Company"
|
||||
appointment.duration = 15
|
||||
appointment.save(ignore_permissions=True)
|
||||
return appointment
|
||||
|
||||
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.due_date = getdate()
|
||||
sales_invoice.is_pos = 0
|
||||
sales_invoice.company = appointment_doc.company
|
||||
sales_invoice.debit_to = "_Test Receivable - _TC"
|
||||
|
||||
create_invoice_items(appointment_doc, sales_invoice)
|
||||
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
sales_invoice.submit()
|
||||
|
||||
def create_invoice_items(appointment, invoice):
|
||||
item_line = invoice.append("items")
|
||||
item_line.item_name = "Consulting Charges"
|
||||
item_line.description = "Consulting Charges: " + appointment.practitioner
|
||||
item_line.uom = "Nos"
|
||||
item_line.conversion_factor = 1
|
||||
item_line.income_account = "_Test Account Cost for Goods Sold - _TC"
|
||||
item_line.cost_center = "_Test Cost Center - _TC"
|
||||
item_line.rate = 250
|
||||
item_line.amount = 250
|
||||
item_line.qty = 1
|
||||
item_line.reference_dt = "Patient Appointment"
|
||||
item_line.reference_dn = appointment.name
|
||||
|
||||
return invoice
|
||||
# appointment should be invoiced as it is not within fee validity and the max_visits are exceeded
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 10), invoice=1)
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertEqual(invoiced, 1)
|
||||
@ -0,0 +1,32 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-03-13 16:08:42.859996",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"appointment"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "appointment",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Patient Appointment",
|
||||
"options": "Patient Appointment",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-15 00:27:02.076470",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Fee Validity Reference",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@ -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 FeeValidityReference(Document):
|
||||
pass
|
||||
@ -4,7 +4,7 @@
|
||||
frappe.ui.form.on('Healthcare Practitioner', {
|
||||
setup: function(frm) {
|
||||
frm.set_query('account', 'accounts', function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
let d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
'root_type': 'Income',
|
||||
@ -16,23 +16,28 @@ frappe.ui.form.on('Healthcare Practitioner', {
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Healthcare Practitioner'};
|
||||
if(!frm.is_new()) {
|
||||
|
||||
if (!frm.is_new()) {
|
||||
frappe.contacts.render_address_and_contact(frm);
|
||||
} else {
|
||||
frappe.contacts.clear_address_and_contact(frm);
|
||||
}
|
||||
frm.set_query("service_unit", "practitioner_schedules", function(){
|
||||
|
||||
frm.set_query('service_unit', 'practitioner_schedules', function(){
|
||||
return {
|
||||
filters: {
|
||||
"is_group": false,
|
||||
"allow_appointments": true
|
||||
'is_group': false,
|
||||
'allow_appointments': true
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
set_query_service_item(frm, 'inpatient_visit_charge_item');
|
||||
set_query_service_item(frm, 'op_consulting_charge_item');
|
||||
}
|
||||
});
|
||||
|
||||
var set_query_service_item = function(frm, service_item_field) {
|
||||
let set_query_service_item = function(frm, service_item_field) {
|
||||
frm.set_query(service_item_field, function() {
|
||||
return {
|
||||
filters: {
|
||||
@ -43,62 +48,62 @@ var set_query_service_item = function(frm, service_item_field) {
|
||||
});
|
||||
};
|
||||
|
||||
frappe.ui.form.on("Healthcare Practitioner", "user_id",function(frm) {
|
||||
if(frm.doc.user_id){
|
||||
frappe.ui.form.on('Healthcare Practitioner', 'user_id',function(frm) {
|
||||
if (frm.doc.user_id) {
|
||||
frappe.call({
|
||||
"method": "frappe.client.get",
|
||||
'method': 'frappe.client.get',
|
||||
args: {
|
||||
doctype: "User",
|
||||
doctype: 'User',
|
||||
name: frm.doc.user_id
|
||||
},
|
||||
callback: function (data) {
|
||||
|
||||
frappe.model.get_value('Employee', {'user_id': frm.doc.user_id}, 'name',
|
||||
function(data) {
|
||||
if(data){
|
||||
if(!frm.doc.employee || frm.doc.employee != data.name)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "employee", data.name);
|
||||
}else{
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "employee", "");
|
||||
if (data) {
|
||||
if (!frm.doc.employee || frm.doc.employee != data.name)
|
||||
frappe.model.set_value(frm.doctype, frm.docname, 'employee', data.name);
|
||||
} else {
|
||||
frappe.model.set_value(frm.doctype, frm.docname, 'employee', '');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if(!frm.doc.first_name || frm.doc.first_name != data.message.first_name)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "first_name", data.message.first_name);
|
||||
if(!frm.doc.middle_name || frm.doc.middle_name != data.message.middle_name)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "middle_name", data.message.middle_name);
|
||||
if(!frm.doc.last_name || frm.doc.last_name != data.message.last_name)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "last_name", data.message.last_name);
|
||||
if(!frm.doc.mobile_phone || frm.doc.mobile_phone != data.message.mobile_no)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "mobile_phone", data.message.mobile_no);
|
||||
if (!frm.doc.first_name || frm.doc.first_name != data.message.first_name)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'first_name', data.message.first_name);
|
||||
if (!frm.doc.middle_name || frm.doc.middle_name != data.message.middle_name)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'middle_name', data.message.middle_name);
|
||||
if (!frm.doc.last_name || frm.doc.last_name != data.message.last_name)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'last_name', data.message.last_name);
|
||||
if (!frm.doc.mobile_phone || frm.doc.mobile_phone != data.message.mobile_no)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'mobile_phone', data.message.mobile_no);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Healthcare Practitioner", "employee", function(frm) {
|
||||
if(frm.doc.employee){
|
||||
frappe.ui.form.on('Healthcare Practitioner', 'employee', function(frm) {
|
||||
if (frm.doc.employee){
|
||||
frappe.call({
|
||||
"method": "frappe.client.get",
|
||||
'method': 'frappe.client.get',
|
||||
args: {
|
||||
doctype: "Employee",
|
||||
doctype: 'Employee',
|
||||
name: frm.doc.employee
|
||||
},
|
||||
callback: function (data) {
|
||||
if(!frm.doc.user_id || frm.doc.user_id != data.message.user_id)
|
||||
frm.set_value("user_id", data.message.user_id);
|
||||
if(!frm.doc.designation || frm.doc.designation != data.message.designation)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "designation", data.message.designation);
|
||||
if(!frm.doc.first_name || !frm.doc.user_id){
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "first_name", data.message.employee_name);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "middle_name", "");
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "last_name", "");
|
||||
if (!frm.doc.user_id || frm.doc.user_id != data.message.user_id)
|
||||
frm.set_value('user_id', data.message.user_id);
|
||||
if (!frm.doc.designation || frm.doc.designation != data.message.designation)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'designation', data.message.designation);
|
||||
if (!frm.doc.first_name || !frm.doc.user_id){
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'first_name', data.message.first_name);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'middle_name', '');
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'last_name', data.message.last_name);
|
||||
}
|
||||
if(!frm.doc.mobile_phone || !frm.doc.user_id)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "mobile_phone", data.message.cell_number);
|
||||
if(!frm.doc.address || frm.doc.address != data.message.current_address)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "address", data.message.current_address);
|
||||
if (!frm.doc.mobile_phone || !frm.doc.user_id)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'mobile_phone', data.message.cell_number);
|
||||
if (!frm.doc.address || frm.doc.address != data.message.current_address)
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'address', data.message.current_address);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,10 +5,10 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe import throw, _
|
||||
from frappe.utils import cstr
|
||||
from frappe import _
|
||||
from erpnext.accounts.party import validate_party_accounts
|
||||
from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address
|
||||
from frappe.model.naming import append_number_if_name_exists
|
||||
from frappe.desk.reportview import build_match_conditions, get_filters_cond
|
||||
|
||||
class HealthcarePractitioner(Document):
|
||||
@ -16,63 +16,66 @@ class HealthcarePractitioner(Document):
|
||||
load_address_and_contact(self)
|
||||
|
||||
def autoname(self):
|
||||
# practitioner first_name and last_name
|
||||
self.name = " ".join(filter(None,
|
||||
[cstr(self.get(f)).strip() for f in ["first_name","middle_name","last_name"]]))
|
||||
# concat first and last name
|
||||
self.name = self.practitioner_name
|
||||
|
||||
if frappe.db.exists('Healthcare Practitioner', self.name):
|
||||
self.name = append_number_if_name_exists('Contact', self.name)
|
||||
|
||||
def validate(self):
|
||||
self.set_full_name()
|
||||
validate_party_accounts(self)
|
||||
if self.inpatient_visit_charge_item:
|
||||
validate_service_item(self.inpatient_visit_charge_item, "Configure a service Item for Inpatient Visit Charge Item")
|
||||
validate_service_item(self.inpatient_visit_charge_item, 'Configure a service Item for Inpatient Consulting Charge Item')
|
||||
if self.op_consulting_charge_item:
|
||||
validate_service_item(self.op_consulting_charge_item, "Configure a service Item for Out Patient Consulting Charge Item")
|
||||
validate_service_item(self.op_consulting_charge_item, 'Configure a service Item for Out Patient Consulting Charge Item')
|
||||
|
||||
if self.user_id:
|
||||
self.validate_for_enabled_user_id()
|
||||
self.validate_duplicate_user_id()
|
||||
existing_user_id = frappe.db.get_value("Healthcare Practitioner", self.name, "user_id")
|
||||
if self.user_id != existing_user_id:
|
||||
frappe.permissions.remove_user_permission(
|
||||
"Healthcare Practitioner", self.name, existing_user_id)
|
||||
|
||||
self.validate_user_id()
|
||||
else:
|
||||
existing_user_id = frappe.db.get_value("Healthcare Practitioner", self.name, "user_id")
|
||||
existing_user_id = frappe.db.get_value('Healthcare Practitioner', self.name, 'user_id')
|
||||
if existing_user_id:
|
||||
frappe.permissions.remove_user_permission(
|
||||
"Healthcare Practitioner", self.name, existing_user_id)
|
||||
'Healthcare Practitioner', self.name, existing_user_id)
|
||||
|
||||
def on_update(self):
|
||||
if self.user_id:
|
||||
frappe.permissions.add_user_permission("Healthcare Practitioner", self.name, self.user_id)
|
||||
frappe.permissions.add_user_permission('Healthcare Practitioner', self.name, self.user_id)
|
||||
|
||||
def set_full_name(self):
|
||||
if self.last_name:
|
||||
self.practitioner_name = ' '.join(filter(None, [self.first_name, self.last_name]))
|
||||
else:
|
||||
self.practitioner_name = self.first_name
|
||||
|
||||
def validate_for_enabled_user_id(self):
|
||||
enabled = frappe.db.get_value("User", self.user_id, "enabled")
|
||||
if enabled is None:
|
||||
frappe.throw(_("User {0} does not exist").format(self.user_id))
|
||||
if enabled == 0:
|
||||
frappe.throw(_("User {0} is disabled").format(self.user_id))
|
||||
def validate_user_id(self):
|
||||
if not frappe.db.exists('User', self.user_id):
|
||||
frappe.throw(_('User {0} does not exist').format(self.user_id))
|
||||
elif not frappe.db.exists('User', self.user_id, 'enabled'):
|
||||
frappe.throw(_('User {0} is disabled').format(self.user_id))
|
||||
|
||||
def validate_duplicate_user_id(self):
|
||||
practitioner = frappe.db.sql_list("""select name from `tabHealthcare Practitioner` where
|
||||
user_id=%s and name!=%s""", (self.user_id, self.name))
|
||||
# check duplicate
|
||||
practitioner = frappe.db.exists('Healthcare Practitioner', {
|
||||
'user_id': self.user_id,
|
||||
'name': ('!=', self.name)
|
||||
})
|
||||
if practitioner:
|
||||
throw(_("User {0} is already assigned to Healthcare Practitioner {1}").format(
|
||||
self.user_id, practitioner[0]), frappe.DuplicateEntryError)
|
||||
frappe.throw(_('User {0} is already assigned to Healthcare Practitioner {1}').format(
|
||||
self.user_id, practitioner))
|
||||
|
||||
def on_trash(self):
|
||||
delete_contact_and_address('Healthcare Practitioner', self.name)
|
||||
|
||||
def validate_service_item(item, msg):
|
||||
if frappe.db.get_value("Item", item, "is_stock_item") == 1:
|
||||
if frappe.db.get_value('Item', item, 'is_stock_item'):
|
||||
frappe.throw(_(msg))
|
||||
|
||||
def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
|
||||
fields = ["name", "first_name", "mobile_phone"]
|
||||
fields = ['name', 'practitioner_name', 'mobile_phone']
|
||||
|
||||
filters = {
|
||||
'name': ("like", "%%%s%%" % txt)
|
||||
'name': ('like', '%%%s%%' % txt)
|
||||
}
|
||||
|
||||
return frappe.get_all("Healthcare Practitioner", fields = fields,
|
||||
filters = filters, start=start, page_length=page_len, order_by="name, first_name", as_list=1)
|
||||
return frappe.get_all('Healthcare Practitioner', fields = fields,
|
||||
filters = filters, start=start, page_length=page_len, order_by='name, practitioner_name', as_list=1)
|
||||
|
||||
@ -9,7 +9,11 @@ def get_data():
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Appointments and Patient Encounters'),
|
||||
'items': ['Patient Appointment', 'Patient Encounter']
|
||||
'items': ['Patient Appointment', 'Patient Encounter', 'Fee Validity']
|
||||
},
|
||||
{
|
||||
'label': _('Consultation'),
|
||||
'items': ['Clinical Procedure', 'Lab Test']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
frappe.ui.form.on('Healthcare Service Unit', {
|
||||
onload: function(frm) {
|
||||
frm.list_route = "Tree/Healthcare Service Unit";
|
||||
frm.list_route = 'Tree/Healthcare Service Unit';
|
||||
|
||||
// get query select healthcare service unit
|
||||
frm.fields_dict['parent_healthcare_service_unit'].get_query = function(doc) {
|
||||
@ -16,32 +16,32 @@ frappe.ui.form.on('Healthcare Service Unit', {
|
||||
};
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frm.trigger("set_root_readonly");
|
||||
frm.set_df_property("service_unit_type", "reqd", 1);
|
||||
frm.add_custom_button(__("Healthcare Service Unit Tree"), function() {
|
||||
frappe.set_route("Tree", "Healthcare Service Unit");
|
||||
frm.trigger('set_root_readonly');
|
||||
frm.set_df_property('service_unit_type', 'reqd', 1);
|
||||
frm.add_custom_button(__('Healthcare Service Unit Tree'), function() {
|
||||
frappe.set_route('Tree', 'Healthcare Service Unit');
|
||||
});
|
||||
},
|
||||
set_root_readonly: function(frm) {
|
||||
// read-only for root healthcare service unit
|
||||
frm.set_intro("");
|
||||
if(!frm.doc.parent_healthcare_service_unit) {
|
||||
frm.set_intro('');
|
||||
if (!frm.doc.parent_healthcare_service_unit) {
|
||||
frm.set_read_only();
|
||||
frm.set_intro(__("This is a root healthcare service unit and cannot be edited."), true);
|
||||
frm.set_intro(__('This is a root healthcare service unit and cannot be edited.'), true);
|
||||
}
|
||||
},
|
||||
allow_appointments: function(frm) {
|
||||
if(!frm.doc.allow_appointments){
|
||||
frm.set_value("overlap_appointments", false);
|
||||
if (!frm.doc.allow_appointments) {
|
||||
frm.set_value('overlap_appointments', false);
|
||||
}
|
||||
},
|
||||
is_group: function(frm) {
|
||||
if(frm.doc.is_group == 1){
|
||||
frm.set_value("allow_appointments", false);
|
||||
frm.set_df_property("service_unit_type", "reqd", 0);
|
||||
if (frm.doc.is_group == 1) {
|
||||
frm.set_value('allow_appointments', false);
|
||||
frm.set_df_property('service_unit_type', 'reqd', 0);
|
||||
}
|
||||
else{
|
||||
frm.set_df_property("service_unit_type", "reqd", 1);
|
||||
else {
|
||||
frm.set_df_property('service_unit_type', 'reqd', 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"healthcare_service_unit_name",
|
||||
"parent_healthcare_service_unit",
|
||||
@ -18,6 +19,7 @@
|
||||
"overlap_appointments",
|
||||
"inpatient_occupancy",
|
||||
"occupancy_status",
|
||||
"column_break_9",
|
||||
"warehouse",
|
||||
"company",
|
||||
"lft",
|
||||
@ -99,9 +101,13 @@
|
||||
"fieldtype": "Select",
|
||||
"label": "Occupancy Status",
|
||||
"no_copy": 1,
|
||||
"options": "Vacant\nOccupied",
|
||||
"options": "\nVacant\nOccupied",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
"depends_on": "eval:doc.is_group != 1",
|
||||
@ -153,13 +159,11 @@
|
||||
"report_hide": 1
|
||||
}
|
||||
],
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-18 18:02:23.713439",
|
||||
"modified": "2020-03-26 16:13:08.675952",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Service Unit",
|
||||
"nsm_parent_field": "parent_healthcare_service_unit",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
|
||||
@ -23,9 +23,9 @@ class HealthcareServiceUnit(NestedSet):
|
||||
self.validate_one_root()
|
||||
|
||||
def validate(self):
|
||||
if self.is_group == 1:
|
||||
if self.is_group:
|
||||
self.allow_appointments = 0
|
||||
self.overlap_appointments = 0
|
||||
self.inpatient_occupancy = 0
|
||||
elif self.allow_appointments != 1:
|
||||
elif not self.allow_appointments:
|
||||
self.overlap_appointments = 0
|
||||
|
||||
@ -2,118 +2,85 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Healthcare Service Unit Type', {
|
||||
refresh: function(frm) {
|
||||
frm.set_df_property('item_code', 'read_only', frm.doc.__islocal ? 0 : 1);
|
||||
if (!frm.doc.__islocal && frm.doc.is_billable) {
|
||||
frm.add_custom_button(__('Change Item Code'), function() {
|
||||
change_item_code(cur_frm, frm.doc);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
service_unit_type: function(frm) {
|
||||
set_item_details(frm);
|
||||
if(!frm.doc.__islocal){
|
||||
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.doc.change_in_item = 1;
|
||||
}
|
||||
},
|
||||
|
||||
is_billable: function(frm) {
|
||||
set_item_details(frm);
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frm.set_df_property("item_code", "read_only", frm.doc.__islocal ? 0 : 1);
|
||||
if(!frm.doc.__islocal) {
|
||||
frm.add_custom_button(__('Change Item Code'), function() {
|
||||
change_item_code(cur_frm,frm.doc);
|
||||
} );
|
||||
if(frm.doc.disabled == 1){
|
||||
frm.add_custom_button(__('Enable'), function() {
|
||||
enable(cur_frm);
|
||||
} );
|
||||
}
|
||||
else{
|
||||
frm.add_custom_button(__('Disable'), function() {
|
||||
disable(cur_frm);
|
||||
} );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
rate: function(frm) {
|
||||
if(!frm.doc.__islocal){
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.doc.change_in_item = 1;
|
||||
}
|
||||
},
|
||||
item_group: function(frm) {
|
||||
if(!frm.doc.__islocal){
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.doc.change_in_item = 1;
|
||||
}
|
||||
},
|
||||
description: function(frm) {
|
||||
if(!frm.doc.__islocal){
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.doc.change_in_item = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var disable = function(frm){
|
||||
var doc = frm.doc;
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
|
||||
args: {status: 1, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
|
||||
callback: function(){
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
});
|
||||
let set_item_details = function(frm) {
|
||||
if (frm.doc.service_unit_type && frm.doc.is_billable) {
|
||||
if (!frm.doc.item_code)
|
||||
frm.set_value('item_code', frm.doc.service_unit_type);
|
||||
if (!frm.doc.description)
|
||||
frm.set_value('description', frm.doc.service_unit_type);
|
||||
if (!frm.doc.item_group)
|
||||
frm.set_value('item_group', 'Services');
|
||||
}
|
||||
};
|
||||
|
||||
var enable = function(frm){
|
||||
var doc = frm.doc;
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
|
||||
args: {status: 0, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
|
||||
callback: function(){
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var change_item_code = function(frm, doc){
|
||||
var d = new frappe.ui.Dialog({
|
||||
title:__("Change Item Code"),
|
||||
fields:[
|
||||
let change_item_code = function(frm, doc) {
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __('Change Item Code'),
|
||||
fields: [
|
||||
{
|
||||
"fieldtype": "Data",
|
||||
"label": "Item Code",
|
||||
"fieldname": "Item Code",
|
||||
reqd:1
|
||||
},
|
||||
{
|
||||
"fieldtype": "Button",
|
||||
"label": __("Change Code"),
|
||||
click: function() {
|
||||
var values = d.get_values();
|
||||
if(!values)
|
||||
return;
|
||||
change_item_code_from_unit_type(values["Item Code"], doc);
|
||||
d.hide();
|
||||
}
|
||||
'fieldtype': 'Data',
|
||||
'label': 'Item Code',
|
||||
'fieldname': 'item_code',
|
||||
'default': doc.item_code,
|
||||
reqd: 1,
|
||||
}
|
||||
]
|
||||
],
|
||||
primary_action: function() {
|
||||
let values = d.get_values();
|
||||
if (values) {
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.change_item_code",
|
||||
"args": {item: doc.item, item_code: values['item_code'], doc_name: doc.name},
|
||||
callback: function () {
|
||||
frm.reload_doc();
|
||||
}
|
||||
});
|
||||
}
|
||||
d.hide();
|
||||
},
|
||||
primary_action_label: __("Change Template Code")
|
||||
});
|
||||
|
||||
d.show();
|
||||
d.set_values({
|
||||
'Item Code': frm.doc.item_code
|
||||
});
|
||||
|
||||
var change_item_code_from_unit_type = function(item_code, doc){
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.change_item_code",
|
||||
"args": {item: doc.item, item_code: item_code, doc_name: doc.name},
|
||||
callback: function () {
|
||||
frm.reload_doc();
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var set_item_details = function(frm) {
|
||||
if(frm.doc.service_unit_type && frm.doc.is_billable == 1){
|
||||
if(!frm.doc.item_code)
|
||||
frm.set_value("item_code", frm.doc.service_unit_type);
|
||||
if(!frm.doc.description)
|
||||
frm.set_value("description", frm.doc.service_unit_type);
|
||||
if(!frm.doc.item_group)
|
||||
frm.set_value("item_group", 'Services');
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,588 +1,164 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:service_unit_type",
|
||||
"beta": 0,
|
||||
"creation": "2018-07-11 16:47:51.414675",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:service_unit_type",
|
||||
"creation": "2018-07-11 16:47:51.414675",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"disabled",
|
||||
"service_unit_type",
|
||||
"allow_appointments",
|
||||
"overlap_appointments",
|
||||
"inpatient_occupancy",
|
||||
"is_billable",
|
||||
"item_details",
|
||||
"item",
|
||||
"item_code",
|
||||
"item_group",
|
||||
"uom",
|
||||
"no_of_hours",
|
||||
"column_break_11",
|
||||
"rate",
|
||||
"description",
|
||||
"change_in_item"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "service_unit_type",
|
||||
"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": "Service Unit Type",
|
||||
"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,
|
||||
"fieldname": "service_unit_type",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Service Unit Type",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.inpatient_occupancy != 1",
|
||||
"fieldname": "allow_appointments",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Allow Appointments",
|
||||
"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
|
||||
},
|
||||
"bold": 1,
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.inpatient_occupancy != 1",
|
||||
"fieldname": "allow_appointments",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Appointments",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.allow_appointments == 1 && doc.inpatient_occupany != 1",
|
||||
"fieldname": "overlap_appointments",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Allow Overlap",
|
||||
"length": 0,
|
||||
"no_copy": 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
|
||||
},
|
||||
"bold": 1,
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.allow_appointments == 1 && doc.inpatient_occupany != 1",
|
||||
"fieldname": "overlap_appointments",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Overlap",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.allow_appointments != 1",
|
||||
"fieldname": "inpatient_occupancy",
|
||||
"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": "Inpatient Occupancy",
|
||||
"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
|
||||
},
|
||||
"bold": 1,
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.allow_appointments != 1",
|
||||
"fieldname": "inpatient_occupancy",
|
||||
"fieldtype": "Check",
|
||||
"label": "Inpatient Occupancy",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.inpatient_occupancy == 1 && doc.allow_appointments != 1",
|
||||
"fieldname": "is_billable",
|
||||
"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": "Is Billable",
|
||||
"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
|
||||
},
|
||||
"bold": 1,
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.inpatient_occupancy == 1 && doc.allow_appointments != 1",
|
||||
"fieldname": "is_billable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Billable"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "is_billable",
|
||||
"fieldname": "item_details",
|
||||
"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": "Item 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
|
||||
},
|
||||
"depends_on": "is_billable",
|
||||
"fieldname": "item_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Item Details"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item",
|
||||
"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": "Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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": "item",
|
||||
"fieldtype": "Link",
|
||||
"label": "Item",
|
||||
"options": "Item",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_code",
|
||||
"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": "Item Code",
|
||||
"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": "item_code",
|
||||
"fieldtype": "Data",
|
||||
"label": "Item Code",
|
||||
"mandatory_depends_on": "eval: doc.is_billable == 1"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_group",
|
||||
"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": "Item Group",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item Group",
|
||||
"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": "item_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Item Group",
|
||||
"mandatory_depends_on": "eval: doc.is_billable == 1",
|
||||
"options": "Item Group"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "uom",
|
||||
"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": "UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "UOM",
|
||||
"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": "uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "UOM",
|
||||
"mandatory_depends_on": "eval: doc.is_billable == 1",
|
||||
"options": "UOM"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "no_of_hours",
|
||||
"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": "UOM Conversion in Hours",
|
||||
"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": "no_of_hours",
|
||||
"fieldtype": "Int",
|
||||
"label": "UOM Conversion in Hours",
|
||||
"mandatory_depends_on": "eval: doc.is_billable == 1"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_11",
|
||||
"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_11",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rate",
|
||||
"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": "Rate / UOM",
|
||||
"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": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rate / UOM"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "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": 1,
|
||||
"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
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Description"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "change_in_item",
|
||||
"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": "Change in Item",
|
||||
"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": "change_in_item",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Change in Item"
|
||||
}
|
||||
],
|
||||
"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-08-08 13:00:23.751635",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Service Unit Type",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-01-30 16:06:00.624496",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Service Unit Type",
|
||||
"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,
|
||||
"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": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "service_unit_type",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "service_unit_type"
|
||||
}
|
||||
@ -10,109 +10,107 @@ from frappe.model.rename_doc import rename_doc
|
||||
|
||||
class HealthcareServiceUnitType(Document):
|
||||
def validate(self):
|
||||
if self.is_billable == 1:
|
||||
if not self.uom or not self.item_group or not self.description or not self.no_of_hours > 0:
|
||||
frappe.throw(_("Configure Item Fields like UOM, Item Group, Description and No of Hours."))
|
||||
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 after_insert(self):
|
||||
if self.inpatient_occupancy and self.is_billable:
|
||||
create_item(self)
|
||||
|
||||
def on_trash(self):
|
||||
if(self.item):
|
||||
if self.item:
|
||||
try:
|
||||
frappe.delete_doc("Item",self.item)
|
||||
frappe.delete_doc('Item', self.item)
|
||||
except Exception:
|
||||
frappe.throw(_("""Not permitted. Please disable the Service Unit Type"""))
|
||||
frappe.throw(_('Not permitted. Please disable the Service Unit Type'))
|
||||
|
||||
def on_update(self):
|
||||
if(self.change_in_item and self.is_billable == 1 and self.item):
|
||||
updating_item(self)
|
||||
item_price = item_price_exist(self)
|
||||
if not item_price:
|
||||
if(self.rate != 0.0):
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if(self.rate):
|
||||
make_item_price(self.item_code, price_list_name, self.rate)
|
||||
else:
|
||||
make_item_price(self.item_code, price_list_name, 0.0)
|
||||
else:
|
||||
frappe.db.set_value("Item Price", item_price, "price_list_rate", self.rate)
|
||||
if self.change_in_item and self.is_billable and self.item:
|
||||
update_item(self)
|
||||
|
||||
frappe.db.set_value(self.doctype,self.name,"change_in_item",0)
|
||||
elif(self.is_billable == 0 and self.item):
|
||||
frappe.db.set_value("Item",self.item,"disabled",1)
|
||||
item_price = item_price_exists(self)
|
||||
|
||||
if not item_price:
|
||||
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
|
||||
if self.rate:
|
||||
make_item_price(self.item_code, price_list_name, self.rate)
|
||||
else:
|
||||
make_item_price(self.item_code, price_list_name, 0.0)
|
||||
else:
|
||||
frappe.db.set_value('Item Price', item_price, 'price_list_rate', self.rate)
|
||||
|
||||
frappe.db.set_value(self.doctype, self.name, 'change_in_item',0)
|
||||
elif not self.is_billable and self.item:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
self.reload()
|
||||
|
||||
def item_price_exist(doc):
|
||||
item_price = frappe.db.exists({
|
||||
"doctype": "Item Price",
|
||||
"item_code": doc.item_code})
|
||||
if(item_price):
|
||||
return item_price[0][0]
|
||||
else:
|
||||
return False
|
||||
|
||||
def updating_item(doc):
|
||||
frappe.db.sql("""update `tabItem` set item_name=%s, item_group=%s, disabled=0, standard_rate=%s,
|
||||
description=%s, modified=NOW() where item_code=%s""",
|
||||
(doc.service_unit_type, doc.item_group , doc.rate, doc.description, doc.item))
|
||||
def item_price_exists(doc):
|
||||
item_price = frappe.db.exists({'doctype': 'Item Price', 'item_code': doc.item_code})
|
||||
if len(item_price):
|
||||
return item_price[0][0]
|
||||
return False
|
||||
|
||||
def create_item(doc):
|
||||
#insert item
|
||||
# insert item
|
||||
item = frappe.get_doc({
|
||||
"doctype": "Item",
|
||||
"item_code": doc.item_code,
|
||||
"item_name":doc.service_unit_type,
|
||||
"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": 0,
|
||||
"stock_uom": doc.uom
|
||||
}).insert(ignore_permissions=True)
|
||||
'doctype': 'Item',
|
||||
'item_code': doc.item_code,
|
||||
'item_name': doc.service_unit_type,
|
||||
'item_group': doc.item_group,
|
||||
'description': doc.description or doc.item_code,
|
||||
'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': 0,
|
||||
'stock_uom': doc.uom
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
#insert item price
|
||||
#get item price list to insert item price
|
||||
if(doc.rate != 0.0):
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if(doc.rate):
|
||||
make_item_price(item.name, price_list_name, doc.rate)
|
||||
item.standard_rate = doc.rate
|
||||
else:
|
||||
make_item_price(item.name, price_list_name, 0.0)
|
||||
item.standard_rate = 0.0
|
||||
item.save(ignore_permissions = True)
|
||||
#Set item to the Doc
|
||||
frappe.db.set_value("Healthcare Service Unit Type", doc.name, "item", item.name)
|
||||
# insert item price
|
||||
# get item price list to insert item price
|
||||
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
|
||||
if doc.rate:
|
||||
make_item_price(item.name, price_list_name, doc.rate)
|
||||
item.standard_rate = doc.rate
|
||||
else:
|
||||
make_item_price(item.name, price_list_name, 0.0)
|
||||
item.standard_rate = 0.0
|
||||
|
||||
doc.reload() #refresh the doc after insert.
|
||||
item.save(ignore_permissions=True)
|
||||
|
||||
# Set item in the doc
|
||||
doc.db_set('item', item.name)
|
||||
|
||||
def make_item_price(item, price_list_name, item_price):
|
||||
frappe.get_doc({
|
||||
"doctype": "Item Price",
|
||||
"price_list": price_list_name,
|
||||
"item_code": item,
|
||||
"price_list_rate": item_price
|
||||
}).insert(ignore_permissions=True)
|
||||
'doctype': 'Item Price',
|
||||
'price_list': price_list_name,
|
||||
'item_code': item,
|
||||
'price_list_rate': item_price
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
def update_item(doc):
|
||||
item = frappe.get_doc("Item", doc.item)
|
||||
if item:
|
||||
item.update({
|
||||
"item_name": doc.service_unit_type,
|
||||
"item_group": doc.item_group,
|
||||
"disabled": 0,
|
||||
"standard_rate": doc.rate,
|
||||
"description": doc.description
|
||||
})
|
||||
item.db_update()
|
||||
|
||||
@frappe.whitelist()
|
||||
def change_item_code(item, item_code, doc_name):
|
||||
item_exist = frappe.db.exists({
|
||||
"doctype": "Item",
|
||||
"item_code": item_code})
|
||||
if(item_exist):
|
||||
frappe.throw(_("Code {0} already exist").format(item_code))
|
||||
if frappe.db.exists({'doctype': 'Item', 'item_code': item_code}):
|
||||
frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
|
||||
else:
|
||||
rename_doc("Item", item, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "item_code", item_code)
|
||||
|
||||
@frappe.whitelist()
|
||||
def disable_enable(status, doc_name, item=None, is_billable=None):
|
||||
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "disabled", status)
|
||||
if(is_billable == 1):
|
||||
frappe.db.set_value("Item", item, "disabled", status)
|
||||
rename_doc('Item', item, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value('Healthcare Service Unit Type', doc_name, 'item_code', item_code)
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'service_unit_type',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Healthcare Service Units'),
|
||||
'items': ['Healthcare Service Unit']
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -3,6 +3,31 @@
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import frappe
|
||||
|
||||
class TestHealthcareServiceUnitType(unittest.TestCase):
|
||||
pass
|
||||
def test_item_creation(self):
|
||||
unit_type = get_unit_type()
|
||||
self.assertTrue(frappe.db.exists('Item', unit_type.item))
|
||||
|
||||
# check item disabled
|
||||
unit_type.disabled = 1
|
||||
unit_type.save()
|
||||
self.assertEqual(frappe.db.get_value('Item', unit_type.item, 'disabled'), 1)
|
||||
|
||||
|
||||
def get_unit_type():
|
||||
if frappe.db.exists('Healthcare Service Unit Type', 'Inpatient Rooms'):
|
||||
return frappe.get_doc('Healthcare Service Unit Type', 'Inpatient Rooms')
|
||||
|
||||
unit_type = frappe.new_doc('Healthcare Service Unit Type')
|
||||
unit_type.service_unit_type = 'Inpatient Rooms'
|
||||
unit_type.inpatient_occupancy = 1
|
||||
unit_type.is_billable = 1
|
||||
unit_type.item_code = 'Inpatient Rooms'
|
||||
unit_type.item_group = 'Services'
|
||||
unit_type.uom = 'Hour'
|
||||
unit_type.no_of_hours = 1
|
||||
unit_type.rate = 4000
|
||||
unit_type.save()
|
||||
return unit_type
|
||||
@ -7,40 +7,40 @@
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"sb_op_settings",
|
||||
"patient_master_name",
|
||||
"manage_customer",
|
||||
"patient_name_by",
|
||||
"link_customer_to_patient",
|
||||
"default_medical_code_standard",
|
||||
"column_break_9",
|
||||
"collect_registration_fee",
|
||||
"registration_fee",
|
||||
"manage_appointment_invoice_automatically",
|
||||
"max_visit",
|
||||
"automate_appointment_invoicing",
|
||||
"enable_free_follow_ups",
|
||||
"max_visits",
|
||||
"valid_days",
|
||||
"healthcare_service_items",
|
||||
"inpatient_visit_charge_item",
|
||||
"op_consulting_charge_item",
|
||||
"column_break_13",
|
||||
"clinical_procedure_consumable_item",
|
||||
"out_patient_sms_alerts",
|
||||
"reg_sms",
|
||||
"reg_msg",
|
||||
"app_con",
|
||||
"app_con_msg",
|
||||
"no_con",
|
||||
"column_break_16",
|
||||
"app_rem",
|
||||
"app_rem_msg",
|
||||
"rem_before",
|
||||
"sb_in_ac",
|
||||
"income_account",
|
||||
"sb_r_ac",
|
||||
"receivable_account",
|
||||
"out_patient_sms_alerts",
|
||||
"send_registration_msg",
|
||||
"registration_msg",
|
||||
"send_appointment_confirmation",
|
||||
"appointment_confirmation_msg",
|
||||
"avoid_confirmation",
|
||||
"column_break_16",
|
||||
"send_appointment_reminder",
|
||||
"appointment_reminder_msg",
|
||||
"remind_before",
|
||||
"sb_lab_settings",
|
||||
"create_test_on_si_submit",
|
||||
"require_sample_collection",
|
||||
"require_test_result_approval",
|
||||
"create_lab_test_on_si_submit",
|
||||
"create_sample_collection_for_lab_test",
|
||||
"column_break_34",
|
||||
"employee_name_and_designation_in_print",
|
||||
"lab_test_approval_required",
|
||||
"custom_signature_in_print",
|
||||
"laboratory_sms_alerts",
|
||||
"sms_printed",
|
||||
@ -53,19 +53,6 @@
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Out Patient Settings"
|
||||
},
|
||||
{
|
||||
"fieldname": "patient_master_name",
|
||||
"fieldtype": "Select",
|
||||
"label": "Patient Name By",
|
||||
"options": "Patient Name\nNaming Series"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"description": "If checked, a customer will be created, mapped to Patient.\nPatient Invoices will be created against this Customer. You can also select existing Customer while creating Patient.",
|
||||
"fieldname": "manage_customer",
|
||||
"fieldtype": "Check",
|
||||
"label": "Manage Customer"
|
||||
},
|
||||
{
|
||||
"fieldname": "default_medical_code_standard",
|
||||
"fieldtype": "Link",
|
||||
@ -78,6 +65,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Checking this will create new Patients with a Disabled status by default and will only be enabled after invoicing the Registration Fee.",
|
||||
"fieldname": "collect_registration_fee",
|
||||
"fieldtype": "Check",
|
||||
"label": "Collect Fee for Patient Registration"
|
||||
@ -91,27 +79,19 @@
|
||||
"options": "Currency"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Manage Appointment Invoice submit and cancel automatically for Patient Encounter",
|
||||
"fieldname": "manage_appointment_invoice_automatically",
|
||||
"fieldtype": "Check",
|
||||
"label": "Invoice Appointments Automatically"
|
||||
},
|
||||
{
|
||||
"fieldname": "max_visit",
|
||||
"fieldtype": "Int",
|
||||
"label": "Patient Encounters in valid days"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enable_free_follow_ups == 1",
|
||||
"description": "Time period (Valid number of days) for free consultations",
|
||||
"fieldname": "valid_days",
|
||||
"fieldtype": "Int",
|
||||
"label": "Valid number of days"
|
||||
"label": "Valid Number of Days",
|
||||
"mandatory_depends_on": "eval:doc.enable_free_follow_ups == 1"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"description": "You can configure default Items for billing consultation charges, procedure consumption items and inpatient visits",
|
||||
"fieldname": "healthcare_service_items",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Healthcare Service Items"
|
||||
"label": "Default Healthcare Service Items"
|
||||
},
|
||||
{
|
||||
"fieldname": "inpatient_visit_charge_item",
|
||||
@ -141,87 +121,25 @@
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Out Patient SMS Alerts"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "reg_sms",
|
||||
"fieldtype": "Check",
|
||||
"label": "Patient Registration"
|
||||
},
|
||||
{
|
||||
"default": "Hello {{doc.patient}}, Thank you for registering with {{doc.company}}. Your ID is {{doc.id}} . Please note this ID for future reference. \nThank You, Get well soon!",
|
||||
"depends_on": "reg_sms",
|
||||
"fieldname": "reg_msg",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Registration Message"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "app_con",
|
||||
"fieldtype": "Check",
|
||||
"label": "Appointment Confirmation"
|
||||
},
|
||||
{
|
||||
"default": "Hello {{doc.patient}}, You have scheduled an appointment with {{doc.practitioner}} by {{doc.start_dt}} at {{doc.company}}.\nThank you, Good day!",
|
||||
"depends_on": "app_con",
|
||||
"fieldname": "app_con_msg",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Confirmation Message"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "app_con",
|
||||
"description": "Do not confirm if appointment is created for the same day",
|
||||
"fieldname": "no_con",
|
||||
"fieldtype": "Check",
|
||||
"label": "Avoid Confirmation"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_16",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "app_rem",
|
||||
"fieldtype": "Check",
|
||||
"label": "Appointment Reminder"
|
||||
},
|
||||
{
|
||||
"default": "Hello {{doc.patient}}, You have an appointment with {{doc.practitioner}} by {{doc.appointment_time}} at {{doc.company}}.\nThank you, Good day!\n",
|
||||
"depends_on": "app_rem",
|
||||
"fieldname": "app_rem_msg",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Reminder Message"
|
||||
},
|
||||
{
|
||||
"depends_on": "app_rem",
|
||||
"fieldname": "rem_before",
|
||||
"fieldtype": "Time",
|
||||
"label": "Remind Before"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"description": "Default income accounts to be used if not set in Healthcare Practitioner to book Appointment charges.",
|
||||
"fieldname": "sb_in_ac",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Income Account"
|
||||
"label": "Default Accounts"
|
||||
},
|
||||
{
|
||||
"description": "Default income accounts to be used if not set in Healthcare Practitioner to book Appointment charges.",
|
||||
"fieldname": "income_account",
|
||||
"fieldtype": "Table",
|
||||
"label": "Income Account",
|
||||
"options": "Party Account"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"description": "Default receivable accounts to be used if not set in Patient to book Appointment charges.",
|
||||
"fieldname": "sb_r_ac",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Receivable Account"
|
||||
},
|
||||
{
|
||||
"description": "Default receivable accounts to be used to book Appointment charges.",
|
||||
"fieldname": "receivable_account",
|
||||
"fieldtype": "Table",
|
||||
"label": "Receivable Account",
|
||||
@ -233,31 +151,13 @@
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Laboratory Settings"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "create_test_on_si_submit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Create Lab Test(s) on Sales Invoice Submit"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Create documents for sample collection",
|
||||
"fieldname": "require_sample_collection",
|
||||
"fieldtype": "Check",
|
||||
"label": "Manage Sample Collection"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "require_test_result_approval",
|
||||
"fieldtype": "Check",
|
||||
"label": "Require Lab Test Approval"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_34",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"description": "Check this if you want the Name and Designation of the Employee associated with the User who submits the document to be printed in the Lab Test Report.",
|
||||
"fieldname": "employee_name_and_designation_in_print",
|
||||
"fieldtype": "Check",
|
||||
"label": "Employee name and designation in print"
|
||||
@ -279,7 +179,7 @@
|
||||
"fieldname": "sms_printed",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Result Printed"
|
||||
"label": "Result Printed Message"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_28",
|
||||
@ -290,12 +190,123 @@
|
||||
"fieldname": "sms_emailed",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Result Emailed"
|
||||
"label": "Result Emailed Message"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Checking this will restrict printing and emailing of Lab Test documents unless they have the status as Approved.",
|
||||
"fieldname": "lab_test_approval_required",
|
||||
"fieldtype": "Check",
|
||||
"label": "Do not print or email Lab Tests without Approval"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"description": "If checked, a customer will be created, mapped to Patient.\nPatient Invoices will be created against this Customer. You can also select existing Customer while creating Patient.",
|
||||
"fieldname": "link_customer_to_patient",
|
||||
"fieldtype": "Check",
|
||||
"label": "Link Customer to Patient"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Checking this will create Lab Test(s) specified in the Sales Invoice on submission.",
|
||||
"fieldname": "create_lab_test_on_si_submit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Create Lab Test(s) on Sales Invoice Submission"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Checking this will create a Sample Collection document every time you create a Lab Test",
|
||||
"fieldname": "create_sample_collection_for_lab_test",
|
||||
"fieldtype": "Check",
|
||||
"label": "Create Sample Collection document for Lab Test"
|
||||
},
|
||||
{
|
||||
"fieldname": "patient_name_by",
|
||||
"fieldtype": "Select",
|
||||
"label": "Patient Name By",
|
||||
"options": "Patient Name\nNaming Series"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Manage Appointment Invoice submit and cancel automatically for Patient Encounter",
|
||||
"fieldname": "automate_appointment_invoicing",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automate Appointment Invoicing"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "send_registration_msg",
|
||||
"fieldtype": "Check",
|
||||
"label": "Patient Registration"
|
||||
},
|
||||
{
|
||||
"default": "Hello {{doc.patient}}, Thank you for registering with {{doc.company}}. Your ID is {{doc.id}} . Please note this ID for future reference. \nThank You, Get well soon!",
|
||||
"depends_on": "send_registration_msg",
|
||||
"fieldname": "registration_msg",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Registration Message"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "send_appointment_confirmation",
|
||||
"fieldtype": "Check",
|
||||
"label": "Appointment Confirmation"
|
||||
},
|
||||
{
|
||||
"default": "Hello {{doc.patient}}, You have scheduled an appointment with {{doc.practitioner}} by {{doc.start_dt}} at {{doc.company}}.\nThank you, Good day!",
|
||||
"depends_on": "send_appointment_confirmation",
|
||||
"fieldname": "appointment_confirmation_msg",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Confirmation Message"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "send_appointment_confirmation",
|
||||
"description": "Do not confirm if appointment is created for the same day",
|
||||
"fieldname": "avoid_confirmation",
|
||||
"fieldtype": "Check",
|
||||
"label": "Avoid Confirmation"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "send_appointment_reminder",
|
||||
"fieldtype": "Check",
|
||||
"label": "Appointment Reminder"
|
||||
},
|
||||
{
|
||||
"default": "Hello {{doc.patient}}, You have an appointment with {{doc.practitioner}} by {{doc.appointment_time}} at {{doc.company}}.\nThank you, Good day!\n",
|
||||
"depends_on": "send_appointment_reminder",
|
||||
"fieldname": "appointment_reminder_msg",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Reminder Message"
|
||||
},
|
||||
{
|
||||
"depends_on": "send_appointment_reminder",
|
||||
"fieldname": "remind_before",
|
||||
"fieldtype": "Time",
|
||||
"label": "Remind Before"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enable_free_follow_ups == 1",
|
||||
"description": "The number of free follow ups (Patient Encounters in valid days) allowed",
|
||||
"fieldname": "max_visits",
|
||||
"fieldtype": "Int",
|
||||
"label": "Number of Patient Encounters in Valid Days",
|
||||
"mandatory_depends_on": "eval:doc.enable_free_follow_ups == 1"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable_free_follow_ups",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Free Follow-ups"
|
||||
}
|
||||
],
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2020-01-23 13:31:43.699711",
|
||||
"modified": "2020-03-26 11:25:21.842092",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Settings",
|
||||
|
||||
@ -11,69 +11,80 @@ import json
|
||||
|
||||
class HealthcareSettings(Document):
|
||||
def validate(self):
|
||||
for key in ["collect_registration_fee","manage_customer","patient_master_name",
|
||||
"require_test_result_approval","require_sample_collection", "default_medical_code_standard"]:
|
||||
for key in ['collect_registration_fee', 'link_customer_to_patient', 'patient_name_by',
|
||||
'lab_test_approval_required', 'create_sample_collection_for_lab_test', 'default_medical_code_standard']:
|
||||
frappe.db.set_default(key, self.get(key, ""))
|
||||
if(self.collect_registration_fee):
|
||||
if self.registration_fee <= 0 :
|
||||
frappe.throw(_("Registration fee can not be Zero"))
|
||||
|
||||
if self.collect_registration_fee:
|
||||
if self.registration_fee <= 0:
|
||||
frappe.throw(_('Registration Fee cannot be negative or zero'))
|
||||
|
||||
if self.inpatient_visit_charge_item:
|
||||
validate_service_item(self.inpatient_visit_charge_item, "Configure a service Item for Inpatient Visit Charge Item")
|
||||
validate_service_item(self.inpatient_visit_charge_item)
|
||||
if self.op_consulting_charge_item:
|
||||
validate_service_item(self.op_consulting_charge_item, "Configure a service Item for Out Patient Consulting Charge Item")
|
||||
validate_service_item(self.op_consulting_charge_item)
|
||||
if self.clinical_procedure_consumable_item:
|
||||
validate_service_item(self.clinical_procedure_consumable_item, "Configure a service Item for Clinical Procedure Consumable Item")
|
||||
validate_service_item(self.clinical_procedure_consumable_item)
|
||||
|
||||
|
||||
def validate_service_item(item):
|
||||
if frappe.db.get_value('Item', item, 'is_stock_item'):
|
||||
frappe.throw(_('Configure a service Item for {0}').format(item))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_sms_text(doc):
|
||||
sms_text = {}
|
||||
doc = frappe.get_doc("Lab Test",doc)
|
||||
#doc = json.loads(doc)
|
||||
context = {"doc": doc, "alert": doc, "comments": None}
|
||||
emailed = frappe.db.get_value("Healthcare Settings", None, "sms_emailed")
|
||||
sms_text['emailed'] = frappe.render_template(emailed, context)
|
||||
printed = frappe.db.get_value("Healthcare Settings", None, "sms_printed")
|
||||
sms_text['printed'] = frappe.render_template(printed, context)
|
||||
return sms_text
|
||||
sms_text = {}
|
||||
doc = frappe.get_doc('Lab Test', doc)
|
||||
context = {'doc': doc, 'alert': doc, 'comments': None}
|
||||
|
||||
emailed = frappe.db.get_value('Healthcare Settings', None, 'sms_emailed')
|
||||
sms_text['emailed'] = frappe.render_template(emailed, context)
|
||||
|
||||
printed = frappe.db.get_value('Healthcare Settings', None, 'sms_printed')
|
||||
sms_text['printed'] = frappe.render_template(printed, context)
|
||||
|
||||
return sms_text
|
||||
|
||||
def send_registration_sms(doc):
|
||||
if (frappe.db.get_value("Healthcare Settings", None, "reg_sms")=='1'):
|
||||
if doc.mobile:
|
||||
context = {"doc": doc, "alert": doc, "comments": None}
|
||||
if doc.get("_comments"):
|
||||
context["comments"] = json.loads(doc.get("_comments"))
|
||||
messages = frappe.db.get_value("Healthcare Settings", None, "reg_msg")
|
||||
messages = frappe.render_template(messages, context)
|
||||
number = [doc.mobile]
|
||||
send_sms(number,messages)
|
||||
else:
|
||||
frappe.msgprint(doc.name + " Has no mobile number to send registration SMS", alert=True)
|
||||
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'send_registration_msg'):
|
||||
if doc.mobile:
|
||||
context = {'doc': doc, 'alert': doc, 'comments': None}
|
||||
if doc.get('_comments'):
|
||||
context['comments'] = json.loads(doc.get('_comments'))
|
||||
messages = frappe.db.get_single_value('Healthcare Settings', 'registration_msg')
|
||||
messages = frappe.render_template(messages, context)
|
||||
number = [doc.mobile]
|
||||
send_sms(number,messages)
|
||||
else:
|
||||
frappe.msgprint(doc.name + ' has no mobile number to send registration SMS', alert=True)
|
||||
|
||||
def get_receivable_account(company):
|
||||
receivable_account = get_account(None, "receivable_account", "Healthcare Settings", company)
|
||||
if receivable_account:
|
||||
return receivable_account
|
||||
return frappe.get_cached_value('Company', company, "default_receivable_account")
|
||||
receivable_account = get_account(None, 'receivable_account', 'Healthcare Settings', company)
|
||||
if receivable_account:
|
||||
return receivable_account
|
||||
|
||||
return frappe.get_cached_value('Company', company, 'default_receivable_account')
|
||||
|
||||
def get_income_account(practitioner, company):
|
||||
if(practitioner):
|
||||
income_account = get_account("Healthcare Practitioner", None, practitioner, company)
|
||||
if income_account:
|
||||
return income_account
|
||||
income_account = get_account(None, "income_account", "Healthcare Settings", company)
|
||||
if income_account:
|
||||
return income_account
|
||||
return frappe.get_cached_value('Company', company, "default_income_account")
|
||||
# check income account in Healthcare Practitioner
|
||||
if practitioner:
|
||||
income_account = get_account('Healthcare Practitioner', None, practitioner, company)
|
||||
if income_account:
|
||||
return income_account
|
||||
|
||||
# else check income account in Healthcare Settings
|
||||
income_account = get_account(None, 'income_account', 'Healthcare Settings', company)
|
||||
if income_account:
|
||||
return income_account
|
||||
|
||||
# else return default income account of company
|
||||
return frappe.get_cached_value('Company', company, 'default_income_account')
|
||||
|
||||
def get_account(parent_type, parent_field, parent, company):
|
||||
if(parent_type):
|
||||
return frappe.db.get_value("Party Account",
|
||||
{"parenttype": parent_type, "parent": parent, "company": company}, "account")
|
||||
if(parent_field):
|
||||
return frappe.db.get_value("Party Account",
|
||||
{"parentfield": parent_field, "parent": parent, "company": company}, "account")
|
||||
if parent_type:
|
||||
return frappe.db.get_value('Party Account',
|
||||
{'parenttype': parent_type, 'parent': parent, 'company': company}, 'account')
|
||||
|
||||
def validate_service_item(item, msg):
|
||||
if frappe.db.get_value("Item", item, "is_stock_item") == 1:
|
||||
frappe.throw(_(msg))
|
||||
if parent_field:
|
||||
return frappe.db.get_value('Party Account',
|
||||
{'parentfield': parent_field, 'parent': parent, 'company': company}, 'account')
|
||||
|
||||
@ -8,11 +8,12 @@ import unittest
|
||||
from frappe.utils import now_datetime, today
|
||||
from frappe.utils.make_random import get_random
|
||||
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
|
||||
from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient
|
||||
|
||||
class TestInpatientRecord(unittest.TestCase):
|
||||
def test_admit_and_discharge(self):
|
||||
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||
patient = get_patient()
|
||||
patient = create_patient()
|
||||
# Schedule Admission
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.save(ignore_permissions = True)
|
||||
@ -41,7 +42,7 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
|
||||
def test_validate_overlap_admission(self):
|
||||
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||
patient = get_patient()
|
||||
patient = create_patient()
|
||||
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.save(ignore_permissions = True)
|
||||
@ -75,17 +76,6 @@ def create_inpatient(patient):
|
||||
inpatient_record.scheduled_date = today()
|
||||
return inpatient_record
|
||||
|
||||
def get_patient():
|
||||
patient = get_random("Patient")
|
||||
if not patient:
|
||||
patient = frappe.new_doc("Patient")
|
||||
patient.patient_name = "Test Patient"
|
||||
patient.sex = "Male"
|
||||
patient.save(ignore_permissions=True)
|
||||
return patient.name
|
||||
return patient
|
||||
|
||||
|
||||
def get_healthcare_service_unit():
|
||||
service_unit = get_random("Healthcare Service Unit", filters={"inpatient_occupancy": 1})
|
||||
if not service_unit:
|
||||
|
||||
@ -1,238 +1,78 @@
|
||||
{
|
||||
"allow_copy": 1,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2016-09-16 16:53:06.882970",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"beta": 1,
|
||||
"creation": "2016-09-16 16:53:06.882970",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"lab_test_code",
|
||||
"lab_test_name",
|
||||
"invoiced",
|
||||
"column_break_4",
|
||||
"lab_test_comment",
|
||||
"lab_test_created"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "lab_test_code",
|
||||
"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": "Test Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Lab Test 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": "lab_test_code",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Lab Test",
|
||||
"options": "Lab Test Template",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "lab_test_code.lab_test_name",
|
||||
"fieldname": "lab_test_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": "Test",
|
||||
"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": "lab_test_code.lab_test_name",
|
||||
"fieldname": "lab_test_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Lab Test Name"
|
||||
},
|
||||
{
|
||||
"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": 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,
|
||||
"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": "lab_test_comment",
|
||||
"fieldtype": "Small Text",
|
||||
"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": "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": "lab_test_comment",
|
||||
"fieldtype": "Small Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Comments"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "lab_test_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": "Test Created",
|
||||
"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": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"default": "0",
|
||||
"fieldname": "lab_test_created",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Test Created",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"report_hide": 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-09-04 09:02:18.592637",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab 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": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-02-26 17:03:00.255560",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Prescription",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@ -29,7 +29,7 @@ frappe.ui.form.on('Lab Test', {
|
||||
get_lab_test_prescribed(frm);
|
||||
});
|
||||
}
|
||||
if(frm.doc.docstatus==1 && frm.doc.status!='Approved' && frm.doc.status!='Rejected' && frappe.defaults.get_default("require_test_result_approval") && frappe.user.has_role("LabTest Approver")){
|
||||
if(frm.doc.docstatus==1 && frm.doc.status!='Approved' && frm.doc.status!='Rejected' && frappe.defaults.get_default("lab_test_approval_required") && frappe.user.has_role("LabTest Approver")){
|
||||
frm.add_custom_button(__('Approve'), function() {
|
||||
status_update(1,frm);
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -191,20 +191,24 @@ def create_specials(template, lab_test):
|
||||
special.template = template.name
|
||||
|
||||
def create_sample_doc(template, patient, invoice):
|
||||
if(template.sample):
|
||||
sample_exist = frappe.db.exists({
|
||||
if template.sample:
|
||||
sample_exists = frappe.db.exists({
|
||||
"doctype": "Sample Collection",
|
||||
"patient": patient.name,
|
||||
"docstatus": 0,
|
||||
"sample": template.sample})
|
||||
if sample_exist :
|
||||
#Update Sample Collection by adding quantity
|
||||
sample_collection = frappe.get_doc("Sample Collection",sample_exist[0][0])
|
||||
quantity = int(sample_collection.sample_quantity)+int(template.sample_quantity)
|
||||
if(template.sample_collection_details):
|
||||
sample_collection_details = sample_collection.sample_collection_details+"\n==============\n"+"Test :"+template.lab_test_name+"\n"+"Collection Detials:\n\t"+template.sample_collection_details
|
||||
frappe.db.set_value("Sample Collection", sample_collection.name, "sample_collection_details",sample_collection_details)
|
||||
frappe.db.set_value("Sample Collection", sample_collection.name, "sample_quantity",quantity)
|
||||
"sample": template.sample
|
||||
})
|
||||
if sample_exists:
|
||||
# update Sample Collection by adding quantity
|
||||
sample_collection = frappe.get_doc("Sample Collection", sample_exists[0][0])
|
||||
quantity = int(sample_collection.sample_qty) + int(template.sample_qty)
|
||||
if template.sample_details:
|
||||
sample_details = sample_collection.sample_details + "\n==============\n" + _("Test: ")
|
||||
sample_details += (template.get("lab_test_name") or template.get("template")) + "\n"
|
||||
sample_details += _("Collection Details: ") + "\n\t" + template.sample_details
|
||||
|
||||
frappe.db.set_value("Sample Collection", sample_collection.name, "sample_details", sample_details)
|
||||
frappe.db.set_value("Sample Collection", sample_collection.name, "sample_qty", quantity)
|
||||
|
||||
else:
|
||||
#create Sample Collection for template, copy vals from Invoice
|
||||
@ -216,15 +220,15 @@ def create_sample_doc(template, patient, invoice):
|
||||
sample_collection.patient_sex = patient.sex
|
||||
sample_collection.sample = template.sample
|
||||
sample_collection.sample_uom = template.sample_uom
|
||||
sample_collection.sample_quantity = template.sample_quantity
|
||||
if(template.sample_collection_details):
|
||||
sample_collection.sample_collection_details = "Test :"+template.lab_test_name+"\n"+"Collection Detials:\n\t"+template.sample_collection_details
|
||||
sample_collection.sample_qty = template.sample_qty
|
||||
if(template.sample_details):
|
||||
sample_collection.sample_details = "Test :" + (template.get("lab_test_name") or template.get("template")) +"\n"+"Collection Detials:\n\t"+template.sample_details
|
||||
sample_collection.save(ignore_permissions=True)
|
||||
|
||||
return sample_collection
|
||||
|
||||
def create_sample_collection(lab_test, template, patient, invoice):
|
||||
if(frappe.db.get_value("Healthcare Settings", None, "require_sample_collection") == "1"):
|
||||
if(frappe.db.get_value("Healthcare Settings", None, "create_sample_collection_for_lab_test") == "1"):
|
||||
sample_collection = create_sample_doc(template, patient, invoice)
|
||||
if(sample_collection):
|
||||
lab_test.sample = sample_collection.name
|
||||
@ -290,10 +294,14 @@ def insert_lab_test_to_medical_record(doc):
|
||||
comment = ""
|
||||
if item.lab_test_comment:
|
||||
comment = str(item.lab_test_comment)
|
||||
event = ""
|
||||
table_row = item.lab_test_name
|
||||
|
||||
if item.lab_test_event:
|
||||
event = item.lab_test_event
|
||||
table_row = item.lab_test_name +" "+ event +" "+ item.result_value
|
||||
table_row += " " + item.lab_test_event
|
||||
|
||||
if item.result_value:
|
||||
table_row += " " + item.result_value
|
||||
|
||||
if item.normal_range:
|
||||
table_row += " normal_range("+item.normal_range+")"
|
||||
table_row += " "+comment
|
||||
|
||||
@ -1,145 +1,68 @@
|
||||
{
|
||||
"allow_copy": 1,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:sample",
|
||||
"beta": 1,
|
||||
"creation": "2016-04-04 17:35:44.823951",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:sample",
|
||||
"beta": 1,
|
||||
"creation": "2016-04-04 17:35:44.823951",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"sample",
|
||||
"sample_uom"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sample",
|
||||
"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": "Sample",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "sample",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Sample",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"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": 0,
|
||||
"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,
|
||||
"unique": 0
|
||||
"bold": 1,
|
||||
"fieldname": "sample_uom",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "UOM",
|
||||
"options": "Lab Test UOM"
|
||||
}
|
||||
],
|
||||
"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": "2017-08-31 13:46:22.508908",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Test Sample",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-01-29 23:02:02.249839",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Test Sample",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Healthcare Administrator",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Healthcare Administrator",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"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": 0,
|
||||
"write": 0
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Laboratory User",
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"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",
|
||||
"title_field": "sample",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "sample",
|
||||
"track_changes": 1
|
||||
}
|
||||
@ -35,8 +35,8 @@
|
||||
"sb_sample_collection",
|
||||
"sample",
|
||||
"sample_uom",
|
||||
"sample_quantity",
|
||||
"sample_collection_details",
|
||||
"sample_qty",
|
||||
"sample_details",
|
||||
"change_in_item"
|
||||
],
|
||||
"fields": [
|
||||
@ -105,7 +105,7 @@
|
||||
"description": "If unchecked, the item wont be appear in Sales Invoice, but can be used in group test creation. ",
|
||||
"fieldname": "is_billable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is billable",
|
||||
"label": "Is Billable",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
@ -114,7 +114,8 @@
|
||||
"fieldname": "lab_test_rate",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Standard Selling Rate"
|
||||
"label": "Rate",
|
||||
"mandatory_depends_on": "eval:doc.is_billable == 1"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.lab_test_template_type == 'Single'",
|
||||
@ -209,18 +210,6 @@
|
||||
"label": "UOM",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "sample_quantity",
|
||||
"fieldtype": "Float",
|
||||
"label": "Quantity"
|
||||
},
|
||||
{
|
||||
"fieldname": "sample_collection_details",
|
||||
"fieldtype": "Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Collection Details"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "change_in_item",
|
||||
@ -236,11 +225,23 @@
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "sample_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Quantity"
|
||||
},
|
||||
{
|
||||
"fieldname": "sample_details",
|
||||
"fieldtype": "Text",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Collection Details"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-01-21 21:02:16.108347",
|
||||
"modified_by": "ruchamahabal2@gmail.com",
|
||||
"modified": "2020-03-25 16:53:01.740103",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Test Template",
|
||||
"owner": "Administrator",
|
||||
|
||||
@ -99,13 +99,10 @@ def create_item_from_template(doc):
|
||||
# get item price list to insert item price
|
||||
if doc.lab_test_rate != 0.0:
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if(doc.lab_test_rate):
|
||||
if doc.lab_test_rate:
|
||||
make_item_price(item.name, price_list_name, doc.lab_test_rate)
|
||||
item.standard_rate = doc.lab_test_rate
|
||||
else:
|
||||
make_item_price(item.name, price_list_name, 0.0)
|
||||
item.standard_rate = 0.0
|
||||
item.save(ignore_permissions = True)
|
||||
# Set item in the template
|
||||
frappe.db.set_value("Lab Test Template", doc.name, "item", item.name)
|
||||
|
||||
|
||||
@ -3,128 +3,77 @@
|
||||
|
||||
frappe.ui.form.on('Patient', {
|
||||
refresh: function (frm) {
|
||||
frm.set_query("patient", "patient_relation", function () {
|
||||
frm.set_query('patient', 'patient_relation', function () {
|
||||
return {
|
||||
filters: [
|
||||
["Patient", "name", "!=", frm.doc.name]
|
||||
['Patient', 'name', '!=', frm.doc.name]
|
||||
]
|
||||
};
|
||||
});
|
||||
if (frappe.defaults.get_default("patient_master_name") != "Naming Series") {
|
||||
frm.toggle_display("naming_series", false);
|
||||
|
||||
if (frappe.defaults.get_default('patient_name_by') != 'Naming Series') {
|
||||
frm.toggle_display('naming_series', false);
|
||||
} else {
|
||||
erpnext.toggle_naming_series();
|
||||
}
|
||||
if (frappe.defaults.get_default("collect_registration_fee") && frm.doc.disabled == 1) {
|
||||
|
||||
if (frappe.defaults.get_default('collect_registration_fee') && frm.doc.status == 'Disabled') {
|
||||
frm.add_custom_button(__('Invoice Patient Registration'), function () {
|
||||
btn_invoice_registration(frm);
|
||||
invoice_registration(frm);
|
||||
});
|
||||
}
|
||||
if (frm.doc.patient_name && frappe.user.has_role("Physician")) {
|
||||
frm.add_custom_button(__('Patient History'), function () {
|
||||
frappe.route_options = { "patient": frm.doc.name };
|
||||
frappe.set_route("patient_history");
|
||||
},"View");
|
||||
|
||||
if (frm.doc.patient_name && frappe.user.has_role('Physician')) {
|
||||
frm.add_custom_button(__('Patient History'), function() {
|
||||
frappe.route_options = {'patient': frm.doc.name};
|
||||
frappe.set_route('patient_history');
|
||||
},'View');
|
||||
}
|
||||
if (!frm.doc.__islocal && (frappe.user.has_role("Nursing User") || frappe.user.has_role("Physician"))) {
|
||||
|
||||
if (!frm.doc.__islocal && (frappe.user.has_role('Nursing User') || frappe.user.has_role('Physician'))) {
|
||||
frm.add_custom_button(__('Vital Signs'), function () {
|
||||
btn_create_vital_signs(frm);
|
||||
}, "Create");
|
||||
create_vital_signs(frm);
|
||||
}, 'Create');
|
||||
frm.add_custom_button(__('Medical Record'), function () {
|
||||
create_medical_record(frm);
|
||||
}, "Create");
|
||||
}, 'Create');
|
||||
frm.add_custom_button(__('Patient Encounter'), function () {
|
||||
btn_create_encounter(frm);
|
||||
}, "Create");
|
||||
create_encounter(frm);
|
||||
}, 'Create');
|
||||
}
|
||||
},
|
||||
onload: function (frm) {
|
||||
if(!frm.doc.dob){
|
||||
$(frm.fields_dict['age_html'].wrapper).html("");
|
||||
$(frm.fields_dict['age_html'].wrapper).html('');
|
||||
}
|
||||
if(frm.doc.dob){
|
||||
$(frm.fields_dict['age_html'].wrapper).html("AGE : " + get_age(frm.doc.dob));
|
||||
$(frm.fields_dict['age_html'].wrapper).html('AGE : ' + get_age(frm.doc.dob));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Patient", "dob", function(frm) {
|
||||
if(frm.doc.dob) {
|
||||
var today = new Date();
|
||||
var birthDate = new Date(frm.doc.dob);
|
||||
if(today < birthDate){
|
||||
frappe.msgprint(__("Please select a valid Date"));
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "dob", "");
|
||||
frappe.ui.form.on('Patient', 'dob', function(frm) {
|
||||
if (frm.doc.dob) {
|
||||
let today = new Date();
|
||||
let birthDate = new Date(frm.doc.dob);
|
||||
if (today < birthDate){
|
||||
frappe.msgprint(__('Please select a valid Date'));
|
||||
frappe.model.set_value(frm.doctype,frm.docname, 'dob', '');
|
||||
}
|
||||
else{
|
||||
var age_str = get_age(frm.doc.dob);
|
||||
$(frm.fields_dict['age_html'].wrapper).html("AGE : " + age_str);
|
||||
else {
|
||||
let age_str = get_age(frm.doc.dob);
|
||||
$(frm.fields_dict['age_html'].wrapper).html('AGE : ' + age_str);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$(frm.fields_dict['age_html'].wrapper).html("");
|
||||
$(frm.fields_dict['age_html'].wrapper).html('');
|
||||
}
|
||||
});
|
||||
|
||||
var create_medical_record = function (frm) {
|
||||
frappe.route_options = {
|
||||
"patient": frm.doc.name,
|
||||
"status": "Open",
|
||||
"reference_doctype": "Patient Medical Record",
|
||||
"reference_owner": frm.doc.owner
|
||||
};
|
||||
frappe.new_doc("Patient Medical Record");
|
||||
};
|
||||
|
||||
var get_age = function (birth) {
|
||||
var ageMS = Date.parse(Date()) - Date.parse(birth);
|
||||
var age = new Date();
|
||||
age.setTime(ageMS);
|
||||
var years = age.getFullYear() - 1970;
|
||||
return years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)";
|
||||
};
|
||||
|
||||
var btn_create_vital_signs = function (frm) {
|
||||
if (!frm.doc.name) {
|
||||
frappe.throw(__("Please save the patient first"));
|
||||
}
|
||||
frappe.route_options = {
|
||||
"patient": frm.doc.name,
|
||||
};
|
||||
frappe.new_doc("Vital Signs");
|
||||
};
|
||||
|
||||
var btn_create_encounter = function (frm) {
|
||||
if (!frm.doc.name) {
|
||||
frappe.throw(__("Please save the patient first"));
|
||||
}
|
||||
frappe.route_options = {
|
||||
"patient": frm.doc.name,
|
||||
};
|
||||
frappe.new_doc("Patient Encounter");
|
||||
};
|
||||
|
||||
var btn_invoice_registration = function (frm) {
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "invoice_patient_registration",
|
||||
callback: function(data){
|
||||
if(!data.exc){
|
||||
if(data.message.invoice){
|
||||
/* frappe.show_alert(__('Sales Invoice {0} created',
|
||||
['<a href="#Form/Sales Invoice/'+data.message.invoice+'">' + data.message.invoice+ '</a>'])); */
|
||||
frappe.set_route("Form", "Sales Invoice", data.message.invoice);
|
||||
}
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
frappe.ui.form.on('Patient Relation', {
|
||||
patient_relation_add: function(frm){
|
||||
frm.fields_dict['patient_relation'].grid.get_field('patient').get_query = function(doc){
|
||||
var patient_list = [];
|
||||
let patient_list = [];
|
||||
if(!doc.__islocal) patient_list.push(doc.name);
|
||||
$.each(doc.patient_relation, function(idx, val){
|
||||
if (val.patient) patient_list.push(val.patient);
|
||||
@ -133,3 +82,56 @@ frappe.ui.form.on('Patient Relation', {
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
let create_medical_record = function (frm) {
|
||||
frappe.route_options = {
|
||||
'patient': frm.doc.name,
|
||||
'status': 'Open',
|
||||
'reference_doctype': 'Patient Medical Record',
|
||||
'reference_owner': frm.doc.owner
|
||||
};
|
||||
frappe.new_doc('Patient Medical Record');
|
||||
};
|
||||
|
||||
let get_age = function (birth) {
|
||||
let ageMS = Date.parse(Date()) - Date.parse(birth);
|
||||
let age = new Date();
|
||||
age.setTime(ageMS);
|
||||
let years = age.getFullYear() - 1970;
|
||||
return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
|
||||
};
|
||||
|
||||
let create_vital_signs = function (frm) {
|
||||
if (!frm.doc.name) {
|
||||
frappe.throw(__('Please save the patient first'));
|
||||
}
|
||||
frappe.route_options = {
|
||||
'patient': frm.doc.name,
|
||||
};
|
||||
frappe.new_doc('Vital Signs');
|
||||
};
|
||||
|
||||
let create_encounter = function (frm) {
|
||||
if (!frm.doc.name) {
|
||||
frappe.throw(__('Please save the patient first'));
|
||||
}
|
||||
frappe.route_options = {
|
||||
'patient': frm.doc.name,
|
||||
};
|
||||
frappe.new_doc('Patient Encounter');
|
||||
};
|
||||
|
||||
let invoice_registration = function (frm) {
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: 'invoice_patient_registration',
|
||||
callback: function(data) {
|
||||
if (!data.exc) {
|
||||
if (data.message.invoice) {
|
||||
frappe.set_route('Form', 'Sales Invoice', data.message.invoice);
|
||||
}
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
@ -11,23 +12,29 @@
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"basic_info",
|
||||
"inpatient_status",
|
||||
"inpatient_record",
|
||||
"naming_series",
|
||||
"first_name",
|
||||
"middle_name",
|
||||
"last_name",
|
||||
"patient_name",
|
||||
"sex",
|
||||
"blood_group",
|
||||
"dob",
|
||||
"age_html",
|
||||
"status",
|
||||
"image",
|
||||
"column_break_14",
|
||||
"status",
|
||||
"inpatient_status",
|
||||
"inpatient_record",
|
||||
"customer",
|
||||
"report_preference",
|
||||
"mobile",
|
||||
"email",
|
||||
"phone",
|
||||
"disabled",
|
||||
"report_preference",
|
||||
"personal_and_social_history",
|
||||
"occupation",
|
||||
"column_break_25",
|
||||
"marital_status",
|
||||
"sb_relation",
|
||||
"patient_relation",
|
||||
"allergy_medical_and_surgical_history",
|
||||
@ -36,10 +43,6 @@
|
||||
"column_break_20",
|
||||
"medical_history",
|
||||
"surgical_history",
|
||||
"personal_and_social_history",
|
||||
"occupation",
|
||||
"column_break_25",
|
||||
"marital_status",
|
||||
"risk_factors",
|
||||
"tobacco_past_use",
|
||||
"tobacco_current_use",
|
||||
@ -78,28 +81,28 @@
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Patient ID",
|
||||
"label": "Series",
|
||||
"options": "HLC-PAT-.YYYY.-",
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
"report_hide": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
"fieldname": "patient_name",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 1,
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Full Name",
|
||||
"no_copy": 1,
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "sex",
|
||||
"fieldtype": "Select",
|
||||
"fieldtype": "Link",
|
||||
"label": "Gender",
|
||||
"options": "\nMale\nFemale\nOther",
|
||||
"options": "Gender",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
@ -125,15 +128,15 @@
|
||||
"report_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "Active",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"options": "Active\nDormant\nOpen",
|
||||
"options": "Active\nDisabled",
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "image",
|
||||
@ -149,12 +152,12 @@
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "If \"Link Customer to Patient\" is checked in Healthcare Settings and an existing Customer is not selected then, a Customer will be created for this Patient for recording transactions in Accounts module.",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Customer",
|
||||
"options": "Customer",
|
||||
"set_only_once": 1
|
||||
"options": "Customer"
|
||||
},
|
||||
{
|
||||
"fieldname": "report_preference",
|
||||
@ -183,19 +186,8 @@
|
||||
"fieldname": "phone",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Phone"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Disabled",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "sb_relation",
|
||||
@ -276,25 +268,25 @@
|
||||
"fieldname": "tobacco_past_use",
|
||||
"fieldtype": "Data",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Tobacco Past Use"
|
||||
"label": "Tobacco Consumption Habbits (Past)"
|
||||
},
|
||||
{
|
||||
"fieldname": "tobacco_current_use",
|
||||
"fieldtype": "Data",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Tobacco Current Use"
|
||||
"label": "Tobacco Consumption Habbits (Present)"
|
||||
},
|
||||
{
|
||||
"fieldname": "alcohol_past_use",
|
||||
"fieldtype": "Data",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Alcohol Past Use"
|
||||
"label": "Alcohol Consumption Habbits (Past)"
|
||||
},
|
||||
{
|
||||
"fieldname": "alcohol_current_use",
|
||||
"fieldtype": "Data",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Alcohol Current Use"
|
||||
"label": "Alcohol Consumption Habbits (Present)"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_32",
|
||||
@ -342,12 +334,30 @@
|
||||
"label": "Default Currency",
|
||||
"options": "Currency",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "last_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Last Name"
|
||||
},
|
||||
{
|
||||
"fieldname": "first_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "First Name",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "middle_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Middle Name (optional)"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-user",
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"max_attachments": 50,
|
||||
"modified": "2019-09-25 23:30:49.905893",
|
||||
"modified": "2020-04-06 12:55:30.807744",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient",
|
||||
|
||||
@ -6,46 +6,57 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, cstr, getdate, flt
|
||||
from frappe.utils import cint, cstr, getdate
|
||||
import dateutil
|
||||
from frappe.model.naming import set_name_by_naming_series
|
||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account,get_income_account,send_registration_sms
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account, send_registration_sms
|
||||
|
||||
class Patient(Document):
|
||||
def after_insert(self):
|
||||
if(frappe.db.get_value("Healthcare Settings", None, "manage_customer") == '1' and not self.customer):
|
||||
create_customer(self)
|
||||
if(frappe.db.get_value("Healthcare Settings", None, "collect_registration_fee") == '1'):
|
||||
frappe.db.set_value("Patient", self.name, "disabled", 1)
|
||||
else:
|
||||
send_registration_sms(self)
|
||||
self.reload()
|
||||
|
||||
def on_update(self):
|
||||
def validate(self):
|
||||
self.set_full_name()
|
||||
self.add_as_website_user()
|
||||
|
||||
def after_insert(self):
|
||||
self.add_as_website_user()
|
||||
self.reload()
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient') and not self.customer:
|
||||
create_customer(self)
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'collect_registration_fee'):
|
||||
frappe.db.set_value('Patient', self.name, 'status', 'Disabled')
|
||||
else:
|
||||
send_registration_sms(self)
|
||||
|
||||
def set_full_name(self):
|
||||
if self.last_name:
|
||||
self.patient_name = ' '.join(filter(None, [self.first_name, self.last_name]))
|
||||
else:
|
||||
self.patient_name = self.first_name
|
||||
|
||||
def add_as_website_user(self):
|
||||
if(self.email):
|
||||
if not frappe.db.exists ("User", self.email):
|
||||
if self.email:
|
||||
if not frappe.db.exists ('User', self.email):
|
||||
user = frappe.get_doc({
|
||||
"doctype": "User",
|
||||
"first_name": self.patient_name,
|
||||
"email": self.email,
|
||||
"user_type": "Website User"
|
||||
'doctype': 'User',
|
||||
'first_name': self.first_name,
|
||||
'last_name': self.last_name,
|
||||
'email': self.email,
|
||||
'user_type': 'Website User'
|
||||
})
|
||||
user.flags.ignore_permissions = True
|
||||
user.add_roles("Patient")
|
||||
user.add_roles('Patient')
|
||||
|
||||
def autoname(self):
|
||||
patient_master_name = frappe.defaults.get_global_default('patient_master_name')
|
||||
if patient_master_name == 'Patient Name':
|
||||
patient_name_by = frappe.db.get_single_value('Healthcare Settings', 'patient_name_by')
|
||||
if patient_name_by == 'Patient Name':
|
||||
self.name = self.get_patient_name()
|
||||
else:
|
||||
set_name_by_naming_series(self)
|
||||
|
||||
def get_patient_name(self):
|
||||
self.set_full_name()
|
||||
name = self.patient_name
|
||||
if frappe.db.get_value("Patient", name):
|
||||
if frappe.db.get_value('Patient', name):
|
||||
count = frappe.db.sql("""select ifnull(MAX(CAST(SUBSTRING_INDEX(name, ' ', -1) AS UNSIGNED)), 0) from tabPatient
|
||||
where name like %s""", "%{0} - %".format(name), as_list=1)[0][0]
|
||||
count = cint(count) + 1
|
||||
@ -54,56 +65,62 @@ class Patient(Document):
|
||||
return name
|
||||
|
||||
def get_age(self):
|
||||
age_str = ""
|
||||
age_str = ''
|
||||
if self.dob:
|
||||
born = getdate(self.dob)
|
||||
age = dateutil.relativedelta.relativedelta(getdate(), born)
|
||||
age_str = str(age.years) + " year(s) " + str(age.months) + " month(s) " + str(age.days) + " day(s)"
|
||||
dob = getdate(self.dob)
|
||||
age = dateutil.relativedelta.relativedelta(getdate(), dob)
|
||||
age_str = str(age.years) + ' year(s) ' + str(age.months) + ' month(s) ' + str(age.days) + ' day(s)'
|
||||
return age_str
|
||||
|
||||
def invoice_patient_registration(self):
|
||||
frappe.db.set_value("Patient", self.name, "disabled", 0)
|
||||
send_registration_sms(self)
|
||||
if(flt(frappe.get_value("Healthcare Settings", None, "registration_fee"))>0):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'registration_fee'):
|
||||
company = frappe.defaults.get_user_default('company')
|
||||
if not company:
|
||||
company = frappe.db.get_value("Global Defaults", None, "default_company")
|
||||
company = frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||
|
||||
sales_invoice = make_invoice(self.name, company)
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
frappe.db.set_value('Patient', self.name, 'status', 'Active')
|
||||
send_registration_sms(self)
|
||||
|
||||
return {'invoice': sales_invoice.name}
|
||||
|
||||
def create_customer(doc):
|
||||
customer_group = frappe.get_value("Selling Settings", None, "customer_group")
|
||||
territory = frappe.get_value("Selling Settings", None, "territory")
|
||||
customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
|
||||
territory = frappe.db.get_single_value('Selling Settings', 'territory')
|
||||
if not (customer_group and territory):
|
||||
customer_group = "Commercial"
|
||||
territory = "Rest Of The World"
|
||||
frappe.msgprint(_("Please set default customer group and territory in Selling Settings"), alert=True)
|
||||
customer = frappe.get_doc({"doctype": "Customer",
|
||||
"customer_name": doc.patient_name,
|
||||
"customer_group": customer_group,
|
||||
"territory" : territory,
|
||||
"customer_type": "Individual"
|
||||
}).insert(ignore_permissions=True)
|
||||
frappe.db.set_value("Patient", doc.name, "customer", customer.name)
|
||||
frappe.msgprint(_("Customer {0} is created.").format(customer.name), alert=True)
|
||||
customer_group = get_root_of('Customer Group')
|
||||
territory = get_root_of('Territory')
|
||||
frappe.msgprint(_('Please set default customer group and territory in Selling Settings'), alert=True)
|
||||
|
||||
customer = frappe.get_doc({
|
||||
'doctype': 'Customer',
|
||||
'customer_name': doc.patient_name,
|
||||
'customer_group': customer_group,
|
||||
'territory' : territory,
|
||||
'customer_type': 'Individual'
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
frappe.db.set_value('Patient', doc.name, 'customer', customer.name)
|
||||
frappe.msgprint(_('Customer {0} is created.').format(customer.name), alert=True)
|
||||
|
||||
def make_invoice(patient, company):
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.customer = frappe.get_value("Patient", patient, "customer")
|
||||
uom = frappe.db.exists('UOM', 'Nos') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
|
||||
sales_invoice = frappe.new_doc('Sales Invoice')
|
||||
sales_invoice.customer = frappe.db.get_value('Patient', patient, 'customer')
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.company = company
|
||||
sales_invoice.is_pos = '0'
|
||||
sales_invoice.is_pos = 0
|
||||
sales_invoice.debit_to = get_receivable_account(company)
|
||||
|
||||
item_line = sales_invoice.append("items")
|
||||
item_line.item_name = "Registeration Fee"
|
||||
item_line.description = "Registeration Fee"
|
||||
item_line = sales_invoice.append('items')
|
||||
item_line.item_name = 'Registeration Fee'
|
||||
item_line.description = 'Registeration Fee'
|
||||
item_line.qty = 1
|
||||
item_line.uom = "Nos"
|
||||
item_line.uom = uom
|
||||
item_line.conversion_factor = 1
|
||||
item_line.income_account = get_income_account(None, company)
|
||||
item_line.rate = frappe.get_value("Healthcare Settings", None, "registration_fee")
|
||||
item_line.rate = frappe.db.get_single_value('Healthcare Settings', 'registration_fee')
|
||||
item_line.amount = item_line.rate
|
||||
sales_invoice.set_missing_values()
|
||||
return sales_invoice
|
||||
@ -112,7 +129,7 @@ def make_invoice(patient, company):
|
||||
def get_patient_detail(patient):
|
||||
patient_dict = frappe.db.sql("""select * from tabPatient where name=%s""", (patient), as_dict=1)
|
||||
if not patient_dict:
|
||||
frappe.throw(_("Patient not found"))
|
||||
frappe.throw(_('Patient not found'))
|
||||
vital_sign = frappe.db.sql("""select * from `tabVital Signs` where patient=%s
|
||||
order by signs_date desc limit 1""", (patient), as_dict=1)
|
||||
|
||||
|
||||
@ -4,8 +4,31 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Patient')
|
||||
import frappe
|
||||
from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient
|
||||
|
||||
class TestPatient(unittest.TestCase):
|
||||
pass
|
||||
def test_customer_created(self):
|
||||
frappe.db.sql("""delete from `tabPatient`""")
|
||||
frappe.db.set_value('Healthcare Settings', None, 'link_customer_to_patient', 1)
|
||||
patient = create_patient()
|
||||
self.assertTrue(frappe.db.get_value('Patient', patient, 'customer'))
|
||||
|
||||
def test_patient_registration(self):
|
||||
frappe.db.sql("""delete from `tabPatient`""")
|
||||
settings = frappe.get_single('Healthcare Settings')
|
||||
settings.collect_registration_fee = 1
|
||||
settings.registration_fee = 500
|
||||
settings.save()
|
||||
|
||||
patient = create_patient()
|
||||
patient = frappe.get_doc('Patient', patient)
|
||||
self.assertEqual(patient.status, 'Disabled')
|
||||
|
||||
# check sales invoice and patient status
|
||||
result = patient.invoice_patient_registration()
|
||||
self.assertTrue(frappe.db.exists('Sales Invoice', result.get('invoice')))
|
||||
self.assertTrue(patient.status, 'Active')
|
||||
|
||||
settings.collect_registration_fee = 0
|
||||
settings.save()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2016, ESS LLP and contributors
|
||||
// For license information, please see license.txt
|
||||
frappe.provide("erpnext.queries");
|
||||
frappe.provide('erpnext.queries');
|
||||
frappe.ui.form.on('Patient Appointment', {
|
||||
setup: function(frm) {
|
||||
frm.custom_make_buttons = {
|
||||
@ -8,151 +8,188 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
'Patient Encounter': 'Patient Encounter'
|
||||
};
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
if (frm.is_new()) {
|
||||
frm.set_value('appointment_time', null);
|
||||
frm.disable_save();
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.set_query("patient", function () {
|
||||
frm.set_query('patient', function () {
|
||||
return {
|
||||
filters: {"disabled": 0}
|
||||
filters: {'status': 'Active'}
|
||||
};
|
||||
});
|
||||
frm.set_query("practitioner", function() {
|
||||
frm.set_query('practitioner', function() {
|
||||
return {
|
||||
filters: {
|
||||
'department': frm.doc.department
|
||||
}
|
||||
};
|
||||
});
|
||||
frm.set_query("service_unit", function(){
|
||||
frm.set_query('service_unit', function(){
|
||||
return {
|
||||
filters: {
|
||||
"is_group": false,
|
||||
"allow_appointments": true
|
||||
'is_group': 0,
|
||||
'allow_appointments': 1
|
||||
}
|
||||
};
|
||||
});
|
||||
if(frm.doc.patient){
|
||||
|
||||
if (frm.is_new()) {
|
||||
frm.page.set_primary_action(__('Check Availability'), function() {
|
||||
if (!frm.doc.patient) {
|
||||
frappe.msgprint({
|
||||
title: __('Not Allowed'),
|
||||
message: __('Please select Patient first'),
|
||||
indicator: 'red'
|
||||
});
|
||||
} else {
|
||||
frappe.call({
|
||||
method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.check_payment_fields_reqd',
|
||||
args: {'patient': frm.doc.patient},
|
||||
callback: function(data) {
|
||||
if (data.message == true) {
|
||||
if (frm.doc.mode_of_payment && frm.doc.paid_amount) {
|
||||
check_and_set_availability(frm);
|
||||
}
|
||||
if (!frm.doc.mode_of_payment) {
|
||||
frappe.msgprint({
|
||||
title: __('Not Allowed'),
|
||||
message: __('Please select a Mode of Payment first'),
|
||||
indicator: 'red'
|
||||
});
|
||||
}
|
||||
if (!frm.doc.paid_amount) {
|
||||
frappe.msgprint({
|
||||
title: __('Not Allowed'),
|
||||
message: __('Please set the Paid Amount first'),
|
||||
indicator: 'red'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
check_and_set_availability(frm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frm.page.set_primary_action(__('Save'), () => frm.save());
|
||||
}
|
||||
|
||||
if (frm.doc.patient) {
|
||||
frm.add_custom_button(__('Patient History'), function() {
|
||||
frappe.route_options = {"patient": frm.doc.patient};
|
||||
frappe.set_route("patient_history");
|
||||
},__("View"));
|
||||
frappe.route_options = {'patient': frm.doc.patient};
|
||||
frappe.set_route('patient_history');
|
||||
}, __('View'));
|
||||
}
|
||||
if(frm.doc.status == "Open"){
|
||||
|
||||
if (frm.doc.status == 'Open' || (frm.doc.status == 'Scheduled' && !frm.doc.__islocal)) {
|
||||
frm.add_custom_button(__('Cancel'), function() {
|
||||
btn_update_status(frm, "Cancelled");
|
||||
update_status(frm, 'Cancelled');
|
||||
});
|
||||
frm.add_custom_button(__('Reschedule'), function() {
|
||||
check_and_set_availability(frm);
|
||||
});
|
||||
if(frm.doc.procedure_template){
|
||||
frm.add_custom_button(__("Procedure"),function(){
|
||||
btn_create_procedure(frm);
|
||||
},"Create");
|
||||
}
|
||||
else{
|
||||
frm.add_custom_button(__("Patient Encounter"),function(){
|
||||
btn_create_encounter(frm);
|
||||
},"Create");
|
||||
|
||||
if (frm.doc.procedure_template) {
|
||||
frm.add_custom_button(__('Clinical Procedure'), function(){
|
||||
frappe.model.open_mapped_doc({
|
||||
method: 'erpnext.healthcare.doctype.clinical_procedure.clinical_procedure.make_procedure',
|
||||
frm: frm,
|
||||
});
|
||||
}, __('Create'));
|
||||
} else {
|
||||
frm.add_custom_button(__('Patient Encounter'), function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.make_encounter',
|
||||
frm: frm,
|
||||
});
|
||||
}, __('Create'));
|
||||
}
|
||||
|
||||
frm.add_custom_button(__('Vital Signs'), function() {
|
||||
btn_create_vital_signs(frm);
|
||||
},"Create");
|
||||
create_vital_signs(frm);
|
||||
}, __('Create'));
|
||||
}
|
||||
if(frm.doc.status == "Scheduled" && !frm.doc.__islocal){
|
||||
frm.add_custom_button(__('Cancel'), function() {
|
||||
btn_update_status(frm, "Cancelled");
|
||||
});
|
||||
frm.add_custom_button(__('Reschedule'), function() {
|
||||
check_and_set_availability(frm);
|
||||
});
|
||||
if(frm.doc.procedure_template){
|
||||
frm.add_custom_button(__("Procedure"),function(){
|
||||
btn_create_procedure(frm);
|
||||
},"Create");
|
||||
}
|
||||
else{
|
||||
frm.add_custom_button(__("Patient Encounter"),function(){
|
||||
btn_create_encounter(frm);
|
||||
},"Create");
|
||||
}
|
||||
},
|
||||
|
||||
frm.add_custom_button(__('Vital Signs'), function() {
|
||||
btn_create_vital_signs(frm);
|
||||
},"Create");
|
||||
patient: function(frm) {
|
||||
if (frm.doc.patient) {
|
||||
frm.trigger('toggle_payment_fields');
|
||||
}
|
||||
if(frm.doc.status == "Pending"){
|
||||
frm.add_custom_button(__('Set Open'), function() {
|
||||
btn_update_status(frm, "Open");
|
||||
});
|
||||
frm.add_custom_button(__('Cancel'), function() {
|
||||
btn_update_status(frm, "Cancelled");
|
||||
});
|
||||
}
|
||||
frm.set_df_property("get_procedure_from_encounter", "read_only", frm.doc.__islocal ? 0 : 1);
|
||||
frappe.db.get_value('Healthcare Settings', {name: 'Healthcare Settings'}, 'manage_appointment_invoice_automatically', (r) => {
|
||||
if(r.manage_appointment_invoice_automatically == 1){
|
||||
frm.set_df_property("mode_of_payment", "hidden", 0);
|
||||
frm.set_df_property("paid_amount", "hidden", 0);
|
||||
frm.set_df_property("mode_of_payment", "reqd", 1);
|
||||
frm.set_df_property("paid_amount", "reqd", 1);
|
||||
}
|
||||
else{
|
||||
frm.set_df_property("mode_of_payment", "hidden", 1);
|
||||
frm.set_df_property("paid_amount", "hidden", 1);
|
||||
frm.set_df_property("mode_of_payment", "reqd", 0);
|
||||
frm.set_df_property("paid_amount", "reqd", 0);
|
||||
},
|
||||
|
||||
get_procedure_from_encounter: function(frm) {
|
||||
get_prescribed_procedure(frm);
|
||||
},
|
||||
|
||||
toggle_payment_fields: function(frm) {
|
||||
frappe.call({
|
||||
method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.check_payment_fields_reqd',
|
||||
args: {'patient': frm.doc.patient},
|
||||
callback: function(data) {
|
||||
if (data.message.fee_validity) {
|
||||
// if fee validity exists and automated appointment invoicing is enabled,
|
||||
// show payment fields as non-mandatory
|
||||
frm.toggle_display('mode_of_payment', 0);
|
||||
frm.toggle_display('paid_amount', 0);
|
||||
frm.toggle_reqd('mode_of_payment', 0);
|
||||
frm.toggle_reqd('paid_amount', 0);
|
||||
} else {
|
||||
// if automated appointment invoicing is disabled, hide fields
|
||||
frm.toggle_display('mode_of_payment', data.message ? 1 : 0);
|
||||
frm.toggle_display('paid_amount', data.message ? 1 : 0);
|
||||
frm.toggle_reqd('mode_of_payment', data.message ? 1 : 0);
|
||||
frm.toggle_reqd('paid_amount', data.message ? 1 :0);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
check_availability: function(frm) {
|
||||
check_and_set_availability(frm);
|
||||
},
|
||||
onload:function(frm){
|
||||
if(frm.is_new()) {
|
||||
frm.set_value("appointment_time", null);
|
||||
frm.disable_save();
|
||||
}
|
||||
},
|
||||
get_procedure_from_encounter: function(frm) {
|
||||
get_procedure_prescribed(frm);
|
||||
}
|
||||
});
|
||||
|
||||
var check_and_set_availability = function(frm) {
|
||||
var selected_slot = null;
|
||||
var service_unit = null;
|
||||
var duration = null;
|
||||
let check_and_set_availability = function(frm) {
|
||||
let selected_slot = null;
|
||||
let service_unit = null;
|
||||
let duration = null;
|
||||
|
||||
show_availability();
|
||||
|
||||
function show_empty_state(practitioner, appointment_date) {
|
||||
frappe.msgprint({
|
||||
title: __('Not Available'),
|
||||
message: __("Healthcare Practitioner {0} not available on {1}", [practitioner.bold(), appointment_date.bold()]),
|
||||
message: __('Healthcare Practitioner {0} not available on {1}', [practitioner.bold(), appointment_date.bold()]),
|
||||
indicator: 'red'
|
||||
});
|
||||
}
|
||||
|
||||
function show_availability() {
|
||||
let selected_practitioner = '';
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Available slots"),
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __('Available slots'),
|
||||
fields: [
|
||||
{ fieldtype: 'Link', options: 'Medical Department', reqd:1, fieldname: 'department', label: 'Medical Department'},
|
||||
{ fieldtype: 'Link', options: 'Medical Department', reqd: 1, fieldname: 'department', label: 'Medical Department'},
|
||||
{ fieldtype: 'Column Break'},
|
||||
{ fieldtype: 'Link', options: 'Healthcare Practitioner', reqd:1, fieldname: 'practitioner', label: 'Healthcare Practitioner'},
|
||||
{ fieldtype: 'Link', options: 'Healthcare Practitioner', reqd: 1, fieldname: 'practitioner', label: 'Healthcare Practitioner'},
|
||||
{ fieldtype: 'Column Break'},
|
||||
{ fieldtype: 'Date', reqd:1, fieldname: 'appointment_date', label: 'Date'},
|
||||
{ fieldtype: 'Date', reqd: 1, fieldname: 'appointment_date', label: 'Date'},
|
||||
{ fieldtype: 'Section Break'},
|
||||
{ fieldtype: 'HTML', fieldname: 'available_slots'}
|
||||
|
||||
],
|
||||
primary_action_label: __("Book"),
|
||||
primary_action_label: __('Book'),
|
||||
primary_action: function() {
|
||||
frm.set_value('appointment_time', selected_slot);
|
||||
frm.set_value('service_unit', service_unit || '');
|
||||
frm.set_value('duration', duration);
|
||||
frm.set_value('practitioner', d.get_value('practitioner'));
|
||||
frm.set_value('department', d.get_value('department'));
|
||||
frm.set_value('appointment_date', d.get_value('appointment_date'));
|
||||
if (service_unit) {
|
||||
frm.set_value('service_unit', service_unit);
|
||||
}
|
||||
d.hide();
|
||||
frm.enable_save();
|
||||
frm.save();
|
||||
@ -167,16 +204,16 @@ var check_and_set_availability = function(frm) {
|
||||
'appointment_date': frm.doc.appointment_date
|
||||
});
|
||||
|
||||
d.fields_dict["department"].df.onchange = () => {
|
||||
d.fields_dict['department'].df.onchange = () => {
|
||||
d.set_values({
|
||||
'practitioner': ''
|
||||
});
|
||||
var department = d.get_value('department');
|
||||
if(department){
|
||||
let department = d.get_value('department');
|
||||
if (department) {
|
||||
d.fields_dict.practitioner.get_query = function() {
|
||||
return {
|
||||
filters: {
|
||||
"department": department
|
||||
'department': department
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -188,13 +225,13 @@ var check_and_set_availability = function(frm) {
|
||||
|
||||
// Field Change Handler
|
||||
|
||||
var fd = d.fields_dict;
|
||||
let fd = d.fields_dict;
|
||||
|
||||
d.fields_dict["appointment_date"].df.onchange = () => {
|
||||
d.fields_dict['appointment_date'].df.onchange = () => {
|
||||
show_slots(d, fd);
|
||||
};
|
||||
d.fields_dict["practitioner"].df.onchange = () => {
|
||||
if(d.get_value('practitioner') && d.get_value('practitioner') != selected_practitioner){
|
||||
d.fields_dict['practitioner'].df.onchange = () => {
|
||||
if (d.get_value('practitioner') && d.get_value('practitioner') != selected_practitioner) {
|
||||
selected_practitioner = d.get_value('practitioner');
|
||||
show_slots(d, fd);
|
||||
}
|
||||
@ -203,8 +240,8 @@ var check_and_set_availability = function(frm) {
|
||||
}
|
||||
|
||||
function show_slots(d, fd) {
|
||||
if (d.get_value('appointment_date') && d.get_value('practitioner')){
|
||||
fd.available_slots.html("");
|
||||
if (d.get_value('appointment_date') && d.get_value('practitioner')) {
|
||||
fd.available_slots.html('');
|
||||
frappe.call({
|
||||
method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_availability_data',
|
||||
args: {
|
||||
@ -212,13 +249,13 @@ var check_and_set_availability = function(frm) {
|
||||
date: d.get_value('appointment_date')
|
||||
},
|
||||
callback: (r) => {
|
||||
var data = r.message;
|
||||
if(data.slot_details.length > 0) {
|
||||
var $wrapper = d.fields_dict.available_slots.$wrapper;
|
||||
let data = r.message;
|
||||
if (data.slot_details.length > 0) {
|
||||
let $wrapper = d.fields_dict.available_slots.$wrapper;
|
||||
|
||||
// make buttons for each slot
|
||||
var slot_details = data.slot_details;
|
||||
var slot_html = "";
|
||||
let slot_details = data.slot_details;
|
||||
let slot_html = '';
|
||||
for (let i = 0; i < slot_details.length; i++) {
|
||||
slot_html = slot_html + `<label>${slot_details[i].slot_name}</label>`;
|
||||
slot_html = slot_html + `<br/>` + slot_details[i].avail_slot.map(slot => {
|
||||
@ -232,14 +269,14 @@ var check_and_set_availability = function(frm) {
|
||||
let booked_moment = moment(booked.appointment_time, 'HH:mm:ss');
|
||||
let end_time = booked_moment.clone().add(booked.duration, 'minutes');
|
||||
// Deal with 0 duration appointments
|
||||
if(booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)){
|
||||
if (booked_moment.isSame(slot_start_time) || booked_moment.isBetween(slot_start_time, slot_to_time)) {
|
||||
if(booked.duration == 0){
|
||||
disabled = 'disabled="disabled"';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Check for overlaps considering appointment duration
|
||||
if(slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)){
|
||||
if (slot_start_time.isBefore(end_time) && slot_to_time.isAfter(booked_moment)) {
|
||||
// There is an overlap
|
||||
disabled = 'disabled="disabled"';
|
||||
return false;
|
||||
@ -263,7 +300,7 @@ var check_and_set_availability = function(frm) {
|
||||
|
||||
// blue button when clicked
|
||||
$wrapper.on('click', 'button', function() {
|
||||
var $btn = $(this);
|
||||
let $btn = $(this);
|
||||
$wrapper.find('button').removeClass('btn-primary');
|
||||
$btn.addClass('btn-primary');
|
||||
selected_slot = $btn.attr('data-name');
|
||||
@ -273,48 +310,57 @@ var check_and_set_availability = function(frm) {
|
||||
d.get_primary_btn().attr('disabled', null);
|
||||
});
|
||||
|
||||
}else {
|
||||
// fd.available_slots.html("Please select a valid date.".bold())
|
||||
} else {
|
||||
// fd.available_slots.html('Please select a valid date.'.bold())
|
||||
show_empty_state(d.get_value('practitioner'), d.get_value('appointment_date'));
|
||||
}
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __("Fetching records......")
|
||||
freeze_message: __('Fetching records......')
|
||||
});
|
||||
}else{
|
||||
fd.available_slots.html("Appointment date and Healthcare Practitioner are Mandatory".bold());
|
||||
} else {
|
||||
fd.available_slots.html(__('Appointment date and Healthcare Practitioner are Mandatory').bold());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var get_procedure_prescribed = function(frm){
|
||||
if(frm.doc.patient){
|
||||
let get_prescribed_procedure = function(frm) {
|
||||
if (frm.doc.patient) {
|
||||
frappe.call({
|
||||
method:"erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_procedure_prescribed",
|
||||
method: 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_procedure_prescribed',
|
||||
args: {patient: frm.doc.patient},
|
||||
callback: function(r){
|
||||
show_procedure_templates(frm, r.message);
|
||||
callback: function(r) {
|
||||
if (r.message && r.message.length) {
|
||||
show_procedure_templates(frm, r.message);
|
||||
} else {
|
||||
frappe.msgprint({
|
||||
title: __('Not Found'),
|
||||
message: __('No Prescribed Procedures found for the selected Patient')
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
frappe.msgprint(__("Please select Patient to get prescribed procedure"));
|
||||
} else {
|
||||
frappe.msgprint({
|
||||
title: __('Not Allowed'),
|
||||
message: __('Please select a Patient first')
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var show_procedure_templates = function(frm, result){
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Prescribed Procedures"),
|
||||
let show_procedure_templates = function(frm, result){
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __('Prescribed Procedures'),
|
||||
fields: [
|
||||
{
|
||||
fieldtype: "HTML", fieldname: "procedure_template"
|
||||
fieldtype: 'HTML', fieldname: 'procedure_template'
|
||||
}
|
||||
]
|
||||
});
|
||||
var html_field = d.fields_dict.procedure_template.$wrapper;
|
||||
let html_field = d.fields_dict.procedure_template.$wrapper;
|
||||
html_field.empty();
|
||||
$.each(result, function(x, y){
|
||||
var row = $(repl('<div class="col-xs-12" style="padding-top:12px; text-align:center;" >\
|
||||
$.each(result, function(x, y) {
|
||||
let row = $(repl('<div class="col-xs-12" style="padding-top:12px; text-align:center;" >\
|
||||
<div class="col-xs-5"> %(encounter)s <br> %(consulting_practitioner)s <br> %(encounter_date)s </div>\
|
||||
<div class="col-xs-5"> %(procedure_template)s <br>%(practitioner)s <br> %(date)s</div>\
|
||||
<div class="col-xs-2">\
|
||||
@ -326,76 +372,47 @@ var show_procedure_templates = function(frm, result){
|
||||
encounter:y[2], consulting_practitioner:y[3], encounter_date:y[4],
|
||||
practitioner:y[5]? y[5]:'', date: y[6]? y[6]:'', department: y[7]? y[7]:''})).appendTo(html_field);
|
||||
row.find("a").click(function() {
|
||||
frm.doc.procedure_template = $(this).attr("data-procedure-template");
|
||||
frm.doc.procedure_prescription = $(this).attr("data-name");
|
||||
frm.doc.practitioner = $(this).attr("data-practitioner");
|
||||
frm.doc.appointment_date = $(this).attr("data-date");
|
||||
frm.doc.department = $(this).attr("data-department");
|
||||
refresh_field("procedure_template");
|
||||
refresh_field("procedure_prescription");
|
||||
refresh_field("appointment_date");
|
||||
refresh_field("practitioner");
|
||||
refresh_field("department");
|
||||
frm.doc.procedure_template = $(this).attr('data-procedure-template');
|
||||
frm.doc.procedure_prescription = $(this).attr('data-name');
|
||||
frm.doc.practitioner = $(this).attr('data-practitioner');
|
||||
frm.doc.appointment_date = $(this).attr('data-date');
|
||||
frm.doc.department = $(this).attr('data-department');
|
||||
refresh_field('procedure_template');
|
||||
refresh_field('procedure_prescription');
|
||||
refresh_field('appointment_date');
|
||||
refresh_field('practitioner');
|
||||
refresh_field('department');
|
||||
d.hide();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
if(!result){
|
||||
var msg = "There are no procedure prescribed for "+frm.doc.patient;
|
||||
if (!result) {
|
||||
let msg = __('There are no procedure prescribed for ') + frm.doc.patient;
|
||||
$(repl('<div class="col-xs-12" style="padding-top:20px;" >%(msg)s</div></div>', {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);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
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 +421,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)';
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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}.<br> {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 += "<b><a href='#Form/Patient Appointment/{0}'>{0}</a></b><br>".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 += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".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,21 @@ 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})
|
||||
order by ct.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()
|
||||
|
||||
@ -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];
|
||||
}
|
||||
};
|
||||
|
||||
@ -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
|
||||
@ -19,297 +19,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)';
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -6,59 +6,63 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
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 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+"<br/>"
|
||||
if(encounter.symptoms):
|
||||
subject += "Symptoms: "+ cstr(encounter.symptoms)+".<br/>"
|
||||
subject = encounter.practitioner + '\n'
|
||||
if encounter.symptoms:
|
||||
subject += _('Symptoms: ') + cstr(encounter.symptoms) + '\n'
|
||||
else:
|
||||
subject += "No Symptoms <br/>"
|
||||
if(encounter.diagnosis):
|
||||
subject += "Diagnosis: "+ cstr(encounter.diagnosis)+".<br/>"
|
||||
subject += _('No Symptoms') + '\n'
|
||||
|
||||
if encounter.diagnosis:
|
||||
subject += _('Diagnosis: ') + cstr(encounter.diagnosis) + '\n'
|
||||
else:
|
||||
subject += "No Diagnosis <br/>"
|
||||
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
|
||||
|
||||
@ -2,5 +2,5 @@
|
||||
(c) ESS 2015-16
|
||||
*/
|
||||
frappe.listview_settings['Patient Encounter'] = {
|
||||
filters:[["docstatus","!=","1"]]
|
||||
filters:[["docstatus","!=","2"]]
|
||||
};
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@ -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"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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;
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
};
|
||||
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
@ -4,417 +4,471 @@
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
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 += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".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") \
|
||||
+ """<b><a href="#Form/Healthcare Settings">Healthcare Settings</a></b>""")
|
||||
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.lab_test_code, ['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 += '''<b><a href='#Form/Healthcare Settings'>Healthcare Settings</a></b>'''
|
||||
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_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) \
|
||||
+ """<b><a href="#Form/Healthcare Settings">Healthcare Settings</a></b>""")
|
||||
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) \
|
||||
+ '''<b><a href='#Form/Healthcare Settings'>Healthcare Settings</a></b>''')
|
||||
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) \
|
||||
+ ''' <b><a href='#Form/Healthcare Practitioner/{0}'>{0}</a></b>'''.format(practitioner))
|
||||
frappe.throw(msg, title=_('Missing Configuration'))
|
||||
|
||||
msg = _(("Please Configure {0} for Healthcare Practitioner").format(charge_name) \
|
||||
+ """ <b><a href="#Form/Healthcare Practitioner/{0}">{0}</a></b>""".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 +479,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 = "<div class='col-md-12 col-sm-12 text-muted'>"
|
||||
for doc in docs:
|
||||
docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + "<br/>"
|
||||
docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + '<br/>'
|
||||
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 = "<div class='col-md-12 col-sm-12'>"
|
||||
section_html = ""
|
||||
section_label = ""
|
||||
html = ""
|
||||
section_html = ''
|
||||
section_label = ''
|
||||
html = ''
|
||||
sec_on = False
|
||||
col_on = 0
|
||||
has_data = False
|
||||
@ -476,8 +535,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 +552,19 @@ def render_doc_as_html(doctype, docname, exclude_fields = []):
|
||||
d-6 col-sm-6'>" + html + "</div><div class='col-md-6 col-sm-6'>"
|
||||
elif sec_on and not col_on:
|
||||
section_html += "<div class='col-md-6 col-sm-6'>"
|
||||
html = ""
|
||||
html = ''
|
||||
col_on += 1
|
||||
if df.label:
|
||||
html += '<br>' + 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 += '<tr>'
|
||||
@ -521,24 +580,24 @@ def render_doc_as_html(doctype, docname, exclude_fields = []):
|
||||
create_head = False
|
||||
table_row += '</tr>'
|
||||
if sec_on:
|
||||
section_html += '<table class="table table-condensed \
|
||||
bordered">' + table_head + table_row + '</table>'
|
||||
section_html += "<table class='table table-condensed \
|
||||
bordered'>" + table_head + table_row + '</table>'
|
||||
else:
|
||||
html += '<table class="table table-condensed table-bordered">' \
|
||||
+ table_head + table_row + '</table>'
|
||||
html += "<table class='table table-condensed table-bordered'>" \
|
||||
+ table_head + table_row + "</table>"
|
||||
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 += "<br>{0} : {1}".format(df.label or df.fieldname, \
|
||||
html += '<br>{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 + "</div></div>"
|
||||
doc_html += section_html + html + '</div></div>'
|
||||
elif sec_on and not col_on and has_data:
|
||||
doc_html += "<div class='col-md-12 col-sm-12'\
|
||||
><div class='col-md-12 col-sm-12'>" \
|
||||
+ section_html + html +"</div></div>"
|
||||
+ section_html + html +'</div></div>'
|
||||
if doc_html:
|
||||
doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='#Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + "</div>"
|
||||
doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='#Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + '</div>'
|
||||
|
||||
return {'html': doc_html}
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
frappe.ready(function() {
|
||||
// bind events here
|
||||
});
|
||||
@ -0,0 +1,397 @@
|
||||
{
|
||||
"accept_payment": 0,
|
||||
"allow_comments": 0,
|
||||
"allow_delete": 0,
|
||||
"allow_edit": 1,
|
||||
"allow_incomplete": 0,
|
||||
"allow_multiple": 0,
|
||||
"allow_print": 0,
|
||||
"amount": 0.0,
|
||||
"amount_based_on_field": 0,
|
||||
"button_label": "Register",
|
||||
"creation": "2020-03-03 01:01:16.250607",
|
||||
"currency": "INR",
|
||||
"doc_type": "Patient",
|
||||
"docstatus": 0,
|
||||
"doctype": "Web Form",
|
||||
"idx": 0,
|
||||
"introduction_text": "",
|
||||
"is_standard": 1,
|
||||
"login_required": 0,
|
||||
"max_attachment_size": 0,
|
||||
"modified": "2020-03-26 17:25:15.361918",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "patient-registration",
|
||||
"owner": "Administrator",
|
||||
"payment_button_label": "Buy Now",
|
||||
"published": 1,
|
||||
"route": "patient-registration",
|
||||
"route_to_success_link": 0,
|
||||
"show_attachments": 0,
|
||||
"show_in_grid": 0,
|
||||
"show_sidebar": 1,
|
||||
"sidebar_items": [],
|
||||
"success_message": "Registration Successfully. Thank You!",
|
||||
"success_url": "/patient-registration",
|
||||
"title": "Patient Registration",
|
||||
"web_form_fields": [
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "basic_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"label": "Patient Demographics",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "fa fa-user",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "first_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "First Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "middle_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Middle Name (optional)",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "last_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Last Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "sex",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Gender",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Gender",
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "blood_group",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"label": "Blood Group",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "\nA Positive\nA Negative\nAB Positive\nAB Negative\nB Positive\nB Negative\nO Positive\nO Negative",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "dob",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"label": "Date of birth",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "mobile",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Mobile",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "email",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Email",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Email",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "phone",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Phone",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"label": "Personal Details",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "occupation",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Occupation",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "marital_status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"label": "Marital Status",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "\nSingle\nMarried\nDivorced\nWidow",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "allergy_medical_and_surgical_history",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"label": "Allergies, Medical and Surgical History",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "allergies",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Allergies",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "medication",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Medication",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "column_break_20",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "medical_history",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Medical History",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "surgical_history",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Surgical History",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "risk_factors",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"label": "Risk Factors",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"default": "0",
|
||||
"fieldname": "tobacco_past_use",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"label": "Check if you have a history of Tobacco Consumption",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"default": "0",
|
||||
"fieldname": "tobacco_current_use",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"label": "Check if you consume Tobacco",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"default": "0",
|
||||
"fieldname": "alcohol_past_use",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"label": "Check if you have a history of Alcohol Consumption",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"default": "0",
|
||||
"fieldname": "alcohol_current_use",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"label": "Check if you consume Alcohol",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "column_break_32",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "surrounding_factors",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Occupational Hazards and Environmental Factors",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "other_risk_factors",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"label": "Other Risk Factors",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
def get_context(context):
|
||||
# do your magic here
|
||||
pass
|
||||
@ -269,7 +269,8 @@ auto_cancel_exempted_doctypes= [
|
||||
|
||||
scheduler_events = {
|
||||
"all": [
|
||||
"erpnext.projects.doctype.project.project.project_status_update_reminder"
|
||||
"erpnext.projects.doctype.project.project.project_status_update_reminder",
|
||||
"erpnext.healthcare_healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder"
|
||||
],
|
||||
"hourly": [
|
||||
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
|
||||
@ -304,21 +305,22 @@ scheduler_events = {
|
||||
"erpnext.support.doctype.service_level_agreement.service_level_agreement.check_agreement_status",
|
||||
"erpnext.crm.doctype.email_campaign.email_campaign.send_email_to_leads_or_contacts",
|
||||
"erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status",
|
||||
"erpnext.selling.doctype.quotation.quotation.set_expired_status"
|
||||
"erpnext.selling.doctype.quotation.quotation.set_expired_status",
|
||||
"erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_appointment_status"
|
||||
],
|
||||
"daily_long": [
|
||||
"erpnext.setup.doctype.email_digest.email_digest.send",
|
||||
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
|
||||
"erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
|
||||
"erpnext.hr.utils.generate_leave_encashment",
|
||||
"erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.check_for_ltv_shortfall",
|
||||
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.make_accrual_interest_entry_for_term_loans"
|
||||
"erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.create_process_loan_security_shortfall",
|
||||
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans"
|
||||
],
|
||||
"monthly_long": [
|
||||
"erpnext.accounts.deferred_revenue.convert_deferred_revenue_to_income",
|
||||
"erpnext.accounts.deferred_revenue.convert_deferred_expense_to_expense",
|
||||
"erpnext.hr.utils.allocate_earned_leaves",
|
||||
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual"
|
||||
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_demand_loans"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -55,8 +55,8 @@ frappe.ui.form.on('Employee',{
|
||||
};
|
||||
});
|
||||
},
|
||||
prefered_contact_email:function(frm){
|
||||
frm.events.update_contact(frm)
|
||||
prefered_contact_email:function(frm){
|
||||
frm.events.update_contact(frm)
|
||||
},
|
||||
personal_email:function(frm){
|
||||
frm.events.update_contact(frm)
|
||||
|
||||
@ -580,19 +580,22 @@ def get_leaves_for_period(employee, leave_type, from_date, to_date):
|
||||
return leave_days
|
||||
|
||||
def skip_expiry_leaves(leave_entry, date):
|
||||
''' Checks whether the expired leaves coincide with the to_date of leave balance check '''
|
||||
''' Checks whether the expired leaves coincide with the to_date of leave balance check.
|
||||
This allows backdated leave entry creation for non carry forwarded allocation '''
|
||||
end_date = frappe.db.get_value("Leave Allocation", {'name': leave_entry.transaction_name}, ['to_date'])
|
||||
return True if end_date == date and not leave_entry.is_carry_forward else False
|
||||
|
||||
def get_leave_entries(employee, leave_type, from_date, to_date):
|
||||
''' Returns leave entries between from_date and to_date '''
|
||||
''' Returns leave entries between from_date and to_date. '''
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
employee, leave_type, from_date, to_date, leaves, transaction_name, transaction_type,
|
||||
is_carry_forward, is_expired
|
||||
FROM `tabLeave Ledger Entry`
|
||||
WHERE employee=%(employee)s AND leave_type=%(leave_type)s
|
||||
AND docstatus=1 AND leaves<0
|
||||
AND docstatus=1
|
||||
AND (leaves<0
|
||||
OR is_expired=1)
|
||||
AND (from_date between %(from_date)s AND %(to_date)s
|
||||
OR to_date between %(from_date)s AND %(to_date)s
|
||||
OR (from_date < %(from_date)s AND to_date > %(to_date)s))
|
||||
|
||||
@ -8,7 +8,6 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import getdate, nowdate, flt
|
||||
from erpnext.hr.utils import set_employee_name
|
||||
from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on
|
||||
from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure
|
||||
from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry
|
||||
from erpnext.hr.doctype.leave_allocation.leave_allocation import get_unused_leaves
|
||||
|
||||
@ -141,6 +141,7 @@ def expire_allocation(allocation, expiry_date=None):
|
||||
leaves = get_remaining_leaves(allocation)
|
||||
expiry_date = expiry_date if expiry_date else allocation.to_date
|
||||
|
||||
# allows expired leaves entry to be created/reverted
|
||||
if leaves:
|
||||
args = dict(
|
||||
leaves=flt(leaves) * -1,
|
||||
@ -160,6 +161,8 @@ def expire_carried_forward_allocation(allocation):
|
||||
from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period
|
||||
leaves_taken = get_leaves_for_period(allocation.employee, allocation.leave_type, allocation.from_date, allocation.to_date)
|
||||
leaves = flt(allocation.leaves) + flt(leaves_taken)
|
||||
|
||||
# allow expired leaves entry to be created
|
||||
if leaves > 0:
|
||||
args = frappe._dict(
|
||||
transaction_name=allocation.name,
|
||||
|
||||
@ -13,7 +13,7 @@ from erpnext.hr.doctype.salary_slip.test_salary_slip import get_salary_component
|
||||
make_earning_salary_component, make_deduction_salary_component
|
||||
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure
|
||||
from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry
|
||||
from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import make_accrual_interest_entry_for_term_loans
|
||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
|
||||
|
||||
class TestPayrollEntry(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@ -81,7 +81,7 @@ class TestPayrollEntry(unittest.TestCase):
|
||||
|
||||
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1))
|
||||
|
||||
make_accrual_interest_entry_for_term_loans(posting_date=nowdate())
|
||||
process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
|
||||
|
||||
|
||||
dates = get_start_end_dates('Monthly', nowdate())
|
||||
|
||||
@ -372,8 +372,7 @@
|
||||
"fieldtype": "Table",
|
||||
"label": "Employee Loan",
|
||||
"options": "Salary Slip Loan",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_43",
|
||||
@ -464,7 +463,7 @@
|
||||
"idx": 9,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-31 17:13:45.146271",
|
||||
"modified": "2020-04-09 20:02:53.159827",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Slip",
|
||||
|
||||
@ -755,30 +755,43 @@ class SalarySlip(TransactionBase):
|
||||
d.amount = self.get_amount_based_on_payment_days(d, joining_date, relieving_date)[0]
|
||||
|
||||
def set_loan_repayment(self):
|
||||
self.set('loans', [])
|
||||
self.total_loan_repayment = 0
|
||||
self.total_interest_amount = 0
|
||||
self.total_principal_amount = 0
|
||||
|
||||
for loan in self.get_loan_details():
|
||||
if not self.get('loans'):
|
||||
for loan in self.get_loan_details():
|
||||
|
||||
amounts = calculate_amounts(loan.name, self.posting_date, "Regular Payment")
|
||||
amounts = calculate_amounts(loan.name, self.posting_date, "Regular Payment")
|
||||
|
||||
total_payment = amounts['interest_amount'] + amounts['payable_principal_amount']
|
||||
if amounts['interest_amount'] or amounts['payable_principal_amount']:
|
||||
self.append('loans', {
|
||||
'loan': loan.name,
|
||||
'total_payment': amounts['interest_amount'] + amounts['payable_principal_amount'],
|
||||
'interest_amount': amounts['interest_amount'],
|
||||
'principal_amount': amounts['payable_principal_amount'],
|
||||
'loan_account': loan.loan_account,
|
||||
'interest_income_account': loan.interest_income_account
|
||||
})
|
||||
|
||||
if total_payment:
|
||||
self.append('loans', {
|
||||
'loan': loan.name,
|
||||
'total_payment': total_payment,
|
||||
'interest_amount': amounts['interest_amount'],
|
||||
'principal_amount': amounts['payable_principal_amount'],
|
||||
'loan_account': loan.loan_account,
|
||||
'interest_income_account': loan.interest_income_account
|
||||
})
|
||||
for payment in self.get('loans'):
|
||||
amounts = calculate_amounts(payment.loan, self.posting_date, "Regular Payment")
|
||||
|
||||
self.total_loan_repayment += total_payment
|
||||
self.total_interest_amount += amounts['interest_amount']
|
||||
self.total_principal_amount += amounts['payable_principal_amount']
|
||||
if payment.interest_amount > amounts['interest_amount']:
|
||||
frappe.throw(_("""Row {0}: Paid Interest amount {1} is greater than pending interest amount {2}
|
||||
against loan {3}""").format(payment.idx, frappe.bold(payment.interest_amount),
|
||||
frappe.bold(amounts['interest_amount']), frappe.bold(payment.loan)))
|
||||
|
||||
if payment.principal_amount > amounts['payable_principal_amount']:
|
||||
frappe.throw(_("""Row {0}: Paid Principal amount {1} is greater than pending principal amount {2}
|
||||
against loan {3}""").format(payment.idx, frappe.bold(payment.principal_amount),
|
||||
frappe.bold(amounts['payable_principal_amount']), frappe.bold(payment.loan)))
|
||||
|
||||
payment.total_payment = payment.interest_amount + payment.principal_amount
|
||||
self.total_interest_amount += payment.interest_amount
|
||||
self.total_principal_amount += payment.principal_amount
|
||||
|
||||
self.total_loan_repayment = self.total_interest_amount + self.total_principal_amount
|
||||
|
||||
def get_loan_details(self):
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
def test_loan_repayment_salary_slip(self):
|
||||
from erpnext.loan_management.doctype.loan.test_loan import create_loan_type, create_loan, make_loan_disbursement_entry, create_loan_accounts
|
||||
from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import make_accrual_interest_entry_for_term_loans
|
||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
|
||||
|
||||
applicant = make_employee("test_loanemployee@salary.com", company="_Test Company")
|
||||
|
||||
@ -166,7 +166,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1))
|
||||
|
||||
make_accrual_interest_entry_for_term_loans(posting_date=nowdate())
|
||||
process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
|
||||
|
||||
ss = make_employee_salary_slip("test_loanemployee@salary.com", "Monthly")
|
||||
ss.submit()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user