Merge pull request #24033 from ruchamahabal/patient-history-enhancements
feat: Patient History Enhancements
This commit is contained in:
commit
13df7a0ca6
@ -100,7 +100,6 @@ class ClinicalProcedure(Document):
|
||||
allow_start = self.set_actual_qty()
|
||||
if allow_start:
|
||||
self.db_set('status', 'In Progress')
|
||||
insert_clinical_procedure_to_medical_record(self)
|
||||
return 'success'
|
||||
return 'insufficient stock'
|
||||
|
||||
@ -247,21 +246,3 @@ def make_procedure(source_name, target_doc=None):
|
||||
}, target_doc, set_missing_values)
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def insert_clinical_procedure_to_medical_record(doc):
|
||||
subject = frappe.bold(_("Clinical Procedure conducted: ")) + cstr(doc.procedure_template) + "<br>"
|
||||
if doc.practitioner:
|
||||
subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
|
||||
if subject and doc.notes:
|
||||
subject += '<br/>' + doc.notes
|
||||
|
||||
medical_record = frappe.new_doc('Patient Medical Record')
|
||||
medical_record.patient = doc.patient
|
||||
medical_record.subject = subject
|
||||
medical_record.status = 'Open'
|
||||
medical_record.communication_date = doc.start_date
|
||||
medical_record.reference_doctype = 'Clinical Procedure'
|
||||
medical_record.reference_name = doc.name
|
||||
medical_record.reference_owner = doc.owner
|
||||
medical_record.save(ignore_permissions=True)
|
||||
|
@ -359,6 +359,7 @@
|
||||
{
|
||||
"fieldname": "normal_test_items",
|
||||
"fieldtype": "Table",
|
||||
"label": "Normal Test Result",
|
||||
"options": "Normal Test Result",
|
||||
"print_hide": 1
|
||||
},
|
||||
@ -380,6 +381,7 @@
|
||||
{
|
||||
"fieldname": "sensitivity_test_items",
|
||||
"fieldtype": "Table",
|
||||
"label": "Sensitivity Test Result",
|
||||
"options": "Sensitivity Test Result",
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
@ -529,6 +531,7 @@
|
||||
{
|
||||
"fieldname": "descriptive_test_items",
|
||||
"fieldtype": "Table",
|
||||
"label": "Descriptive Test Result",
|
||||
"options": "Descriptive Test Result",
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
@ -549,13 +552,14 @@
|
||||
{
|
||||
"fieldname": "organism_test_items",
|
||||
"fieldtype": "Table",
|
||||
"label": "Organism Test Result",
|
||||
"options": "Organism Test Result",
|
||||
"print_hide": 1
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-07-30 18:18:38.516215",
|
||||
"modified": "2020-11-30 11:04:17.195848",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Test",
|
||||
|
@ -17,11 +17,9 @@ class LabTest(Document):
|
||||
self.validate_result_values()
|
||||
self.db_set('submitted_date', getdate())
|
||||
self.db_set('status', 'Completed')
|
||||
insert_lab_test_to_medical_record(self)
|
||||
|
||||
def on_cancel(self):
|
||||
self.db_set('status', 'Cancelled')
|
||||
delete_lab_test_from_medical_record(self)
|
||||
self.reload()
|
||||
|
||||
def on_update(self):
|
||||
@ -330,60 +328,6 @@ def get_employee_by_user_id(user_id):
|
||||
return frappe.get_doc('Employee', emp_id)
|
||||
return None
|
||||
|
||||
def insert_lab_test_to_medical_record(doc):
|
||||
table_row = False
|
||||
subject = cstr(doc.lab_test_name)
|
||||
if doc.practitioner:
|
||||
subject += frappe.bold(_('Healthcare Practitioner: '))+ doc.practitioner + '<br>'
|
||||
if doc.normal_test_items:
|
||||
item = doc.normal_test_items[0]
|
||||
comment = ''
|
||||
if item.lab_test_comment:
|
||||
comment = str(item.lab_test_comment)
|
||||
table_row = frappe.bold(_('Lab Test Conducted: ')) + item.lab_test_name
|
||||
|
||||
if item.lab_test_event:
|
||||
table_row += frappe.bold(_('Lab Test Event: ')) + item.lab_test_event
|
||||
|
||||
if item.result_value:
|
||||
table_row += ' ' + frappe.bold(_('Lab Test Result: ')) + item.result_value
|
||||
|
||||
if item.normal_range:
|
||||
table_row += ' ' + _('Normal Range: ') + item.normal_range
|
||||
table_row += ' ' + comment
|
||||
|
||||
elif doc.descriptive_test_items:
|
||||
item = doc.descriptive_test_items[0]
|
||||
|
||||
if item.lab_test_particulars and item.result_value:
|
||||
table_row = item.lab_test_particulars + ' ' + item.result_value
|
||||
|
||||
elif doc.sensitivity_test_items:
|
||||
item = doc.sensitivity_test_items[0]
|
||||
|
||||
if item.antibiotic and item.antibiotic_sensitivity:
|
||||
table_row = item.antibiotic + ' ' + item.antibiotic_sensitivity
|
||||
|
||||
if table_row:
|
||||
subject += '<br>' + table_row
|
||||
if doc.lab_test_comment:
|
||||
subject += '<br>' + cstr(doc.lab_test_comment)
|
||||
|
||||
medical_record = frappe.new_doc('Patient Medical Record')
|
||||
medical_record.patient = doc.patient
|
||||
medical_record.subject = subject
|
||||
medical_record.status = 'Open'
|
||||
medical_record.communication_date = doc.result_date
|
||||
medical_record.reference_doctype = 'Lab Test'
|
||||
medical_record.reference_name = doc.name
|
||||
medical_record.reference_owner = doc.owner
|
||||
medical_record.save(ignore_permissions = True)
|
||||
|
||||
def delete_lab_test_from_medical_record(self):
|
||||
medical_record_id = frappe.db.sql('select name from `tabPatient Medical Record` where reference_name=%s', (self.name))
|
||||
|
||||
if medical_record_id and medical_record_id[0][0]:
|
||||
frappe.delete_doc('Patient Medical Record', medical_record_id[0][0])
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_lab_test_prescribed(patient):
|
||||
|
@ -208,6 +208,7 @@ def create_healthcare_service_items():
|
||||
item.item_name = 'Consulting Charges'
|
||||
item.item_group = 'Services'
|
||||
item.is_stock_item = 0
|
||||
item.stock_uom = 'Nos'
|
||||
item.save()
|
||||
return item.name
|
||||
|
||||
|
@ -210,7 +210,7 @@
|
||||
{
|
||||
"fieldname": "drug_prescription",
|
||||
"fieldtype": "Table",
|
||||
"label": "Items",
|
||||
"label": "Drug Prescription",
|
||||
"options": "Drug Prescription"
|
||||
},
|
||||
{
|
||||
@ -328,7 +328,7 @@
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-05-16 21:00:08.644531",
|
||||
"modified": "2020-11-30 10:39:00.783119",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient Encounter",
|
||||
|
@ -17,10 +17,6 @@ class PatientEncounter(Document):
|
||||
def on_update(self):
|
||||
if self.appointment:
|
||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
|
||||
update_encounter_medical_record(self)
|
||||
|
||||
def after_insert(self):
|
||||
insert_encounter_to_medical_record(self)
|
||||
|
||||
def on_submit(self):
|
||||
if self.therapies:
|
||||
@ -33,8 +29,6 @@ class PatientEncounter(Document):
|
||||
if self.inpatient_record and self.drug_prescription:
|
||||
delete_ip_medication_order(self)
|
||||
|
||||
delete_medical_record(self)
|
||||
|
||||
def set_title(self):
|
||||
self.title = _('{0} with {1}').format(self.patient_name or self.patient,
|
||||
self.practitioner_name or self.practitioner)[:100]
|
||||
@ -102,61 +96,7 @@ def create_therapy_plan(encounter):
|
||||
frappe.msgprint(_('Therapy Plan {0} created successfully.').format(frappe.bold(doc.name)), alert=True)
|
||||
|
||||
|
||||
def insert_encounter_to_medical_record(doc):
|
||||
subject = set_subject_field(doc)
|
||||
medical_record = frappe.new_doc('Patient Medical Record')
|
||||
medical_record.patient = doc.patient
|
||||
medical_record.subject = subject
|
||||
medical_record.status = 'Open'
|
||||
medical_record.communication_date = doc.encounter_date
|
||||
medical_record.reference_doctype = 'Patient Encounter'
|
||||
medical_record.reference_name = doc.name
|
||||
medical_record.reference_owner = doc.owner
|
||||
medical_record.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def update_encounter_medical_record(encounter):
|
||||
medical_record_id = frappe.db.exists('Patient Medical Record', {'reference_name': encounter.name})
|
||||
|
||||
if medical_record_id and medical_record_id[0][0]:
|
||||
subject = set_subject_field(encounter)
|
||||
frappe.db.set_value('Patient Medical Record', medical_record_id[0][0], 'subject', subject)
|
||||
else:
|
||||
insert_encounter_to_medical_record(encounter)
|
||||
|
||||
|
||||
def delete_medical_record(encounter):
|
||||
record = frappe.db.exists('Patient Medical Record', {'reference_name', encounter.name})
|
||||
if record:
|
||||
frappe.delete_doc('Patient Medical Record', record, force=1)
|
||||
|
||||
def delete_ip_medication_order(encounter):
|
||||
record = frappe.db.exists('Inpatient Medication Order', {'patient_encounter': encounter.name})
|
||||
if record:
|
||||
frappe.delete_doc('Inpatient Medication Order', record, force=1)
|
||||
|
||||
|
||||
def set_subject_field(encounter):
|
||||
subject = frappe.bold(_('Healthcare Practitioner: ')) + encounter.practitioner + '<br>'
|
||||
if encounter.symptoms:
|
||||
subject += frappe.bold(_('Symptoms: ')) + '<br>'
|
||||
for entry in encounter.symptoms:
|
||||
subject += cstr(entry.complaint) + '<br>'
|
||||
else:
|
||||
subject += frappe.bold(_('No Symptoms')) + '<br>'
|
||||
|
||||
if encounter.diagnosis:
|
||||
subject += frappe.bold(_('Diagnosis: ')) + '<br>'
|
||||
for entry in encounter.diagnosis:
|
||||
subject += cstr(entry.diagnosis) + '<br>'
|
||||
else:
|
||||
subject += frappe.bold(_('No Diagnosis')) + '<br>'
|
||||
|
||||
if encounter.drug_prescription:
|
||||
subject += '<br>' + _('Drug(s) Prescribed.')
|
||||
if encounter.lab_test_prescription:
|
||||
subject += '<br>' + _('Test(s) Prescribed.')
|
||||
if encounter.procedure_prescription:
|
||||
subject += '<br>' + _('Procedure(s) Prescribed.')
|
||||
|
||||
return subject
|
||||
frappe.delete_doc('Inpatient Medication Order', record, force=1)
|
@ -0,0 +1,55 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-11-25 13:40:23.054469",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"document_type",
|
||||
"date_fieldname",
|
||||
"add_edit_fields",
|
||||
"selected_fields"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "document_type",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Document Type",
|
||||
"options": "DocType",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "selected_fields",
|
||||
"fieldtype": "Code",
|
||||
"label": "Selected Fields",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "add_edit_fields",
|
||||
"fieldtype": "Button",
|
||||
"in_list_view": 1,
|
||||
"label": "Add / Edit Fields"
|
||||
},
|
||||
{
|
||||
"fieldname": "date_fieldname",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Date Fieldname",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-30 13:54:37.474671",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient History Custom Document Type",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PatientHistoryCustomDocumentType(Document):
|
||||
pass
|
@ -0,0 +1,133 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Patient History Settings', {
|
||||
refresh: function(frm) {
|
||||
frm.set_query('document_type', 'custom_doctypes', () => {
|
||||
return {
|
||||
filters: {
|
||||
custom: 1,
|
||||
is_submittable: 1,
|
||||
module: 'Healthcare',
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
field_selector: function(frm, doc, standard=1) {
|
||||
let document_fields = [];
|
||||
if (doc.selected_fields)
|
||||
document_fields = (JSON.parse(doc.selected_fields)).map(f => f.fieldname);
|
||||
|
||||
frm.call({
|
||||
method: 'get_doctype_fields',
|
||||
doc: frm.doc,
|
||||
args: {
|
||||
document_type: doc.document_type,
|
||||
fields: document_fields
|
||||
},
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
let doctype = 'Patient History Custom Document Type';
|
||||
if (standard)
|
||||
doctype = 'Patient History Standard Document Type';
|
||||
|
||||
frm.events.show_field_selector_dialog(frm, doc, doctype, r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
show_field_selector_dialog: function(frm, doc, doctype, doc_fields) {
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __('{0} Fields', [__(doc.document_type)]),
|
||||
fields: [
|
||||
{
|
||||
label: __('Select Fields'),
|
||||
fieldtype: 'MultiCheck',
|
||||
fieldname: 'fields',
|
||||
options: doc_fields,
|
||||
columns: 2
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
d.$body.prepend(`
|
||||
<div class="columns-search">
|
||||
<input type="text" placeholder="${__('Search')}" data-element="search" class="form-control input-xs">
|
||||
</div>`
|
||||
);
|
||||
|
||||
frappe.utils.setup_search(d.$body, '.unit-checkbox', '.label-area');
|
||||
|
||||
d.set_primary_action(__('Save'), () => {
|
||||
let values = d.get_values().fields;
|
||||
|
||||
let selected_fields = [];
|
||||
|
||||
frappe.model.with_doctype(doc.document_type, function() {
|
||||
for (let idx in values) {
|
||||
let value = values[idx];
|
||||
|
||||
let field = frappe.get_meta(doc.document_type).fields.filter((df) => df.fieldname == value)[0];
|
||||
if (field) {
|
||||
selected_fields.push({
|
||||
label: field.label,
|
||||
fieldname: field.fieldname,
|
||||
fieldtype: field.fieldtype
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
d.refresh();
|
||||
frappe.model.set_value(doctype, doc.name, 'selected_fields', JSON.stringify(selected_fields));
|
||||
});
|
||||
|
||||
d.hide();
|
||||
});
|
||||
|
||||
d.show();
|
||||
},
|
||||
|
||||
get_date_field_for_dt: function(frm, row) {
|
||||
frm.call({
|
||||
method: 'get_date_field_for_dt',
|
||||
doc: frm.doc,
|
||||
args: {
|
||||
document_type: row.document_type
|
||||
},
|
||||
callback: function(data) {
|
||||
if (data.message) {
|
||||
frappe.model.set_value('Patient History Custom Document Type',
|
||||
row.name, 'date_fieldname', data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Patient History Custom Document Type', {
|
||||
document_type: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
if (row.document_type) {
|
||||
frm.events.get_date_field_for_dt(frm, row);
|
||||
}
|
||||
},
|
||||
|
||||
add_edit_fields: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
if (row.document_type) {
|
||||
frm.events.field_selector(frm, row, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Patient History Standard Document Type', {
|
||||
add_edit_fields: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
if (row.document_type) {
|
||||
frm.events.field_selector(frm, row);
|
||||
}
|
||||
}
|
||||
});
|
@ -0,0 +1,55 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-11-25 13:41:37.675518",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"standard_doctypes",
|
||||
"section_break_2",
|
||||
"custom_doctypes"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "section_break_2",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "custom_doctypes",
|
||||
"fieldtype": "Table",
|
||||
"label": "Custom Document Types",
|
||||
"options": "Patient History Custom Document Type"
|
||||
},
|
||||
{
|
||||
"fieldname": "standard_doctypes",
|
||||
"fieldtype": "Table",
|
||||
"label": "Standard Document Types",
|
||||
"options": "Patient History Standard Document Type",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-25 13:43:38.511771",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient History Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
# -*- 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 cstr, cint
|
||||
from frappe.model.document import Document
|
||||
from erpnext.healthcare.page.patient_history.patient_history import get_patient_history_doctypes
|
||||
|
||||
class PatientHistorySettings(Document):
|
||||
def validate(self):
|
||||
self.validate_submittable_doctypes()
|
||||
self.validate_date_fieldnames()
|
||||
|
||||
def validate_submittable_doctypes(self):
|
||||
for entry in self.custom_doctypes:
|
||||
if not cint(frappe.db.get_value('DocType', entry.document_type, 'is_submittable')):
|
||||
msg = _('Row #{0}: Document Type {1} is not submittable. ').format(
|
||||
entry.idx, frappe.bold(entry.document_type))
|
||||
msg += _('Patient Medical Record can only be created for submittable document types.')
|
||||
frappe.throw(msg)
|
||||
|
||||
def validate_date_fieldnames(self):
|
||||
for entry in self.custom_doctypes:
|
||||
field = frappe.get_meta(entry.document_type).get_field(entry.date_fieldname)
|
||||
if not field:
|
||||
frappe.throw(_('Row #{0}: No such Field named {1} found in the Document Type {2}.').format(
|
||||
entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)))
|
||||
|
||||
if field.fieldtype not in ['Date', 'Datetime']:
|
||||
frappe.throw(_('Row #{0}: Field {1} in Document Type {2} is not a Date / Datetime field.').format(
|
||||
entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)))
|
||||
|
||||
def get_doctype_fields(self, document_type, fields):
|
||||
multicheck_fields = []
|
||||
doc_fields = frappe.get_meta(document_type).fields
|
||||
|
||||
for field in doc_fields:
|
||||
if field.fieldtype not in frappe.model.no_value_fields or \
|
||||
field.fieldtype in frappe.model.table_fields and not field.hidden:
|
||||
multicheck_fields.append({
|
||||
'label': field.label,
|
||||
'value': field.fieldname,
|
||||
'checked': 1 if field.fieldname in fields else 0
|
||||
})
|
||||
|
||||
return multicheck_fields
|
||||
|
||||
def get_date_field_for_dt(self, document_type):
|
||||
meta = frappe.get_meta(document_type)
|
||||
date_fields = meta.get('fields', {
|
||||
'fieldtype': ['in', ['Date', 'Datetime']]
|
||||
})
|
||||
|
||||
if date_fields:
|
||||
return date_fields[0].get('fieldname')
|
||||
|
||||
def create_medical_record(doc, method=None):
|
||||
medical_record_required = validate_medical_record_required(doc)
|
||||
if not medical_record_required:
|
||||
return
|
||||
|
||||
if frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name }):
|
||||
return
|
||||
|
||||
subject = set_subject_field(doc)
|
||||
date_field = get_date_field(doc.doctype)
|
||||
medical_record = frappe.new_doc('Patient Medical Record')
|
||||
medical_record.patient = doc.patient
|
||||
medical_record.subject = subject
|
||||
medical_record.status = 'Open'
|
||||
medical_record.communication_date = doc.get(date_field)
|
||||
medical_record.reference_doctype = doc.doctype
|
||||
medical_record.reference_name = doc.name
|
||||
medical_record.reference_owner = doc.owner
|
||||
medical_record.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def update_medical_record(doc, method=None):
|
||||
medical_record_required = validate_medical_record_required(doc)
|
||||
if not medical_record_required:
|
||||
return
|
||||
|
||||
medical_record_id = frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name })
|
||||
|
||||
if medical_record_id:
|
||||
subject = set_subject_field(doc)
|
||||
frappe.db.set_value('Patient Medical Record', medical_record_id[0][0], 'subject', subject)
|
||||
else:
|
||||
create_medical_record(doc)
|
||||
|
||||
|
||||
def delete_medical_record(doc, method=None):
|
||||
medical_record_required = validate_medical_record_required(doc)
|
||||
if not medical_record_required:
|
||||
return
|
||||
|
||||
record = frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name })
|
||||
if record:
|
||||
frappe.delete_doc('Patient Medical Record', record, force=1)
|
||||
|
||||
|
||||
def set_subject_field(doc):
|
||||
from frappe.utils.formatters import format_value
|
||||
|
||||
meta = frappe.get_meta(doc.doctype)
|
||||
subject = ''
|
||||
patient_history_fields = get_patient_history_fields(doc)
|
||||
|
||||
for entry in patient_history_fields:
|
||||
fieldname = entry.get('fieldname')
|
||||
if entry.get('fieldtype') == 'Table' and doc.get(fieldname):
|
||||
formatted_value = get_formatted_value_for_table_field(doc.get(fieldname), meta.get_field(fieldname))
|
||||
subject += frappe.bold(_(entry.get('label')) + ': ') + '<br>' + cstr(formatted_value) + '<br>'
|
||||
|
||||
else:
|
||||
if doc.get(fieldname):
|
||||
formatted_value = format_value(doc.get(fieldname), meta.get_field(fieldname), doc)
|
||||
subject += frappe.bold(_(entry.get('label')) + ': ') + cstr(formatted_value) + '<br>'
|
||||
|
||||
return subject
|
||||
|
||||
|
||||
def get_date_field(doctype):
|
||||
dt = get_patient_history_config_dt(doctype)
|
||||
|
||||
return frappe.db.get_value(dt, { 'document_type': doctype }, 'date_fieldname')
|
||||
|
||||
|
||||
def get_patient_history_fields(doc):
|
||||
dt = get_patient_history_config_dt(doc.doctype)
|
||||
patient_history_fields = frappe.db.get_value(dt, { 'document_type': doc.doctype }, 'selected_fields')
|
||||
|
||||
if patient_history_fields:
|
||||
return json.loads(patient_history_fields)
|
||||
|
||||
|
||||
def get_formatted_value_for_table_field(items, df):
|
||||
child_meta = frappe.get_meta(df.options)
|
||||
|
||||
table_head = ''
|
||||
table_row = ''
|
||||
html = ''
|
||||
create_head = True
|
||||
for item in items:
|
||||
table_row += '<tr>'
|
||||
for cdf in child_meta.fields:
|
||||
if cdf.in_list_view:
|
||||
if create_head:
|
||||
table_head += '<td>' + cdf.label + '</td>'
|
||||
if item.get(cdf.fieldname):
|
||||
table_row += '<td>' + str(item.get(cdf.fieldname)) + '</td>'
|
||||
else:
|
||||
table_row += '<td></td>'
|
||||
create_head = False
|
||||
table_row += '</tr>'
|
||||
|
||||
html += "<table class='table table-condensed table-bordered'>" + table_head + table_row + "</table>"
|
||||
|
||||
return html
|
||||
|
||||
|
||||
def get_patient_history_config_dt(doctype):
|
||||
if frappe.db.get_value('DocType', doctype, 'custom'):
|
||||
return 'Patient History Custom Document Type'
|
||||
else:
|
||||
return 'Patient History Standard Document Type'
|
||||
|
||||
|
||||
def validate_medical_record_required(doc):
|
||||
if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_setup_wizard \
|
||||
or get_module(doc) != 'Healthcare':
|
||||
return False
|
||||
|
||||
if doc.doctype not in get_patient_history_doctypes():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_module(doc):
|
||||
module = doc.meta.module
|
||||
if not module:
|
||||
module = frappe.db.get_value('DocType', doc.doctype, 'module')
|
||||
|
||||
return module
|
@ -0,0 +1,104 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
import json
|
||||
from frappe.utils import getdate
|
||||
from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_patient
|
||||
|
||||
class TestPatientHistorySettings(unittest.TestCase):
|
||||
def setUp(self):
|
||||
dt = create_custom_doctype()
|
||||
settings = frappe.get_single("Patient History Settings")
|
||||
settings.append("custom_doctypes", {
|
||||
"document_type": dt.name,
|
||||
"date_fieldname": "date",
|
||||
"selected_fields": json.dumps([{
|
||||
"label": "Date",
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"label": "Rating",
|
||||
"fieldname": "rating",
|
||||
"fieldtype": "Rating"
|
||||
},
|
||||
{
|
||||
"label": "Feedback",
|
||||
"fieldname": "feedback",
|
||||
"fieldtype": "Small Text"
|
||||
}])
|
||||
})
|
||||
settings.save()
|
||||
|
||||
def test_custom_doctype_medical_record(self):
|
||||
# tests for medical record creation of standard doctypes in test_patient_medical_record.py
|
||||
patient = create_patient()
|
||||
doc = create_doc(patient)
|
||||
|
||||
# check for medical record
|
||||
medical_rec = frappe.db.exists("Patient Medical Record", {"status": "Open", "reference_name": doc.name})
|
||||
self.assertTrue(medical_rec)
|
||||
|
||||
medical_rec = frappe.get_doc("Patient Medical Record", medical_rec)
|
||||
expected_subject = "<b>Date: </b>{0}<br><b>Rating: </b>3<br><b>Feedback: </b>Test Patient History Settings<br>".format(
|
||||
frappe.utils.format_date(getdate()))
|
||||
self.assertEqual(medical_rec.subject, expected_subject)
|
||||
self.assertEqual(medical_rec.patient, patient)
|
||||
self.assertEqual(medical_rec.communication_date, getdate())
|
||||
|
||||
|
||||
def create_custom_doctype():
|
||||
if not frappe.db.exists("DocType", "Test Patient Feedback"):
|
||||
doc = frappe.get_doc({
|
||||
"doctype": "DocType",
|
||||
"module": "Healthcare",
|
||||
"custom": 1,
|
||||
"is_submittable": 1,
|
||||
"fields": [{
|
||||
"label": "Date",
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"label": "Patient",
|
||||
"fieldname": "patient",
|
||||
"fieldtype": "Link",
|
||||
"options": "Patient"
|
||||
},
|
||||
{
|
||||
"label": "Rating",
|
||||
"fieldname": "rating",
|
||||
"fieldtype": "Rating"
|
||||
},
|
||||
{
|
||||
"label": "Feedback",
|
||||
"fieldname": "feedback",
|
||||
"fieldtype": "Small Text"
|
||||
}],
|
||||
"permissions": [{
|
||||
"role": "System Manager",
|
||||
"read": 1
|
||||
}],
|
||||
"name": "Test Patient Feedback",
|
||||
})
|
||||
doc.insert()
|
||||
return doc
|
||||
else:
|
||||
return frappe.get_doc("DocType", "Test Patient Feedback")
|
||||
|
||||
|
||||
def create_doc(patient):
|
||||
doc = frappe.get_doc({
|
||||
"doctype": "Test Patient Feedback",
|
||||
"patient": patient,
|
||||
"date": getdate(),
|
||||
"rating": 3,
|
||||
"feedback": "Test Patient History Settings"
|
||||
}).insert()
|
||||
doc.submit()
|
||||
|
||||
return doc
|
@ -0,0 +1,57 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-11-25 13:39:36.014814",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"document_type",
|
||||
"date_fieldname",
|
||||
"add_edit_fields",
|
||||
"selected_fields"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "document_type",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Document Type",
|
||||
"options": "DocType",
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "selected_fields",
|
||||
"fieldtype": "Code",
|
||||
"label": "Selected Fields",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "add_edit_fields",
|
||||
"fieldtype": "Button",
|
||||
"in_list_view": 1,
|
||||
"label": "Add / Edit Fields"
|
||||
},
|
||||
{
|
||||
"fieldname": "date_fieldname",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Date Fieldname",
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-30 13:54:56.773325",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Patient History Standard Document Type",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PatientHistoryStandardDocumentType(Document):
|
||||
pass
|
@ -18,6 +18,7 @@ class TestPatientMedicalRecord(unittest.TestCase):
|
||||
patient, medical_department, practitioner = create_healthcare_docs()
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), invoice=1)
|
||||
encounter = create_encounter(appointment)
|
||||
|
||||
# check for encounter
|
||||
medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': encounter.name})
|
||||
self.assertTrue(medical_rec)
|
||||
|
@ -41,7 +41,6 @@ class TherapySession(Document):
|
||||
|
||||
def on_submit(self):
|
||||
self.update_sessions_count_in_therapy_plan()
|
||||
insert_session_medical_record(self)
|
||||
|
||||
def on_update(self):
|
||||
if self.appointment:
|
||||
@ -142,23 +141,3 @@ def get_therapy_item(therapy, item):
|
||||
item.reference_dt = 'Therapy Session'
|
||||
item.reference_dn = therapy.name
|
||||
return item
|
||||
|
||||
|
||||
def insert_session_medical_record(doc):
|
||||
subject = frappe.bold(_('Therapy: ')) + cstr(doc.therapy_type) + '<br>'
|
||||
if doc.therapy_plan:
|
||||
subject += frappe.bold(_('Therapy Plan: ')) + cstr(doc.therapy_plan) + '<br>'
|
||||
if doc.practitioner:
|
||||
subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
|
||||
subject += frappe.bold(_('Total Counts Targeted: ')) + cstr(doc.total_counts_targeted) + '<br>'
|
||||
subject += frappe.bold(_('Total Counts Completed: ')) + cstr(doc.total_counts_completed) + '<br>'
|
||||
|
||||
medical_record = frappe.new_doc('Patient Medical Record')
|
||||
medical_record.patient = doc.patient
|
||||
medical_record.subject = subject
|
||||
medical_record.status = 'Open'
|
||||
medical_record.communication_date = doc.start_date
|
||||
medical_record.reference_doctype = 'Therapy Session'
|
||||
medical_record.reference_name = doc.name
|
||||
medical_record.reference_owner = doc.owner
|
||||
medical_record.save(ignore_permissions=True)
|
@ -12,47 +12,7 @@ class VitalSigns(Document):
|
||||
def validate(self):
|
||||
self.set_title()
|
||||
|
||||
def on_submit(self):
|
||||
insert_vital_signs_to_medical_record(self)
|
||||
|
||||
def on_cancel(self):
|
||||
delete_vital_signs_from_medical_record(self)
|
||||
|
||||
def set_title(self):
|
||||
self.title = _('{0} on {1}').format(self.patient_name or self.patient,
|
||||
frappe.utils.format_date(self.signs_date))[:100]
|
||||
|
||||
def insert_vital_signs_to_medical_record(doc):
|
||||
subject = set_subject_field(doc)
|
||||
medical_record = frappe.new_doc('Patient Medical Record')
|
||||
medical_record.patient = doc.patient
|
||||
medical_record.subject = subject
|
||||
medical_record.status = 'Open'
|
||||
medical_record.communication_date = doc.signs_date
|
||||
medical_record.reference_doctype = 'Vital Signs'
|
||||
medical_record.reference_name = doc.name
|
||||
medical_record.reference_owner = doc.owner
|
||||
medical_record.flags.ignore_mandatory = True
|
||||
medical_record.save(ignore_permissions=True)
|
||||
|
||||
def delete_vital_signs_from_medical_record(doc):
|
||||
medical_record = frappe.db.get_value('Patient Medical Record', {'reference_name': doc.name})
|
||||
if medical_record:
|
||||
frappe.delete_doc('Patient Medical Record', medical_record)
|
||||
|
||||
def set_subject_field(doc):
|
||||
subject = ''
|
||||
if doc.temperature:
|
||||
subject += frappe.bold(_('Temperature: ')) + cstr(doc.temperature) + '<br>'
|
||||
if doc.pulse:
|
||||
subject += frappe.bold(_('Pulse: ')) + cstr(doc.pulse) + '<br>'
|
||||
if doc.respiratory_rate:
|
||||
subject += frappe.bold(_('Respiratory Rate: ')) + cstr(doc.respiratory_rate) + '<br>'
|
||||
if doc.bp:
|
||||
subject += frappe.bold(_('BP: ')) + cstr(doc.bp) + '<br>'
|
||||
if doc.bmi:
|
||||
subject += frappe.bold(_('BMI: ')) + cstr(doc.bmi) + '<br>'
|
||||
if doc.nutrition_note:
|
||||
subject += frappe.bold(_('Note: ')) + cstr(doc.nutrition_note) + '<br>'
|
||||
|
||||
return subject
|
||||
|
@ -109,6 +109,11 @@
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.patient-history-filter {
|
||||
margin-left: 35px;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
#page-medical_record .plot-wrapper {
|
||||
padding: 20px 15px;
|
||||
border-bottom: 1px solid #d1d8dd;
|
||||
|
@ -1,6 +1,5 @@
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-3">
|
||||
<p class="text-center">{%= __("Select Patient") %}</p>
|
||||
<p class="patient" style="margin: auto; max-width: 300px; margin-bottom: 20px;"></p>
|
||||
<div class="patient_details" style="z-index=0"></div>
|
||||
</div>
|
||||
@ -11,6 +10,13 @@
|
||||
<div id="chart" class="col-sm-12 patient_vital_charts">
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-separator col-sm-12 d-flex border-bottom py-3" style="display:none"></div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 d-flex">
|
||||
<div class="patient-history-filter doctype-filter"></div>
|
||||
<div class="patient-history-filter date-filter"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 patient_documents_list">
|
||||
</div>
|
||||
<div class="col-sm-12 text-center py-3">
|
||||
|
@ -1,141 +1,225 @@
|
||||
frappe.provide("frappe.patient_history");
|
||||
frappe.provide('frappe.patient_history');
|
||||
frappe.pages['patient_history'].on_page_load = function(wrapper) {
|
||||
var me = this;
|
||||
var page = frappe.ui.make_app_page({
|
||||
let me = this;
|
||||
let page = frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Patient History',
|
||||
single_column: true
|
||||
});
|
||||
|
||||
frappe.breadcrumbs.add("Healthcare");
|
||||
frappe.breadcrumbs.add('Healthcare');
|
||||
let pid = '';
|
||||
page.main.html(frappe.render_template("patient_history", {}));
|
||||
var patient = frappe.ui.form.make_control({
|
||||
parent: page.main.find(".patient"),
|
||||
page.main.html(frappe.render_template('patient_history', {}));
|
||||
page.main.find('.header-separator').hide();
|
||||
|
||||
let patient = frappe.ui.form.make_control({
|
||||
parent: page.main.find('.patient'),
|
||||
df: {
|
||||
fieldtype: "Link",
|
||||
options: "Patient",
|
||||
fieldname: "patient",
|
||||
change: function(){
|
||||
if(pid != patient.get_value() && patient.get_value()){
|
||||
fieldtype: 'Link',
|
||||
options: 'Patient',
|
||||
fieldname: 'patient',
|
||||
placeholder: __('Select Patient'),
|
||||
only_select: true,
|
||||
change: function() {
|
||||
let patient_id = patient.get_value();
|
||||
if (pid != patient_id && patient_id) {
|
||||
me.start = 0;
|
||||
me.page.main.find(".patient_documents_list").html("");
|
||||
get_documents(patient.get_value(), me);
|
||||
show_patient_info(patient.get_value(), me);
|
||||
show_patient_vital_charts(patient.get_value(), me, "bp", "mmHg", "Blood Pressure");
|
||||
me.page.main.find('.patient_documents_list').html('');
|
||||
setup_filters(patient_id, me);
|
||||
get_documents(patient_id, me);
|
||||
show_patient_info(patient_id, me);
|
||||
show_patient_vital_charts(patient_id, me, 'bp', 'mmHg', 'Blood Pressure');
|
||||
}
|
||||
pid = patient.get_value();
|
||||
pid = patient_id;
|
||||
}
|
||||
},
|
||||
only_input: true,
|
||||
});
|
||||
patient.refresh();
|
||||
|
||||
if (frappe.route_options){
|
||||
if (frappe.route_options) {
|
||||
patient.set_value(frappe.route_options.patient);
|
||||
}
|
||||
|
||||
this.page.main.on("click", ".btn-show-chart", function() {
|
||||
var btn_show_id = $(this).attr("data-show-chart-id"), pts = $(this).attr("data-pts");
|
||||
var title = $(this).attr("data-title");
|
||||
this.page.main.on('click', '.btn-show-chart', function() {
|
||||
let btn_show_id = $(this).attr('data-show-chart-id'), pts = $(this).attr('data-pts');
|
||||
let title = $(this).attr('data-title');
|
||||
show_patient_vital_charts(patient.get_value(), me, btn_show_id, pts, title);
|
||||
});
|
||||
|
||||
this.page.main.on("click", ".btn-more", function() {
|
||||
var doctype = $(this).attr("data-doctype"), docname = $(this).attr("data-docname");
|
||||
if(me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched') == "1"){
|
||||
me.page.main.find("."+docname).hide();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').show();
|
||||
}else{
|
||||
if(doctype && docname){
|
||||
let exclude = ["patient", "patient_name", 'patient_sex', "encounter_date"];
|
||||
this.page.main.on('click', '.btn-more', function() {
|
||||
let doctype = $(this).attr('data-doctype'), docname = $(this).attr('data-docname');
|
||||
if (me.page.main.find('.'+docname).parent().find('.document-html').attr('data-fetched') == '1') {
|
||||
me.page.main.find('.'+docname).hide();
|
||||
me.page.main.find('.'+docname).parent().find('.document-html').show();
|
||||
} else {
|
||||
if (doctype && docname) {
|
||||
let exclude = ['patient', 'patient_name', 'patient_sex', 'encounter_date'];
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.utils.render_doc_as_html",
|
||||
method: 'erpnext.healthcare.utils.render_doc_as_html',
|
||||
args:{
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
exclude_fields: exclude
|
||||
},
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
if (r.message){
|
||||
me.page.main.find("."+docname).hide();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').html(r.message.html+"\
|
||||
<div align='center'><a class='btn octicon octicon-chevron-up btn-default btn-xs\
|
||||
btn-less' data-doctype='"+doctype+"' data-docname='"+docname+"'></a></div>");
|
||||
me.page.main.find("."+docname).parent().find('.document-html').show();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched', "1");
|
||||
if (r.message) {
|
||||
me.page.main.find('.' + docname).hide();
|
||||
|
||||
me.page.main.find('.' + docname).parent().find('.document-html').html(
|
||||
`${r.message.html}
|
||||
<div align='center'>
|
||||
<a class='btn octicon octicon-chevron-up btn-default btn-xs btn-less'
|
||||
data-doctype='${doctype}'
|
||||
data-docname='${docname}'>
|
||||
</a>
|
||||
</div>
|
||||
`);
|
||||
|
||||
me.page.main.find('.' + docname).parent().find('.document-html').show();
|
||||
me.page.main.find('.' + docname).parent().find('.document-html').attr('data-fetched', '1');
|
||||
}
|
||||
},
|
||||
freeze: true
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.page.main.on("click", ".btn-less", function() {
|
||||
var docname = $(this).attr("data-docname");
|
||||
me.page.main.find("."+docname).parent().find('.document-id').show();
|
||||
me.page.main.find("."+docname).parent().find('.document-html').hide();
|
||||
this.page.main.on('click', '.btn-less', function() {
|
||||
let docname = $(this).attr('data-docname');
|
||||
me.page.main.find('.' + docname).parent().find('.document-id').show();
|
||||
me.page.main.find('.' + docname).parent().find('.document-html').hide();
|
||||
});
|
||||
me.start = 0;
|
||||
me.page.main.on("click", ".btn-get-records", function(){
|
||||
me.page.main.on('click', '.btn-get-records', function() {
|
||||
get_documents(patient.get_value(), me);
|
||||
});
|
||||
};
|
||||
|
||||
var get_documents = function(patient, me){
|
||||
let setup_filters = function(patient, me) {
|
||||
$('.doctype-filter').empty();
|
||||
frappe.xcall(
|
||||
'erpnext.healthcare.page.patient_history.patient_history.get_patient_history_doctypes'
|
||||
).then(document_types => {
|
||||
let doctype_filter = frappe.ui.form.make_control({
|
||||
parent: $('.doctype-filter'),
|
||||
df: {
|
||||
fieldtype: 'MultiSelectList',
|
||||
fieldname: 'document_type',
|
||||
placeholder: __('Select Document Type'),
|
||||
input_class: 'input-xs',
|
||||
change: () => {
|
||||
me.start = 0;
|
||||
me.page.main.find('.patient_documents_list').html('');
|
||||
get_documents(patient, me, doctype_filter.get_value(), date_range_field.get_value());
|
||||
},
|
||||
get_data: () => {
|
||||
return document_types.map(document_type => {
|
||||
return {
|
||||
description: document_type,
|
||||
value: document_type
|
||||
};
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
doctype_filter.refresh();
|
||||
|
||||
$('.date-filter').empty();
|
||||
let date_range_field = frappe.ui.form.make_control({
|
||||
df: {
|
||||
fieldtype: 'DateRange',
|
||||
fieldname: 'date_range',
|
||||
placeholder: __('Date Range'),
|
||||
input_class: 'input-xs',
|
||||
change: () => {
|
||||
let selected_date_range = date_range_field.get_value();
|
||||
if (selected_date_range && selected_date_range.length === 2) {
|
||||
me.start = 0;
|
||||
me.page.main.find('.patient_documents_list').html('');
|
||||
get_documents(patient, me, doctype_filter.get_value(), selected_date_range);
|
||||
}
|
||||
}
|
||||
},
|
||||
parent: $('.date-filter')
|
||||
});
|
||||
date_range_field.refresh();
|
||||
});
|
||||
};
|
||||
|
||||
let get_documents = function(patient, me, document_types="", selected_date_range="") {
|
||||
let filters = {
|
||||
name: patient,
|
||||
start: me.start,
|
||||
page_length: 20
|
||||
};
|
||||
if (document_types)
|
||||
filters['document_types'] = document_types;
|
||||
if (selected_date_range)
|
||||
filters['date_range'] = selected_date_range;
|
||||
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.page.patient_history.patient_history.get_feed",
|
||||
args: {
|
||||
name: patient,
|
||||
start: me.start,
|
||||
page_length: 20
|
||||
},
|
||||
callback: function (r) {
|
||||
var data = r.message;
|
||||
if(data.length){
|
||||
'method': 'erpnext.healthcare.page.patient_history.patient_history.get_feed',
|
||||
args: filters,
|
||||
callback: function(r) {
|
||||
let data = r.message;
|
||||
if (data.length) {
|
||||
add_to_records(me, data);
|
||||
}else{
|
||||
me.page.main.find(".patient_documents_list").append("<div class='text-muted' align='center'><br><br>No more records..<br><br></div>");
|
||||
me.page.main.find(".btn-get-records").hide();
|
||||
} else {
|
||||
me.page.main.find('.patient_documents_list').append(`
|
||||
<div class='text-muted' align='center'>
|
||||
<br><br>${__('No more records..')}<br><br>
|
||||
</div>`);
|
||||
me.page.main.find('.btn-get-records').hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var add_to_records = function(me, data){
|
||||
var details = "<ul class='nav nav-pills nav-stacked'>";
|
||||
var i;
|
||||
for(i=0; i<data.length; i++){
|
||||
if(data[i].reference_doctype){
|
||||
let add_to_records = function(me, data) {
|
||||
let details = "<ul class='nav nav-pills nav-stacked'>";
|
||||
let i;
|
||||
for (i=0; i<data.length; i++) {
|
||||
if (data[i].reference_doctype) {
|
||||
let label = '';
|
||||
if(data[i].subject){
|
||||
label += "<br/>"+data[i].subject;
|
||||
if (data[i].subject) {
|
||||
label += "<br/>" + data[i].subject;
|
||||
}
|
||||
data[i] = add_date_separator(data[i]);
|
||||
if(frappe.user_info(data[i].owner).image){
|
||||
|
||||
if (frappe.user_info(data[i].owner).image) {
|
||||
data[i].imgsrc = frappe.utils.get_file_link(frappe.user_info(data[i].owner).image);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
data[i].imgsrc = false;
|
||||
}
|
||||
var time_line_heading = data[i].practitioner ? `${data[i].practitioner} ` : ``;
|
||||
time_line_heading += data[i].reference_doctype + " - "+ data[i].reference_name;
|
||||
details += `<li data-toggle='pill' class='patient_doc_menu'
|
||||
data-doctype='${data[i].reference_doctype}' data-docname='${data[i].reference_name}'>
|
||||
<div class='col-sm-12 d-flex border-bottom py-3'>`;
|
||||
if (data[i].imgsrc){
|
||||
details += `<span class='mr-3'>
|
||||
<img class='avtar' src='${data[i].imgsrc}' width='32' height='32'>
|
||||
</img>
|
||||
</span>`;
|
||||
}else{
|
||||
details += `<span class='mr-3 avatar avatar-small' style='width:32px; height:32px;'><div align='center' class='standard-image'
|
||||
style='background-color: #fafbfc;'>${data[i].practitioner ? data[i].practitioner.charAt(0) : "U"}</div></span>`;
|
||||
|
||||
let time_line_heading = data[i].practitioner ? `${data[i].practitioner} ` : ``;
|
||||
time_line_heading += data[i].reference_doctype + " - " +
|
||||
`<a onclick="frappe.set_route('Form', '${data[i].reference_doctype}', '${data[i].reference_name}');">
|
||||
${data[i].reference_name}
|
||||
</a>`;
|
||||
|
||||
details += `
|
||||
<li data-toggle='pill' class='patient_doc_menu'
|
||||
data-doctype='${data[i].reference_doctype}' data-docname='${data[i].reference_name}'>
|
||||
<div class='col-sm-12 d-flex border-bottom py-3'>`;
|
||||
|
||||
if (data[i].imgsrc) {
|
||||
details += `
|
||||
<span class='mr-3'>
|
||||
<img class='avtar' src='${data[i].imgsrc}' width='32' height='32'></img>
|
||||
</span>`;
|
||||
} else {
|
||||
details += `<span class='mr-3 avatar avatar-small' style='width:32px; height:32px;'>
|
||||
<div align='center' class='standard-image' style='background-color: #fafbfc;'>
|
||||
${data[i].practitioner ? data[i].practitioner.charAt(0) : 'U'}
|
||||
</div>
|
||||
</span>`;
|
||||
}
|
||||
|
||||
details += `<div class='d-flex flex-column width-full'>
|
||||
<div>
|
||||
`+time_line_heading+` on
|
||||
`+time_line_heading+`
|
||||
<span>
|
||||
${data[i].date_sep}
|
||||
</span>
|
||||
@ -156,133 +240,150 @@ var add_to_records = function(me, data){
|
||||
</li>`;
|
||||
}
|
||||
}
|
||||
details += "</ul>";
|
||||
me.page.main.find(".patient_documents_list").append(details);
|
||||
|
||||
details += '</ul>';
|
||||
me.page.main.find('.patient_documents_list').append(details);
|
||||
me.start += data.length;
|
||||
if(data.length===20){
|
||||
|
||||
if (data.length === 20) {
|
||||
me.page.main.find(".btn-get-records").show();
|
||||
}else{
|
||||
} else {
|
||||
me.page.main.find(".btn-get-records").hide();
|
||||
me.page.main.find(".patient_documents_list").append("<div class='text-muted' align='center'><br><br>No more records..<br><br></div>");
|
||||
me.page.main.find(".patient_documents_list").append(`
|
||||
<div class='text-muted' align='center'>
|
||||
<br><br>${__('No more records..')}<br><br>
|
||||
</div>`);
|
||||
}
|
||||
};
|
||||
|
||||
var add_date_separator = function(data) {
|
||||
var date = frappe.datetime.str_to_obj(data.creation);
|
||||
let add_date_separator = function(data) {
|
||||
let date = frappe.datetime.str_to_obj(data.communication_date);
|
||||
let pdate = '';
|
||||
let diff = frappe.datetime.get_day_diff(frappe.datetime.get_today(), frappe.datetime.obj_to_str(date));
|
||||
|
||||
var diff = frappe.datetime.get_day_diff(frappe.datetime.get_today(), frappe.datetime.obj_to_str(date));
|
||||
if(diff < 1) {
|
||||
var pdate = 'Today';
|
||||
} else if(diff < 2) {
|
||||
pdate = 'Yesterday';
|
||||
if (diff < 1) {
|
||||
pdate = __('Today');
|
||||
} else if (diff < 2) {
|
||||
pdate = __('Yesterday');
|
||||
} else {
|
||||
pdate = frappe.datetime.global_date_format(date);
|
||||
pdate = __('on ') + frappe.datetime.global_date_format(date);
|
||||
}
|
||||
data.date_sep = pdate;
|
||||
return data;
|
||||
};
|
||||
|
||||
var show_patient_info = function(patient, me){
|
||||
let show_patient_info = function(patient, me) {
|
||||
frappe.call({
|
||||
"method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
|
||||
'method': 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
|
||||
args: {
|
||||
patient: patient
|
||||
},
|
||||
callback: function (r) {
|
||||
var data = r.message;
|
||||
var details = "";
|
||||
if(data.image){
|
||||
details += "<div><img class='thumbnail' width=75% src='"+data.image+"'></div>";
|
||||
callback: function(r) {
|
||||
let data = r.message;
|
||||
let details = '';
|
||||
if (data.image) {
|
||||
details += `<div><img class='thumbnail' width=75% src='${data.image}'></div>`;
|
||||
}
|
||||
details += "<b>" + data.patient_name +"</b><br>" + data.sex;
|
||||
if(data.email) details += "<br>" + data.email;
|
||||
if(data.mobile) details += "<br>" + data.mobile;
|
||||
if(data.occupation) details += "<br><br><b>Occupation :</b> " + data.occupation;
|
||||
if(data.blood_group) details += "<br><b>Blood group : </b> " + data.blood_group;
|
||||
if(data.allergies) details += "<br><br><b>Allergies : </b> "+ data.allergies.replace("\n", "<br>");
|
||||
if(data.medication) details += "<br><b>Medication : </b> "+ data.medication.replace("\n", "<br>");
|
||||
if(data.alcohol_current_use) details += "<br><br><b>Alcohol use : </b> "+ data.alcohol_current_use;
|
||||
if(data.alcohol_past_use) details += "<br><b>Alcohol past use : </b> "+ data.alcohol_past_use;
|
||||
if(data.tobacco_current_use) details += "<br><b>Tobacco use : </b> "+ data.tobacco_current_use;
|
||||
if(data.tobacco_past_use) details += "<br><b>Tobacco past use : </b> "+ data.tobacco_past_use;
|
||||
if(data.medical_history) details += "<br><br><b>Medical history : </b> "+ data.medical_history.replace("\n", "<br>");
|
||||
if(data.surgical_history) details += "<br><b>Surgical history : </b> "+ data.surgical_history.replace("\n", "<br>");
|
||||
if(data.surrounding_factors) details += "<br><br><b>Occupational hazards : </b> "+ data.surrounding_factors.replace("\n", "<br>");
|
||||
if(data.other_risk_factors) details += "<br><b>Other risk factors : </b> " + data.other_risk_factors.replace("\n", "<br>");
|
||||
if(data.patient_details) details += "<br><br><b>More info : </b> " + data.patient_details.replace("\n", "<br>");
|
||||
|
||||
if(details){
|
||||
details = "<div style='padding-left:10px; font-size:13px;' align='center'>" + details + "</div>";
|
||||
details += `<b> ${data.patient_name} </b><br> ${data.sex}`;
|
||||
if (data.email) details += `<br> ${data.email}`;
|
||||
if (data.mobile) details += `<br> ${data.mobile}`;
|
||||
if (data.occupation) details += `<br><br><b> ${__('Occupation')} : </b> ${data.occupation}`;
|
||||
if (data.blood_group) details += `<br><b> ${__('Blood Group')} : </b> ${data.blood_group}`;
|
||||
if (data.allergies) details += `<br><br><b> ${__('Allerigies')} : </b> ${data.allergies.replace("\n", ", ")}`;
|
||||
if (data.medication) details += `<br><b> ${__('Medication')} : </b> ${data.medication.replace("\n", ", ")}`;
|
||||
if (data.alcohol_current_use) details += `<br><br><b> ${__('Alcohol use')} : </b> ${data.alcohol_current_use}`;
|
||||
if (data.alcohol_past_use) details += `<br><b> ${__('Alcohol past use')} : </b> ${data.alcohol_past_use}`;
|
||||
if (data.tobacco_current_use) details += `<br><b> ${__('Tobacco use')} : </b> ${data.tobacco_current_use}`;
|
||||
if (data.tobacco_past_use) details += `<br><b> ${__('Tobacco past use')} : </b> ${data.tobacco_past_use}`;
|
||||
if (data.medical_history) details += `<br><br><b> ${__('Medical history')} : </b> ${data.medical_history.replace("\n", ", ")}`;
|
||||
if (data.surgical_history) details += `<br><b> ${__('Surgical history')} : </b> ${data.surgical_history.replace("\n", ", ")}`;
|
||||
if (data.surrounding_factors) details += `<br><br><b> ${__('Occupational hazards')} : </b> ${data.surrounding_factors.replace("\n", ", ")}`;
|
||||
if (data.other_risk_factors) details += `<br><b> ${__('Other risk factors')} : </b> ${data.other_risk_factors.replace("\n", ", ")}`;
|
||||
if (data.patient_details) details += `<br><br><b> ${__('More info')} : </b> ${data.patient_details.replace("\n", ", ")}`;
|
||||
|
||||
if (details) {
|
||||
details = `<div style='padding-left:10px; font-size:13px;' align='left'>` + details + `</div>`;
|
||||
}
|
||||
me.page.main.find(".patient_details").html(details);
|
||||
me.page.main.find('.patient_details').html(details);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var show_patient_vital_charts = function(patient, me, btn_show_id, pts, title) {
|
||||
let show_patient_vital_charts = function(patient, me, btn_show_id, pts, title) {
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.utils.get_patient_vitals",
|
||||
method: 'erpnext.healthcare.utils.get_patient_vitals',
|
||||
args:{
|
||||
patient: patient
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message){
|
||||
var show_chart_btns_html = "<div style='padding-top:5px;'><a class='btn btn-default btn-xs btn-show-chart' \
|
||||
data-show-chart-id='bp' data-pts='mmHg' data-title='Blood Pressure'>Blood Pressure</a>\
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='pulse_rate' \
|
||||
data-pts='per Minutes' data-title='Respiratory/Pulse Rate'>Respiratory/Pulse Rate</a>\
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='temperature' \
|
||||
data-pts='°C or °F' data-title='Temperature'>Temperature</a>\
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='bmi' \
|
||||
data-pts='' data-title='BMI'>BMI</a></div>";
|
||||
me.page.main.find(".show_chart_btns").html(show_chart_btns_html);
|
||||
var data = r.message;
|
||||
if (r.message) {
|
||||
let show_chart_btns_html = `
|
||||
<div style='padding-top:10px;'>
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='bp' data-pts='mmHg' data-title='Blood Pressure'>
|
||||
${__('Blood Pressure')}
|
||||
</a>
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='pulse_rate' data-pts='per Minutes' data-title='Respiratory/Pulse Rate'>
|
||||
${__('Respiratory/Pulse Rate')}
|
||||
</a>
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='temperature' data-pts='°C or °F' data-title='Temperature'>
|
||||
${__('Temperature')}
|
||||
</a>
|
||||
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='bmi' data-pts='' data-title='BMI'>
|
||||
${__('BMI')}
|
||||
</a>
|
||||
</div>`;
|
||||
|
||||
me.page.main.find('.show_chart_btns').html(show_chart_btns_html);
|
||||
let data = r.message;
|
||||
let labels = [], datasets = [];
|
||||
let bp_systolic = [], bp_diastolic = [], temperature = [];
|
||||
let pulse = [], respiratory_rate = [], bmi = [], height = [], weight = [];
|
||||
for(var i=0; i<data.length; i++){
|
||||
labels.push(data[i].signs_date+"||"+data[i].signs_time);
|
||||
if(btn_show_id=="bp"){
|
||||
|
||||
for (let i=0; i<data.length; i++) {
|
||||
labels.push(data[i].signs_date+'||'+data[i].signs_time);
|
||||
|
||||
if (btn_show_id === 'bp') {
|
||||
bp_systolic.push(data[i].bp_systolic);
|
||||
bp_diastolic.push(data[i].bp_diastolic);
|
||||
}
|
||||
if(btn_show_id=="temperature"){
|
||||
if (btn_show_id === 'temperature') {
|
||||
temperature.push(data[i].temperature);
|
||||
}
|
||||
if(btn_show_id=="pulse_rate"){
|
||||
if (btn_show_id === 'pulse_rate') {
|
||||
pulse.push(data[i].pulse);
|
||||
respiratory_rate.push(data[i].respiratory_rate);
|
||||
}
|
||||
if(btn_show_id=="bmi"){
|
||||
if (btn_show_id === 'bmi') {
|
||||
bmi.push(data[i].bmi);
|
||||
height.push(data[i].height);
|
||||
weight.push(data[i].weight);
|
||||
}
|
||||
}
|
||||
if(btn_show_id=="temperature"){
|
||||
datasets.push({name: "Temperature", values: temperature, chartType:'line'});
|
||||
if (btn_show_id === 'temperature') {
|
||||
datasets.push({name: 'Temperature', values: temperature, chartType: 'line'});
|
||||
}
|
||||
if(btn_show_id=="bmi"){
|
||||
datasets.push({name: "BMI", values: bmi, chartType:'line'});
|
||||
datasets.push({name: "Height", values: height, chartType:'line'});
|
||||
datasets.push({name: "Weight", values: weight, chartType:'line'});
|
||||
if (btn_show_id === 'bmi') {
|
||||
datasets.push({name: 'BMI', values: bmi, chartType: 'line'});
|
||||
datasets.push({name: 'Height', values: height, chartType: 'line'});
|
||||
datasets.push({name: 'Weight', values: weight, chartType: 'line'});
|
||||
}
|
||||
if(btn_show_id=="bp"){
|
||||
datasets.push({name: "BP Systolic", values: bp_systolic, chartType:'line'});
|
||||
datasets.push({name: "BP Diastolic", values: bp_diastolic, chartType:'line'});
|
||||
if (btn_show_id === 'bp') {
|
||||
datasets.push({name: 'BP Systolic', values: bp_systolic, chartType: 'line'});
|
||||
datasets.push({name: 'BP Diastolic', values: bp_diastolic, chartType: 'line'});
|
||||
}
|
||||
if(btn_show_id=="pulse_rate"){
|
||||
datasets.push({name: "Heart Rate / Pulse", values: pulse, chartType:'line'});
|
||||
datasets.push({name: "Respiratory Rate", values: respiratory_rate, chartType:'line'});
|
||||
if (btn_show_id === 'pulse_rate') {
|
||||
datasets.push({name: 'Heart Rate / Pulse', values: pulse, chartType: 'line'});
|
||||
datasets.push({name: 'Respiratory Rate', values: respiratory_rate, chartType: 'line'});
|
||||
}
|
||||
new frappe.Chart( ".patient_vital_charts", {
|
||||
new frappe.Chart('.patient_vital_charts', {
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: datasets
|
||||
},
|
||||
|
||||
title: title,
|
||||
type: 'axis-mixed', // 'axis-mixed', 'bar', 'line', 'pie', 'percentage'
|
||||
type: 'axis-mixed',
|
||||
height: 200,
|
||||
colors: ['purple', '#ffa3ef', 'light-blue'],
|
||||
|
||||
@ -291,9 +392,11 @@ var show_patient_vital_charts = function(patient, me, btn_show_id, pts, title) {
|
||||
formatTooltipY: d => d + ' ' + pts,
|
||||
}
|
||||
});
|
||||
}else{
|
||||
me.page.main.find(".patient_vital_charts").html("");
|
||||
me.page.main.find(".show_chart_btns").html("");
|
||||
me.page.main.find('.header-separator').show();
|
||||
} else {
|
||||
me.page.main.find('.patient_vital_charts').html('');
|
||||
me.page.main.find('.show_chart_btns').html('');
|
||||
me.page.main.find('.header-separator').hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -4,36 +4,70 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import json
|
||||
from frappe.utils import cint
|
||||
from erpnext.healthcare.utils import render_docs_as_html
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_feed(name, start=0, page_length=20):
|
||||
def get_feed(name, document_types=None, date_range=None, start=0, page_length=20):
|
||||
"""get feed"""
|
||||
result = frappe.db.sql("""select name, owner, creation,
|
||||
reference_doctype, reference_name, subject
|
||||
from `tabPatient Medical Record`
|
||||
where patient=%(patient)s
|
||||
order by creation desc
|
||||
limit %(start)s, %(page_length)s""",
|
||||
{
|
||||
"patient": name,
|
||||
"start": cint(start),
|
||||
"page_length": cint(page_length)
|
||||
}, as_dict=True)
|
||||
filters = get_filters(name, document_types, date_range)
|
||||
|
||||
result = frappe.db.get_all('Patient Medical Record',
|
||||
fields=['name', 'owner', 'communication_date',
|
||||
'reference_doctype', 'reference_name', 'subject'],
|
||||
filters=filters,
|
||||
order_by='communication_date DESC',
|
||||
limit=cint(page_length),
|
||||
start=cint(start)
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_filters(name, document_types=None, date_range=None):
|
||||
filters = {'patient': name}
|
||||
if document_types:
|
||||
document_types = json.loads(document_types)
|
||||
if len(document_types):
|
||||
filters['reference_doctype'] = ['IN', document_types]
|
||||
|
||||
if date_range:
|
||||
try:
|
||||
date_range = json.loads(date_range)
|
||||
if date_range:
|
||||
filters['communication_date'] = ['between', [date_range[0], date_range[1]]]
|
||||
except json.decoder.JSONDecodeError:
|
||||
pass
|
||||
|
||||
return filters
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_feed_for_dt(doctype, docname):
|
||||
"""get feed"""
|
||||
result = frappe.db.sql("""select name, owner, modified, creation,
|
||||
reference_doctype, reference_name, subject
|
||||
from `tabPatient Medical Record`
|
||||
where reference_name=%(docname)s and reference_doctype=%(doctype)s
|
||||
order by creation desc""",
|
||||
{
|
||||
"docname": docname,
|
||||
"doctype": doctype
|
||||
}, as_dict=True)
|
||||
result = frappe.db.get_all('Patient Medical Record',
|
||||
fields=['name', 'owner', 'communication_date',
|
||||
'reference_doctype', 'reference_name', 'subject'],
|
||||
filters={
|
||||
'reference_doctype': doctype,
|
||||
'reference_name': docname
|
||||
},
|
||||
order_by='communication_date DESC'
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_patient_history_doctypes():
|
||||
document_types = []
|
||||
settings = frappe.get_single("Patient History Settings")
|
||||
|
||||
for entry in settings.standard_doctypes:
|
||||
document_types.append(entry.document_type)
|
||||
|
||||
for entry in settings.custom_doctypes:
|
||||
document_types.append(entry.document_type)
|
||||
|
||||
return document_types
|
||||
|
@ -16,6 +16,7 @@ def setup_healthcare():
|
||||
create_healthcare_item_groups()
|
||||
create_sensitivity()
|
||||
add_healthcare_service_unit_tree_root()
|
||||
setup_patient_history_settings()
|
||||
|
||||
def create_medical_departments():
|
||||
departments = [
|
||||
@ -213,3 +214,82 @@ def get_company():
|
||||
if company:
|
||||
return company[0].name
|
||||
return None
|
||||
|
||||
def setup_patient_history_settings():
|
||||
import json
|
||||
|
||||
settings = frappe.get_single('Patient History Settings')
|
||||
configuration = get_patient_history_config()
|
||||
for dt, config in configuration.items():
|
||||
settings.append("standard_doctypes", {
|
||||
"document_type": dt,
|
||||
"date_fieldname": config[0],
|
||||
"selected_fields": json.dumps(config[1])
|
||||
})
|
||||
settings.save()
|
||||
|
||||
def get_patient_history_config():
|
||||
return {
|
||||
"Patient Encounter": ("encounter_date", [
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Symptoms", "fieldname": "symptoms", "fieldtype": "Table Multiselect"},
|
||||
{"label": "Diagnosis", "fieldname": "diagnosis", "fieldtype": "Table Multiselect"},
|
||||
{"label": "Drug Prescription", "fieldname": "drug_prescription", "fieldtype": "Table"},
|
||||
{"label": "Lab Tests", "fieldname": "lab_test_prescription", "fieldtype": "Table"},
|
||||
{"label": "Clinical Procedures", "fieldname": "procedure_prescription", "fieldtype": "Table"},
|
||||
{"label": "Therapies", "fieldname": "therapies", "fieldtype": "Table"},
|
||||
{"label": "Review Details", "fieldname": "encounter_comment", "fieldtype": "Small Text"}
|
||||
]),
|
||||
"Clinical Procedure": ("start_date", [
|
||||
{"label": "Procedure Template", "fieldname": "procedure_template", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Notes", "fieldname": "notes", "fieldtype": "Small Text"},
|
||||
{"label": "Service Unit", "fieldname": "service_unit", "fieldtype": "Healthcare Service Unit"},
|
||||
{"label": "Start Time", "fieldname": "start_time", "fieldtype": "Time"},
|
||||
{"label": "Sample", "fieldname": "sample", "fieldtype": "Link"}
|
||||
]),
|
||||
"Lab Test": ("result_date", [
|
||||
{"label": "Test Template", "fieldname": "template", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Test Name", "fieldname": "lab_test_name", "fieldtype": "Data"},
|
||||
{"label": "Lab Technician Name", "fieldname": "employee_name", "fieldtype": "Data"},
|
||||
{"label": "Sample ID", "fieldname": "sample", "fieldtype": "Link"},
|
||||
{"label": "Normal Test Result", "fieldname": "normal_test_items", "fieldtype": "Table"},
|
||||
{"label": "Descriptive Test Result", "fieldname": "descriptive_test_items", "fieldtype": "Table"},
|
||||
{"label": "Organism Test Result", "fieldname": "organism_test_items", "fieldtype": "Table"},
|
||||
{"label": "Sensitivity Test Result", "fieldname": "sensitivity_test_items", "fieldtype": "Table"},
|
||||
{"label": "Comments", "fieldname": "lab_test_comment", "fieldtype": "Table"}
|
||||
]),
|
||||
"Therapy Session": ("start_date", [
|
||||
{"label": "Therapy Type", "fieldname": "therapy_type", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Therapy Plan", "fieldname": "therapy_plan", "fieldtype": "Link"},
|
||||
{"label": "Duration", "fieldname": "duration", "fieldtype": "Int"},
|
||||
{"label": "Location", "fieldname": "location", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Service Unit", "fieldname": "service_unit", "fieldtype": "Link"},
|
||||
{"label": "Start Time", "fieldname": "start_time", "fieldtype": "Time"},
|
||||
{"label": "Exercises", "fieldname": "exercises", "fieldtype": "Table"},
|
||||
{"label": "Total Counts Targeted", "fieldname": "total_counts_targeted", "fieldtype": "Int"},
|
||||
{"label": "Total Counts Completed", "fieldname": "total_counts_completed", "fieldtype": "Int"}
|
||||
]),
|
||||
"Vital Signs": ("signs_date", [
|
||||
{"label": "Body Temperature", "fieldname": "temperature", "fieldtype": "Data"},
|
||||
{"label": "Heart Rate / Pulse", "fieldname": "pulse", "fieldtype": "Data"},
|
||||
{"label": "Respiratory rate", "fieldname": "respiratory_rate", "fieldtype": "Data"},
|
||||
{"label": "Tongue", "fieldname": "tongue", "fieldtype": "Select"},
|
||||
{"label": "Abdomen", "fieldname": "abdomen", "fieldtype": "Select"},
|
||||
{"label": "Reflexes", "fieldname": "reflexes", "fieldtype": "Select"},
|
||||
{"label": "Blood Pressure", "fieldname": "bp", "fieldtype": "Data"},
|
||||
{"label": "Notes", "fieldname": "vital_signs_note", "fieldtype": "Small Text"},
|
||||
{"label": "Height (In Meter)", "fieldname": "height", "fieldtype": "Float"},
|
||||
{"label": "Weight (In Kilogram)", "fieldname": "weight", "fieldtype": "Float"},
|
||||
{"label": "BMI", "fieldname": "bmi", "fieldtype": "Float"}
|
||||
]),
|
||||
"Inpatient Medication Order": ("start_date", [
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Start Date", "fieldname": "start_date", "fieldtype": "Date"},
|
||||
{"label": "End Date", "fieldname": "end_date", "fieldtype": "Date"},
|
||||
{"label": "Medication Orders", "fieldname": "medication_orders", "fieldtype": "Table"},
|
||||
{"label": "Total Orders", "fieldname": "total_orders", "fieldtype": "Float"}
|
||||
])
|
||||
}
|
@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
||||
import math
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils.formatters import format_value
|
||||
from frappe.utils import time_diff_in_hours, rounded
|
||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account
|
||||
from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity
|
||||
@ -648,11 +649,15 @@ def render_doc_as_html(doctype, docname, exclude_fields = []):
|
||||
html += "<table class='table table-condensed table-bordered'>" \
|
||||
+ table_head + table_row + "</table>"
|
||||
continue
|
||||
|
||||
#on other field types add label and value to html
|
||||
if not df.hidden and not df.print_hide and doc.get(df.fieldname) and df.fieldname not in exclude_fields:
|
||||
html += '<br>{0} : {1}'.format(df.label or df.fieldname, \
|
||||
doc.get(df.fieldname))
|
||||
if doc.get(df.fieldname):
|
||||
formatted_value = format_value(doc.get(df.fieldname), meta.get_field(df.fieldname), doc)
|
||||
html += '<br>{0} : {1}'.format(df.label or df.fieldname, formatted_value)
|
||||
|
||||
if not has_data : has_data = True
|
||||
|
||||
if sec_on and col_on and has_data:
|
||||
doc_html += section_html + html + '</div></div>'
|
||||
elif sec_on and not col_on and has_data:
|
||||
|
@ -221,6 +221,11 @@ standard_queries = {
|
||||
}
|
||||
|
||||
doc_events = {
|
||||
"*": {
|
||||
"on_submit": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.create_medical_record",
|
||||
"on_update_after_submit": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.update_medical_record",
|
||||
"on_cancel": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.delete_medical_record"
|
||||
},
|
||||
"Stock Entry": {
|
||||
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
|
||||
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty"
|
||||
|
@ -746,3 +746,4 @@ erpnext.patches.v13_0.update_returned_qty_in_pr_dn
|
||||
erpnext.patches.v13_0.update_project_template_tasks
|
||||
erpnext.patches.v13_0.set_company_in_leave_ledger_entry
|
||||
erpnext.patches.v13_0.convert_qi_parameter_to_link_field
|
||||
erpnext.patches.v13_0.setup_patient_history_settings_for_standard_doctypes
|
||||
|
@ -0,0 +1,13 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.healthcare.setup import setup_patient_history_settings
|
||||
|
||||
def execute():
|
||||
if "Healthcare" not in frappe.get_active_domains():
|
||||
return
|
||||
|
||||
frappe.reload_doc("healthcare", "doctype", "Patient History Settings")
|
||||
frappe.reload_doc("healthcare", "doctype", "Patient History Standard Document Type")
|
||||
frappe.reload_doc("healthcare", "doctype", "Patient History Custom Document Type")
|
||||
|
||||
setup_patient_history_settings()
|
Loading…
x
Reference in New Issue
Block a user