diff --git a/erpnext/config/healthcare.py b/erpnext/config/healthcare.py
index 2b461273ad..da24d11538 100644
--- a/erpnext/config/healthcare.py
+++ b/erpnext/config/healthcare.py
@@ -214,5 +214,41 @@ def get_data():
"label": _("Lab Test Report")
}
]
+ },
+ {
+ "label": _("Rehabilitation"),
+ "icon": "icon-cog",
+ "items": [
+ {
+ "type": "doctype",
+ "name": "Exercise Type",
+ "label": _("Exercise Type")
+ },
+ {
+ "type": "doctype",
+ "name": "Exercise Difficulty Level",
+ "label": _("Exercise Difficulty Level")
+ },
+ {
+ "type": "doctype",
+ "name": "Therapy Type",
+ "label": _("Therapy Type")
+ },
+ {
+ "type": "doctype",
+ "name": "Therapy Plan",
+ "label": _("Therapy Plan")
+ },
+ {
+ "type": "doctype",
+ "name": "Therapy Session",
+ "label": _("Therapy Session")
+ },
+ {
+ "type": "doctype",
+ "name": "Motor Assessment Scale",
+ "label": _("Motor Assessment Scale")
+ }
+ ]
}
]
diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py
index d02308d8f2..8839e002a4 100644
--- a/erpnext/controllers/tests/test_mapper.py
+++ b/erpnext/controllers/tests/test_mapper.py
@@ -13,7 +13,7 @@ class TestMapper(unittest.TestCase):
'''Test mapping of multiple source docs on a single target doc'''
make_test_records("Item")
- items = frappe.get_all("Item", fields = ["name", "item_code"], filters = {'is_sales_item': 1, 'has_variants': 0})
+ items = frappe.get_all("Item", fields = ["name", "item_code"], filters = {'is_sales_item': 1, 'has_variants': 0, 'disabled': 0})
customers = frappe.get_all("Customer")
if items and customers:
# Make source docs (quotations) and a target doc (sales order)
diff --git a/erpnext/healthcare/desk_page/healthcare/healthcare.json b/erpnext/healthcare/desk_page/healthcare/healthcare.json
index 54798ba08f..24c6d6fc37 100644
--- a/erpnext/healthcare/desk_page/healthcare/healthcare.json
+++ b/erpnext/healthcare/desk_page/healthcare/healthcare.json
@@ -1,48 +1,53 @@
{
"cards": [
{
- "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": "Masters",
+ "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]"
},
{
- "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": "Consultation Setup",
+ "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]"
},
{
- "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\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]"
},
{
- "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"
+ "hidden": 0,
+ "label": "Settings",
+ "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]"
},
{
- "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"
+ "hidden": 0,
+ "label": "Laboratory Setup",
+ "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]"
},
{
- "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"
+ "hidden": 0,
+ "label": "Laboratory",
+ "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]"
},
{
- "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"
+ "hidden": 0,
+ "label": "Rehabilitation and Physiotherapy",
+ "links": "[\n {\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Exercise Type\",\n\t\t\"label\": \"Exercise Type\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Therapy Type\",\n\t\t\"label\": \"Therapy Type\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Therapy Plan\",\n\t\t\"label\": \"Therapy Plan\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Therapy Session\",\n\t\t\"label\": \"Therapy Session\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Assessment Template\",\n\t\t\"label\": \"Patient Assessment Template\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Assessment\",\n\t\t\"label\": \"Patient Assessment\"\n\t}\n]"
},
{
- "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"
+ "hidden": 0,
+ "label": "Records and History",
+ "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]"
+ },
+ {
+ "hidden": 0,
+ "label": "Reports",
+ "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]"
}
],
"category": "Domains",
- "charts": [
- {
- "chart_name": "Patient Appointments",
- "label": "Patient Appointments"
- }
- ],
+ "charts": [],
"charts_label": "",
"creation": "2020-03-02 17:23:17.919682",
"developer_mode_only": 0,
@@ -53,7 +58,7 @@
"idx": 0,
"is_standard": 1,
"label": "Healthcare",
- "modified": "2020-03-26 16:10:44.629795",
+ "modified": "2020-04-20 11:42:43.889576",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare",
@@ -64,32 +69,32 @@
"shortcuts": [
{
"format": "{} Open",
- "is_query_report": 0,
+ "label": "Patient Appointment",
"link_to": "Patient Appointment",
"stats_filter": "{\n \"status\": \"Open\"\n}",
"type": "DocType"
},
{
"format": "{} Active",
- "is_query_report": 0,
+ "label": "Patient",
"link_to": "Patient",
"stats_filter": "{\n \"status\": \"Active\"\n}",
"type": "DocType"
},
{
"format": "{} Vacant",
- "is_query_report": 0,
+ "label": "Healthcare Service Unit",
"link_to": "Healthcare Service Unit",
"stats_filter": "{\n \"occupancy_status\": \"Vacant\",\n \"is_group\": 0\n}",
"type": "DocType"
},
{
- "is_query_report": 0,
+ "label": "Healthcare Practitioner",
"link_to": "Healthcare Practitioner",
"type": "DocType"
},
{
- "is_query_report": 0,
+ "label": "Patient History",
"link_to": "patient_history",
"type": "Page"
}
diff --git a/erpnext/healthcare/doctype/body_part/__init__.py b/erpnext/healthcare/doctype/body_part/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/body_part/body_part.js b/erpnext/healthcare/doctype/body_part/body_part.js
new file mode 100644
index 0000000000..d2f9d09937
--- /dev/null
+++ b/erpnext/healthcare/doctype/body_part/body_part.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Body Part', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/healthcare/doctype/body_part/body_part.json b/erpnext/healthcare/doctype/body_part/body_part.json
new file mode 100644
index 0000000000..6e3d1d4ce3
--- /dev/null
+++ b/erpnext/healthcare/doctype/body_part/body_part.json
@@ -0,0 +1,45 @@
+{
+ "actions": [],
+ "autoname": "field:body_part",
+ "creation": "2020-04-10 12:21:55.036402",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "body_part"
+ ],
+ "fields": [
+ {
+ "fieldname": "body_part",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Body Part",
+ "reqd": 1,
+ "unique": 1
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-10 12:26:44.087985",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Body Part",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/body_part/body_part.py b/erpnext/healthcare/doctype/body_part/body_part.py
new file mode 100644
index 0000000000..300493a52b
--- /dev/null
+++ b/erpnext/healthcare/doctype/body_part/body_part.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class BodyPart(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/body_part/test_body_part.py b/erpnext/healthcare/doctype/body_part/test_body_part.py
new file mode 100644
index 0000000000..cb3a61150e
--- /dev/null
+++ b/erpnext/healthcare/doctype/body_part/test_body_part.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestBodyPart(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/body_part_link/__init__.py b/erpnext/healthcare/doctype/body_part_link/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/body_part_link/body_part_link.json b/erpnext/healthcare/doctype/body_part_link/body_part_link.json
new file mode 100644
index 0000000000..400b7c6fe8
--- /dev/null
+++ b/erpnext/healthcare/doctype/body_part_link/body_part_link.json
@@ -0,0 +1,32 @@
+{
+ "actions": [],
+ "creation": "2020-04-10 12:23:15.259816",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "body_part"
+ ],
+ "fields": [
+ {
+ "fieldname": "body_part",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Body Part",
+ "options": "Body Part",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-10 12:25:23.101749",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Body Part Link",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/body_part_link/body_part_link.py b/erpnext/healthcare/doctype/body_part_link/body_part_link.py
new file mode 100644
index 0000000000..0371529769
--- /dev/null
+++ b/erpnext/healthcare/doctype/body_part_link/body_part_link.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class BodyPartLink(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/exercise/__init__.py b/erpnext/healthcare/doctype/exercise/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/exercise/exercise.json b/erpnext/healthcare/doctype/exercise/exercise.json
new file mode 100644
index 0000000000..2486a5d53a
--- /dev/null
+++ b/erpnext/healthcare/doctype/exercise/exercise.json
@@ -0,0 +1,61 @@
+{
+ "actions": [],
+ "creation": "2020-03-11 09:25:00.968572",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "exercise_type",
+ "difficulty_level",
+ "counts_target",
+ "counts_completed",
+ "assistance_level"
+ ],
+ "fields": [
+ {
+ "fieldname": "exercise_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Exercise Type",
+ "options": "Exercise Type",
+ "reqd": 1
+ },
+ {
+ "fetch_from": "exercise_type.difficulty_level",
+ "fieldname": "difficulty_level",
+ "fieldtype": "Link",
+ "label": "Difficulty Level",
+ "options": "Exercise Difficulty Level"
+ },
+ {
+ "fieldname": "counts_target",
+ "fieldtype": "Int",
+ "in_list_view": 1,
+ "label": "Counts Target"
+ },
+ {
+ "depends_on": "eval:doc.parenttype==\"Therapy\";",
+ "fieldname": "counts_completed",
+ "fieldtype": "Int",
+ "label": "Counts Completed"
+ },
+ {
+ "fieldname": "assistance_level",
+ "fieldtype": "Select",
+ "label": "Assistance Level",
+ "options": "\nPassive\nActive Assist\nActive"
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-10 13:41:06.662351",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Exercise",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/exercise/exercise.py b/erpnext/healthcare/doctype/exercise/exercise.py
new file mode 100644
index 0000000000..efd89997fe
--- /dev/null
+++ b/erpnext/healthcare/doctype/exercise/exercise.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class Exercise(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/exercise_difficulty_level/__init__.py b/erpnext/healthcare/doctype/exercise_difficulty_level/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.js b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.js
new file mode 100644
index 0000000000..ff51c34f3f
--- /dev/null
+++ b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Exercise Difficulty Level', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.json b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.json
new file mode 100644
index 0000000000..a6aed75e7a
--- /dev/null
+++ b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.json
@@ -0,0 +1,45 @@
+{
+ "actions": [],
+ "autoname": "field:difficulty_level",
+ "creation": "2020-03-29 21:12:55.835941",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "difficulty_level"
+ ],
+ "fields": [
+ {
+ "fieldname": "difficulty_level",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Difficulty Level",
+ "reqd": 1,
+ "unique": 1
+ }
+ ],
+ "links": [],
+ "modified": "2020-03-31 23:14:33.554066",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Exercise Difficulty Level",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.py b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.py
new file mode 100644
index 0000000000..17e97b8960
--- /dev/null
+++ b/erpnext/healthcare/doctype/exercise_difficulty_level/exercise_difficulty_level.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ExerciseDifficultyLevel(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/exercise_difficulty_level/test_exercise_difficulty_level.py b/erpnext/healthcare/doctype/exercise_difficulty_level/test_exercise_difficulty_level.py
new file mode 100644
index 0000000000..80ef3a7de8
--- /dev/null
+++ b/erpnext/healthcare/doctype/exercise_difficulty_level/test_exercise_difficulty_level.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestExerciseDifficultyLevel(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/exercise_type/__init__.py b/erpnext/healthcare/doctype/exercise_type/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/exercise_type/exercise_type.js b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
new file mode 100644
index 0000000000..f450c9bccb
--- /dev/null
+++ b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
@@ -0,0 +1,180 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Exercise Type', {
+ refresh: function(frm) {
+ let wrapper = frm.fields_dict.steps_html.wrapper;
+
+ frm.ExerciseEditor = new erpnext.ExerciseEditor(frm, wrapper);
+ }
+});
+
+erpnext.ExerciseEditor = Class.extend({
+ init: function(frm, wrapper) {
+ this.wrapper = wrapper;
+ this.frm = frm;
+ this.make(frm, wrapper);
+ },
+
+ make: function(frm, wrapper) {
+ $(this.wrapper).empty();
+
+ this.exercise_toolbar = $('
', {therapy:y[0],
+ name: y[1], encounter:y[2], practitioner:y[3], date:y[4],
+ department:y[6]? y[6]:'', therapy_plan:y[5]})).appendTo(html_field);
+
+ row.find("a").click(function() {
+ frm.doc.therapy_type = $(this).attr("data-therapy");
+ frm.doc.practitioner = $(this).attr("data-practitioner");
+ frm.doc.department = $(this).attr("data-department");
+ frm.doc.therapy_plan = $(this).attr("data-therapy-plan");
+ frm.refresh_field("therapy_type");
+ frm.refresh_field("practitioner");
+ frm.refresh_field("department");
+ frm.refresh_field("therapy-plan");
+ frappe.db.get_value('Therapy Type', frm.doc.therapy_type, 'default_duration', (r) => {
+ if (r.default_duration) {
+ frm.set_value('duration', r.default_duration)
+ }
+ });
+ d.hide();
+ return false;
+ });
+ });
+ d.show();
+};
+
let create_vital_signs = function(frm) {
if (!frm.doc.patient) {
frappe.throw(__('Please select patient'));
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
index 7f9a671d47..57e6c479d1 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
@@ -20,6 +20,9 @@
"procedure_template",
"get_procedure_from_encounter",
"procedure_prescription",
+ "therapy_type",
+ "get_prescribed_therapies",
+ "therapy_plan",
"service_unit",
"section_break_12",
"practitioner",
@@ -269,6 +272,28 @@
"print_hide": 1,
"report_hide": 1
},
+ {
+ "depends_on": "eval:doc.patient;",
+ "fieldname": "therapy_type",
+ "fieldtype": "Link",
+ "label": "Therapy",
+ "options": "Therapy Type",
+ "set_only_once": 1
+ },
+ {
+ "depends_on": "eval:doc.patient && doc.__islocal;",
+ "fieldname": "get_prescribed_therapies",
+ "fieldtype": "Button",
+ "label": "Get Prescribed Therapies"
+ },
+ {
+ "depends_on": "eval: doc.patient && doc.therapy_type",
+ "fieldname": "therapy_plan",
+ "fieldtype": "Link",
+ "label": "Therapy Plan",
+ "mandatory_depends_on": "eval: doc.patient && doc.therapy_type",
+ "options": "Therapy Plan"
+ },
{
"fieldname": "ref_sales_invoice",
"fieldtype": "Link",
@@ -285,7 +310,7 @@
}
],
"links": [],
- "modified": "2020-03-27 11:27:33.773195",
+ "modified": "2020-03-31 16:16:32.116865",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Patient Appointment",
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index a2d9d0240f..512d44ec37 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -412,11 +412,36 @@ def get_events(start, end, filters=None):
@frappe.whitelist()
def get_procedure_prescribed(patient):
- return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
- ct.encounter_date, pp.practitioner, pp.date, pp.department
- from `tabPatient Encounter` ct, `tabProcedure Prescription` pp
- where ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
- order by ct.creation desc""", {'patient': patient})
+ return frappe.db.sql(
+ """
+ SELECT
+ pp.name, pp.procedure, pp.parent, ct.practitioner,
+ ct.encounter_date, pp.practitioner, pp.date, pp.department
+ FROM
+ `tabPatient Encounter` ct, `tabProcedure Prescription` pp
+ WHERE
+ ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
+ ORDER BY
+ ct.creation desc
+ """, {'patient': patient}
+ )
+
+
+@frappe.whitelist()
+def get_prescribed_therapies(patient):
+ return frappe.db.sql(
+ """
+ SELECT
+ t.therapy_type, t.name, t.parent, e.practitioner,
+ e.encounter_date, e.therapy_plan, e.visit_department
+ FROM
+ `tabPatient Encounter` e, `tabTherapy Plan Detail` t
+ WHERE
+ e.patient=%(patient)s and t.parent=e.name
+ ORDER BY
+ e.creation desc
+ """, {'patient': patient}
+ )
def update_appointment_status():
diff --git a/erpnext/healthcare/doctype/patient_assessment/__init__.py b/erpnext/healthcare/doctype/patient_assessment/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.js b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.js
new file mode 100644
index 0000000000..c7074e88d5
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.js
@@ -0,0 +1,86 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Patient Assessment', {
+ refresh: function(frm) {
+ if (frm.doc.assessment_template) {
+ frm.trigger('set_score_range');
+ }
+
+ if (!frm.doc.__islocal) {
+ frm.trigger('show_patient_progress');
+ }
+ },
+
+ assessment_template: function(frm) {
+ if (frm.doc.assessment_template) {
+ frappe.call({
+ 'method': 'frappe.client.get',
+ args: {
+ doctype: 'Patient Assessment Template',
+ name: frm.doc.assessment_template
+ },
+ callback: function(data) {
+ frm.doc.assessment_sheet = [];
+ $.each(data.message.parameters, function(_i, e) {
+ let entry = frm.add_child('assessment_sheet');
+ entry.parameter = e.assessment_parameter;
+ });
+
+ frm.set_value('scale_min', data.message.scale_min);
+ frm.set_value('scale_max', data.message.scale_max);
+ frm.set_value('assessment_description', data.message.assessment_description);
+ frm.set_value('total_score', data.message.scale_max * data.message.parameters.length);
+ frm.trigger('set_score_range');
+ refresh_field('assessment_sheet');
+ }
+ });
+ }
+ },
+
+ set_score_range: function(frm) {
+ let options = [];
+ for(let i = frm.doc.scale_min; i <= frm.doc.scale_max; i++) {
+ options.push(i);
+ }
+ frappe.meta.get_docfield('Patient Assessment Sheet', 'score', frm.doc.name).options = [''].concat(options);
+ },
+
+ calculate_total_score: function(frm, cdt, cdn) {
+ let row = locals[cdt][cdn];
+ let total_score = 0;
+ $.each(frm.doc.assessment_sheet || [], function(_i, item) {
+ if (item.score) {
+ total_score += parseInt(item.score);
+ }
+ });
+
+ frm.set_value('total_score_obtained', total_score);
+ },
+
+ show_patient_progress: function(frm) {
+ let bars = [];
+ let message = '';
+ let added_min = false;
+
+ let title = __('{0} out of {1}', [frm.doc.total_score_obtained, frm.doc.total_score]);
+
+ bars.push({
+ 'title': title,
+ 'width': (frm.doc.total_score_obtained / frm.doc.total_score * 100) + '%',
+ 'progress_class': 'progress-bar-success'
+ });
+ if (bars[0].width == '0%') {
+ bars[0].width = '0.5%';
+ added_min = 0.5;
+ }
+ message = title;
+ frm.dashboard.add_progress(__('Status'), bars, message);
+ },
+});
+
+frappe.ui.form.on('Patient Assessment Sheet', {
+ score: function(frm, cdt, cdn) {
+ frm.events.calculate_total_score(frm, cdt, cdn);
+ }
+});
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json
new file mode 100644
index 0000000000..3952a8153f
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json
@@ -0,0 +1,172 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2020-04-19 22:45:12.356209",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "therapy_session",
+ "patient",
+ "assessment_template",
+ "column_break_4",
+ "healthcare_practitioner",
+ "assessment_datetime",
+ "assessment_description",
+ "section_break_7",
+ "assessment_sheet",
+ "section_break_9",
+ "total_score_obtained",
+ "column_break_11",
+ "total_score",
+ "scale_min",
+ "scale_max",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fetch_from": "therapy_session.patient",
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
+ {
+ "fieldname": "assessment_template",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Assessment Template",
+ "options": "Patient Assessment Template",
+ "reqd": 1
+ },
+ {
+ "fieldname": "therapy_session",
+ "fieldtype": "Link",
+ "label": "Therapy Session",
+ "options": "Therapy Session"
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "therapy_session.practitioner",
+ "fieldname": "healthcare_practitioner",
+ "fieldtype": "Link",
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner"
+ },
+ {
+ "fieldname": "assessment_datetime",
+ "fieldtype": "Datetime",
+ "label": "Assessment Datetime"
+ },
+ {
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "assessment_sheet",
+ "fieldtype": "Table",
+ "label": "Assessment Sheet",
+ "options": "Patient Assessment Sheet"
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "total_score",
+ "fieldtype": "Int",
+ "label": "Total Score",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_score_obtained",
+ "fieldtype": "Int",
+ "label": "Total Score Obtained",
+ "read_only": 1
+ },
+ {
+ "fieldname": "scale_min",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "Scale Min",
+ "read_only": 1
+ },
+ {
+ "fieldname": "scale_max",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "Scale Max",
+ "read_only": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Naming Series",
+ "options": "HLC-PA-.YYYY.-"
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Patient Assessment",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "assessment_description",
+ "fieldtype": "Small Text",
+ "label": "Assessment Description"
+ }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-04-21 13:23:09.815007",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py
new file mode 100644
index 0000000000..3033a3e6ac
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe.model.mapper import get_mapped_doc
+
+class PatientAssessment(Document):
+ def validate(self):
+ self.set_total_score()
+
+ def set_total_score(self):
+ total_score = 0
+ for entry in self.assessment_sheet:
+ total_score += int(entry.score)
+ self.total_score_obtained = total_score
+
+@frappe.whitelist()
+def create_patient_assessment(source_name, target_doc=None):
+ doc = get_mapped_doc('Therapy Session', source_name, {
+ 'Therapy Session': {
+ 'doctype': 'Patient Assessment',
+ 'field_map': [
+ ['therapy_session', 'name'],
+ ['patient', 'patient'],
+ ['practitioner', 'practitioner']
+ ]
+ }
+ }, target_doc)
+
+ return doc
+
+
+
diff --git a/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py b/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py
new file mode 100644
index 0000000000..3fda8550f6
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment/test_patient_assessment.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestPatientAssessment(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_detail/__init__.py b/erpnext/healthcare/doctype/patient_assessment_detail/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.json b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.json
new file mode 100644
index 0000000000..179f441044
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.json
@@ -0,0 +1,32 @@
+{
+ "actions": [],
+ "creation": "2020-04-19 19:33:00.115395",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "assessment_parameter"
+ ],
+ "fields": [
+ {
+ "fieldname": "assessment_parameter",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Assessment Parameter",
+ "options": "Patient Assessment Parameter",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-19 19:33:00.115395",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py
new file mode 100644
index 0000000000..0519599ac0
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_detail/patient_assessment_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentDetail(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/__init__.py b/erpnext/healthcare/doctype/patient_assessment_parameter/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.js b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.js
new file mode 100644
index 0000000000..2c5d270d57
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Patient Assessment Parameter', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.json b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.json
new file mode 100644
index 0000000000..098bdefea7
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.json
@@ -0,0 +1,45 @@
+{
+ "actions": [],
+ "autoname": "field:assessment_parameter",
+ "creation": "2020-04-15 14:34:46.551042",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "assessment_parameter"
+ ],
+ "fields": [
+ {
+ "fieldname": "assessment_parameter",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Assessment Parameter",
+ "reqd": 1,
+ "unique": 1
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-20 09:22:19.135196",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Parameter",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py
new file mode 100644
index 0000000000..b8e0074717
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/patient_assessment_parameter.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentParameter(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py b/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py
new file mode 100644
index 0000000000..e722f9905e
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_parameter/test_patient_assessment_parameter.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestPatientAssessmentParameter(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_sheet/__init__.py b/erpnext/healthcare/doctype/patient_assessment_sheet/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.json b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.json
new file mode 100644
index 0000000000..64e4aef7cf
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.json
@@ -0,0 +1,57 @@
+{
+ "actions": [],
+ "creation": "2020-04-19 23:07:02.220244",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "parameter",
+ "score",
+ "time",
+ "column_break_4",
+ "comments"
+ ],
+ "fields": [
+ {
+ "fieldname": "parameter",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Parameter",
+ "options": "Patient Assessment Parameter",
+ "reqd": 1
+ },
+ {
+ "fieldname": "score",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Score",
+ "reqd": 1
+ },
+ {
+ "fieldname": "time",
+ "fieldtype": "Time",
+ "label": "Time"
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "comments",
+ "fieldtype": "Small Text",
+ "label": "Comments"
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-20 09:56:28.746619",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Sheet",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py
new file mode 100644
index 0000000000..40da763013
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_sheet/patient_assessment_sheet.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentSheet(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/__init__.py b/erpnext/healthcare/doctype/patient_assessment_template/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.js b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.js
new file mode 100644
index 0000000000..40419362a4
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Patient Assessment Template', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.json b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.json
new file mode 100644
index 0000000000..de006b1805
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.json
@@ -0,0 +1,109 @@
+{
+ "actions": [],
+ "autoname": "field:assessment_name",
+ "creation": "2020-04-19 19:33:13.204707",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "assessment_name",
+ "section_break_2",
+ "parameters",
+ "assessment_scale_details_section",
+ "scale_min",
+ "scale_max",
+ "column_break_8",
+ "assessment_description"
+ ],
+ "fields": [
+ {
+ "fieldname": "parameters",
+ "fieldtype": "Table",
+ "label": "Parameters",
+ "options": "Patient Assessment Detail"
+ },
+ {
+ "fieldname": "assessment_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Assessment Name",
+ "reqd": 1,
+ "unique": 1
+ },
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break",
+ "label": "Assessment Parameters"
+ },
+ {
+ "fieldname": "assessment_scale_details_section",
+ "fieldtype": "Section Break",
+ "label": "Assessment Scale"
+ },
+ {
+ "fieldname": "scale_min",
+ "fieldtype": "Int",
+ "label": "Scale Minimum"
+ },
+ {
+ "fieldname": "scale_max",
+ "fieldtype": "Int",
+ "label": "Scale Maximum"
+ },
+ {
+ "fieldname": "column_break_8",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "assessment_description",
+ "fieldtype": "Small Text",
+ "label": "Assessment Description"
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-21 13:14:19.075167",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Assessment Template",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py
new file mode 100644
index 0000000000..083cab5d01
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/patient_assessment_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PatientAssessmentTemplate(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py b/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py
new file mode 100644
index 0000000000..86dbd5438c
--- /dev/null
+++ b/erpnext/healthcare/doctype/patient_assessment_template/test_patient_assessment_template.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestPatientAssessmentTemplate(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
index 83c5d2be9c..78e789d359 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
@@ -3,6 +3,10 @@
frappe.ui.form.on('Patient Encounter', {
setup: function(frm) {
+ frm.get_field('therapies').grid.editable_fields = [
+ {fieldname: 'therapy_type', columns: 8},
+ {fieldname: 'no_of_sessions', columns: 2}
+ ];
frm.get_field('drug_prescription').grid.editable_fields = [
{fieldname: 'drug_code', columns: 2},
{fieldname: 'drug_name', columns: 2},
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
index d00e7bc7dd..5f11039e19 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
@@ -42,6 +42,10 @@
"lab_test_prescription",
"sb_procedures",
"procedure_prescription",
+ "rehabilitation_section",
+ "therapy_plan",
+ "therapies",
+ "section_break_33",
"encounter_comment",
"amended_from"
],
@@ -256,6 +260,29 @@
"print_hide": 1,
"read_only": 1
},
+ {
+ "fieldname": "rehabilitation_section",
+ "fieldtype": "Section Break",
+ "label": "Rehabilitation"
+ },
+ {
+ "fieldname": "therapies",
+ "fieldtype": "Table",
+ "label": "Therapies",
+ "options": "Therapy Plan Detail"
+ },
+ {
+ "fieldname": "section_break_33",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "therapy_plan",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Therapy Plan",
+ "options": "Therapy Plan",
+ "read_only": 1
+ },
{
"fieldname": "appointment_type",
"fieldtype": "Link",
@@ -291,7 +318,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-02-27 12:42:21.751964",
+ "modified": "2020-04-14 16:18:08.180457",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Patient Encounter",
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
index ade4748ece..767643bc73 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
+from frappe import _
from frappe.model.document import Document
from frappe.utils import cstr
from frappe import _
@@ -22,6 +23,24 @@ class PatientEncounter(Document):
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
delete_medical_record(self)
+ def on_submit(self):
+ create_therapy_plan(self)
+
+def create_therapy_plan(encounter):
+ if len(encounter.therapies):
+ doc = frappe.new_doc('Therapy Plan')
+ doc.patient = encounter.patient
+ doc.start_date = encounter.encounter_date
+ for entry in encounter.therapies:
+ doc.append('therapy_plan_details', {
+ 'therapy_type': entry.therapy_type,
+ 'no_of_sessions': entry.no_of_sessions
+ })
+ doc.save(ignore_permissions=True)
+ if doc.get('name'):
+ encounter.db_set('therapy_plan', doc.name)
+ frappe.msgprint(_('Therapy Plan {0} created successfully.').format(frappe.bold(doc.name)), alert=True)
+
def insert_encounter_to_medical_record(doc):
subject = set_subject_field(doc)
medical_record = frappe.new_doc('Patient Medical Record')
diff --git a/erpnext/healthcare/doctype/therapy_plan/__init__.py b/erpnext/healthcare/doctype/therapy_plan/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
new file mode 100644
index 0000000000..526bb95b70
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.utils import getdate
+from erpnext.healthcare.doctype.therapy_type.test_therapy_type import create_therapy_type
+from erpnext.healthcare.doctype.therapy_plan.therapy_plan import make_therapy_session
+from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_patient
+
+class TestTherapyPlan(unittest.TestCase):
+ def test_creation_on_encounter_submission(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ encounter = create_encounter(patient, medical_department, practitioner)
+ self.assertTrue(frappe.db.exists('Therapy Plan', encounter.therapy_plan))
+
+ def test_status(self):
+ plan = create_therapy_plan()
+ self.assertEquals(plan.status, 'Not Started')
+
+ session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab')
+ frappe.get_doc(session).submit()
+ self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'In Progress')
+
+ session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab')
+ frappe.get_doc(session).submit()
+ self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
+
+
+def create_therapy_plan():
+ patient = create_patient()
+ therapy_type = create_therapy_type()
+ plan = frappe.new_doc('Therapy Plan')
+ plan.patient = patient
+ plan.start_date = getdate()
+ plan.append('therapy_plan_details', {
+ 'therapy_type': therapy_type.name,
+ 'no_of_sessions': 2
+ })
+ plan.save()
+ return plan
+
+def create_encounter(patient, medical_department, practitioner):
+ encounter = frappe.new_doc('Patient Encounter')
+ encounter.patient = patient
+ encounter.practitioner = practitioner
+ encounter.medical_department = medical_department
+ therapy_type = create_therapy_type()
+ encounter.append('therapies', {
+ 'therapy_type': therapy_type.name,
+ 'no_of_sessions': 2
+ })
+ encounter.save()
+ encounter.submit()
+ return encounter
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.js b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.js
new file mode 100644
index 0000000000..dea0cfeb84
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.js
@@ -0,0 +1,90 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Therapy Plan', {
+ setup: function(frm) {
+ frm.get_field('therapy_plan_details').grid.editable_fields = [
+ {fieldname: 'therapy_type', columns: 6},
+ {fieldname: 'no_of_sessions', columns: 2},
+ {fieldname: 'sessions_completed', columns: 2}
+ ];
+ },
+
+ refresh: function(frm) {
+ if (!frm.doc.__islocal) {
+ frm.trigger('show_progress_for_therapies');
+ }
+
+ if (!frm.doc.__islocal && frm.doc.status != 'Completed') {
+ let therapy_types = (frm.doc.therapy_plan_details || []).map(function(d){ return d.therapy_type });
+ const fields = [{
+ fieldtype: 'Link',
+ label: __('Therapy Type'),
+ fieldname: 'therapy_type',
+ options: 'Therapy Type',
+ reqd: 1,
+ get_query: function() {
+ return {
+ filters: { 'therapy_type': ['in', therapy_types]}
+ }
+ }
+ }];
+
+ frm.add_custom_button(__('Therapy Session'), function() {
+ frappe.prompt(fields, data => {
+ frappe.call({
+ method: 'erpnext.healthcare.doctype.therapy_plan.therapy_plan.make_therapy_session',
+ args: {
+ therapy_plan: frm.doc.name,
+ patient: frm.doc.patient,
+ therapy_type: data.therapy_type
+ },
+ freeze: true,
+ callback: function(r) {
+ if (r.message) {
+ frappe.model.sync(r.message);
+ frappe.set_route('Form', r.message.doctype, r.message.name);
+ }
+ }
+ });
+ }, __('Select Therapy Type'), __('Create'));
+ }, __('Create'));
+ }
+ },
+
+ show_progress_for_therapies: function(frm) {
+ let bars = [];
+ let message = '';
+ let added_min = false;
+
+ // completed sessions
+ let title = __('{0} sessions completed', [frm.doc.total_sessions_completed]);
+ if (frm.doc.total_sessions_completed === 1) {
+ title = __('{0} session completed', [frm.doc.total_sessions_completed]);
+ }
+ title += __(' out of {0}', [frm.doc.total_sessions]);
+
+ bars.push({
+ 'title': title,
+ 'width': (frm.doc.total_sessions_completed / frm.doc.total_sessions * 100) + '%',
+ 'progress_class': 'progress-bar-success'
+ });
+ if (bars[0].width == '0%') {
+ bars[0].width = '0.5%';
+ added_min = 0.5;
+ }
+ message = title;
+ frm.dashboard.add_progress(__('Status'), bars, message);
+ },
+});
+
+frappe.ui.form.on('Therapy Plan Detail', {
+ no_of_sessions: function(frm) {
+ let total = 0;
+ $.each(frm.doc.therapy_plan_details, function(_i, e) {
+ total += e.no_of_sessions;
+ });
+ frm.set_value('total_sessions', total);
+ refresh_field('total_sessions');
+ }
+});
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json
new file mode 100644
index 0000000000..ca78b6618e
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json
@@ -0,0 +1,151 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2020-03-29 20:56:49.758602",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "patient",
+ "patient_name",
+ "column_break_4",
+ "status",
+ "start_date",
+ "section_break_3",
+ "therapy_plan_details",
+ "title",
+ "section_break_9",
+ "total_sessions",
+ "column_break_11",
+ "total_sessions_completed"
+ ],
+ "fields": [
+ {
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
+ {
+ "fieldname": "start_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Start Date",
+ "reqd": 1
+ },
+ {
+ "fieldname": "section_break_3",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "therapy_plan_details",
+ "fieldtype": "Table",
+ "label": "Therapy Plan Details",
+ "options": "Therapy Plan Detail",
+ "reqd": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Naming Series",
+ "options": "HLC-THP-.YYYY.-"
+ },
+ {
+ "fetch_from": "patient.patient_name",
+ "fieldname": "patient_name",
+ "fieldtype": "Data",
+ "label": "Patient Name",
+ "read_only": 1
+ },
+ {
+ "default": "{patient_name}",
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Title",
+ "no_copy": 1
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "total_sessions",
+ "fieldtype": "Int",
+ "label": "Total Sessions",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_sessions_completed",
+ "fieldtype": "Int",
+ "label": "Total Sessions Completed",
+ "read_only": 1
+ },
+ {
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "options": "Not Started\nIn Progress\nCompleted\nCancelled",
+ "read_only": 1
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-21 13:13:43.956014",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Plan",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "search_fields": "patient",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
new file mode 100644
index 0000000000..201264f829
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class TherapyPlan(Document):
+ def validate(self):
+ self.set_totals()
+ self.set_status()
+
+ def set_status(self):
+ if not self.total_sessions_completed:
+ self.status = 'Not Started'
+ else:
+ if self.total_sessions_completed < self.total_sessions:
+ self.status = 'In Progress'
+ elif self.total_sessions_completed == self.total_sessions:
+ self.status = 'Completed'
+
+ def set_totals(self):
+ total_sessions = sum([int(d.no_of_sessions) for d in self.get('therapy_plan_details')])
+ total_sessions_completed = sum([int(d.sessions_completed) for d in self.get('therapy_plan_details')])
+ self.db_set('total_sessions', total_sessions)
+ self.db_set('total_sessions_completed', total_sessions_completed)
+
+
+@frappe.whitelist()
+def make_therapy_session(therapy_plan, patient, therapy_type):
+ therapy_type = frappe.get_doc('Therapy Type', therapy_type)
+
+ therapy_session = frappe.new_doc('Therapy Session')
+ therapy_session.therapy_plan = therapy_plan
+ therapy_session.patient = patient
+ therapy_session.therapy_type = therapy_type.name
+ therapy_session.duration = therapy_type.default_duration
+ therapy_session.rate = therapy_type.rate
+ therapy_session.exercises = therapy_type.exercises
+
+ return therapy_session.as_dict()
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py
new file mode 100644
index 0000000000..df647829db
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'therapy_plan',
+ 'transactions': [
+ {
+ 'label': _('Therapy Sessions'),
+ 'items': ['Therapy Session']
+ }
+ ]
+ }
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan_list.js b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_list.js
new file mode 100644
index 0000000000..63967aff33
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan_list.js
@@ -0,0 +1,11 @@
+frappe.listview_settings['Therapy Plan'] = {
+ get_indicator: function(doc) {
+ var colors = {
+ 'Completed': 'green',
+ 'In Progress': 'orange',
+ 'Not Started': 'red',
+ 'Cancelled': 'grey'
+ };
+ return [__(doc.status), colors[doc.status], 'status,=,' + doc.status];
+ }
+};
diff --git a/erpnext/healthcare/doctype/therapy_plan_detail/__init__.py b/erpnext/healthcare/doctype/therapy_plan_detail/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.json b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.json
new file mode 100644
index 0000000000..9eb20e2ef3
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.json
@@ -0,0 +1,48 @@
+{
+ "actions": [],
+ "creation": "2020-03-29 20:52:57.068731",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "therapy_type",
+ "no_of_sessions",
+ "sessions_completed"
+ ],
+ "fields": [
+ {
+ "fieldname": "therapy_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Therapy Type",
+ "options": "Therapy Type",
+ "reqd": 1
+ },
+ {
+ "fieldname": "no_of_sessions",
+ "fieldtype": "Int",
+ "in_list_view": 1,
+ "label": "No of Sessions"
+ },
+ {
+ "default": "0",
+ "depends_on": "eval:doc.parenttype=='Therapy Plan';",
+ "fieldname": "sessions_completed",
+ "fieldtype": "Int",
+ "label": "Sessions Completed",
+ "read_only": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-30 22:02:01.740109",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Plan Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py
new file mode 100644
index 0000000000..44211f32e3
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_plan_detail/therapy_plan_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class TherapyPlanDetail(Document):
+ pass
diff --git a/erpnext/healthcare/doctype/therapy_session/__init__.py b/erpnext/healthcare/doctype/therapy_session/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py b/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py
new file mode 100644
index 0000000000..75bb8df196
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/test_therapy_session.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestTherapySession(unittest.TestCase):
+ pass
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.js b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
new file mode 100644
index 0000000000..bb675752bb
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
@@ -0,0 +1,60 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Therapy Session', {
+ setup: function(frm) {
+ frm.get_field('exercises').grid.editable_fields = [
+ {fieldname: 'exercise_type', columns: 7},
+ {fieldname: 'counts_target', columns: 1},
+ {fieldname: 'counts_completed', columns: 1},
+ {fieldname: 'assistance_level', columns: 1}
+ ];
+ },
+
+ refresh: function(frm) {
+ if (!frm.doc.__islocal) {
+ let target = 0;
+ let completed = 0;
+ $.each(frm.doc.exercises, function(_i, e) {
+ target += e.counts_target;
+ completed += e.counts_completed;
+ });
+ frm.dashboard.add_indicator(__('Counts Targetted: {0}', [target]), 'blue');
+ frm.dashboard.add_indicator(__('Counts Completed: {0}', [completed]), (completed < target) ? 'orange' : 'green');
+ }
+
+ if (frm.doc.docstatus === 1) {
+ frm.add_custom_button(__('Patient Assessment'),function() {
+ frappe.model.open_mapped_doc({
+ method: 'erpnext.healthcare.doctype.patient_assessment.patient_assessment.create_patient_assessment',
+ frm: frm,
+ })
+ }, 'Create');
+ }
+ },
+
+ therapy_type: function(frm) {
+ if (frm.doc.therapy_type) {
+ frappe.call({
+ 'method': 'frappe.client.get',
+ args: {
+ doctype: 'Therapy Type',
+ name: frm.doc.therapy_type
+ },
+ callback: function(data) {
+ frm.set_value('duration', data.message.default_duration);
+ frm.set_value('rate', data.message.rate);
+ frm.doc.exercises = [];
+ $.each(data.message.exercises, function(_i, e) {
+ let exercise = frm.add_child('exercises');
+ exercise.exercise_type = e.exercise_type;
+ exercise.difficulty_level = e.difficulty_level;
+ exercise.counts_target = e.counts_target;
+ exercise.assistance_level = e.assistance_level;
+ });
+ refresh_field('exercises');
+ }
+ });
+ }
+ }
+});
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.json b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
new file mode 100644
index 0000000000..5ff719672f
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
@@ -0,0 +1,218 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2020-03-11 08:57:40.669857",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "appointment",
+ "patient",
+ "patient_age",
+ "gender",
+ "column_break_5",
+ "therapy_plan",
+ "therapy_type",
+ "practitioner",
+ "department",
+ "details_section",
+ "duration",
+ "rate",
+ "location",
+ "company",
+ "column_break_12",
+ "service_unit",
+ "start_date",
+ "start_time",
+ "invoiced",
+ "exercises_section",
+ "exercises",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "HLC-THP-.YYYY.-"
+ },
+ {
+ "fieldname": "appointment",
+ "fieldtype": "Link",
+ "label": "Appointment",
+ "options": "Patient Appointment"
+ },
+ {
+ "fieldname": "patient",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Patient",
+ "options": "Patient",
+ "reqd": 1
+ },
+ {
+ "fetch_from": "patient.sex",
+ "fieldname": "gender",
+ "fieldtype": "Link",
+ "label": "Gender",
+ "options": "Gender",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "practitioner",
+ "fieldtype": "Link",
+ "label": "Healthcare Practitioner",
+ "options": "Healthcare Practitioner"
+ },
+ {
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Medical Department",
+ "options": "Medical Department"
+ },
+ {
+ "fieldname": "details_section",
+ "fieldtype": "Section Break",
+ "label": "Details"
+ },
+ {
+ "fetch_from": "therapy_template.default_duration",
+ "fieldname": "duration",
+ "fieldtype": "Int",
+ "label": "Duration"
+ },
+ {
+ "fieldname": "location",
+ "fieldtype": "Select",
+ "label": "Location",
+ "options": "\nCenter\nHome\nTele"
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "therapy_template.rate",
+ "fieldname": "rate",
+ "fieldtype": "Currency",
+ "label": "Rate"
+ },
+ {
+ "fieldname": "exercises_section",
+ "fieldtype": "Section Break",
+ "label": "Exercises"
+ },
+ {
+ "fieldname": "exercises",
+ "fieldtype": "Table",
+ "label": "Exercises",
+ "options": "Exercise"
+ },
+ {
+ "depends_on": "eval: doc.therapy_plan",
+ "fieldname": "therapy_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Therapy Type",
+ "options": "Therapy Type",
+ "reqd": 1
+ },
+ {
+ "fieldname": "therapy_plan",
+ "fieldtype": "Link",
+ "label": "Therapy Plan",
+ "options": "Therapy Plan",
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Therapy Session",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "service_unit",
+ "fieldtype": "Link",
+ "label": "Healthcare Service Unit",
+ "options": "Healthcare Service Unit"
+ },
+ {
+ "fieldname": "start_date",
+ "fieldtype": "Date",
+ "label": "Start Date"
+ },
+ {
+ "fieldname": "start_time",
+ "fieldtype": "Time",
+ "label": "Start Time"
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company"
+ },
+ {
+ "default": "0",
+ "fieldname": "invoiced",
+ "fieldtype": "Check",
+ "label": "Invoiced",
+ "read_only": 1
+ },
+ {
+ "fieldname": "patient_age",
+ "fieldtype": "Data",
+ "label": "Patient Age",
+ "read_only": 1
+ }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-04-21 13:16:46.378798",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Session",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "search_fields": "patient,appointment,therapy_plan,therapy_type",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "patient",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.py b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
new file mode 100644
index 0000000000..45d2ee60e6
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe.model.mapper import get_mapped_doc
+
+class TherapySession(Document):
+ def on_submit(self):
+ self.update_sessions_count_in_therapy_plan()
+
+ def on_cancel(self):
+ self.update_sessions_count_in_therapy_plan(on_cancel=True)
+
+ def update_sessions_count_in_therapy_plan(self, on_cancel=False):
+ therapy_plan = frappe.get_doc('Therapy Plan', self.therapy_plan)
+ for entry in therapy_plan.therapy_plan_details:
+ if entry.therapy_type == self.therapy_type:
+ if on_cancel:
+ entry.sessions_completed -= 1
+ else:
+ entry.sessions_completed += 1
+ therapy_plan.save()
+
+
+@frappe.whitelist()
+def create_therapy_session(source_name, target_doc=None):
+ def set_missing_values(source, target):
+ therapy_type = frappe.get_doc('Therapy Type', source.therapy_type)
+ target.exercises = therapy_type.exercises
+
+ doc = get_mapped_doc('Patient Appointment', source_name, {
+ 'Patient Appointment': {
+ 'doctype': 'Therapy Session',
+ 'field_map': [
+ ['appointment', 'name'],
+ ['patient', 'patient'],
+ ['patient_age', 'patient_age'],
+ ['gender', 'patient_sex'],
+ ['therapy_type', 'therapy_type'],
+ ['therapy_plan', 'therapy_plan'],
+ ['practitioner', 'practitioner'],
+ ['department', 'department'],
+ ['start_date', 'appointment_date'],
+ ['start_time', 'appointment_time'],
+ ['service_unit', 'service_unit'],
+ ['company', 'company'],
+ ['invoiced', 'invoiced']
+ ]
+ }
+ }, target_doc, set_missing_values)
+
+ return doc
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py b/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py
new file mode 100644
index 0000000000..9de7e29323
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'therapy_session',
+ 'transactions': [
+ {
+ 'label': _('Assessments'),
+ 'items': ['Patient Assessment']
+ }
+ ]
+ }
diff --git a/erpnext/healthcare/doctype/therapy_type/__init__.py b/erpnext/healthcare/doctype/therapy_type/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py
new file mode 100644
index 0000000000..03a1be8a4e
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestTherapyType(unittest.TestCase):
+ def test_therapy_type_item(self):
+ therapy_type = create_therapy_type()
+ self.assertTrue(frappe.db.exists('Item', therapy_type.item))
+
+ therapy_type.disabled = 1
+ therapy_type.save()
+ self.assertEquals(frappe.db.get_value('Item', therapy_type.item, 'disabled'), 1)
+
+def create_therapy_type():
+ exercise = create_exercise_type()
+ therapy_type = frappe.db.exists('Therapy Type', 'Basic Rehab')
+ if not therapy_type:
+ therapy_type = frappe.new_doc('Therapy Type')
+ therapy_type.therapy_type = 'Basic Rehab'
+ therapy_type.default_duration = 30
+ therapy_type.is_billable = 1
+ therapy_type.rate = 5000
+ therapy_type.item_code = 'Basic Rehab'
+ therapy_type.item_name = 'Basic Rehab'
+ therapy_type.item_group = 'Services'
+ therapy_type.append('exercises', {
+ 'exercise_type': exercise.name,
+ 'counts_target': 10,
+ 'assistance_level': 'Passive'
+ })
+ therapy_type.save()
+ else:
+ therapy_type = frappe.get_doc('Therapy Type', 'Basic Rehab')
+ return therapy_type
+
+def create_exercise_type():
+ exercise_type = frappe.db.exists('Exercise Type', 'Sit to Stand')
+ if not exercise_type:
+ exercise_type = frappe.new_doc('Exercise Type')
+ exercise_type.exercise_name = 'Sit to Stand'
+ exercise_type.append('steps_table', {
+ 'title': 'Step 1',
+ 'description': 'Squat and Rise'
+ })
+ exercise_type.save()
+ return exercise_type
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.js b/erpnext/healthcare/doctype/therapy_type/therapy_type.js
new file mode 100644
index 0000000000..7a61b0def0
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.js
@@ -0,0 +1,93 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Therapy Type', {
+ setup: function(frm) {
+ frm.get_field('exercises').grid.editable_fields = [
+ {fieldname: 'exercise_type', columns: 7},
+ {fieldname: 'difficulty_level', columns: 1},
+ {fieldname: 'counts_target', columns: 1},
+ {fieldname: 'assistance_level', columns: 1}
+ ];
+ },
+
+ refresh: function(frm) {
+ if (!frm.doc.__islocal) {
+ cur_frm.add_custom_button(__('Change Item Code'), function() {
+ change_template_code(frm.doc);
+ });
+ }
+ },
+
+ therapy_type: function(frm) {
+ if (!frm.doc.item_code)
+ frm.set_value('item_code', frm.doc.therapy_type);
+ if (!frm.doc.description)
+ frm.set_value('description', frm.doc.therapy_type);
+ mark_change_in_item(frm);
+ },
+
+ rate: function(frm) {
+ mark_change_in_item(frm);
+ },
+
+ is_billable: function (frm) {
+ mark_change_in_item(frm);
+ },
+
+ item_group: function(frm) {
+ mark_change_in_item(frm);
+ },
+
+ description: function(frm) {
+ mark_change_in_item(frm);
+ },
+
+ medical_department: function(frm) {
+ mark_change_in_item(frm);
+ }
+});
+
+let mark_change_in_item = function(frm) {
+ if (!frm.doc.__islocal) {
+ frm.doc.change_in_item = 1;
+ }
+};
+
+let change_template_code = function(doc) {
+ let d = new frappe.ui.Dialog({
+ title:__('Change Item Code'),
+ fields:[
+ {
+ 'fieldtype': 'Data',
+ 'label': 'Item Code',
+ 'fieldname': 'item_code',
+ reqd: 1
+ }
+ ],
+ primary_action: function() {
+ let values = d.get_values();
+
+ if (values) {
+ frappe.call({
+ 'method': 'erpnext.healthcare.doctype.therapy_type.therapy_type.change_item_code_from_therapy',
+ 'args': {item_code: values.item_code, doc: doc},
+ callback: function () {
+ cur_frm.reload_doc();
+ frappe.show_alert({
+ message: 'Item Code renamed successfully',
+ indicator: 'green'
+ });
+ }
+ });
+ }
+ d.hide();
+ },
+ primary_action_label: __('Change Item Code')
+ });
+ d.show();
+
+ d.set_values({
+ 'item_code': doc.item_code
+ });
+};
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.json b/erpnext/healthcare/doctype/therapy_type/therapy_type.json
new file mode 100644
index 0000000000..0b3c3caeaa
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.json
@@ -0,0 +1,211 @@
+{
+ "actions": [],
+ "autoname": "field:therapy_type",
+ "creation": "2020-03-29 20:48:31.715063",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "disabled",
+ "section_break_2",
+ "therapy_type",
+ "default_duration",
+ "medical_department",
+ "column_break_3",
+ "is_billable",
+ "rate",
+ "healthcare_service_unit",
+ "item_details_section",
+ "item",
+ "item_code",
+ "item_name",
+ "item_group",
+ "column_break_12",
+ "description",
+ "section_break_18",
+ "therapy_for",
+ "add_exercises",
+ "section_break_6",
+ "exercises",
+ "change_in_item"
+ ],
+ "fields": [
+ {
+ "fieldname": "therapy_type",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Therapy Type",
+ "reqd": 1,
+ "unique": 1
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_billable",
+ "fieldtype": "Check",
+ "label": "Is Billable"
+ },
+ {
+ "depends_on": "eval:doc.is_billable;",
+ "fieldname": "rate",
+ "fieldtype": "Currency",
+ "label": "Rate",
+ "mandatory_depends_on": "eval:doc.is_billable;"
+ },
+ {
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break",
+ "label": "Exercises"
+ },
+ {
+ "fieldname": "exercises",
+ "fieldtype": "Table",
+ "label": "Exercises",
+ "options": "Exercise"
+ },
+ {
+ "fieldname": "default_duration",
+ "fieldtype": "Int",
+ "label": "Default Duration (In Minutes)"
+ },
+ {
+ "default": "0",
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "label": "Disabled"
+ },
+ {
+ "fieldname": "item_details_section",
+ "fieldtype": "Section Break",
+ "label": "Item Details"
+ },
+ {
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "label": "Item",
+ "options": "Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "item_code",
+ "fieldtype": "Data",
+ "label": "Item Code",
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "label": "Item Group",
+ "options": "Item Group",
+ "reqd": 1
+ },
+ {
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description"
+ },
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "medical_department",
+ "fieldtype": "Link",
+ "label": "Medical Department",
+ "options": "Medical Department"
+ },
+ {
+ "default": "0",
+ "fieldname": "change_in_item",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Change In Item",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
+ {
+ "fieldname": "therapy_for",
+ "fieldtype": "Table MultiSelect",
+ "label": "Therapy For",
+ "options": "Body Part Link"
+ },
+ {
+ "fieldname": "healthcare_service_unit",
+ "fieldtype": "Link",
+ "label": "Healthcare Service Unit",
+ "options": "Healthcare Service Unit"
+ },
+ {
+ "depends_on": "eval: doc.therapy_for",
+ "fieldname": "add_exercises",
+ "fieldtype": "Button",
+ "label": "Add Exercises",
+ "options": "add_exercises"
+ },
+ {
+ "fieldname": "section_break_18",
+ "fieldtype": "Section Break"
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-21 13:09:04.006289",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Therapy Type",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Healthcare Administrator",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Physician",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.py b/erpnext/healthcare/doctype/therapy_type/therapy_type.py
new file mode 100644
index 0000000000..ea3d84e7c5
--- /dev/null
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.py
@@ -0,0 +1,122 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import json
+from frappe import _
+from frappe.utils import cint
+from frappe.model.document import Document
+from frappe.model.rename_doc import rename_doc
+
+class TherapyType(Document):
+ def validate(self):
+ self.enable_disable_item()
+
+ def after_insert(self):
+ create_item_from_therapy(self)
+
+ def on_update(self):
+ if self.change_in_item:
+ self.update_item_and_item_price()
+
+ def enable_disable_item(self):
+ if self.is_billable:
+ if self.disabled:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
+ else:
+ frappe.db.set_value('Item', self.item, 'disabled', 0)
+
+ def update_item_and_item_price(self):
+ if self.is_billable and self.item:
+ item_doc = frappe.get_doc('Item', {'item_code': self.item})
+ item_doc.item_name = self.item_name
+ item_doc.item_group = self.item_group
+ item_doc.description = self.description
+ item_doc.disabled = 0
+ item_doc.ignore_mandatory = True
+ item_doc.save(ignore_permissions=True)
+
+ if self.rate:
+ item_price = frappe.get_doc('Item Price', {'item_code': self.item})
+ item_price.item_name = self.item_name
+ item_price.price_list_name = self.rate
+ item_price.ignore_mandatory = True
+ item_price.save()
+
+ elif not self.is_billable and self.item:
+ frappe.db.set_value('Item', self.item, 'disabled', 1)
+
+ self.db_set('change_in_item', 0)
+
+ def add_exercises(self):
+ exercises = self.get_exercises_for_body_parts()
+ last_idx = max([cint(d.idx) for d in self.get('exercises')] or [0,])
+ for i, d in enumerate(exercises):
+ ch = self.append('exercises', {})
+ ch.exercise_type = d.parent
+ ch.idx = last_idx + i + 1
+
+ def get_exercises_for_body_parts(self):
+ body_parts = [entry.body_part for entry in self.therapy_for]
+
+ exercises = frappe.db.sql(
+ """
+ SELECT DISTINCT
+ b.parent, e.name, e.difficulty_level
+ FROM
+ `tabExercise Type` e, `tabBody Part Link` b
+ WHERE
+ b.body_part IN %(body_parts)s AND b.parent=e.name
+ """, {'body_parts': body_parts}, as_dict=1)
+
+ return exercises
+
+
+def create_item_from_therapy(doc):
+ disabled = doc.disabled
+ if doc.is_billable and not doc.disabled:
+ disabled = 0
+
+ uom = frappe.db.exists('UOM', 'Unit') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
+
+ item = frappe.get_doc({
+ 'doctype': 'Item',
+ 'item_code': doc.item_code,
+ 'item_name': doc.item_name,
+ 'item_group': doc.item_group,
+ 'description': doc.description,
+ 'is_sales_item': 1,
+ 'is_service_item': 1,
+ 'is_purchase_item': 0,
+ 'is_stock_item': 0,
+ 'show_in_website': 0,
+ 'is_pro_applicable': 0,
+ 'disabled': disabled,
+ 'stock_uom': uom
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
+
+ make_item_price(item.name, doc.rate)
+ doc.db_set('item', item.name)
+
+
+def make_item_price(item, item_price):
+ price_list_name = frappe.db.get_value('Price List', {'selling': 1})
+ frappe.get_doc({
+ 'doctype': 'Item Price',
+ 'price_list': price_list_name,
+ 'item_code': item,
+ 'price_list_rate': item_price
+ }).insert(ignore_permissions=True, ignore_mandatory=True)
+
+@frappe.whitelist()
+def change_item_code_from_therapy(item_code, doc):
+ doc = frappe._dict(json.loads(doc))
+
+ if frappe.db.exists('Item', {'item_code': item_code}):
+ frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
+ else:
+ rename_doc('Item', doc.item, item_code, ignore_permissions=True)
+ frappe.db.set_value('Therapy Type', doc.name, 'item_code', item_code)
+ return
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index 246242ad84..9a32c737cf 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -30,8 +30,9 @@ def get_healthcare_services_to_invoice(patient):
lab_tests = get_lab_tests_to_invoice(patient)
clinical_procedures = get_clinical_procedures_to_invoice(patient)
inpatient_services = get_inpatient_services_to_invoice(patient)
+ therapy_sessions = get_therapy_sessions_to_invoice(patient)
- items_to_invoice += encounters + lab_tests + clinical_procedures + inpatient_services
+ items_to_invoice += encounters + lab_tests + clinical_procedures + inpatient_services + therapy_sessions
return items_to_invoice
def validate_customer_created(patient):
@@ -243,6 +244,25 @@ def get_inpatient_services_to_invoice(patient):
return services_to_invoice
+def get_therapy_sessions_to_invoice(patient):
+ therapy_sessions_to_invoice = []
+ therapy_sessions = frappe.get_list(
+ 'Therapy Session',
+ fields='*',
+ filters={'patient': patient.name, 'invoiced': False}
+ )
+ for therapy in therapy_sessions:
+ if not therapy.appointment:
+ if therapy.therapy_type and frappe.db.get_value('Therapy Type', therapy.therapy_type, 'is_billable'):
+ therapy_sessions_to_invoice.append({
+ 'reference_type': 'Therapy Session',
+ 'reference_name': therapy.name,
+ 'service': frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
+ })
+
+ return therapy_sessions_to_invoice
+
+
def get_service_item_and_practitioner_charge(doc):
is_inpatient = doc.inpatient_record
if is_inpatient:
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js
index 96e5cd57c3..b49b0ba0f7 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.js
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js
@@ -188,7 +188,7 @@ frappe.ui.form.on('Production Plan', {
},
get_items_for_mr: function(frm) {
- const set_fields = ['actual_qty', 'item_code','item_name', 'description', 'uom',
+ const set_fields = ['actual_qty', 'item_code','item_name', 'description', 'uom',
'min_order_qty', 'quantity', 'sales_order', 'warehouse', 'projected_qty', 'material_request_type'];
frappe.call({
method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_items_for_material_requests",
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index 1490374d2d..e94d1ffe5c 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -1,18 +1,18 @@
{
- "css/erpnext.css": [
- "public/less/erpnext.less",
- "public/less/hub.less",
- "public/less/call_popup.less"
- ],
- "css/marketplace.css": [
- "public/less/hub.less"
- ],
- "js/erpnext-web.min.js": [
- "public/js/website_utils.js",
- "public/js/shopping_cart.js"
- ],
+ "css/erpnext.css": [
+ "public/less/erpnext.less",
+ "public/less/hub.less",
+ "public/less/call_popup.less"
+ ],
+ "css/marketplace.css": [
+ "public/less/hub.less"
+ ],
+ "js/erpnext-web.min.js": [
+ "public/js/website_utils.js",
+ "public/js/shopping_cart.js"
+ ],
"css/erpnext-web.css": [
- "public/scss/website.scss"
+ "public/scss/website.scss"
],
"js/marketplace.min.js": [
"public/js/hub/marketplace.js"
@@ -47,15 +47,15 @@
"public/js/templates/item_quick_entry.html",
"public/js/utils/item_quick_entry.js",
"public/js/utils/customer_quick_entry.js",
- "public/js/education/student_button.html",
- "public/js/education/assessment_result_tool.html",
- "public/js/hub/hub_factory.js",
- "public/js/call_popup/call_popup.js",
- "public/js/utils/dimension_tree_filter.js"
- ],
- "js/item-dashboard.min.js": [
- "stock/dashboard/item_dashboard.html",
- "stock/dashboard/item_dashboard_list.html",
- "stock/dashboard/item_dashboard.js"
- ]
+ "public/js/education/student_button.html",
+ "public/js/education/assessment_result_tool.html",
+ "public/js/hub/hub_factory.js",
+ "public/js/call_popup/call_popup.js",
+ "public/js/utils/dimension_tree_filter.js"
+ ],
+ "js/item-dashboard.min.js": [
+ "stock/dashboard/item_dashboard.html",
+ "stock/dashboard/item_dashboard_list.html",
+ "stock/dashboard/item_dashboard.js"
+ ]
}
diff --git a/erpnext/public/css/erpnext.css b/erpnext/public/css/erpnext.css
index c55e422151..6e4efcb668 100644
--- a/erpnext/public/css/erpnext.css
+++ b/erpnext/public/css/erpnext.css
@@ -370,3 +370,39 @@ body[data-route="pos"] .collapse-btn {
.leaderboard .list-item_content {
padding-right: 45px;
}
+.exercise-card {
+ box-shadow: 0 1px 3px rgba(0,0,0,0.30);
+ border-radius: 2px;
+ padding: 6px 6px 6px 8px;
+ margin-top: 10px;
+ height: 100% !important;
+}
+.exercise-card .card-img-top {
+ width: 100%;
+ height: 15vw;
+ object-fit: cover;
+}
+.exercise-card .btn-edit {
+ position: absolute;
+ bottom: 10px;
+ left: 20px;
+}
+.exercise-card .btn-del {
+ position: absolute;
+ bottom: 10px;
+ left: 50px;
+}
+.exercise-card .card-body {
+ margin-bottom: 10px;
+}
+.exercise-card .card-footer {
+ padding: 10px;
+}
+.exercise-row {
+ height: 100% !important;
+ display: flex;
+ flex-wrap: wrap;
+}
+.exercise-col {
+ padding: 10px;
+}
diff --git a/erpnext/public/less/erpnext.less b/erpnext/public/less/erpnext.less
index abe48685f0..8685837d33 100644
--- a/erpnext/public/less/erpnext.less
+++ b/erpnext/public/less/erpnext.less
@@ -458,4 +458,50 @@ body[data-route="pos"] {
.list-item_content {
padding-right: 45px;
}
+}
+
+// Healthcare
+
+.exercise-card {
+ box-shadow: 0 1px 3px rgba(0,0,0,0.30);
+ border-radius: 2px;
+ padding: 6px 6px 6px 8px;
+ margin-top: 10px;
+ height: 100% !important;
+
+ .card-img-top {
+ width: 100%;
+ height: 15vw;
+ object-fit: cover;
+ }
+
+ .btn-edit {
+ position: absolute;
+ bottom: 10px;
+ left: 20px;
+ }
+
+ .btn-del {
+ position: absolute;
+ bottom: 10px;
+ left: 50px;
+ }
+
+ .card-body {
+ margin-bottom: 10px;
+ }
+
+ .card-footer {
+ padding: 10px;
+ }
+}
+
+.exercise-row {
+ height: 100% !important;
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.exercise-col {
+ padding: 10px;
}
\ No newline at end of file