Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
def14f1
fix: uom conversion factor default to 1
akurungadam May 20, 2026
87daac2
fix: as per upstream changes
akurungadam May 22, 2026
acd4792
fix: allow ip occupancy billing at zero price list rate
akurungadam May 22, 2026
7d15e85
fix: failing tests, add currency to ItemDetailsCtx
akurungadam May 23, 2026
d9f3d7c
fix: merge conflicts
akurungadam May 30, 2026
c233629
fix: merge conflicts
akurungadam May 30, 2026
9e3fc1d
fix: resolve type hint issue in make_material_receipt submit parameter
Sajinsr Jun 2, 2026
6c35941
fix: exclude OT service unit types from normal inpatient transfer
md-umair-21 May 26, 2026
43f8037
chore: add test service unit for ip
akurungadam May 21, 2026
231872c
refactor: make tests for ip deterministic
akurungadam May 21, 2026
832fcd6
fix: fetch service unit type item code from linked item code
md-umair-21 Jun 6, 2026
f35128a
feat(healthcare): prevent future DOB selection for patients
Sreeragtv007 Jun 9, 2026
1b1bd28
fix(healthcare): restrict service request order template type to sele…
md-umair-21 Jun 12, 2026
46f25f8
fix(insurance): restrict DocType creation from item insurance eligibi…
md-umair-21 Jun 13, 2026
b563190
refactor: remove use of deprecated cur_frm
akurungadam Jun 14, 2026
a1da9a5
fix: accept data kwarg in dashboard get_data() for Frappe v15 compati…
rtmalikian Jun 18, 2026
750b80b
refactor: use get_terms_and_conditions for Observation result templates
akurungadam Jun 14, 2026
3937534
fix: set permissions for observation
akurungadam Jun 15, 2026
586caef
feat: add Triage Level and Emergency Recrod
akurungadam Jun 15, 2026
a98216b
feat: record vitals form emrgency record,
akurungadam Jun 15, 2026
59d5972
feat: triage indicators on healthcare doctypes
akurungadam Jun 15, 2026
5d931db
chore: link emergency record in all healthcare services doctypes
akurungadam Jun 15, 2026
25c25fb
fix: patch to create new masters (triage level, observation templates…
akurungadam Jun 15, 2026
f8f2889
feat: emergency triage queue report
akurungadam Jun 16, 2026
7c02802
fix: show vitals recent first
akurungadam Jun 16, 2026
7f98d5a
feat(tests): tests for emergency
akurungadam Jun 16, 2026
41ab005
feat: emergency workspace
akurungadam Jun 16, 2026
137ec55
feat: emergency consultation billing
akurungadam Jun 16, 2026
c07beec
feat: billing emergency occupancy
akurungadam Jun 16, 2026
3954284
feat: billing emergency record via Get Items in Sales Invoice
akurungadam Jun 16, 2026
a0b5c1b
feat: Send to Emergency buttons
akurungadam Jun 16, 2026
356fa27
fix: triage level indicator in Patient form
akurungadam Jun 16, 2026
445a614
feat: emergency record list view
akurungadam Jun 17, 2026
05c96d6
chore: add type hints to get_healthcare_services_to_invoice
akurungadam Jun 17, 2026
40a9253
chore: add type hints
akurungadam Jun 17, 2026
740328d
fix: escape all fields before HTML insertion
akurungadam Jun 17, 2026
62ed4e6
fix: raise-condition on bed assignment
akurungadam Jun 17, 2026
fa00517
fix: inconsistent occupancy_qty logic
akurungadam Jun 17, 2026
f34f73a
fix: avoid negative minutes for future arrival_datetime
akurungadam Jun 17, 2026
f6b0951
fix: clear stale dashboard headline when triage is absent or fetch fails
akurungadam Jun 17, 2026
a724724
fix: keep seeded triage identifiers locale-stable
akurungadam Jun 17, 2026
6dc6976
fix: implement fetch from patient for emergency_record in all healthc…
akurungadam Jun 17, 2026
6c29631
fix: handle unidetifiable patient
akurungadam Jun 18, 2026
b84f143
fix: add tests
akurungadam Jun 18, 2026
39ed4b6
feat: button to identify patient
akurungadam Jun 18, 2026
23e1ac1
fix: add validation to cehck if same Item is linked with other servic…
akurungadam Jun 21, 2026
52806ce
chore: bump version to 16.2.0
Sajinsr Jun 21, 2026
487fdec
fix: department/service unit filter
akurungadam Jun 24, 2026
6c0e4b4
fix(reference-range): show reference range "To" field for observation…
md-umair-21 Jun 24, 2026
a8e4b97
fix: payments app version
akurungadam Jun 25, 2026
cb1f134
fix: api to check in an appointment
akurungadam Jun 26, 2026
8d4bb0b
fix: api to check-in an appointment
akurungadam Jun 26, 2026
b41cc39
fix: add tests for check-in api
akurungadam Jun 26, 2026
08e323c
fix: appointment status
akurungadam Jun 26, 2026
c76c0b3
fix: add missing type hints
akurungadam Jun 26, 2026
8d24912
fix(Sample Collection): fetch reference_doc when linking sales invoic…
syedirfan33 Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/helper/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ sed -i 's/schedule:/# schedule:/g' Procfile
sed -i 's/socketio:/# socketio:/g' Procfile
sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile

bench get-app payments
bench get-app payments --branch "${branchtoclone}"
bench get-app https://github.com/frappe/erpnext --branch "${branchtoclone}"
bench get-app healthcare "${GITHUB_WORKSPACE}"

Expand Down
2 changes: 1 addition & 1 deletion healthcare/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "16.1.1"
__version__ = "16.2.0"
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ frappe.ui.form.on("Appointment Type", {
let child = locals[cdt][cdn];
if (child.dt === "Medical Department") {
let item_list = doc.items
.filter(item => item.dt === "Medical Department")
.filter(item => item.dt === "Medical Department" && item.dn)
.map(({ dn }) => dn);
return {
filters: [["Medical Department", "name", "not in", item_list]],
};
} else if (child.dt === "Healthcare Service Unit") {
let item_list = doc.items
.filter(item => item.dt === "Healthcare Service Unit")
.filter(item => item.dt === "Healthcare Service Unit" && item.dn)
.map(({ dn }) => dn);
return {
filters: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def has_required_qty(self):
return True

@frappe.whitelist()
def make_material_receipt(self, submit: bool = False) -> dict:
def make_material_receipt(self, submit: bool | None = False) -> dict:
stock_entry = frappe.new_doc("Stock Entry")

stock_entry.stock_entry_type = "Material Receipt"
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"actions": [],
"creation": "2026-06-15 00:00:00.000000",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"service_unit",
"check_in",
"left",
"check_out",
"invoiced",
"insurance_coverage",
"coverage_status"
],
"fields": [
{
"fieldname": "service_unit",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Healthcare Service Unit",
"options": "Healthcare Service Unit",
"reqd": 1
},
{
"fieldname": "check_in",
"fieldtype": "Datetime",
"in_list_view": 1,
"label": "Check In"
},
{
"default": "0",
"fieldname": "left",
"fieldtype": "Check",
"label": "Left",
"read_only": 1,
"search_index": 1
},
{
"fieldname": "check_out",
"fieldtype": "Datetime",
"in_list_view": 1,
"label": "Check Out",
"read_only": 1
},
{
"default": "0",
"fieldname": "invoiced",
"fieldtype": "Check",
"label": "Invoiced",
"read_only": 1
},
{
"fieldname": "insurance_coverage",
"fieldtype": "Link",
"label": "Insurance Coverage",
"options": "Patient Insurance Coverage",
"read_only": 1
},
{
"fetch_from": "insurance_coverage.status",
"fieldname": "coverage_status",
"fieldtype": "Data",
"label": "Coverage Status",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2026-06-15 00:00:00.000000",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Emergency Occupancy",
"owner": "Administrator",
"permissions": [],
"restrict_to_domain": "Healthcare",
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2026, earthians and contributors
# For license information, please see license.txt

from frappe.model.document import Document


class EmergencyOccupancy(Document):
_DOCTYPE_NAME = "Emergency Occupancy"
Empty file.
256 changes: 256 additions & 0 deletions healthcare/healthcare/doctype/emergency_record/emergency_record.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
// Copyright (c) 2026, earthians Health Informatics Pvt. Ltd. and contributors
// For license information, please see license.txt

frappe.ui.form.on("Emergency Record", {
refresh(frm) {
frm.trigger("render_vital_signs");
if (frm.is_new()) return;

const active = !["Closed", "Cancelled"].includes(frm.doc.status);
if (active) {
frm.add_custom_button(
__("Triage"),
() => triage_dialog(frm),
__("Actions"),
);
frm.add_custom_button(
__("Record Vitals"),
() => vitals_dialog(frm),
__("Actions"),
);
frm.add_custom_button(
frm.doc.service_unit ? __("Transfer Bed") : __("Assign Bed"),
() => bed_dialog(frm),
__("Actions"),
);
frm.add_custom_button(
__("Encounter"),
() => open_linked(frm, "Patient Encounter"),
__("Create"),
);
frm.add_custom_button(
__("Order"),
() => open_linked(frm, "Service Request"),
__("Create"),
);
frm.add_custom_button(
__("Disposition"),
() => disposition_dialog(frm),
__("Actions"),
);
}

if (!frm.is_new() && frm.doc.patient && frm.doc.patient.startsWith("ER-")) {
frm.add_custom_button(
__("Identify Patient"),
() => identify_dialog(frm),
__("Actions"),
);
}

if (!frm.is_new() && !frm.doc.sales_invoice) {
frm.add_custom_button(
__("Sales Invoice"),
() =>
frm.call("create_sales_invoice").then(r => {
if (r.message) {
frm.reload_doc();
frappe.set_route("Form", "Sales Invoice", r.message);
}
}),
__("Create"),
);
if (frm.doc.insurance_policy) {
frm.add_custom_button(
__("Insurance Coverage"),
() =>
frm
.call("create_insurance_coverage")
.then(() => frm.reload_doc()),
__("Create"),
);
}
}
},

patient(frm) {
frm.trigger("render_vital_signs");
},

render_vital_signs(frm) {
if (frm.is_new() || !frm.fields_dict.vital_signs_html) return;
frm.call("get_vital_signs").then(r => {
const rows = (r.message || [])
.map(
v =>
`<tr><td>${frappe.utils.escape_html(
v.observation_template || "",
)}</td><td>${frappe.utils.escape_html(
v.result_data || "",
)} ${frappe.utils.escape_html(
v.permitted_unit || "",
)}</td></tr>`,
)
.join("");
frm.fields_dict.vital_signs_html.$wrapper.html(
rows
? `<table class="table table-bordered"><thead><tr><th>${__(
"Observation",
)}</th><th>${__(
"Result",
)}</th></tr></thead><tbody>${rows}</tbody></table>`
: `<div class="text-muted">${__("No vital signs recorded")}</div>`,
);
});
},
});

function triage_dialog(frm) {
frappe.prompt(
[
{
fieldname: "triage_level",
fieldtype: "Link",
options: "Triage Level",
label: __("Triage Level"),
reqd: 1,
},
],
values =>
frm
.call("record_triage", { triage_level: values.triage_level })
.then(() => frm.reload_doc()),
__("Record Triage"),
__("Save"),
);
}

function bed_dialog(frm) {
const method = frm.doc.service_unit ? "transfer_bed" : "assign_bed";
frappe.prompt(
[
{
fieldname: "service_unit",
fieldtype: "Link",
options: "Healthcare Service Unit",
label: __("Bed"),
reqd: 1,
get_query: () => ({
filters: { occupancy_status: "Vacant", is_group: 0 },
}),
},
],
values =>
frm
.call(method, { service_unit: values.service_unit })
.then(() => frm.reload_doc()),
__("Select Bed"),
__("Save"),
);
}

function vitals_dialog(frm) {
const dialog = new frappe.ui.Dialog({
title: __("Record Vital Signs"),
fields: [
{
fieldname: "vitals",
fieldtype: "Table",
cannot_add_rows: false,
in_place_edit: true,
data: [],
fields: [
{
fieldname: "template",
fieldtype: "Link",
options: "Observation Template",
label: __("Observation"),
in_list_view: 1,
reqd: 1,
get_query: () => ({
filters: { observation_category: "Vital Signs" },
}),
},
{
fieldname: "result",
fieldtype: "Data",
label: __("Result"),
in_list_view: 1,
},
],
},
],
primary_action_label: __("Save"),
primary_action: values => {
frm.call("add_vital_signs", { vitals: values.vitals || [] }).then(() => {
dialog.hide();
frm.trigger("render_vital_signs");
});
},
});
dialog.show();
}

function disposition_dialog(frm) {
frappe.prompt(
[
{
fieldname: "disposition",
fieldtype: "Select",
options: [
"Discharged",
"Admitted",
"Transferred",
"Left Without Being Seen",
"Deceased",
],
label: __("Disposition"),
reqd: 1,
},
{ fieldname: "notes", fieldtype: "Small Text", label: __("Notes") },
],
values =>
frm
.call("set_disposition", {
disposition: values.disposition,
notes: values.notes,
})
.then(() => frm.reload_doc()),
__("Set Disposition"),
__("Save"),
);
}

function identify_dialog(frm) {
frappe.prompt(
[
{
fieldname: "target_patient",
fieldtype: "Link",
options: "Patient",
label: __("Merge Into Patient"),
reqd: 1,
get_query: () => ({ filters: { name: ["!=", frm.doc.patient] } }),
},
],
values =>
frm
.call("merge_patient", { target_patient: values.target_patient })
.then(() => frm.reload_doc()),
__("Identify Patient"),
__("Merge"),
);
}

function open_linked(frm, doctype) {
frappe.route_options = {
patient: frm.doc.patient,
emergency_record: frm.doc.name,
company: frm.doc.company,
};
if (doctype === "Patient Encounter") {
frappe.route_options.practitioner = frm.doc.attending_practitioner;
frappe.route_options.medical_department = frm.doc.medical_department;
}
frappe.new_doc(doctype);
}
Loading