All work
02/B2B operations

Trading Operations

An operations platform that runs an import/export trading business from customer enquiry to final payment, with AI drafting the repetitive paperwork and staff approving every decision.

Domain
Import/export trading · industrial and defence buyers
Status
Verified live end to end
01

The challenge

SMC Group imports industrial and technical goods from international suppliers and resells them to industrial and defence customers. Every deal is operationally heavy: RFQs out to vendors, quote comparison across currencies, purchase orders, shipping documents, goods receipt, delivery challans, GST invoicing, payment reconciliation — routinely with partial shipments and partial payments landing against the same order.

All of it ran on spreadsheets, email, and a status sheet somebody updated by hand every day. That meant slow handoffs between sales, procurement, warehouse and accounts, the same documents retyped for every deal, and nowhere to look to find out where an order actually stood.

The multiplier was three companies sharing one team. The same seven people operate three legal entities, which turns every pricing decision, every document number and every cross-company lookup into somewhere an error can hide — and a manual process gives you no way to find it afterwards.

02

Our role

End-to-end delivery: requirements, architecture, backend, frontend, AI integration, testing and deployment documentation.

That started with translating the client's real trading process and their actual document formats into a formal spec and capability matrix — the part that decides whether software like this fits the business, or the business has to bend around the software. From there: the modular monolith backend with capability-based RBAC and per-company data isolation, the React SPA carrying role-based dashboards and the order-detail workflow, the Claude integration for drafting and extraction, deterministic PDF generation and GST invoicing, and live end-to-end verification across all eighteen steps.

03

What we built

The order lifecycle — one screen, eighteen steps, and only the next valid action visible.

  • 18-step order lifecycle — enquiry through vendor sourcing, procurement, shipment, delivery, invoicing and payment, on a single order-detail screen. Each role sees only the action that is theirs and next: Sales, Purchase, Owner, Sales, Purchase, Warehouse, Accounts, then automatic reconciliation.
  • Quote comparison — vendors ranked by effective cost — price adjusted for payment terms — with a caution flag when the comparison crosses currencies, and an Owner approval gate before any procurement spend.
  • Multi-company operations — three entities running in isolation, a consolidated view for Owner and Admin, and gap-free sequential document numbering per company.
  • Live status board — replaces the manual daily-update sheet, refreshing roughly every thirty seconds.
  • Receivables and reporting — partial payments, CRV-gated payment release, aging tiers, and revenue, GST and margin reports exportable to PDF and Excel.
  • Full audit trail — every state change logged with who, what, when, and the before and after. Nothing is hard-deleted.

Where the AI sits — three touchpoints, all of them drafting rather than deciding.

Claude writes vendor RFQ cover letters, extracts structured line items out of vendor quote documents with confidence flags on low-certainty fields, and drafts payment reminders. Nothing is sent or finalised without a person approving it.

The numbers that matter are never model output. Vendor RFQ, Commercial Offer, customer and vendor purchase orders, GRN, Delivery Challan and the GST Sales Tax Invoice are all generated deterministically as PDFs from system data.

The design principle, stated once and enforced everywhere: AI drafts, humans approve, and the backend is authoritative on money, GST and document numbers. Nothing financial is recomputed in the browser.

04

Stack

Technology stack, by layer
LayerWhat we used
AI / ML
  • Anthropic Claude (claude-sonnet-4-6)
  • Groq fallback (openai/gpt-oss-120b)
  • Pydantic v2 schema validation
  • Structured JSON extraction
  • ai_outputs audit logging
Frontend
  • Vite · React 18 · TypeScript
  • React Query · Zustand · React Router · Axios
  • Tailwind CSS · Recharts
  • Vitest · Testing Library · MSW
Backend
  • Python 3.12 · FastAPI
  • SQLAlchemy 2 (async) · Alembic
  • PostgreSQL 16 · Redis 7
  • JWT auth · bcrypt
  • WeasyPrint (PDF) · openpyxl (Excel)
Infrastructure / DevOps
  • Docker Compose for local development
  • Vercel (frontend)
  • Container host with managed Postgres / Supabase
  • S3-compatible object storage for PDFs
  • GitHub Actions CI
  • HMAC-signed file URLs
05

Decisions

Decision01

AI that never blocks the business

