All work

Internal Tools

Order Export for Production Planning

Removing the developer from a routine data request

2026Internal production

At a glance

Credit

Built by
Denandro YusufDesign · Directing Claude Code from specs · The warehouse-attribution rule and the conservative stock verdict · Requirements with the planning team · Deployment and the handover to planners

Run the demo synthetic data

Problem
Planners needed one row per order line, tagged to the warehouse that ships it.
What I did
I ruled that a warehouse is named by where units ship, and kept the stock verdict conservative.
Outcome
Planners self-serve an export that used to need a developer.

Explore

The component graph, from the source repository. Follow the arrows: left to right, and down where two steps share a column. The burgundy bars are where decisions are made; the numbers on the lines are the key flows, written out under the graph.

Order Export for Production Planning: architectureData flows through 11 components: Planning team browser (Interface: Server-rendered page, no build step); TLS + Google sign-in (Service: oauth2-proxy · Workspace domain allow-list); FastAPI export service (Service: Stateless, non-root container); Preview cache (Store: 10 min TTL, keyed by request hash); Warehouse resolver (Decision logic: fulfilled → assigned → Unknown); Secret Manager (Store: Client secret → ~24h token); Structured logging (Output: PII-redacted by construction); Stock matcher (Decision logic: style + colour + size; conservative); Shopify Admin GraphQL (External: Cost-aware pacing, read-only scopes); Excel / CSV builders (Output: Generated fully in memory); Stock workbooks ×3 (External: Read-only service account, fails soft). Connections: Planning team browser to TLS + Google sign-in (HTTPS + sign-in); TLS + Google sign-in to FastAPI export service (verified identity); FastAPI export service to Preview cache (preview → export reuse); FastAPI export service to Warehouse resolver (date range); Warehouse resolver to Shopify Admin GraphQL (two-pass fetch); Warehouse resolver to Stock matcher (line item + qty); Stock matcher to Stock workbooks ×3 (read-only, cached); FastAPI export service to Secret Manager; Warehouse resolver to Excel / CSV builders (rows + summary); Excel / CSV builders to Planning team browser (.xlsx / .csv); FastAPI export service to Structured logging.Planning team browser — Server-rendered page, no build stepPlanning teambrowserServer-rendered page,no build stepTLS + Google sign-in — oauth2-proxy · Workspace domain allow-listTLS + Googlesign-inoauth2-proxy ·Workspace domainallow-listFastAPI export service — Stateless, non-root containerFastAPI exportserviceStateless, non-rootcontainerPreview cache — 10 min TTL, keyed by request hashPreview cache10 min TTL, keyed byrequest hashWarehouse resolver — fulfilled → assigned → UnknownWarehouse resolverfulfilled → assigned →UnknownSecret Manager — Client secret → ~24h tokenSecret ManagerClient secret → ~24htokenStructured logging — PII-redacted by constructionStructured loggingPII-redacted byconstructionStock matcher — style + colour + size; conservativeStock matcherstyle + colour + size;conservativeShopify Admin GraphQL — Cost-aware pacing, read-only scopesShopify AdminGraphQLCost-aware pacing,read-only scopesExcel / CSV builders — Generated fully in memoryExcel / CSVbuildersGenerated fully inmemoryStock workbooks ×3 — Read-only service account, fails softStock workbooks ×3Read-only serviceaccount, fails soft123456789

Key flows

  1. Planning team browser to TLS + Google sign-in: HTTPS + sign-in
  2. TLS + Google sign-in to FastAPI export service: verified identity
  3. FastAPI export service to Preview cache: preview → export reuse
  4. FastAPI export service to Warehouse resolver: date range
  5. Warehouse resolver to Shopify Admin GraphQL: two-pass fetch
  6. Warehouse resolver to Stock matcher: line item + qty
  7. Stock matcher to Stock workbooks ×3: read-only, cached
  8. Warehouse resolver to Excel / CSV builders: rows + summary
  9. Excel / CSV builders to Planning team browser: .xlsx / .csv

Go deeper

The full account

Problem
Production planners needed one row per line item, each tagged with the warehouse that will actually ship it. Shopify's native export does not produce that shape, and Shopify exposes several non-equivalent 'location' values — so 'which warehouse' is a decision problem, not a field lookup.
What was built
A stateless FastAPI service where the planning team picks a date range, previews the orders in-browser, and downloads Excel or CSV — behind company Google sign-in, with nothing customer-related written to disk.
Role
Designed and built it, with Claude Code writing to my design documents. Took the requirements from the production-planning team, ruled that a warehouse is named from where units ship rather than from where stock sits, kept the stock verdict conservative and carrying its provenance, and ran the deployment and the handover to planners. My engineers now develop it further, as the credits show.
What changed
A non-technical team now self-serves data that previously required a developer to run local scripts on request.

