Research
This guide is written from the shipped module source, not from a plan. This page records exactly which files were read so every statement — permissions, routes, the statutory math, the sub-toggles, the API — can be traced back to live code. If the module changes, refresh the guide against these same files.
Documented version: Pharmacy 0.5.0 (Phases 1–5, plus the read-only API and DPA privacy hardening).
Why this page exists
The module's documentation is intentionally evidence-based. The earlier version of this guide covered only Phase 1 (the Compliance Center) and had gone stale as Phases 2–7 shipped. This refresh was produced by re-reading the authoritative files below and rewriting each page to match what the code actually does — no invented features, and compliance framed honestly as "configured for the tenant's registered setup," never "certified."
Manifest, README & changelog
| File | What it established |
|---|---|
module.json | Version 0.5.0, slug pharmacy, the 26 tables, the six migrations, the full permission list, the dependencies (POS, Warehouse, Procurement, Inventory, Finance), the sub-toggles, and the api block (both surfaces + endpoints). |
README.md | Purpose, audiences, the reuse boundaries, and the version/permissions/tables summary. |
CHANGELOG.md | The phase-by-phase feature history (0.1.0 → 0.5.0): Compliance Center, Catalog, Prescriptions, Dispensing (FEFO + Senior/PWD + BIR receipt), and Safety, plus the notes/boundaries for each. |
Config sidecars
| File | What it established |
|---|---|
config/menu.php | The nine sidebar items, their routes, permissions, and the two setting-gated advanced items. |
config/default_menu.php | The group display label ("Pharmacy") and the default menu slice / ordering. |
config/permissions.php | Every permission key and its Roles-editor category — the source of the permission tables. |
config/routes.php | The full route map (compliance, catalog, prescriptions, patients, controlled, quality, settings). |
config/system_logs.php | The audit action:component keys and severities across all phases. |
config/widgets.php | The two dashboard widgets and their gating. |
config/api_routes.php, config/euapi_routes.php, config/api_scope.php | The integration + end-user API endpoints and the pharmacy:read scope. |
Controllers read
The controllers were read to confirm the real screens, actions, gating and workflow — not assumed from names:
Pharmacy.php,Compliance_center.php— the Overview and compliance hub (read-only via the helper).Duty_sessions.php— start/end duty; the non-expired-credential precondition; the on-duty gate.Pharmacy_prescriptions.php— the Rx queue, capture, atomic status transitions, the validate/dispense on-duty checks, FEFO issue, the statutory benefit decision, and the label/receipt print views.Pharmacy_patients.php— patient CRUD, representatives, medication profile, and the auditedreveal_idunmask (DPA).Controlled_register.php— the append-only ledger, the entry directions, correction-by-reversal, and reconciliation; themodule_pharmacy_controlledgate.Pharmacy_quality.php— recalls (with the Warehouse batch quarantine), adverse events, cold-chain readings; themodule_pharmacy_qualitygate.Pharmacy_products.php,Pharmacy_expiry.php— the catalog (extends stock items), regulatory verifications, and the read-only near-expiry dashboard, both degrading gracefully without Warehouse.Pharmacy_settings.php— branch profiles and the Advanced Modules sub-toggle save.Pharmacy_api.php,Pharmacy_euapi.php— the read-only endpoints, their scopes/permits, and themodule_unavailablebehavior.
Helpers & cron jobs
| File | What it established |
|---|---|
helpers/pharmacy_helper.php | The statutory benefit computation (VAT-exempt base then 20% discount; senior/PWD mutually exclusive; ineligible lines pay gross), the DPA encryption-at-rest note, the expiry buckets, the readiness/on-duty helpers, and the default benefit rule (20% / 12% VAT / senior booklet off). |
jobs/LicenseExpiryReminderJob.php | Daily 07:00; 30-day expiry horizon; self-gates on module_pharmacy. |
jobs/NearExpiryStockJob.php | Daily 06:30; 90-day window; guards the Warehouse tables and self-gates on module_pharmacy. |
Key claims & where they come from
| Claim in this guide | Source of truth |
|---|---|
| ₱112 covered item → ₱80 payable; strip 12% VAT then 20% off; senior/PWD mutually exclusive; ineligible lines pay gross | pharmacy_compute_statutory_benefit() in pharmacy_helper.php; canonical example in CHANGELOG.md 0.4.0 |
| Prescription validation and dispensing block unless a pharmacist is on duty | Pharmacy_prescriptions::validate_rx() / record_fill() guard on pharmacy_is_pharmacist_on_duty() |
| Duty needs a non-expired credential | Duty_sessions::save() → _valid_credential_for() |
| Controlled register is append-only; corrections are linked reversals; running balance recomputed | Controlled_register::post_entry() / correct() |
| Activating a recall quarantines the matching Warehouse batch | Pharmacy_quality::recall_activate() (via Stock_batches_model) |
| Patient IDs encrypted at rest, masked to last-4, audited unmask | Pharmacy_patients::save() / reveal_id(); pharmacy_encrypt_id() etc. in the helper |
| Sub-toggles off by default; direct URL redirected while off | Controlled_register / Pharmacy_quality constructors; Pharmacy_settings::save_options() |
| API hides existence when the module is off (404 module_unavailable) | Pharmacy_api::requireModule() / Pharmacy_euapi::requireModule() |
Next: FAQ & Troubleshooting →