Membership Discount Troubleshooter - hmislk/hmis GitHub Wiki

Membership Discount Troubleshooter

Use this page when a bill (OPD, Inward, Channelling, or Pharmacy) does not apply an expected membership/payment-scheme discount, even though the patient is enrolled in a scheme.

How membership discounts are evaluated

For every billable fee line, the system checks โ€” in order:

  1. Does the parent Item have Discount Allowed = true?
  2. Does the specific Fee line (Hospital Fee, Reagent Fee, Staff Fee, Additional/Other Fee, etc.) have Discount Allowed = true?
  3. Is there a matching discount-percent row in the pricing matrix for the patient's Payment Scheme (the UI calls this "Membership Scheme"), Payment Method, Admission Type, and โ€” for inward bills โ€” Department / Category / Item?

If any one of the three is missing, the computed discount is 0.00, silently, with no error shown to the billing clerk.

Step-by-step check

  1. Confirm the patient's scheme is attached. Open the patient's admission/encounter and confirm a Payment Scheme (Membership Scheme) is selected. For inward, this is set at admission time, not per-bill.
  2. Confirm the discount matrix has a row for that scheme. Open the relevant "Manage Discount Schemes" / "Discounts for Payment Method" admin page for the billing type (Inward, OPD, Channelling, or Pharmacy) and search using the same Membership Scheme, Payment Method, and Admission Type as the patient's encounter. A missing row, or a row with 0%, means no discount will apply regardless of item configuration.
  3. Confirm the item allows discount. Open the item's admin/service record โ€” Discount Allowed must be switched on.
  4. Confirm the item's individual fee lines allow discount. Under Manage Item Fees, each fee line (Hospital Fee, Reagent Fee, Additional/Other Fee, Staff Fee, etc.) has its own independent Discount Allowed toggle. This is the setting most often missed โ€” an item can be discount-allowed while every one of its fee lines is not, giving 0.00 discount with no visible error anywhere in the billing screen.
  5. Re-add the item to the bill. Discount is computed at the moment a line is added to the bill โ€” a line already sitting in the cart will not retroactively pick up a configuration change made afterward; remove it and re-add it.

See Manage-Membership-Discounts for the full configuration walkthrough with screenshots, including where each admin page listed above lives in the menu.

Using the API to check and fix fee-level configuration

For services and investigations, the fee list and its discountAllowed flag can be inspected and corrected directly via the REST API, as an alternative to the admin UI:

GET  /api/services/{itemId}/fees
     Header: Finance: <api-key>

PUT  /api/services/{itemId}/fees/{feeId}
     Header: Finance: <api-key>
     Body:   {"discountAllowed": true}

This is useful for a fast, auditable, scriptable fix on an individual item without navigating the admin UI, and has the same effect as toggling "Discount Allowed" on the Manage Item Fees page. An AI coding assistant with access to this API and to the local database can typically diagnose and correct this class of issue end-to-end: confirm the patient's scheme, check the discount matrix row, check item- and fee-level discountAllowed, apply the fix via the API, and verify the corrected discount on a re-added bill line.

Investigations: item-level discountAllowed via API (added for issue #23308)

Until issue #23308, the item-level Discount Allowed flag (step 3 above) could only be read or set for Investigations one at a time through the Manage Investigation admin page โ€” there was no API access to it at all, unlike Services. The investigation API now supports it directly:

GET  /api/investigations/search
     Header: Finance: <api-key>
     -> each result includes "discountAllowed": true|false

PUT  /api/investigations/{id}
     Header: Finance: <api-key>
     Body:   {"discountAllowed": true}

Bulk-enabling discount flags for a whole category or item type

Fixing item- and fee-level discountAllowed one item at a time doesn't scale when hundreds of investigations need it turned on at once โ€” and there is no API to list every Investigation Category to loop over. Two bulk endpoints cover this, both accepting categoryId and/or itemType (Investigation | Service | InwardService โ€” at least one required):

POST /api/services/items/bulk-discount-allowed        (item-level Discount Allowed)
POST /api/services/fees/bulk-margin                    (fee-level Discount Allowed / Service Charge Allowed)
     Header: Finance: <api-key>
     Body:   {"itemType": "Investigation", "discountAllowed": true}

itemType targets every item of that subtype directly (e.g. "every Investigation" in the whole system), regardless of category โ€” use this instead of categoryId when the goal is "turn this on everywhere," not "turn this on for one category."

Inward Discount Matrix: department wildcard (fixed for issue #23237 / #23308)

A discount-matrix row saved without a department โ€” intended to mean "any department" โ€” used to require an exact department match at the category and department resolution tiers, so it silently never matched a bill line whose item has its own processing department set (true for almost every Investigation, since each lab investigation carries its own lab department, unlike many Services which fall back to the ward department). This is now fixed: a department-less row correctly wildcard-matches any department, the same way a payment-method-less or admission-type-less row already did. A department-specific row still takes priority over the wildcard when both exist.

Practical effect: a single discount-matrix row per payment scheme โ€” no department, no category, no admission type โ€” now reliably applies to every investigation and service under that scheme, instead of needing one row per department/category combination (which is easy to leave gaps in, as issue #23308 demonstrated).

If everything above is configured and the discount still doesn't apply

Rebuild and redeploy the application before troubleshooting further. On an environment where the discount-calculation code was changed but the running server was not redeployed, the server continues executing the previously deployed logic โ€” no amount of configuration will surface a fix that only exists in code that hasn't been deployed yet.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