Production URL: royalsweetsleicester.co.uk
Live online ordering platform for Royal Sweets, handling customer orders, Stripe payments, stock-aware checkout reservations, same-day delivery planning, staff fulfilment, refunds, receipt printing and customer notifications.
The screenshots below are public-safe mockups created with fake or blurred data. They are not production customer records.
THE EMPLOYEE PAGES ARE DEPRECATED. They have been replaced by a more secure solution but the screenshots represent how we handle operations.
flowchart LR
Customer["Customer browser"] --> Django["Django app\nproducts, cart, checkout, accounts"]
Staff["Employee browser"] --> Django
Django --> PostgreSQL["PostgreSQL\norders, products, stock limits, delivery slots"]
Django --> Stripe["Stripe PaymentIntents\nPayment Element, refunds"]
Stripe --> Webhook["Signed Stripe webhooks\npayment and refund events"]
Webhook --> Django
Django --> Email["Transactional email\nconfirmation, refund, delivery updates"]
Django --> Twilio["Twilio SMS\nconfirmation and delivery updates"]
Django --> Maps["Maps and postcode services\navailability, geocoding, routes"]
Django --> Printer["Receipt printer poller\nRadxa device"]
Django --> Media["Media storage\nproduct images"]
flowchart TD
Cart["Cart"] --> Validate["Checkout validation\ncart, date, postcode, stock"]
Validate --> Reserve["Atomic reservation\nlock products and delivery slot"]
Reserve --> PaymentIntent["Stripe PaymentIntent\nidempotency key and metadata"]
PaymentIntent --> CustomerPays["Customer confirms payment"]
CustomerPays --> Verify{"Payment verified?"}
Verify -->|yes| Paid["Order marked paid\npaid_at, payment method summary"]
Verify -->|no| Failed["Payment failed\nreservation expires"]
Paid --> Notify["Email and Twilio confirmation"]
Paid --> Receipt["Receipt queued for printer"]
Paid --> Staff["Staff fulfilment\norders, stock, totals, routes"]
Staff --> Fulfilment{"Delivery or collection"}
Fulfilment --> Delivery["Delivery route\nMaps navigation and delivered status"]
Fulfilment --> Collection["Collection in store"]
Delivery --> Completed["Delivery completed notification"]
Paid --> RefundRequest["Staff refund action"]
RefundRequest --> StripeRefund["Stripe Refund API"]
StripeRefund --> RefundWebhook["Refund webhook verification"]
RefundWebhook --> Refunded["Order marked refunded\ncustomer refund email"]
- Django: server-rendered customer and employee flows keep the operational surface simple, with Django auth, forms, admin, templates, and management commands in one deployable app.
- PostgreSQL: relational order, product, stock, reservation, and delivery-slot data fits transactional consistency. Checkout uses atomic transactions, row locks, reservation expiry, and idempotency keys to avoid duplicate orders.
- Stripe webhooks: payments use PaymentIntents and Stripe Elements. Webhook events are signature-verified, then payment and refund events are checked against order id, amount, currency, and metadata before order state changes.
- Stock consistency: paid orders and unexpired pending reservations both count against active stock limits. Stock rules are category-specific because mithai, chilled desserts, savouries, and cooked meals have different fresh-stock and preorder windows.
- Twilio: customers can receive SMS updates for order confirmation, delivery estimates, and delivered status, alongside transactional email.
- Maps: postcode availability protects the delivery area, while Maps services support geocoding, route planning, and driver navigation links.
- Employee operations: staff screens expose service-time workflows: stock toggles, confirmed orders, receipt reprints, order totals, route status, quick cooked-meal updates, holiday blocks, and refunds.
- Same-day delivery and collection windows before 5pm.
- Perishable food stock with daily and weekly availability rules.
- Staff (cashier, driver, franchise owner(s)) need fast operational screens during service.