An operations platform cannot depend on a language model being available. If the LLM is down, the trading company still has to send RFQs — so a design where the workflow waits on an API is a design that stops the business for reasons the business cannot see or fix.

All three AI touchpoints route through one call layer with a defined fallback ladder: try Anthropic, retry on Groq with JSON mode forced, and if both fail, degrade to a pre-filled manual form so the eighteen-step cycle continues. Every output is validated against a Pydantic schema before it reaches a user or a document, retrying up to three times. Token usage and confidence are logged for cost and quality tracking.

The result is that the AI is a labour saving on a process that already works without it. That is the only version of this a business can actually run on.

Decision02

Correctness on the paths that aren't the happy one

Import/export trading is not linear, and a system that only models the clean path quietly produces wrong numbers. Partial receipts, partial payments, several delivery challans and several invoices against one order are normal here, not exceptional.

They are all first-class flows, and the backend enforces the rules rather than trusting the interface: over-receipt is rejected, GST invoicing is blocked before delivery is confirmed, payment is blocked before CRV where the customer requires it, and vendor purchase orders are priced from the winning vendor quote rather than from the company's own selling price.

Several of those guards exist because live end-to-end testing found the gap. That is the argument for running a real order through the whole cycle before handover rather than testing the steps in isolation.

Decision03

A modular monolith, not microservices

The requirement is roughly 100 to 150 concurrent users across three companies that constantly need consistent reads of shared reference data. Microservices would have bought independent scaling nobody needed and paid for it in distributed transactions across exactly the data where a trading business cannot tolerate drift.

So: one PostgreSQL database with native ACID, one deployable, and company scoping enforced server-side through a company header plus capability RBAC rather than through separate services. Adversarial testing verified fifteen of fifteen isolation and RBAC scenarios — cross-company reads return 404, a forged company header returns 403, role-action mismatches return 403.

Decision04

The extraction bug worth writing down

An early version of quote extraction sent the model the document's storage key instead of the document. It returned plausible output — which is the failure mode that matters, because plausible output from a model that never saw the input is indistinguishable from working software until somebody checks a number against the source.

The fix was to pass the document text into the prompt along with the enquiry line context, so part numbers have something to match against. Live verification then extracted two vendor quotes at 0.97 to 0.99 confidence, with correct EUR and PKR totals and lead times normalised — '6 weeks' resolved to 42 days.

The lesson generalises past this project: with an LLM feature, 'it returned something' is not evidence that it read anything.

06

Results

The figures below come from the project's QA and end-to-end verification reports. No production usage metrics — orders processed, time saved, revenue impact — were tracked, so none are claimed.

0/76
Backend tests passing
0/15
RBAC and adversarial checks passed
Results
CheckResult
Full enquiry-to-paid lifecycleCompleted live on hosted Supabase — including partial receipt, two delivery challans, two invoices, CRV gating, partial payments and automatic order close-out
Backend tests76/76 pytest passing in-container
Frontend tests6/6 Vitest passing; production build ~311 KB (~98 KB gzipped)
Security15/15 RBAC and adversarial isolation checks passed live
AI confidenceRFQ draft 0.92; vendor quote extraction 0.97–0.99
Audit trail73 audit rows visible in the consolidated Owner view for a single test order
Design target, not measured in productionRFQ generation under 5 minutes including human review, against roughly 45 minutes manual for a 30-line RFQ
07

Screenshots

SMC Trading Platform landing page — from enquiry to payment, without the paperwork
Landing page
The eighteen-step trading lifecycle compressed into six phases
The 18-step lifecycle
Quote comparison ranking vendors by effective cost, alongside the backend-authority rule
Quote comparison
Role dashboard showing open enquiries, items in fulfilment, awaiting payment and overdue
Dashboard
Enquiry list for the selected company with status and next action
Enquiries
Enquiry detail at stage 2 of 18, recording vendor quotes from an uploaded document
Enquiry detail
Archive of won, lost, open and expired enquiries with full history
Archive
Live project status board, auto-refreshing, replacing the manual daily update sheet
Live status board
Customer master data with payment terms, CRV requirement and credit limits
Customers
Supplier records with currency, terms, categories and lead times
Suppliers
Item catalogue across every enquiry, grouped by category
Item catalogue
Reporting across receivables, revenue, GST summary and per-order margin
Reports
Financial movement — received, paid out, net movement and receipts for the period
Financial movement