PharmaDesk — Changelog

Every user-visible change to PharmaDesk, newest first.

This log covers changes that matter to users — new features, behaviour changes, removals, and bug-fix summaries. Internal refactors, dependency bumps, and build-system tweaks are left out. The format follows Keep a Changelog.

Back to PharmaDesk

How entries are labelled
  • Added — new capabilities.
  • Changed — adjustments to existing behaviour you should notice.
  • Fixed — defects that affected the product day to day.
  • Security — access-control and protection improvements.
  • Removed — capabilities that were taken out.

1.1.1 — 2026-05-23

Security gates, modal accessibility, FEFO dispensing, and a wave of report fixes.

Added
  • Seven new reports for Admin and Salesman roles — P&L Statement, Customer-wise Sales, Cash Flow, Supplier Performance, Return Analysis, Discount Analysis, and Expiry Loss.
  • Sales Returns module — full create and list flow with linked stock reversal and audit trail, separate from the Sales navigation.
  • Multi-sale draft tabs — a Salesman can pause one bill, start another, and switch back without losing state. Drafts persist per session.
  • FEFO autoselect skips expired batches — sale entry now picks the earliest-expiring batch that still has stock and is not past its expiry.
  • Sliding 30-minute session timeout, with instant lockout when a user is deactivated.
  • Favicon route so browsers stop logging 404s and the tab favicon matches the app icon.
Changed
  • Sidebar navigation rewritten per role — each role now sees exactly what the permission matrix documents:
    • Salesman: Dashboard, Medicines, Stock, Sales group, Purchases group, Suppliers, Reports, User Guide.
    • Cashier: Dashboard, Pending Bills, Sales Returns, Sales (view), Medicines (view), Stock (view), User Guide.
    • Pharmacist: Dashboard, Medicines, Stock, Sales (view), Reports, User Guide — read-only.
    • Admin: full access.
  • Cashier discount decoupled from line-item discount. Both are stored, both are preserved in reports, and the receipt shows the final charged amount.
  • Modals share Escape-to-close, focus trap, and auto-focus — the first interactive field is focused on open, Tab and Shift+Tab cycle inside the modal, and Escape closes the top-most one.
  • Sale and purchase pages now use the shared modal helper, so future modal improvements take effect everywhere automatically.
Fixed
  • Expired-batch check no longer rejects every sale. A date-comparison bug compared locale-formatted dates lexically against ISO dates; now compared as real dates.
  • Stock Movement report no longer fails with “Database operation failed” — the underlying SQL was restructured and now reports “days since last sale” cleanly.
  • Customer Debtors report no longer reads the wrong column — previously a field-name typo could surface zero paid amounts on unpaid bills.
  • Discount Analysis percentages no longer round to 0 (SQLite integer division fixed).
  • Supplier Performance no longer hides deactivated suppliers — they appear with an “inactive” badge.
  • Receipt numbers are now zero-padded as RX-00001 (previously space-padded as RX-    1).
  • Sale total reflects cashier discount on receipts and sales lists.
  • Concurrent sales no longer collide — two cashiers cannot create duplicate receipt numbers or push stock negative under race conditions.
  • Save Bill button in sale entry guards against double-submit during validation.
  • “Bill Created” success modal preserves its custom button cycling (Print Slip / New Sale / Back to Sales).
  • Cashier dashboard no longer redirects unknown roles to the admin dashboard.
  • Expiry Report days-threshold input now actually reaches the backend.
  • Schema migration race on a fresh database no longer leaves a column unmigrated when the database is created in the same boot.
Security
  • Two SQL-injection sites closed in new report queries — both report endpoints now bind every user filter via parameters.
  • Role gates added to 11 mutation endpoints that were previously protected only by login — a Pharmacist (documented read-only) can no longer hit them.
  • 13 GET endpoints now enforce role server-side — Cashier and Pharmacist sessions get a clean 403 instead of relying on the UI hiding buttons.
  • Sessions are invalidated when a user is deactivated — an already-logged-in user loses access immediately.
  • Login API returns HTTP 401 on failure (was 200 with success:false).
  • Error envelopes sanitised — raw database errors no longer leak to clients; UNIQUE / FOREIGN KEY / NOT NULL violations are translated to friendly messages.
  • Constant-time password comparison for legacy plaintext accounts (timing-attack mitigation).
  • Secure session ID generation — no fallback to a weak random source if the OS crypto API fails.
Removed
  • Obsolete dashboard_pharm route renamed to dashboard_salesman to match its actual role.
  • Legacy plaintext-fill helper retired across the codebase — all responses now flow through the safer JSON builder.

1.0 — Initial public release

First publicly available build of PharmaDesk.

Added
  • Two-role sales workflow — Salesman creates the bill, Cashier collects payment.
  • Medicine catalogue with form, strength, generic name, category, supplier info, reorder levels, and shelf location.
  • Batch-level inventory with FEFO dispensing — the oldest batch sells first.
  • Dashboard alerts for low stock and approaching expiries.
  • Purchasing and supplier management with purchase returns, supplier balances, and credit terms.
  • Stock adjustments and sales returns with reason and full audit trail.
  • Invoicing and payment tracking with cash, card, and bank transfer; printed receipts.
  • Multi-draft sales — pause one bill, start another, switch back.
  • Four-role access control — Admin, Pharmacist, Salesman, Cashier. Every endpoint enforces role checks server-side.
  • User management with forced password change, active/inactive flag, and last-login tracking.
  • Built-in reports — sales summary, profit and margin, stock valuation by batch and cost, purchase summary, and expiry report.
  • Configurable pharmacy settings — name, contact info, and currency symbol used on receipts and in the UI.
  • Browser-based UI served from the Windows server — no client install.
  • SQLite with WAL mode for reliable concurrent multi-user access; foreign keys, triggers, and performance indexes set up automatically.

Back to PharmaDesk