SCANMAN · warehouse management software
Real-time production insights and sales orders · Rule-based today, AI-ready tomorrow · ERPNext + ScanMan + Cloudflare
C.O Designs manufactures configurable office furniture — privacy pods, acoustic booths, benching systems — in Cape Town, and sells into enterprise clients across South Africa from a Johannesburg showroom. Every order has options: sizes, finishes, fabric codes, ventilation, glazing, branding. Every order has to land on the factory floor with the right BOM, the right materials on hand, and a promised delivery date that nobody regrets.
ScanMan is a Durban-based warehouse and shop-floor scanning specialist. This explainer shows how ScanMan would deliver the full stack for C.O Designs on a rule-based foundation that is AI-ready by design: ERPNext as the system of record, ScanMan's WMS and barcode capabilities on every workstation and stock bin, and Cloudflare's edge platform — Workers, Tunnel, R2, D1, Queues, Durable Objects, Pages, Zero Trust — as the secure, fast, predictable integration and delivery layer. Every transaction is traceable, every rule is auditable, every result is the same on Tuesday as it was on Monday. And when the business is ready to layer intelligence on top — forecasting, natural-language quoting, anomaly detection — the architecture is already shaped to accept it.
Sales quotes live in Excel, the factory runs on printed job cards, and stock is reconciled monthly. When a client adds 4 more CitiPods™ mid-order, nobody knows if it delays the existing run or whether the laminate is in stock.
ERPNext is the system of record: Customer, Quotation, Sales Order, BOM, Work Order, Job Card, Stock Entry, Delivery Note. ScanMan adds barcode-driven goods receiving, put-away, picking, and Job Card scanning. Cloudflare is the edge layer — Workers for integrations, Tunnel for secure access, R2 for file storage, D1 for read-optimised dashboards, Pages for the sales and exec front ends.
A sales rep in Sandton sees the same production status as the foreman in Maitland. The exec dashboard shows "pods shipping this week" as a live chart fed directly from Work Order state — no report generation, no waiting, no ambiguity. And because every event flows through Workers and Queues, layering AI on top later is a change of inputs, not a re-platform.
C.O Designs' catalogue isn't a list of SKUs — it's a family of configurable systems. Each product line has structural parts, finish options, and optional modules. ERPNext's Product Bundle, Item Variant, and templated BOM features map directly onto this. 2nth.AI sits on top and helps sales reps and clients explore the option space in natural language.
Room-in-room acoustic pods for focused work inside open-plan offices. Configurable by footprint, ceiling type (solid, glass SkyLite™), glazing, door hardware, ventilation, lighting, upholstery, and branding. Each variant compiles to a distinct BOM with tracked sub-assemblies.
Semi-enclosed acoustic booths for collaboration and semi-private work. Lounge, canopy, and open-front configurations. Fabric selections drive lead time — some imported fabrics add 6–8 weeks that must flow into the promised ship date.
Sound-dampening panels and baffles sold as made-to-size items. Cut-to-length workflows use ERPNext's scrap management and Item UOM conversions. Imported Caimi lines are stocked differently to the Cape Town-made range.
Institutional-grade desk systems built from repeatable modules: frames, tops, screens, cable management, power units. Long orders (50+ desks) trigger multi-BOM work orders planned against shared sub-assembly capacity.
Activity-based furniture for flexible layouts. Modular table systems with site-specific footprints — quote stage needs a fast feasibility check against available leg/top combinations.
Lower-variance range often sold as add-ons to the headline pod/booth orders. These ride the same Sales Order but source from different suppliers and workstations.
Every headline product is really a family of variants. A quote for "12 × ChatterBox Classic in charcoal Divina fabric with glass doors and white oak trim" must resolve to a specific BOM, a specific materials requirement, and a specific lead time — before the client hangs up. Without structured product data, the sales team makes promises the factory can't keep. With ERPNext's BOM + Item Variant model plus 2nth.AI's brief-parsing agents, the quote-to-promise loop tightens from days to minutes.
This is the path a new enquiry takes through the combined platform. ERPNext provides every DocType and every transition. 2nth.AI accelerates the human-in-the-loop parts: reading the brief, suggesting the configuration, checking feasibility, drafting the quotation PDF.
A client emails a floor plan to quotes@codesigns.co.za. Cloudflare Email Routing forwards it to a Worker that creates an Opportunity in ERPNext via the Frappe REST API, attaches the PDF to R2, and links the file URL back to the record. Rule-based — same email, same result, every time. (AI-ready: the same Worker can later call a language model to pre-fill quantities and product intent from the PDF, without changing the surrounding flow.)
The sales rep opens the draft on the Cloudflare Pages-hosted showroom app. Product variants are picked from dropdowns backed by ERPNext's Item Variant attributes. The rep selects ChatterBox Classic in Divina Charcoal, Clear 10mm glazing, White Oak trim — a Worker resolves the exact Item code and BOM in one API call.
Before quoting, a Worker runs a rules-based feasibility check against ERPNext: on-hand stock (bin.actual_qty), open POs (PO.pending_qty), Work Centre capacity for the next 30 days, and supplier lead time tables for imported fabrics. The answer is a number — a promised ship date with a known confidence margin.
ERPNext's Quotation DocType is created with line items tied to real Item codes. A Cloudflare Browser Rendering Worker generates the client-ready PDF from the Pages template and stores it in R2. The rep reviews the signed URL and sends.
On client approval, the Quotation converts to a Sales Order (one-click in ERPNext). This is the commercial commitment. Deposit invoice is raised automatically. An ERPNext webhook lands in a Cloudflare Queue and kicks off downstream integrations.
ERPNext's Production Plan pulls pending Sales Orders, explodes BOMs, generates Material Requests for anything short, and creates Work Orders per item line. A scheduled Worker (Cron Trigger) runs bottleneck detection against a rules matrix — shared sub-assemblies, single-machine capacity — and posts alerts to the planner's dashboard.
// Sales flow, ERPNext DocType transitions Lead → Opportunity → Quotation → Sales Order ↓ Production Plan → Work Order → Job Card ↓ Stock Entry → Delivery Note → Sales Invoice
A sales order is a promise. Production insight is how the business keeps it. ERPNext's Work Order and Job Card DocTypes already track operations, quantities, start/end times, and operator assignments. 2nth.AI turns that telemetry into decisions — before problems become apologies.
Each workstation has a ScanMan-issued handheld and tablet. Operators scan a Job Card barcode to start, pause, and complete operations. Component consumption is scanned off the trolley at the bench. ERPNext records actual time vs standard and posts stock movements against the BOM automatically. No more paper routing slips going missing between the panel saw and the upholstery bench.
Because every Work Order lists the workstations it needs, the planner dashboard (Cloudflare Pages reading from a D1 mirror) shows a week-by-week capacity heatmap. Red cells mean a workstation is over 100% booked. The planner decides — the system shows the truth, no guessing.
ScanMan's receiving, put-away, and cycle-counting flows keep warehouse balances accurate in real time. Material Requests flow straight from exploded BOMs. A scheduled Worker joins required-by dates against supplier lead time tables and flags anything that will land late — the planner sees the issue 10 days out, not on the day.
ERPNext's Quality Inspection DocType attaches to Job Cards. Acoustic pods get a seal test, fabrics get a match check, electrics get a continuity test. Any failure is logged against the Work Order and visible on the same live dashboard.
"Will we ship everything we promised this month?" Today: a phone call to the factory manager, a WhatsApp to the foreman, a spreadsheet that's already out of date. On the new platform: a live dashboard on Cloudflare Pages, fed from a D1 mirror of Work Order state, showing the committed-vs-capacity picture with at-risk orders highlighted in red, and a drill-through to the specific Job Cards causing the risk. One URL, always current, always the same number for everyone looking at it.
The split is deliberate. ERPNext owns data, transactions, and the audit trail — the system of record. ScanMan owns the physical-to-digital interface — barcode capture, handheld workflows, warehouse and shop-floor UX. Cloudflare owns the edge — secure access, integrations, file storage, scheduled jobs, fast read models, and all the user-facing surfaces. Every component is rule-based and every call path is traceable. Nothing ships today that guesses. But every seam in the architecture is the exact shape an AI layer will want later — clean events, clean state, clean interfaces.
Customers, Items, BOMs, Sales Orders, Work Orders, Job Cards, Stock Entries, Invoices. Frappe Framework as the underlying app platform. MariaDB for storage. All transactional truth lives here. Exposed to the edge via Cloudflare Tunnel — no public IP, no exposed ports.
Barcode-driven goods receiving, put-away, picking, cycle counting, and shop-floor Job Card execution. Handhelds and workstation tablets. Every scan posts directly into the ERPNext DocType it belongs to — Stock Entry, Job Card, Delivery Note — with zero double entry.
Workers for API glue and webhooks. Tunnel for private ERPNext access. R2 for PDFs, photos, and attachments. D1 for read-optimised dashboards. Queues for async integrations. Durable Objects for per-Sales-Order state machines. Pages for the sales and exec front ends. Zero Trust for identity. All running at Cloudflare's Johannesburg and Cape Town POPs — fast for SA users, no cross-border data hops.
| Layer | Technology | Details |
|---|---|---|
| ERP Core | ERPNext v15 | Frappe Framework, Python backend, MariaDB, background job queue via Redis |
| WMS & Capture | ScanMan | Server + scanner software, goods receiving, stock traceability, put-away strategies, picking & delivery control, shelf-life tracking, direct ERPNext integration |
| Edge Compute | Cloudflare Workers | Stateless JS/TS functions running at every POP. Host integrations, webhook handlers, PDF generation, scheduled jobs. Rule-based execution today; the same runtime can bind to Workers AI later with a single config change. |
| Private Access | Cloudflare Tunnel | ERPNext lives on a private VPS in SA; Tunnel gives Workers access without exposing any port. Outbound-only connection from the ERPNext host. |
| Object Storage | R2 | Inbound client PDFs, quotation PDFs, install photos, signed delivery notes. S3-compatible API, zero egress fees. |
| Read Models | D1 | SQLite at the edge. Holds denormalised projections of Work Orders, Job Cards, and stock balances for dashboard queries — keeps ERPNext's MariaDB off the hot path. |
| Async & State | Queues + Durable Objects | Queues for ERPNext webhook fan-out and retries. Durable Objects for per-Sales-Order coordination (e.g. "has this SO raised its deposit invoice yet?"). |
| Front Ends | Cloudflare Pages | Showroom / sales-rep app, planner dashboard, exec dashboard, customer portal. Static-first, hydrated with Workers API calls, globally cached. |
| Identity | Cloudflare Access | Zero Trust auth for internal users (Google / Microsoft / OTP). Turnstile on public forms. Every Worker route policy-gated. |
| Shop Floor | Handheld + Tablet | ScanMan handhelds for stock movements; ruggedised Android tablets at each workstation running the ERPNext Job Card PWA through Cloudflare Access. |
| Hosting | Frappe Cloud / VPS | South Africa region for ERPNext; daily backups + hot standby. Reached only via Cloudflare Tunnel — zero public attack surface. |
One of the reasons ERPNext is the right backbone: almost every concept C.O Designs needs already exists as a DocType. Configurable products are Item Templates with Variants. Acoustic panels are cut-to-size Items with UOM conversions. Multi-step manufacturing is Operations on Routings. The work is in modelling their catalogue correctly, not in building a new ERP from scratch.
// Typical object graph for one "ChatterBox Classic x 6" order Customer ─→ Opportunity ─→ Quotation ─→ Sales Order ├─→ Production Plan │ └─→ Work Order (×6) │ ├─→ Job Card (cut) │ ├─→ Job Card (frame assembly) │ ├─→ Job Card (upholstery) │ └─→ Job Card (glaze + QC) ├─→ Material Request → Purchase Order ├─→ Delivery Note └─→ Sales Invoice → Payment Entry
Standard: all DocTypes above, default workflows, default permissions, default reports. Light custom: Item Variant attributes for fabric/glazing/size, Routing definitions per pod family, a few custom fields on Sales Order for install-site details, a custom Print Format for the quotation PDF. 2nth.AI-owned: the intake parser, the configurator, the planner co-pilot, the exec conversational agent. None of these replace ERPNext — they sit beside it and call its APIs.
Every integration in this stack runs on Cloudflare's edge platform — rule-based code, rule-based storage, rule-based scheduling. Every bug is reproducible, every behaviour is testable, every cost is predictable, and every byte of customer data stays on infrastructure with Johannesburg and Cape Town POPs. That is the foundation C.O Designs needs today.
Six Cloudflare primitives do the heavy lifting. Each one has a narrow job and a clean contract. Together they cover integration, storage, state, scheduling, delivery, and identity — everything around ERPNext that isn't ERPNext. And because the primitives are composable, adding an AI layer later — Cloudflare Workers AI, Vectorize for retrieval, AI Gateway for observability — means binding new services to existing Workers, not rebuilding the stack.
Stateless TypeScript functions at every POP. Host ERPNext webhook handlers, Email Routing receivers, Pages API backends, scheduled reconciliation jobs. Every Worker is a small, pure function: a signed webhook arrives, a defined action happens, an audit row lands. Execution is rule-based — the same input produces the same output and the same ERPNext calls, always. The same Worker runtime can later bind to Workers AI when the business is ready for inference inside the flow.
ERPNext runs on a SA-region VPS with no public IP, no open ports, no exposed admin. A cloudflared daemon on the ERPNext host makes a single outbound connection to Cloudflare, and Workers reach Frappe's REST API through that tunnel. Zero attack surface, no VPN to maintain.
S3-compatible storage with zero egress fees. Holds every inbound client brief PDF, every generated Quotation PDF, every delivery-note photo, every install sign-off. Signed URLs expose files to clients when needed. Buckets are versioned and replicated — no "where did the quote PDF go?" moments.
Edge-resident SQLite. Workers keep a denormalised mirror of the ERPNext data the dashboards need — Work Order status, Job Card timings, stock balances, Sales Order ship-readiness. Dashboards query D1, not MariaDB, so ERPNext never sees a dashboard query load spike. Sub-millisecond reads, global replication built in.
Queues absorb ERPNext webhook bursts, retry failed integrations with exponential backoff, and fan events out to downstream Workers (raise deposit invoice, notify planner, index file in R2). Durable Objects provide per-Sales-Order state machines so concurrent events can't corrupt an order's status — strong consistency where it matters.
Cloudflare Pages hosts every user-facing surface — showroom app, planner dashboard, exec dashboard, customer portal. Globally cached, instant, zero server to patch. Cloudflare Access sits in front of every internal route with Zero Trust auth (Google Workspace, Microsoft Entra, or one-time PIN). Turnstile on public forms. One identity model across everything.
User stage (today). The rule-based foundation laid out in this document. ERPNext is the system of record, ScanMan wires the factory floor to it, Cloudflare delivers the edge. Staff use the system; the system does not yet think. This is the solid ground everything else stands on.
Builder stage (next). With the data flowing cleanly through Queues and D1, purpose-built AI workflows start appearing in places where the value is obvious and the risk is contained — brief parsing, configurator suggestions, shortage forecasting. Every AI call piggybacks on a rule-based path that already works, so the fallback is always "do what we did yesterday."
Operator stage (future). AI runs the routine and humans run the exceptions. Autonomous agents co-ordinate across Sales Orders, production plans, and supplier POs, with human oversight reserved for edge cases. The architecture does not need to change — the same primitives simply carry more intelligence on top.
// Worker: ERPNext webhook → Queue fan-out export default { async fetch(req: Request, env: Env) { const evt = await req.json(); if (!verifySignature(req, env.SECRET)) return new Response("401", { status: 401 }); await env.SO_QUEUE.send({ type: evt.doctype, // "Sales Order" name: evt.name, // "SAL-ORD-0042" ts: Date.now() }); return new Response("ok"); } }
// Cron Worker: nightly bottleneck check export default { async scheduled(_e, env: Env) { const rows = await env.D1.prepare(` SELECT workstation, week, SUM(planned_hours) AS load FROM work_order_ops WHERE week BETWEEN ? AND ? GROUP BY workstation, week HAVING load > capacity * 1.0 `).bind(thisWeek, thisWeek + 4).all(); await postToDashboard(env, rows); } }
Reads inbound emails, PDFs, and showroom notes. Extracts quantities, products, site addresses, and deadlines. Creates or updates an Opportunity and attaches the source documents. Human reviews before quoting. Tools: Opportunity.create, File.upload, Customer.search.
Given a brief, proposes concrete Item Variants and Bundle selections. Resolves BOM. Calculates cost, margin, and lead time. Drafts a Quotation. Sales rep adjusts and approves before it goes out. Tools: Item.variant_lookup, BOM.get_cost, Quotation.create_draft.
Watches Work Order state and stock positions. Flags bottlenecks, material shortages, and at-risk ship dates. Suggests re-sequencing. Does not auto-reschedule — production manager decides. Tools: Work Order.list, Stock.balance, Production Plan.propose.
Conversational interface for the exec team. "What ships this week?" "Which customer has the most open value in production?" "Where are we short on laminate?" Answers from live ERPNext data with source links. Read-only. Tools: Report.run, Dashboard.query.
// Configurator agent runs on Cloudflare Workers AI // (wrangler.toml) [ai] binding = "AI" [[vectorize]] binding = "CATALOGUE" index_name = "co-designs-items" // worker.ts — invoke open model at the edge const result = await env.AI.run( "@cf/meta/llama-3.3-70b-instruct-fp8-fast", { messages: [ { role: "system", content: configuratorPrompt }, { role: "user", content: brief } ], tools: erpnextTools } );
// Agent's resolved tool call into ERPNext POST /api/method/erpnext.stock. get_item_details.get_item_details Authorization: Bearer {erpnext_token} { "item_code": "CHATTERBOX-CLASSIC-V", "attributes": { "Fabric": "Divina Charcoal", "Glazing": "Clear 10mm", "Trim": "White Oak" } } // Response — exact BOM + lead time { "item_code": "CHATTERBOX-DIVCH-CLR10-WOAK", "bom_no": "BOM-CCLASSIC-004", "rate": 42500.00, "lead_days": 21 }
Three reasons. Data residency: Cloudflare runs inference at its own edge POPs, including Johannesburg and Cape Town — customer briefs, BOM costs, and margin data don't need to travel to US-hosted APIs. Latency: an 80ms round trip to a local POP beats a 400ms round trip to us-east-1 for every interactive agent call. Open weights: Llama, Mistral, Qwen are published models, not vendor black boxes — ScanMan can fine-tune on C.O Designs' own quote history, swap models per agent, and never get held hostage by a pricing change upstream. Supporting services on the same platform: Vectorize for catalogue retrieval, AI Gateway for observability and caching, Durable Objects for per-conversation state, R2 for attached files.
ERPNext's Role Profile system gives each team member a tailored Desk. The 2nth.AI agents respect those same permissions — an agent speaking to a sales rep can't leak production cost detail, and an agent speaking to the shop floor won't expose customer margins.
Leads, Opportunities, Quotations, live lead-time lookups. Showroom app served from Cloudflare Pages, auth via Access. No access to cost detail or production plan internals.
Production Plan, Work Orders, Material Requests, Purchase Orders. Planner dashboard on Cloudflare Pages showing capacity heatmaps and shortage alerts. Sole authority to accept or re-sequence the schedule.
Assigned Job Cards only. Scan in / scan out, record quantities, flag defects, request material. No access to anything else. Tablet-first UX.
Sales Invoices, Purchase Invoices, Payment Entries, account ledgers. Standard ERPNext Accounts module. WIP value and cash-flow projections surface on the exec dashboard, refreshed from D1.
Delivery Notes, Installation Notes, sign-off photos. Mobile access only. Updates flow straight back to the Sales Order for handover to accounts.
Read-only dashboards across the whole business, served from Cloudflare Pages with D1 read models. Open one URL, see the numbers. The "no-monthly-report-needed" layer.
The fastest way to derail an ERP rollout is to try to switch everything on at once. ScanMan sequences the build so each phase delivers a working slice of value and is independently reversible.
Weeks 1–6. Stand up ERPNext. Model the catalogue: Items, Variants, BOMs, Routings for the top 3 pod families. Import customer master. Train sales on Quotation → Sales Order. Go live on sales side only. Outcome: every quote and every sales order lives in one system.
Weeks 6–14. Label the warehouse, barcode the items, roll out ScanMan handhelds for receiving, put-away, picking, and cycle counts. Tablets at each workstation for Job Card execution. Production Plan + Material Requests feeding Purchase Orders. Outcome: real-time factory and warehouse visibility, paper routing slips retired, deliveries promised against live capacity.
Weeks 10–18, overlapping. Stand up Cloudflare Tunnel, Workers, R2, D1, Queues, Pages, Access. Port the showroom app, planner dashboard, and exec dashboard to Pages. Wire ERPNext webhooks through Workers → Queues → D1. Outcome: one secure, fast, rule-based edge layer fronting everything — users, dashboards, integrations — and a clean seam ready for the AI-ready Builder stage when the business calls for it.
Every Sales Order is traceable from enquiry through install on one screen. Quotes come back same-day with realistic lead times calculated from live data. Production has zero surprise material shortages because a scheduled Worker flagged them 10 days out. The exec team has stopped asking for weekly status reports because the dashboard is always current. And the Cape Town factory and the Johannesburg showroom are finally looking at the same numbers at the same time — fast, secure, auditable, deterministic.
codesigns.co.za ↗
Cape Town head office + factory
Johannesburg satellite showroom
Office furniture & acoustic solutions since 1994
scanman.co.za ↗
34 Emoyeni Drive, Hillcrest, Durban
Warehouse management & barcode capture
Premium Build Partner of 2nth.AI
ERPNext ↗
Frappe Framework ↗
Cloudflare Workers ↗
Cloudflare Tunnel ↗
D1 · R2 · Queues ↗
A conceptual explainer by ScanMan showing how an existing manufacturer — C.O Designs of Cape Town — could operate on a rule-based, AI-ready stack: ERPNext as the system of record, ScanMan's WMS and shop-floor scanning as the physical-to-digital layer, and Cloudflare Workers, Tunnel, R2, D1, Queues, Durable Objects, Pages and Access as the edge platform. Rule-based at the User stage; architected so the Builder and Operator stages of the maturity model follow without a re-platform. Product names, trademarks, and business details belong to their respective owners.