Context

The business is made-to-order, but sometimes has matching finished stock sitting in spreadsheets maintained outside Shopify. Planners were manually cross-checking each order line against three separate Google Sheets.

The result was a developer-in-the-loop process for a routine request — the kind of dependency that looks small until you count how often it happens.

Architecture and the system

A stateless container behind Google sign-in. Identity is terminated at the proxy, the app holds no durable storage beyond a short-lived preview cache, and every external dependency is allowed to fail without taking the export with it.

Two passes, because one query is too expensive

A single fully-nested query for orders, line items and fulfillment data exceeds Shopify's 1000-point per-query cost cap. So the fetch runs in two passes: orders plus line items, then per-order fulfillment.

The HTTP client reads the throttle status from the cost extension on every response and paces against the real bucket, rather than guessing at a safe delay.

Warehouse attribution with provenance

A dedicated resolver assigns each unit to a location using the actual fulfillment location first, then the assigned fulfillment-order location — never inventory levels, which answer a different question.

A split line item fans out into multiple rows, each tagged with how the warehouse was determined: fulfilled, assigned, or Unknown. Planners can see how much to trust each row instead of receiving a confident guess.

A conservative stock recommendation

A separate module reads three stock workbooks via a read-only service account and indexes them on normalized style, colour and size — deliberately never on style ID, because season prefixes differ between systems.

It emits Yes / Partial / No / Review per line, and fails soft: if the sheets are unreachable, the export still ships without the stock column rather than failing entirely.

Stateless by design

Exports are generated in memory. Nothing customer-related is written to disk or to a database; structured logs carry order references, counts and statuses only. The GraphQL documents deliberately select no customer name, email, address, phone or payment field.

What was hard

'Which warehouse' has three plausible answers

Shopify exposes the actual fulfillment location, the assigned fulfillment-order location, and inventory levels — and they disagree. Picking an order of preference and then shipping the provenance alongside the answer turned an ambiguous field lookup into information a planner can reason about.

Matching stock across two naming systems

The stock workbooks and Shopify do not agree on style IDs, because season prefixes differ. Indexing on normalized style, colour and size instead is less elegant and considerably more correct.

A stale build shipped once

The deployment runbook records the incident and the grep freshness check added to prevent it. Writing down the pitfall that actually happened, in the runbook, is worth more than a process document nobody reads.

AI and automation

Automation

Replaces a developer running local scripts on request, and the manual cross-check of each order line against three stock spreadsheets. Line-item fan-out, warehouse attribution, split-shipment expansion, timezone conversion and the stock recommendation are all computed rather than hand-assembled.

Direction and delivery

The build is mine, made with Claude Code against my own written specification — the export's requirements, the implementation, its QA and the rollout. So are the documents: eleven numbered deliverable documents covering requirements analysis, architecture, data mapping, warehouse logic, GraphQL cost math, security controls, deployment, a deployment checklist, a non-technical end-user guide, and a prioritized roadmap that names the infrastructure each idea would add. The README carries an explicit 'caveats to verify before production' list. The operational timezone was deliberately reversed at one point, and the reason is recorded. Prada Dipa and Luthfi Aditya now develop it further.

Size signals

Application modules
25
Test functions
90
Numbered docs
11
Export columns
33
GraphQL passes
2

Counted from the source repository. No impact metric is claimed that the source does not prove.

What I would tell the next person

  • Ship provenance with an inferred value. 'Warehouse: X (assigned)' is more useful than 'Warehouse: X'.
  • Let non-critical dependencies fail soft. A missing stock column beats a failed export.
  • Record the incident that actually happened, next to the check that now prevents it.

Technologies and access

  • Python 3.12
  • FastAPI
  • Pydantic v2
  • httpx
  • tenacity
  • Jinja2
  • XlsxWriter
  • gspread
  • Docker
  • Cloud Run
  • Cloud Build
  • IAP
  • oauth2-proxy
  • Caddy
  • pytest
  • ruff

Integrations

  • Shopify Admin GraphQL (orders, fulfillment orders, fulfillments)
  • Google Sheets API (three stock workbooks, read-only)
  • Google Cloud Secret Manager
  • Google Identity-Aware Proxy

Internal service behind company Google sign-in.