PharmaDesk Documentation
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.
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 asRX- 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_pharmroute renamed todashboard_salesmanto 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.