Skip to content

Commit

Permalink
feat(Healthcare): Capacity for Service Unit, concurrent appointments …
Browse files Browse the repository at this point in the history
…based on capacity, Patient Appointments (frappe#27219)

* feat(Healthcare): Capacity for Service Unit, concurrent appointments based on Capacity, Patient enhancements

* fix: appointment test

Co-authored-by: Anoop <3326959+akurungadam@users.noreply.github.com>
  • Loading branch information
2 people authored and ahmadpak committed Aug 30, 2021
1 parent bbb997c commit 159ab6f
Show file tree
Hide file tree
Showing 23 changed files with 1,035 additions and 326 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class TestClinicalProcedure(unittest.TestCase):
def test_procedure_template_item(self):
patient, medical_department, practitioner = create_healthcare_docs()
patient, practitioner = create_healthcare_docs()
procedure_template = create_clinical_procedure_template()
self.assertTrue(frappe.db.exists('Item', procedure_template.item))

Expand All @@ -20,7 +20,7 @@ def test_procedure_template_item(self):
self.assertEqual(frappe.db.get_value('Item', procedure_template.item, 'disabled'), 1)

def test_consumables(self):
patient, medical_department, practitioner = create_healthcare_docs()
patient, practitioner = create_healthcare_docs()
procedure_template = create_clinical_procedure_template()
procedure_template.allow_stock_consumption = 1
consumable = create_consumable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_fee_validity(self):
healthcare_settings.automate_appointment_invoicing = 1
healthcare_settings.op_consulting_charge_item = item
healthcare_settings.save(ignore_permissions=True)
patient, medical_department, practitioner = create_healthcare_docs()
patient, practitioner = create_healthcare_docs()

# For first appointment, invoice is generated. First appointment not considered in fee validity
appointment = create_appointment(patient, practitioner, nowdate())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ frappe.ui.form.on('Healthcare Service Unit', {

// get query select healthcare service unit
frm.fields_dict['parent_healthcare_service_unit'].get_query = function(doc) {
return{
filters:[
return {
filters: [
['Healthcare Service Unit', 'is_group', '=', 1],
['Healthcare Service Unit', 'name', '!=', doc.healthcare_service_unit_name]
]
Expand All @@ -21,6 +21,14 @@ frappe.ui.form.on('Healthcare Service Unit', {
frm.add_custom_button(__('Healthcare Service Unit Tree'), function() {
frappe.set_route('Tree', 'Healthcare Service Unit');
});

frm.set_query('warehouse', function() {
return {
filters: {
'company': frm.doc.company
}
};
});
},
set_root_readonly: function(frm) {
// read-only for root healthcare service unit
Expand All @@ -43,5 +51,10 @@ frappe.ui.form.on('Healthcare Service Unit', {
else {
frm.set_df_property('service_unit_type', 'reqd', 1);
}
},
overlap_appointments: function(frm) {
if (frm.doc.overlap_appointments == 0) {
frm.set_value('service_unit_capacity', '');
}
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"service_unit_type",
"allow_appointments",
"overlap_appointments",
"service_unit_capacity",
"inpatient_occupancy",
"occupancy_status",
"column_break_9",
Expand All @@ -31,6 +32,8 @@
{
"fieldname": "healthcare_service_unit_name",
"fieldtype": "Data",
"hide_days": 1,
"hide_seconds": 1,
"in_global_search": 1,
"in_list_view": 1,
"label": "Service Unit",
Expand All @@ -41,6 +44,8 @@
"bold": 1,
"fieldname": "parent_healthcare_service_unit",
"fieldtype": "Link",
"hide_days": 1,
"hide_seconds": 1,
"ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Parent Service Unit",
Expand All @@ -52,13 +57,17 @@
"depends_on": "eval:doc.inpatient_occupancy != 1 && doc.allow_appointments != 1",
"fieldname": "is_group",
"fieldtype": "Check",
"hide_days": 1,
"hide_seconds": 1,
"label": "Is Group"
},
{
"bold": 1,
"depends_on": "eval:doc.is_group != 1",
"fieldname": "service_unit_type",
"fieldtype": "Link",
"hide_days": 1,
"hide_seconds": 1,
"label": "Service Unit Type",
"options": "Healthcare Service Unit Type"
},
Expand All @@ -68,6 +77,8 @@
"fetch_from": "service_unit_type.allow_appointments",
"fieldname": "allow_appointments",
"fieldtype": "Check",
"hide_days": 1,
"hide_seconds": 1,
"in_list_view": 1,
"label": "Allow Appointments",
"no_copy": 1,
Expand All @@ -79,6 +90,8 @@
"fetch_from": "service_unit_type.overlap_appointments",
"fieldname": "overlap_appointments",
"fieldtype": "Check",
"hide_days": 1,
"hide_seconds": 1,
"label": "Allow Overlap",
"no_copy": 1,
"read_only": 1
Expand All @@ -90,6 +103,8 @@
"fetch_from": "service_unit_type.inpatient_occupancy",
"fieldname": "inpatient_occupancy",
"fieldtype": "Check",
"hide_days": 1,
"hide_seconds": 1,
"in_list_view": 1,
"label": "Inpatient Occupancy",
"no_copy": 1,
Expand All @@ -100,27 +115,35 @@
"depends_on": "eval:doc.inpatient_occupancy == 1",
"fieldname": "occupancy_status",
"fieldtype": "Select",
"hide_days": 1,
"hide_seconds": 1,
"label": "Occupancy Status",
"no_copy": 1,
"options": "Vacant\nOccupied",
"read_only": 1
},
{
"fieldname": "column_break_9",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"hide_days": 1,
"hide_seconds": 1
},
{
"bold": 1,
"depends_on": "eval:doc.is_group != 1",
"fieldname": "warehouse",
"fieldtype": "Link",
"hide_days": 1,
"hide_seconds": 1,
"label": "Warehouse",
"no_copy": 1,
"options": "Warehouse"
},
{
"fieldname": "company",
"fieldtype": "Link",
"hide_days": 1,
"hide_seconds": 1,
"ignore_user_permissions": 1,
"in_list_view": 1,
"in_standard_filter": 1,
Expand All @@ -134,6 +157,8 @@
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"hide_days": 1,
"hide_seconds": 1,
"label": "lft",
"no_copy": 1,
"print_hide": 1,
Expand All @@ -143,6 +168,8 @@
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"hide_days": 1,
"hide_seconds": 1,
"label": "rgt",
"no_copy": 1,
"print_hide": 1,
Expand All @@ -152,6 +179,8 @@
"fieldname": "old_parent",
"fieldtype": "Link",
"hidden": 1,
"hide_days": 1,
"hide_seconds": 1,
"ignore_user_permissions": 1,
"label": "Old Parent",
"no_copy": 1,
Expand All @@ -163,14 +192,26 @@
"collapsible": 1,
"fieldname": "tree_details_section",
"fieldtype": "Section Break",
"hide_days": 1,
"hide_seconds": 1,
"label": "Tree Details"
},
{
"depends_on": "eval:doc.overlap_appointments == 1",
"fieldname": "service_unit_capacity",
"fieldtype": "Int",
"label": "Service Unit Capacity",
"mandatory_depends_on": "eval:doc.overlap_appointments == 1",
"non_negative": 1
}
],
"is_tree": 1,
"links": [],
"modified": "2020-05-20 18:26:56.065543",
"modified": "2021-08-19 14:09:11.643464",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Service Unit",
"nsm_parent_field": "parent_healthcare_service_unit",
"owner": "Administrator",
"permissions": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@
from __future__ import unicode_literals

from frappe.utils.nestedset import NestedSet
from frappe.utils import cint, cstr
import frappe
from frappe import _
import json


class HealthcareServiceUnit(NestedSet):
nsm_parent_field = 'parent_healthcare_service_unit'

def validate(self):
self.set_service_unit_properties()

def autoname(self):
if self.company:
suffix = " - " + frappe.get_cached_value('Company', self.company, "abbr")
suffix = " - " + frappe.get_cached_value('Company', self.company, 'abbr')
if not self.healthcare_service_unit_name.endswith(suffix):
self.name = self.healthcare_service_unit_name + suffix
else:
Expand All @@ -22,16 +29,86 @@ def on_update(self):
super(HealthcareServiceUnit, self).on_update()
self.validate_one_root()

def after_insert(self):
def set_service_unit_properties(self):
if self.is_group:
self.allow_appointments = 0
self.overlap_appointments = 0
self.inpatient_occupancy = 0
elif self.service_unit_type:
self.allow_appointments = False
self.overlap_appointments = False
self.inpatient_occupancy = False
self.service_unit_capacity = 0
self.occupancy_status = ''
self.service_unit_type = ''
elif self.service_unit_type != '':
service_unit_type = frappe.get_doc('Healthcare Service Unit Type', self.service_unit_type)
self.allow_appointments = service_unit_type.allow_appointments
self.overlap_appointments = service_unit_type.overlap_appointments
self.inpatient_occupancy = service_unit_type.inpatient_occupancy
if self.inpatient_occupancy:

if self.inpatient_occupancy and self.occupancy_status != '':
self.occupancy_status = 'Vacant'
self.overlap_appointments = 0

if service_unit_type.overlap_appointments:
self.overlap_appointments = True
else:
self.overlap_appointments = False
self.service_unit_capacity = 0

if self.overlap_appointments:
if not self.service_unit_capacity:
frappe.throw(_('Please set a valid Service Unit Capacity to enable Overlapping Appointments'),
title=_('Mandatory'))


@frappe.whitelist()
def add_multiple_service_units(parent, data):
'''
parent - parent service unit under which the service units are to be created
data (dict) - company, healthcare_service_unit_name, count, service_unit_type, warehouse, service_unit_capacity
'''
if not parent or not data:
return

data = json.loads(data)
company = data.get('company') or \
frappe.defaults.get_defaults().get('company') or \
frappe.db.get_single_value('Global Defaults', 'default_company')

if not data.get('healthcare_service_unit_name') or not company:
frappe.throw(_('Service Unit Name and Company are mandatory to create Healthcare Service Units'),
title=_('Missing Required Fields'))

count = cint(data.get('count') or 0)
if count <= 0:
frappe.throw(_('Number of Service Units to be created should at least be 1'),
title=_('Invalid Number of Service Units'))

capacity = cint(data.get('service_unit_capacity') or 1)

service_unit = {
'doctype': 'Healthcare Service Unit',
'parent_healthcare_service_unit': parent,
'service_unit_type': data.get('service_unit_type') or None,
'service_unit_capacity': capacity if capacity > 0 else 1,
'warehouse': data.get('warehouse') or None,
'company': company
}

service_unit_name = '{}'.format(data.get('healthcare_service_unit_name').strip(' -'))

last_suffix = frappe.db.sql("""SELECT
IFNULL(MAX(CAST(SUBSTRING(name FROM %(start)s FOR 4) AS UNSIGNED)), 0)
FROM `tabHealthcare Service Unit`
WHERE name like %(prefix)s AND company=%(company)s""",
{'start': len(service_unit_name)+2, 'prefix': '{}-%'.format(service_unit_name), 'company': company},
as_list=1)[0][0]
start_suffix = cint(last_suffix) + 1

failed_list = []
for i in range(start_suffix, count + start_suffix):
# name to be in the form WARD-####
service_unit['healthcare_service_unit_name'] = '{}-{}'.format(service_unit_name, cstr('%0*d' % (4, i)))
service_unit_doc = frappe.get_doc(service_unit)
try:
service_unit_doc.insert()
except Exception:
failed_list.append(service_unit['healthcare_service_unit_name'])

return failed_list
Loading

0 comments on commit 159ab6f

Please sign in to comment.