feat: Patient Appointment Analytics Script Report
This commit is contained in:
parent
9565e62e3a
commit
85aab34421
@ -228,7 +228,6 @@
|
||||
"default": "0",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Invoiced",
|
||||
"read_only": 1
|
||||
},
|
||||
@ -286,7 +285,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-02-25 17:57:56.971064",
|
||||
"modified": "2020-03-02 14:35:54.040428",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient Appointment",
|
||||
|
@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
/* eslint-disable */
|
||||
|
||||
frappe.query_reports['Patient Appointment Analytics'] = {
|
||||
"filters": [
|
||||
{
|
||||
fieldname: 'tree_type',
|
||||
label: __('Tree Type'),
|
||||
fieldtype: 'Select',
|
||||
options: ['Healthcare Practitioner', 'Medical Department'],
|
||||
default: 'Healthcare Practitioner',
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'status',
|
||||
label: __('Appointment Status'),
|
||||
fieldtype: 'Select',
|
||||
options:[
|
||||
{label: __('Scheduled'), value: 'Scheduled'},
|
||||
{label: __('Open'), value: 'Open'},
|
||||
{label: __('Closed'), value: 'Closed'},
|
||||
{label: __('Expired'), value: 'Expired'},
|
||||
{label: __('Cancelled'), value: 'Cancelled'}
|
||||
]
|
||||
},
|
||||
{
|
||||
fieldname: 'appointment_type',
|
||||
label: __('Appointment Type'),
|
||||
fieldtype: 'Link',
|
||||
options: 'Appointment Type'
|
||||
},
|
||||
{
|
||||
fieldname: 'practitioner',
|
||||
label: __('Healthcare Practitioner'),
|
||||
fieldtype: 'Link',
|
||||
options: 'Healthcare Practitioner'
|
||||
},
|
||||
{
|
||||
fieldname: 'department',
|
||||
label: __('Medical Department'),
|
||||
fieldtype: 'Link',
|
||||
options: 'Medical Department'
|
||||
},
|
||||
{
|
||||
fieldname: 'from_date',
|
||||
label: __('From Date'),
|
||||
fieldtype: 'Date',
|
||||
default: frappe.defaults.get_user_default('year_start_date'),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'to_date',
|
||||
label: __('To Date'),
|
||||
fieldtype: 'Date',
|
||||
default: frappe.defaults.get_user_default('year_end_date'),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'range',
|
||||
label: __('Range'),
|
||||
fieldtype: 'Select',
|
||||
options:[
|
||||
{label: __('Weekly'), value: 'Weekly'},
|
||||
{label: __('Monthly'), value: 'Monthly'},
|
||||
{label: __('Quarterly'), value: 'Quarterly'},
|
||||
{label: __('Yearly'), value: 'Yearly'}
|
||||
],
|
||||
default: 'Monthly',
|
||||
reqd: 1
|
||||
}
|
||||
]
|
||||
};
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"add_total_row": 1,
|
||||
"creation": "2020-03-02 15:13:16.273493",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2020-03-02 15:13:16.273493",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient Appointment Analytics",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Patient Appointment",
|
||||
"report_name": "Patient Appointment Analytics",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Healthcare Administrator"
|
||||
},
|
||||
{
|
||||
"role": "LabTest Approver"
|
||||
},
|
||||
{
|
||||
"role": "Physician"
|
||||
},
|
||||
{
|
||||
"role": "Nursing User"
|
||||
},
|
||||
{
|
||||
"role": "Laboratory User"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import getdate, flt, add_to_date, add_days
|
||||
from frappe import _ , scrub
|
||||
from six import iteritems
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
|
||||
def execute(filters=None):
|
||||
return Analytics(filters).run()
|
||||
|
||||
class Analytics(object):
|
||||
def __init__(self, filters=None):
|
||||
self.filters = frappe._dict(filters or {})
|
||||
self.months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||
self.get_period_date_ranges()
|
||||
|
||||
def run(self):
|
||||
self.get_columns()
|
||||
self.get_data()
|
||||
self.get_chart_data()
|
||||
|
||||
self.chart = ''
|
||||
return self.columns, self.data, None, self.chart
|
||||
|
||||
def get_period_date_ranges(self):
|
||||
from dateutil.relativedelta import relativedelta, MO
|
||||
from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date)
|
||||
|
||||
increment = {
|
||||
'Monthly': 1,
|
||||
'Quarterly': 3,
|
||||
'Half-Yearly': 6,
|
||||
'Yearly': 12
|
||||
}.get(self.filters.range, 1)
|
||||
|
||||
if self.filters.range in ['Monthly', 'Quarterly']:
|
||||
from_date = from_date.replace(day=1)
|
||||
elif self.filters.range == 'Yearly':
|
||||
from_date = get_fiscal_year(from_date)[1]
|
||||
else:
|
||||
from_date = from_date + relativedelta(from_date, weekday=MO(-1))
|
||||
|
||||
self.periodic_daterange = []
|
||||
for dummy in range(1, 53):
|
||||
if self.filters.range == 'Weekly':
|
||||
period_end_date = add_days(from_date, 6)
|
||||
else:
|
||||
period_end_date = add_to_date(from_date, months=increment, days=-1)
|
||||
|
||||
if period_end_date > to_date:
|
||||
period_end_date = to_date
|
||||
|
||||
self.periodic_daterange.append(period_end_date)
|
||||
|
||||
from_date = add_days(period_end_date, 1)
|
||||
if period_end_date == to_date:
|
||||
break
|
||||
|
||||
def get_columns(self):
|
||||
self.columns = []
|
||||
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
self.columns.append({
|
||||
'label': _('Healthcare Practitioner'),
|
||||
'options': 'Healthcare Practitioner',
|
||||
'fieldname': 'practitioner',
|
||||
'fieldtype': 'Link',
|
||||
'width': 200
|
||||
})
|
||||
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
self.columns.append({
|
||||
'label': _('Medical Department'),
|
||||
'fieldname': 'department',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Medical Department',
|
||||
'width': 150
|
||||
})
|
||||
|
||||
for end_date in self.periodic_daterange:
|
||||
period = self.get_period(end_date)
|
||||
self.columns.append({
|
||||
'label': _(period),
|
||||
'fieldname': scrub(period),
|
||||
'fieldtype': 'Float',
|
||||
'width': 120
|
||||
})
|
||||
|
||||
self.columns.append({
|
||||
'label': _('Total'),
|
||||
'fieldname': 'total',
|
||||
'fieldtype': 'Float',
|
||||
'width': 120
|
||||
})
|
||||
|
||||
def get_data(self):
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
self.get_appointments_based_on_healthcare_practitioner()
|
||||
self.get_rows()
|
||||
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
self.get_appointments_based_on_medical_department()
|
||||
self.get_rows()
|
||||
|
||||
def get_chart_data(self):
|
||||
pass
|
||||
|
||||
def get_period(self, appointment_date):
|
||||
if self.filters.range == 'Weekly':
|
||||
period = 'Week ' + str(appointment_date.isocalendar()[1]) + ' ' + str(appointment_date.year)
|
||||
elif self.filters.range == 'Monthly':
|
||||
period = str(self.months[appointment_date.month - 1]) + ' ' + str(appointment_date.year)
|
||||
elif self.filters.range == 'Quarterly':
|
||||
period = 'Quarter ' + str(((appointment_date.month - 1) // 3) + 1) + ' ' + str(appointment_date.year)
|
||||
else:
|
||||
year = get_fiscal_year(appointment_date, company=self.filters.company)
|
||||
period = str(year[0])
|
||||
|
||||
return period
|
||||
|
||||
def get_appointments_based_on_healthcare_practitioner(self):
|
||||
filters = self.get_common_filters()
|
||||
|
||||
self.entries = frappe.db.get_all('Patient Appointment',
|
||||
fields=['appointment_date', 'name', 'patient', 'practitioner'],
|
||||
filters=filters
|
||||
)
|
||||
|
||||
def get_appointments_based_on_medical_department(self):
|
||||
filters = self.get_common_filters()
|
||||
if not filters.get('department'):
|
||||
filters['department'] = ('!=', '')
|
||||
|
||||
self.entries = frappe.db.get_all('Patient Appointment',
|
||||
fields=['appointment_date', 'name', 'patient', 'practitioner', 'department'],
|
||||
filters=filters
|
||||
)
|
||||
|
||||
def get_common_filters(self):
|
||||
filters = {}
|
||||
filters['appointment_date'] = ('between', [self.filters.from_date, self.filters.to_date])
|
||||
for entry in ['appointment_type', 'practitioner', 'department', 'status']:
|
||||
if self.filters.get(entry):
|
||||
filters[entry] = self.filters.get(entry)
|
||||
|
||||
return filters
|
||||
|
||||
def get_rows(self):
|
||||
self.data = []
|
||||
self.get_periodic_data()
|
||||
|
||||
for entity, period_data in iteritems(self.appointment_periodic_data):
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
row = {'practitioner': entity}
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
row = {'department': entity}
|
||||
|
||||
total = 0
|
||||
for end_date in self.periodic_daterange:
|
||||
period = self.get_period(end_date)
|
||||
amount = flt(period_data.get(period, 0.0))
|
||||
row[scrub(period)] = amount
|
||||
total += amount
|
||||
|
||||
row['total'] = total
|
||||
|
||||
self.data.append(row)
|
||||
|
||||
def get_periodic_data(self):
|
||||
self.appointment_periodic_data = frappe._dict()
|
||||
|
||||
for d in self.entries:
|
||||
period = self.get_period(d.get('appointment_date'))
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
self.appointment_periodic_data.setdefault(d.practitioner, frappe._dict()).setdefault(period, 0.0)
|
||||
self.appointment_periodic_data[d.practitioner][period] += 1
|
||||
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
self.appointment_periodic_data.setdefault(d.department, frappe._dict()).setdefault(period, 0.0)
|
||||
self.appointment_periodic_data[d.department][period] += 1
|
Loading…
x
Reference in New Issue
Block a user