Retail Service Operations Portal
One platform for customers, orders, payments, layaway, repairs and inventory across a multi-branch retailer.
- Context
- A multi-branch fine-jewelry retailer (client anonymized)
- Role
- Sole developer, from discovery to deployment
- Year
- 2026
- Status
- In production
Sales this month
₱4.82M
+12%
Active layaways
37
6 due
Open service jobs
14
3 ready
Incoming transfers
2
pending
| Ref | Type | Branch | Amount | Status |
|---|---|---|---|---|
| ORD-0142 | Pre-order | Branch A | ₱128,400 | In production |
| LW-0031 | Layaway | Branch B | ₱86,950 | 3 of 6 paid |
| MNT-0058 | Service | Branch A | ₱1,500 | Sent abroad |
| ORD-0139 | On-stock | Branch C | ₱54,200 | Released |
| ORD-0137 | On-stock | Branch B | ₱212,000 | Awaiting proof |
Layaway LW-0031
ActivePiece reserved · hidden from sales pickers
Mockup with sample data. Client screens and figures are withheld.
The problem
The business ran on separate Excel calculators, a Google Form and manual tracking. Prices were worked out by hand in multi-step spreadsheets.
Orders, layaways, repairs and stock lived in different places, so it was easy to promise a piece twice or lose track of a payment, and there was no clear view of which sales came from advertising.
The solution
Working in-house, I gathered requirements directly from sales, finance and management, then designed and shipped a single system of record covering the whole customer lifecycle.
Orders & payments
Multi-item orders, proof-of-payment uploads, overpayment and future-date guards, voids and refunds.
Layaway
Contracts of sale, editable payment schedules, and automatic inventory reservation so a reserved piece can't be sold again.
Service & repairs
Ticketed workflow from received to released, a separate payment stream, and printable claim slips.
Inventory & transfers
Branch-to-branch transfers with an in-transit lock and accept/reject by the receiving branch.
Pricing engines
Spreadsheet pricing rebuilt as live, admin-editable engines across 963 ring variants and a supplier diamond feed.
Customer intake & catalog
A public intake form and product catalog on their own domains, isolated from the staff portal.
Hard problems, solved
- A
Stopping the same piece from selling twice
Inventory status is the single gate: layaways reserve a piece, transfers mark it in transit, and only available pieces appear in any picker. Transfers re-check status inside a database transaction so they can't race a sale.
- B
Replacing spreadsheet pricing without changing a price
Long spreadsheet chains (capital, forex, markup, incentive, invoice tax, payment-term tiers) became tested engines backed by editable tables. Fixed reference quotes act as a regression check so engine changes still reproduce the original numbers exactly.
- C
Closing a hidden data exposure
An audit showed the database's auto-generated public API exposed 59 tables to anyone holding the browser key. After confirming the app's server role bypasses row-level security, I locked every table, with no downtime and nothing broken.
My responsibilities
- Requirements discovery with sales, finance and management
- Data model and migrations (58 models, 52 migrations)
- Backend: 141 API endpoints with per-action permission checks
- UI: 89 screens, PDF contracts, claim slips and quotes
- Deployment, custom domains and database security
Results
- ✓One system of record replacing separate spreadsheets, a Google Form and manual tracking
- ✓Every price computed live from editable tables, matching the old spreadsheets to the peso
- ✓Role-based access for admin, sales, finance and photography staff, with an audit trail
- ✓89 screens, 141 API endpoints and 58 data models running in production across 3 domains
Next case study
AI-Powered Social Media Automation