Skip to main content

09 / WORK / CASE STUDY

Multi-tenant B2B Wholesale Commerce Platform

Self-service wholesale purchasing for corporate clients — tiered pricing, credit limits, monthly billing and payment/logistics sync. The merchant portal is live; the admin console is complete but held back pending acceptance.

TYPE
FULL STACK
SCOPE
Internal · merchant portal live
STACK
DJANGO · DRF · CELERY · MYSQL · REACT · TYPESCRIPT
LINKS
Internal project (private)

01 / PROBLEM

Wholesale ordering tends to live in phone calls, chat apps and spreadsheets: no volume-tiered pricing applied automatically, no credit-limit control, reconciliation done by hand against shipping manifests. This system pulls self-service B2B ordering, authoritative pricing (unit prices recomputed server-side, never trusted from the client), monthly billing with dispute handling, and order/payment/logistics sync into one service — corporate clients buy like it is ordinary e-commerce while credit and billing control stays in-house.

02 / CONSTRAINTS

  • Company-internal; the codebase is private. Payment- and order-path fixes must land without interrupting live transactions.
  • Must integrate with five-plus existing platform services without breaking their contracts — membership, the payment gateway, inventory, analytics, sales attribution — owning none of that data, only the integration.
  • Merchant portal and admin console share one backend: a single missing permission check lets one company see another’s data.
  • Bare-metal and self-hosted with no cloud budget; service lifecycles are managed by hand-built scripts.

03 / ARCHITECTURE

A standalone Django + DRF microservice: 12 business apps (auth, company, product, B2B pricing, cart, sales orders, settlement, quotations, notifications, promotions, billing, contact), 35 models, 21 resource registrations plus 97 custom actions, 30 Celery tasks, ~14k lines; the frontend is a separate React 19 + TypeScript SPA of ~41k lines — 22 merchant pages live, 30 admin pages built and gated. B2B is its own service rather than a bolt-on to the e-commerce service because quoting, credit and monthly billing diverge enough from B2C pricing to deserve independent evolution.

JWT auth with a global IsAuthenticated default — unauthenticated endpoints (login, registration, payment callbacks, service-to-service) are declared one by one. MySQL plus Redis (cache and critical tasks on separate logical DBs); services talk REST with a shared internal secret; payments ride the platform’s all-in-one gateway. The frontend runs dual axios instances (merchant/admin), with single-flight token refresh on 401 and queued replay of concurrent requests.

04 / RESPONSIBILITIES

Independent full-stack development (all 24 backend and 102 frontend commits mine; 2025/10–2026/07): models and APIs across 12 modules, the payment integration and refund chain, permission remediation and backend tests, plus every merchant and admin page, both clients and the design-token system. The membership, gateway and inventory services it integrates belong to the wider platform, not this project.

05 / CHALLENGES → SOLUTIONS

CHALLENGE

An audit found the cancel-paid-order path looked complete — a schedule existed, refund-service calls existed — but the schedule was hitting an endpoint that only queries, never refunds. Orders showed cancelled; cardholders’ money never moved. The flaw spanned three services disagreeing about whether that endpoint actually refunds.

SOLUTION

Added a client that performs the actual refund and wired it into both cancellation entry points; select_for_update stops two devices double-refunding one order; the refund call is non-idempotent and now explicitly marked no-retry; benefit reversals moved to post-commit async jobs, cutting cancellation response from 17 seconds to ~3. Verified end-to-end with a real order — gateway confirmed cancelled, repeat calls idempotent.

CHALLENGE

After moving checkout to the gateway’s all-in-one flow, the payment page intermittently failed with a signature-mismatch error. The algorithm looked wrong but matched the spec exactly — the real culprit was the relay page injecting item names into hidden form fields unescaped, so a name containing & or < got truncated by the HTML parser and the POSTed string no longer matched the signed one.

SOLUTION

The relay page now HTML-escapes every hidden field so what the browser posts is byte-for-byte what was signed; the same batch added a B2B order-type lane so B2B and POS orders stop overwriting each other’s idempotency sequence. The error has not recurred.

CHALLENGE

A security review found endpoints exempting “internal” traffic from auth — with “internal” judged by X-Forwarded-For, a header any client can forge; one 127.0.0.1 skipped login entirely. The same audit caught checkout trusting client-sent unit prices, and order-level discounts not prorated, inflating statement totals above what was owed.

SOLUTION

Removed the forgeable exemption — authentication is the default, real exceptions declared one by one; added an authoritative-pricing module recomputing unit prices server-side from current tiers and promotions; fixed discount proration so statements match receivables. All three landed with accompanying tests and are live.

06 / SYSTEM FACTS

35

models across 12 apps

297

backend test functions

~41k

lines of TypeScript

126

commits, single author

07 / LESSONS

“The job ran” is not “the business happened”: the refund schedule executed cleanly for months while hitting a query endpoint. For jobs whose whole point is a side effect — refunds above all — monitor the side effect, not the trigger.

Hard-coding the backend URL into the frontend was speed-bought debt: standing up a test environment now means editing code and rebuilding instead of flipping a variable. Next time the API base is an environment variable on day one, even with only one environment in sight.

NEXT

Field Sales On-site Activation PWA