Food & Grocery Wholesale Distribution
- Location:
- United Kingdom
- Type:
- Custom Software — Back-Office POS & Delivery Management Web Application
100%
of orders centralized in one system of record
~80%
reduction in route-preparation time
~90%
reduction in report preparation time
~70%
faster bulk document generation
Overview
Client is a UK-based wholesale food distributor supplying rice, cooking oil, ghee, spices, lentils, poppadoms, chutneys, and food-service packaging to independent restaurants, takeaways, and retailers across the West Midlands and neighboring regions. Unlike a typical e-commerce operation, Client's business runs on recurring, route-based delivery: customers are grouped onto weekly routes (e.g. Coventry, Pleck), and a driver works through a fixed round of drops each delivery day rather than one-off shipments. Its product catalogue spans dozens of SKUs across seven categories, each with its own pricing, VAT treatment, and stock behavior. Before this platform, Client ran order-taking, invoicing, delivery planning, and payment collection through a mix of manual processes, spreadsheets, and paperwork carried by drivers — with no single system tying an order to its invoice, its delivery, and its payment.
The challenge
Client needed to replace fragmented, manual back-office processes with one system covering the full order-to-cash cycle — while continuing to operate a physical, route-based delivery business that still depends on printed paperwork in the warehouse and on the road.
- Order status, invoicing, delivery, and payment were tracked separately, with no single record connecting them
- Warehouse staff had no consolidated view of what to load for a route — items had to be tallied manually from individual orders
- Drivers had no structured drop-by-drop paperwork, and no formal way to collect and record payments while out on a route
- Reconciling what a client owed across multiple invoices, credit notes, and part-payments was a manual, error-prone exercise
- Returns and disputed invoices had no clean, auditable credit note process
- Cheque payments that later bounced had no defined reversal process
- Management had no on-demand visibility into per-client profitability, per-product profitability, or overall profit and loss
- Pricing communicated to customers (a price list) had to be prepared and kept up to date manually
Objectives
- Digitize the full order-to-cash lifecycle — order creation, invoicing, route-based delivery, payment collection, and statement reconciliation — inside one system
- Automate route-based delivery planning with system-generated consolidated pick lists (warehouse) and drop lists (drivers), replacing manual tallies
- Build a reliable multi-mode payment engine handling opening balances, oldest-first allocation across unpaid orders, and cheque-bounce reversal
- Give management on-demand reporting: client profitability, product profitability, daily sales, and profit & loss
- Harden the codebase post-launch into a maintainable, request-independent, secure modular architecture that can keep evolving safely
Success criteria
- Every order trackable end-to-end through Pending → Invoiced → Processing → Paid without spreadsheets
- Warehouse and drivers work entirely off system-generated pick lists, drop lists, and recovery sheets
- A client's balance is always reconcilable to one authoritative statement combining invoices, credit notes, and payments
- Management reports (client, product, sales, P&L) generated on demand instead of manually compiled
- Credit notes and cheque-bounce reversals follow a single auditable path instead of manual balance edits
- Bulk invoice and delivery-receipt generation runs through queued jobs instead of blocking the admin UI
Our solution
We built Client as a modular Laravel application (using nwidart/laravel-modules) with nine dedicated modules — Admin, Client, Order, Delivery, Payment, Inventory, Supplier, Expense, and Reporting — each isolated around its own domain but sharing the Admin module's core authentication, layouts, and helpers. At the center of the platform is an explicit order status pipeline and a route-based delivery engine.
Route-Based Delivery Engine
Clients are assigned to named, recurring weekly routes. Processing a shipment auto-creates the per-client delivery records for that route, and drivers mark each one delivered from the field.
Full Document Generation Suite
Price Lists, Invoices, Credit Notes, Delivery Notes, Consolidated Pick Lists, Delivery Drop Lists, Driver Recovery Lists, Customer Statements, and four management reports — all generated as PDFs through a single, shared pipeline.
Multi-Mode Payment Engine
A single client payment first clears their opening balance, then distributes the remainder oldest-first across unpaid orders, with a dedicated cheque-bounce reversal path that reinstates the balance via a negative log entry.
Bulk, Queued PDF Generation
Invoicing or generating delivery paperwork for many orders at once is handled by queued jobs, so bulk actions on a route or a batch of orders don't block the admin UI.
Role-Based Back Office
Spatie laravel-permission-driven access control, with granular permissions per module and a Super-Admin role that receives every permission automatically.
Key capabilities
- Instant Customer Flow for walk-in/cash sales that bypasses the normal delivery lifecycle entirely
- Consolidated pick lists that total every item across an entire route into one warehouse-ready checklist
- Driver recovery lists for structured, on-route cash/cheque collection with a paper trail back to the office
- Per-client running balance statements combining invoices, credit notes, and payments in one ledger
- Exportable client, product, sales, and profit-and-loss reports for management
Architecture & tech stack
The solution is a scalable modular monolith — a single Laravel codebase cleanly separated into independent domain modules, avoiding the operational overhead of microservices while keeping each business area isolated and independently testable.
- Frontend: Blade templates + Bootstrap + Alpine.js (server-rendered, no SPA)
- Backend: Laravel 13, PHP 8.4, organized via nwidart/laravel-modules
- Database: MySQL
- Queue: Laravel Queue, database driver, powering bulk invoice and delivery-receipt generation
- Document Generation: Spatie Browsershot (headless Chrome) behind a shared BrowsershotService
- Authentication: Laravel Breeze on a dedicated auth:admin guard
- Authorization: Spatie laravel-permission, seeded per module and assigned to roles
| Frontend | Blade + Bootstrap + Alpine.js |
|---|---|
| Backend | Laravel 13, PHP 8.4 |
| Database | MySQL |
| Hosting | Client-managed server |
| Document Generation | Spatie Browsershot, Spatie laravel-pdf |
| Queue | Laravel Queue — database driver |
| Authorization | Spatie laravel-permission (RBAC) |
| Modules | nwidart/laravel-modules |
| Testing | PHPUnit, manual QA against client feedback each iteration |
Key features
Route-Based Delivery Planning
Clients are grouped onto named, recurring weekly routes. Processing a shipment automatically creates the delivery records for every client on that route, and the system generates a Consolidated Pick List and a Delivery Drop List from the same underlying data — removing the manual tallying that used to precede every delivery day.
Full Document Generation Suite
Every customer- and driver-facing document is generated from live system data through one shared PDF pipeline, so pricing, balances, and order details are always consistent with what's in the system, not re-typed by hand.
Multi-Mode Payment Engine
A single payment against a client account automatically settles any opening balance first, then distributes what's left oldest-first across unpaid orders. Bounced cheques are reversed through a dedicated path that reinstates the balance with a negative log entry.
Management Reporting
Four on-demand reports — Clients, Products, Sales, and Profit-Loss — give management a per-client and per-product view of revenue, VAT, profit, and margin, generated from live data instead of manually compiled at period end.
Results
The implementation replaced manual, paper-and-spreadsheet coordination with a structured system spanning order intake through delivery and payment reconciliation.
| Area | Before | After | Improvement |
|---|---|---|---|
| Order/Invoice/Delivery Tracking | Tracked separately, cross-checked by hand | Single order record driving invoice, delivery, and payment status | 100% of orders centralized |
| Route Preparation | Manually tallied per order for each route | System-generated consolidated pick list and drop list per route | ~80% reduction in prep time |
| Client Balance Reconciliation | Manual reconciliation across invoices/payments | One running-balance customer statement, always current | 100% reconcilable from one statement |
| Returns & Adjustments | No formal process | Auditable credit notes tied to the original invoice | 100% tracked with a full audit trail |
| Bulk Document Generation | Prepared individually | Queued bulk generation for invoices and delivery receipts | ~70% faster turnaround |
| Management Visibility | No on-demand profitability view | Client, product, sales, and P&L reports on demand | ~90% reduction in prep time |
Faster, error-free route preparation
Warehouse staff work from one system-generated pick list per route instead of manually tallying items across every order on that route.
Fewer balance disputes
Clients and staff can point to one statement showing every invoice, credit note, and payment in date order with a running balance.
Cleaner returns handling
Credit notes are tied directly to the original invoice, so the order history stays intact while the client's balance is corrected.
On-demand profitability visibility
Management can pull client, product, sales, and profit-and-loss reports for any date range without manual computation.
Challenges & how we solved them
- A prior attempt to extract shared helpers out of the core payment-allocation methods destabilized the live payment engine and had to be reverted
- Getting print-accurate PDF layouts consistent across every document type, rendered through headless Chrome
- Untangling business logic that had accumulated directly inside Blade views across dozens of screens
- Eliminating N+1 query patterns on the Order and Client listing screens as data volume grew
For the payment engine, we treated the core payment methods as intentionally off-limits to structural refactoring going forward — they can be cleaned for style, but their control flow is frozen, and any simplification is scoped to net-new code around them instead. For document layout, print-orientation and pagination issues were resolved iteratively against real client feedback. For the Blade-embedded logic, we ran a dedicated multi-phase pass moving profit, balance, and due-amount calculations out of the views and into controllers and services, backed by model query scopes. N+1 issues were resolved with targeted eager loading once profiling identified the offending listing queries.
Security & compliance
- Role-based access control via Spatie laravel-permission, with permissions seeded per module and a Super-Admin role granted every permission automatically
- Dedicated auth:admin guard separating back-office access from any other authentication context
- Server-side quantity and input validation on the order cart, not just client-side checks
- Form Request classes handling validation for every store/update action
- Services kept free of direct request() access, so authorization and validation stay owned by the controller layer
Scalability & roadmap
- A self-service client portal for viewing statements and placing repeat orders directly
- A driver-facing mobile app to replace the printed drop list and recovery sheet with a live, on-device version
- Automated route/schedule generation instead of manually assigning clients to routes
- Expanded automated test coverage across the Order, Delivery, and Payment modules
- Deeper analytics and exportable BI dashboards built on top of the existing reporting module
Why the client chose us
- Deep experience with Laravel modular architecture, from route-based delivery domains to multi-mode payment allocation
- Meticulous, iterative approach to print-accurate document generation — a core requirement for a business still running on physical paperwork
- Willingness to invest in a dedicated post-launch hardening phase rather than leaving technical debt to accumulate
- Careful, conservative handling of business-critical logic — recognizing when a working payment engine should be preserved rather than restructured for its own sake
- Ongoing, hands-on support that keeps pace with real day-to-day operational feedback from warehouse and driver staff
Client needed to turn a manual, paperwork-driven wholesale distribution operation into a system that tracks every order, delivery, invoice, credit note, and payment in one place — without giving up the printed pick lists, drop lists, and recovery sheets its warehouse and drivers depend on day to day. The platform replaces scattered manual coordination with an explicit order-to-cash pipeline: orders drive invoicing, invoicing drives delivery paperwork, and every payment reconciles automatically against a client's running balance.
