# STP Ecommerce — Deploy Readiness (Aug 2026) Everything from `PENDING_WORK_AUDIT_2026-08.md` that could safely be built without live testing has been built this round. This document is the handoff: what changed, what you need to run, and what's still genuinely left before flipping this to production. --- ## What was built this round ### 1. Email settings now actually control real mail - `AppServiceProvider::applyDbEmailSettings()` (new) applies the SMTP host/port/username/password/encryption/from-name/from-email saved on the Email Settings page to `config('mail.*')` on every boot — exactly the pattern already proven for Payment settings. Before this, only the page's own "Send Test Email" button used those values; real order emails ignored them. - `SendOrderPlacedEmail`, `SendOrderNotificationEmail` (shipped/delivered/ cancelled), and `SendPrescriptionStatusEmail` (approved/rejected) now check their matching `notify_*` toggle from the Email Settings page before sending. Defaults to "on" if the page has never been saved, so nothing changes for you unless you've actually visited that page. - `confirmed` and `refunded` order-status emails have no corresponding toggle on the settings page (never did), so they keep sending unconditionally — that's a UI gap on the settings page itself, not a wiring bug, and out of scope for this pass. ### 2. Notification (SMS/WhatsApp) settings now actually control real sends - `NotificationServiceProvider::applyDbNotificationSettings()` (new) overlays the DB-selected SMS provider's credentials onto `config('notification.*')` — Sparrow or Twilio, matching whichever the admin picked on the Notification Settings page. - `NotificationService::sms()` now respects "SMS Provider: None (disabled)" as a real kill switch — previously that dropdown was cosmetic. - `sms_order_placed` / `sms_order_shipped` / `sms_otp_enabled` toggles are now actually checked before sending. - The "BULK SMS Nepal" provider option still has no backing channel implementation — selecting it is a no-op (same as "None"). Building that integration is new work, not a wiring fix, and wasn't done here (see "Still open" below). - WhatsApp remains `.env`-only, same as before — the Notification Settings page never offered WhatsApp controls, so there was nothing to wire. ### 3. Roles & Permissions admin UI New `RoleResource` under Admin → People → Roles & Permissions (`/admin/roles`), restricted to `super_admin`. Create/edit roles, assign permissions via checkboxes, delete roles — with the `super_admin` role itself protected from deletion (it bypasses every `Gate` check in this app; deleting it would lock everyone out with no recovery path). ### 4. Sales / Tax / Customer / Inventory reports Four new pages under a new **Reports** sidebar group: - **Sales Report** — date-range revenue summary, daily revenue table, top products, order status breakdown, CSV export. - **Tax Report** — Nepal VAT or India GST (GSTR-1), date-range, CSV export (reuses `TaxReportService`, which had two real bugs fixed as part of this — see below). - **Customer Report** — new vs. returning customers, top customers by spend (two new `AnalyticsService` methods). - **Inventory Report** — every tracked SKU (not just low-stock, that's still the separate Low Stock Report), with stock-status filters and CSV export. ### 5. Two pre-existing bugs fixed along the way Found while building the Tax Report page on top of `TaxReportService`: - `getNepalVatReport()` read `$item->name`, which doesn't exist on `OrderItem` (the field is `product_name`) — every row would have shown a blank product name. - `getIndiaGstReport()` summed `order_items.tax`, a column that doesn't exist (it's `tax_amount`) — this would have thrown a SQL error the first time anyone ran an India GST report. --- ## What you need to run **No new migrations.** Everything above uses tables that already exist (`settings`, Spatie's `roles`/`permissions`, existing order/inventory tables). From your terminal, in the project folder: ```bash composer dump-autoload php artisan route:clear && php artisan config:clear && php artisan view:clear ./vendor/bin/pest ``` Please paste me the full `pest` output once it finishes — I don't have a way to run PHP in this environment, so that's how we close the loop on whether everything above actually works. I added five new test files (`EmailNotificationSettingsTest`, `SmsNotificationSettingsTest`, `RoleResourceTest`, `TaxReportServiceTest`, `AnalyticsCustomerReportTest`) plus extended the existing `AdminSidebarNavigationTest` to cover every new page — that last one specifically catches "page works but is invisible in the sidebar," which is a real trap in this codebase (the sidebar is a hand-maintained JS array, not Filament's auto-discovery). If anything fails, paste the output and I'll fix it in the next round — per how we've been working this whole session, I edit based on what your terminal actually says, not by running things myself. --- ## Still open — genuinely new work, not done this round I deliberately did not build these, because they're new features rather than "wire up something that already exists," and I have no way to test new third-party integrations or new email/observer flows myself before handing them to you live: - **`notify_new_vendor` and `notify_low_stock` toggles** on the Email Settings page still don't do anything — there's no listener for `VendorRegistered` at all, and no low-stock-crossing detection/event anywhere in the codebase. Building these means a new Mailable + view + listener (vendor case) and a new Observer on the `Inventory` model plus a Mailable + view (low-stock case). Recommend as a follow-up once you want it, or removing those two toggles from the settings page if you'd rather they not imply functionality that isn't there. - **"BULK SMS Nepal" provider** — no channel implementation exists; selecting it silently does nothing (same as "None"). - **Guest checkout invoice access** — the order-slip route I added last turn still requires login + ownership, so guest (non-account) orders can't self-serve their invoice. ## Deployment/ops steps (unchanged from the earlier audit — config, not code) These were already documented and nothing here changes them; repeating so this file is a complete checklist: - Real payment gateway keys (most of `.env.example` for Razorpay/Stripe/PayPal/Paytm/CCAvenue/Delhivery are placeholders). - SMS/WhatsApp tokens (`SPARROWSMS_TOKEN` or the Notification Settings DB equivalent, `TWILIO_SID`, `WHATSAPP_TOKEN`). - `BROADCAST_CONNECTION=reverb` (with a running Reverb server) for the notification bell to push live instead of polling. - `SCOUT_DRIVER=meilisearch` (with a running Meilisearch instance) instead of the local `tntsearch` driver. - **A running queue worker is mandatory now more than ever** — every order/prescription email and SMS is `ShouldQueue`, and the fixes in this round only affect *whether* something gets queued, not the fact that something still has to process that queue. `php artisan queue:work` under Supervisor, per the Phase 4 worklog's VPS checklist. ## Suggested next step Run the commands above, paste me the `pest` output, and I'll fix whatever comes back red. Once that's clean, the two "still open" feature gaps and the ops checklist are the only things standing between this and a real production deploy.