Inpatient Bill Cancellations and Refunds Overview - hmislk/hmis GitHub Wiki
The inpatient module provides dedicated cancellation and refund pages for each bill type. All cancellations require privilege and record a reason; cancelled bills are retained in the database for audit purposes.
| Bill Type | Page | Notes |
|---|---|---|
| Final bill | /inward/inward_cancel_bill_final.xhtml |
Cancels the final bill; returns BHT to pre-settlement state |
| Payment bill | /inward/inward_cancel_bill_payment.xhtml |
Cancels a collected payment |
| Professional fee bill | /inward/inward_cancel_bill_professional.xhtml |
Cancels a professional fee bill |
| Provisional bill | /inward/inward_cancel_bill_provisional.xhtml |
Cancels a provisional bill |
| Refund bill | /inward/inward_cancel_bill_refund.xhtml |
Cancels an already-issued refund |
| Service bill | /inward/inward_cancel_bill_service.xhtml |
Cancels a services & investigations bill |
| BHT bill (general) | /inward/bht_bill_cancel.xhtml |
General BHT bill cancellation |
| Deposit payment | /inward/inward_deposit_cancel_bill_payment.xhtml |
Cancels a deposit collection |
| Refund Type | Page | Notes |
|---|---|---|
| General inpatient refund | /inward/inward_bill_refund.xhtml |
Refund against a settled bill |
| Service bill refund | /inward/inward_bill_service_refund.xhtml |
Refund for a specific service bill item โ InwardServiceController
|
Pharmacy-related inpatient cancellations (issue cancellations, reprint) are handled by the pharmacy module. See:
When a bill is cancelled:
- The bill record is flagged
cancelled = trueand aCancelledBillrecord is created โ the bill itself is not deleted - Bill items and fee lines remain
retired = falseso that cancellation print-outs display correctly - A new contra-bill may be created depending on the cancellation type
- The BHT totals are recalculated
Note: Cancellation does NOT set
retired = trueon bill fee lines. This distinction is important for reports and print-outs โ cancelled bills remain queryable.
Once a patient's nursing discharge has been confirmed (Inward > Search > Admissions > Nursing WorkBench > Nursing Discharge), the Return and To Cancel actions on that patient's inward service bills (/inward/inward_reprint_bill_service.xhtml, reached via Inward > Search > Service Bill) are disabled by default:

Before nursing discharge: both Return and To Cancel are enabled.

After nursing discharge: To Cancel is disabled. Return stays enabled here only because this user holds the escape-hatch privilege below.
This mirrors the nursing-discharge check that already existed for Add Charges (InwardAddChargesAfterNursingDischarge). Each action has its own escape-hatch privilege for staff who genuinely need to act after nursing discharge:
| Action | Escape-hatch privilege |
|---|---|
| Return | InwardProcessReturnAfterNursingDischarge |
| Cancel | InwardProcessCancelAfterNursingDischarge |
A user without the relevant privilege sees the button disabled in the UI; the same check is enforced server-side (InwardSearch.navigateToCancelInpatientBill() / .cancelBillService(), InwardServiceRefundController.navigateToRefundInwardServiceBill() / .refundInwardServiceBill()), so the restriction cannot be bypassed by a direct form submission.
The privileges above only unlock cancel/return for a bill that is still genuinely pending โ nothing has been done with it yet. They are not a blanket override. Once a lab sample has been collected from the patient, an OPD bill has started lab processing, or a surgery has been validated/closed, cancellation and return are blocked unconditionally โ no privilege, including the ones above, can bypass this (issue #23576, reopened 2026-09-08 after the initial fix above missed this; the threshold was tightened from "accepted" to "sent to lab" in issue #23598, then from "sent to lab" to "sample collected" in a 2026-09-27 follow-up to #23598). Returning a collected-sample test shows Cannot return "" - the sample has already been collected for this test.; cancelling shows "This bill is processed in the Laboratory."

The "To Cancel" button is enabled here because this user holds InwardProcessCancelAfterNursingDischarge โ but the bill's lab investigation has already reached SAMPLE_ACCEPTED.

Submitting the cancellation is still blocked server-side, with "This bill is processed in the Laboratory." โ the privilege only covers pending bills.
| Bill type | What locks it | Enforced in |
|---|---|---|
| Inward service bill (incl. lab/OPD investigations billed as an inward service) | Lab sample reaches SAMPLE_COLLECTED or later, or a report has been entered |
InwardSearch.checkCancelBill() / .checkInvestigation() (cancel), InwardServiceRefundController.checkLabSampleGuard() (return) |
| OPD bill | Same lab-processing check |
BillSearch.cancelOpdBill() (cancel), BillSearch.sampleHasBeenCollected() via .refundOpdBill() (return) |
| Surgery bill | Surgery has been validated (Bill.completed, set by Validate Surgery, InwardSurgeryValidate) |
InwardSearch.cancelSurgeryBill() |
A regular (non-lab) inward service that is still pending remains cancellable/returnable by a user holding the nursing-discharge escape-hatch privilege, exactly as documented above โ that behavior is unchanged.
Every cancellation records:
- Cancelling user
- Cancellation timestamp
- Reason for cancellation
- Inpatient โ Final Bill Generation โ the bill being cancelled
- Inpatient โ Patient Deposits โ deposit cancellations
- Inpatient โ Final Bill Payment โ payment cancellations