ERPNext is the only system of record; we build tools on it
Deploy test site / deploy (push) Successful in 46s

User (October 2026): we only build tools and interfaces that interact
with ERPNext; invoices, stock and the rest are kept there, except
telemetry and other machine data.

digital-factory.md: standing decision, decisions 2, 3, 6, 7 and 10
rewritten (ERPNext holds every record of the business and of production,
including artist gates, metal-part genealogy as serial numbers with
parents, and quality inspections; the machine-data store keeps only
cycle and record rows, the hash chain and time series, keyed to ERPNext
names; ERPNext first, then custom fields or document types in cnx_erp,
then a tool, never a second business database). Systems table,
architecture labels, factory application section (modules as a table:
records in ERPNext, what we build, machine data outside; our only tables
are the machine-data ones), ownership table, integration rules 4 and 8,
phasing and estimates (cnx_erp app 2 to 3 person-months; total 3.5 to 6).
artist-platform.md: campaigns are an ERPNext document from launch, pledges
post as advance payment entries; traceability, README, facility security
(archive location on the serial number), production timeline (sets per
mother on the mother's serial number), crane-workshop spares store,
total-investment.

Factory console: KPI row no longer touches the postings card (user
screenshot); ERPNext page, order card, sidenote and ledger say every
record lives in ERPNext and only machine data stays outside; new
postings for artist gates, stamper metrology inspections, stamper set
serial numbers (grown, retired with play count). Checked headless:
Edge dark and light, 1440/1024/390, no overflow or page errors, rows
aligned, pw_fc, pw_wo, pw_feed and pw_erp pass.
This commit is contained in:
grabowski committed 2026-10-16 12:14:52 +07:00
1 parent a101c9f7db
commit 5c303dfc61
9 files changed
+188 -158

No files matched your search

+144 -126
View File
@@ -21,13 +21,19 @@ Nothing is built twice. Vendor instrument PCs (Keyence, vision controllers,
PLC HMIs) are appliances, not servers: they export into the NixOS estate
and never host a service of ours.
**Standing decision (October 2026): the whole plant runs ERPNext**,
self-hosted on a NixOS machine in the same clan. It is the master for
customers, prices, orders, money, items, stock and assets, and every tool
this plan builds (the factory application with its stations and customer
portal, the artist platform, the instrument integrations) reads from and
writes to it through one integration layer; none keeps a second master of
what ERPNext owns ([ERPNext](#erpnext-the-plants-erp)).
**Standing decision (October 2026): the whole plant runs ERPNext, and
it is the only system of record.** Self-hosted on a NixOS machine in the
same clan, it keeps every record of the business and of production:
customers, prices, orders and the artist gates, invoices and payments,
items, BOMs, stock and batches, work orders and job cards, quality
inspections, metal parts and their genealogy, deliveries, assets and the
accounts. What we build are **tools and interfaces that read and write
ERPNext** (station kiosks, the customer portal, the artist platform,
instrument adapters, reports); none keeps business records of its own.
The one exception is machine data: time series, per-cycle and per-record
rows, instrument raw files and images, audio captures. That stays in the
machine-data store on the plant core, keyed to ERPNext's document names
([ERPNext](#erpnext-the-plants-erp)).
## What the fleet already provides
@@ -66,26 +72,32 @@ TODO list or small extensions to existing modules):
already there. A failed box is replaced from a fresh disk with
`clan machines install`; a change is `clan machines update`. Nothing is
configured by hand on a running machine.
2. **Two stores, by shape of the data.** Everything with an identity
(orders, gates, genealogy, lots, press runs, per-cycle rows, QC
verdicts, events) lives in PostgreSQL on the plant core. Everything
that is a time series (1 Hz machine tags, zone environment, energy,
water) lives in a plant-local VictoriaMetrics, the same engine and
modules the fleet already runs on `control`, so dashboards, PromQL and
vmalert rules carry over unchanged. Per-cycle rows carry a snapshot of
2. **ERPNext for records, a machine-data store for machine data.**
Every record of the business and of production (orders, gates,
genealogy, lots, press runs, inspections, deliveries, money) lives in
ERPNext (decision 10). What machines produce at machine speed lives
in the machine-data store on the plant core, in two parts. Rows with
an identity that are too many for an ERP (press cycles keyed by press
and counter, per-record optical results, audio sample scores,
per-unit packaging scans, the hash-chained event log) go to
PostgreSQL, each carrying the ERPNext job card, batch and serial
numbers it belongs to. Time series (1 Hz machine tags, zone
environment, energy, water) go to a plant-local VictoriaMetrics, the
same engine and modules the fleet already runs on `control`, so
dashboards, PromQL and vmalert rules carry over unchanged. Per-cycle rows carry a snapshot of
the zone environment and the key press values, so the relational join
"this record, that cycle, those conditions" never needs the time-series
store; the curve behind the snapshot is one PromQL range query away.
(TimescaleDB in PostgreSQL is the fallback if that split proves
awkward; it is not the starting point.) Business documents (sales
orders, stock, invoices) are ERPNext's, decision 10.
awkward; it is not the starting point.)
3. **MQTT is the plant bus, Telegraf is the universal collector.** Every
machine, meter and sensor is read by a Telegraf instance on the edge
collector nearest it (Modbus, OPC UA, Siemens S7 and MQTT inputs are
stock plugins) and published to Mosquitto on the core. On the core,
Telegraf writes the stream to VictoriaMetrics (InfluxDB line protocol,
native to VM) and the factory application subscribes to the event
topics (cycle complete, alarm, instrument result) and writes rows.
topics (cycle complete, alarm, instrument result), writes rows to the
machine-data store and posts the totals and verdicts to ERPNext.
Custom code exists only where no plugin does (vision results,
instrument CSV ingestion, the audio QC pipeline).
4. **Read-only toward machines.** The data platform never writes to a PLC
@@ -96,14 +108,18 @@ TODO list or small extensions to existing modules):
machine's own cycle counter; every instrument result carries the part
serial it was read from. Wall-clock time is recorded (UTC, chrony from
the fleet baseline) but is never what two systems are joined on.
6. **Append-only, hash-chained.** Process events, gate approvals and QC
verdicts are written once and never updated; corrections are new events
that reference the old. Each event carries the hash of the previous one
so the log's integrity can be checked, which is what lets the customer
portal be trusted.
7. **The customer portal is a view, not a copy.** It reads the same
database through the same application with a customer role; there is
no exported report to keep in sync.
6. **Append-only, hash-chained.** Machine events are written once and
never updated; corrections are new events that reference the old. Each
event carries the hash of the previous one so the log's integrity can
be checked, and records the ERPNext document it led to. In ERPNext,
gate approvals, quality inspections, job cards and stock entries are
submitted documents: a correction is a cancel and amend that keeps
both, with ERPNext's version history. Together that is what lets the
customer portal be trusted.
7. **The customer portal is a view, not a copy.** It reads the
customer's records in ERPNext and the machine data of the same orders
through one portal tool scoped to the ERPNext customer; there is no
exported report to keep in sync.
8. **The plant runs without the internet.** Everything that pressing,
QC and traceability need is on site. A WAN outage stops only the
customer portal, off-site backup, fleet monitoring and remote support,
@@ -116,28 +132,33 @@ TODO list or small extensions to existing modules):
live feedback loops that the staff use to improve production, rather
than only for management reporting, decide whether a plant succeeds
([exhibitor briefing](suppliers/making-vinyl-europe-2026-exhibitors.md#after-the-show)).
10. **ERPNext owns the business, the factory application owns the floor.**
ERPNext holds every business document (customer, sales order, work
order, job card, batch, quality inspection, stock entry, delivery
note, invoice, asset); the factory application holds what happens at
machine speed (cycles, per-record inspection, metrology, genealogy,
gates, the hash-chained log) and posts results to ERPNext in
business-sized pieces. ERPNext document names are the keys both sides
share ([ERPNext](#erpnext-the-plants-erp)).
10. **ERPNext is the system of record; we build tools and interfaces.**
(October 2026.) Invoices, stock and every other record of the
business and of production live in ERPNext: customer, sales order,
artist gate, work order, job card, batch, quality inspection, serial
number per metal part with its parents, stock entry, delivery note,
invoice, asset. What we build reads and writes those records; the only
data kept outside is machine data (decision 2), which ERPNext receives
as totals and verdicts per job card, run, batch and shipment. A new
need is met with a standard ERPNext document type first, then with
custom fields or a custom document type in our `cnx_erp` app, and only
then with a tool of ours that still keeps its records in ERPNext;
never with a second database of business records. ERPNext document
names are the keys everything shares ([ERPNext](#erpnext-the-plants-erp)).
## The systems on one page
| System | What it does | Runs on | Phase |
|---|---|---|---|
| Site gateway | PPPoE WAN, VLAN zoning, DHCP/DNS, NTP for the site, internal TLS proxy, CrowdSec | `gw-<site>-1` (existing `cnx.router` module) | Build |
| Plant core | PostgreSQL, Mosquitto, Telegraf persister, VictoriaMetrics + vmalert + Grafana, Alertmanager, factory application, file datasets on ZFS | `vinyl-core` | Build |
| Factory application | Orders, gates, genealogy, materials, press runs, QC verdicts, packaging, fulfillment, customer portal, audit log; the ERPNext integration layer | `vinyl-core` | Build (v1), Launch (v2) |
| ERPNext | Accounting with Thai VAT and withholding tax, customers, prices, sales and purchase orders, items, BOMs, work orders and job cards, stock and batches, incoming quality inspections, assets and maintenance, payroll | `vinyl-erp` | from the first capex invoice; manufacturing at commissioning |
| Plant core | Machine-data store (PostgreSQL for cycle and record rows, VictoriaMetrics + vmalert + Grafana for time series), Mosquitto, Telegraf persister, Alertmanager, factory application, file datasets on ZFS | `vinyl-core` | Build |
| ERPNext | The system of record: accounting with Thai VAT and withholding tax, customers, prices, sales and purchase orders, artist gates, items, BOMs, work orders and job cards, stock and batches, quality inspections, metal parts and their genealogy, deliveries, assets and maintenance, payroll | `vinyl-erp` | from the first capex invoice; production records at commissioning |
| Factory application | The tools and interfaces we build on ERPNext: station kiosks working the job cards, customer portal, machine-data service (cycles and per-record results in, totals and verdicts to ERPNext), instrument adapters, reports; the ERPNext integration layer. No business records of its own | `vinyl-core` | Build (v1), Launch (v2) |
| Edge collectors | Telegraf per machine zone, disk-backed store-and-forward, NTP to the OT segment, vision result receiver | `vinyl-edge-press`, `vinyl-edge-util`, `vinyl-edge-galv` | Build, Expand |
| Environmental monitoring | Zone temperature, humidity, PM, differential pressure; alarms; correlation with production | RS485 loops into the edge collectors | Build |
| Machine telemetry | Presses, extruders, hydraulics, boiler, chiller, compressor, heat pump, HVAC, PV, BESS, energy and water meters | edge collectors | Build |
| QC instrument integration | Optical inspection results and images, metrology CSV ingestion, PVC lab entries, audio QC scores, packaging scans | stations plus `vinyl-edge-press` | Launch, Expand |
| Station kiosks | Badge check-in and scanning at each manual step; kiosk browser on the factory application | `vinyl-st-*` | Build |
| Station kiosks | Badge check-in and scanning at each manual step against the station's ERPNext job card; kiosk browser on the factory application | `vinyl-st-*` | Build |
| Process alerting | Environment, utilities, reject rate, stamper life, PV/BESS, fire and BESS detection contacts, UPS, data silence; delivered to phones | `vinyl-core` (vmalert + Alertmanager) | Build |
| Fleet monitoring | Host metrics, journals, host alerts for every plant machine | `control` (existing) | Build |
| Backup and DR | ZFS snapshots and replication, Borg to the plant backup server and off site, PostgreSQL point-in-time recovery, restore drills | `vinyl-backup`, off-site destination | Build |
@@ -169,8 +190,8 @@ flowchart LR
subgraph L2[Plant core, NixOS, servers VLAN]
MQ[Mosquitto]
VM[(VictoriaMetrics<br/>vmalert, Grafana)]
DB[(PostgreSQL)]
APP[Factory application]
DB[(PostgreSQL<br/>machine data)]
APP[Factory application<br/>tools on ERPNext]
AM[Alertmanager]
ERP[(ERPNext<br/>vinyl-erp)]
end
@@ -507,12 +528,17 @@ same watcher pattern as the metrology exports below. See
## The factory application
Working name `cnx-factory`, its own repository. Server-rendered web
application in Rust (axum, SQLx, minijinja templates, HTMX) on PostgreSQL,
the stack B4L already uses for its other in-house tooling, with the same
append-only ledger and hash-chained audit log pattern. It subscribes to
the MQTT event topics (cycle complete, machine alarm, instrument result)
and owns every write to the identity tables; Telegraf owns the writes to
Working name `cnx-factory`, its own repository: **the tools and
interfaces we build on ERPNext**, not a second system of record.
Server-rendered web application in Rust (axum, SQLx, minijinja templates,
HTMX), the stack B4L already uses for its other in-house tooling. Every
business and production record it shows or changes is read from and
written to ERPNext through the integration layer
([ERPNext](#erpnext-the-plants-erp)). The only data it owns is the
machine-data store: it subscribes to the MQTT event topics (cycle
complete, machine alarm, instrument result), writes cycle and record rows
to PostgreSQL with the append-only, hash-chained event log, and posts
totals and verdicts to ERPNext; Telegraf owns the writes to
VictoriaMetrics. Packaged as a flake so the clan repo pins it as an input.
**Demo.** [Factory console and order status](factory-console.html) (test
@@ -530,91 +556,75 @@ gates, copies pressed so far, the lab certificate of the compound lot,
listening checks). All orders, values and IDs are simulated; limits are
illustrative until the acceptance specifications are written.
Modules, in build order:
Modules, in build order. Each keeps its records in ERPNext; the last
column is the machine data it keeps outside.
1. **Orders and releases**: customer, order, release, sides, formats, run
quantity, bill of materials (record, inner sleeve, jacket, inserts,
shrink), due dates.
2. **Audio intake and the client vault**: upload via portal or SFTP with
checksums, versions, handler, technical QA form; files in an encrypted,
access-logged dataset separate from everything else.
3. **The three artist gates**: master plan, master, test pressing; each is
an event with who approved, when, from which portal session or on whose
verbal instruction, and nothing downstream is schedulable without it.
4. **Mastering and cutting sessions**: engineer, chain settings, lacquer
IDs, dead-wax scribe text and fiducial applied, microscope check result.
5. **Metal genealogy**: lacquer to father to mother to stamper, or bridged
supplier plus batch; per-part metrology history; stamper lifecycle
(mounted on which press, play count, retired why), archive location
(box and shelf position in the mobile shelving,
[facility security](facility-security.md#archive-room-mobile-shelving)),
stamper sets grown per mother.
6. **Materials**: PVC lots with the lab gate and CoA, regrind batches,
label lots with print inspection and oven pre-dry, carton and sleeve
lots with incoming QC.
7. **Press runs and cycles**: a run binds order, stamper pair, press,
operator, shift, PVC lot in the hopper, regrind batch, label lot; each
cycle event from the PLC becomes a row keyed by press + counter with
the key press values and the zone environment snapshot; the record key
is derived from it per side.
8. **QC verdicts**: optical per record, audio per sampled record, lab per
lot, packaging per unit; reject reasons; test-pressing hold state.
9. **Finishing, packaging, fulfillment**: assembly checks, consignment
against the BOM, carrier and tracking per shipment or dropship end
customer.
10. **Customer portal**: per-order timeline of everything above, scoped so
one customer sees only its own orders; PDF export of the trace. The
public front of order intake (price calculator, uploads with
automatic checks, fan-funded campaigns) is planned in
[artist platform](artist-platform.md), including why its public
side should not depend on the plant's WAN link.
11. **Reports and signals**: yield per stamper, reject rate drift, audio
score trend versus play count (the automatic retirement signal),
energy per record, environment excursions overlaid on runs (the
curves fetched from VictoriaMetrics for the run's window).
| # | Module | Records in ERPNext | What we build | Machine data, outside ERPNext |
|---|---|---|---|---|
| 1 | Orders and releases | Customer, Sales Order, an Item and BOM per release and format (record, inner sleeve, jacket, inserts, shrink), custom Release and Side documents, due dates | order intake on the artist platform, order views | none |
| 2 | Audio intake and the client vault | custom Audio Asset document per file version: checksum, handler, technical QA form | upload via portal or SFTP with automatic checks | the audio files, in an encrypted, access-logged dataset separate from everything else |
| 3 | The three artist gates | custom Artist Gate document per gate (master plan, master, test pressing), submitted on approval: who, when, from which portal session or on whose verbal instruction; the next job card cannot start without it | approve and report-a-problem in the portal | none |
| 4 | Mastering and cutting sessions | Job Card with custom fields: engineer, chain settings, lacquer serial numbers, dead-wax scribe text and fiducial, microscope check | mastering and cutting-room kiosks | lathe logs, microscope images |
| 5 | Metal genealogy | Serial No per lacquer, father, mother and stamper with its parent (or the bridged supplier and batch), its warehouse (archive with box and shelf position in the mobile shelving, [facility security](facility-security.md#archive-room-mobile-shelving); rack; press), play count and retirement reason, stamper sets grown per mother; a Quality Inspection per measured part | plating, stamper-prep and archive scanning | Keyence and XRF raw files |
| 6 | Materials | Batch per PVC lot, regrind batch, label lot, carton and sleeve lot; Purchase Receipt; Quality Inspection for the lab gate (CoA attached), label print inspection and incoming QC; Stock Entry into the hopper | lab station, goods-in scanning | instrument raw files |
| 7 | Press runs | Job Card per run: press (workstation), stamper serial numbers, operator, shift, batches consumed, good and rejected quantities; Downtime Entry per stop; Stock Entry (manufacture) at the end | press-side kiosk, the machine-data service | every cycle as a row keyed by press + counter with the key press values and the zone environment snapshot; the record key is derived from it per side |
| 8 | QC verdicts | Quality Inspection per run, batch and test pressing with reject reasons; flagged listening checks with the engineer's verdict; the test-pressing hold | QC views, listening station | optical result and image per record, audio captures and scores per sampled record, packaging scan per unit |
| 9 | Finishing, packaging, fulfillment | packing Job Card, Delivery Note, Shipment with carrier and tracking per consignment or dropshipped end customer, Sales Invoice | packing and dispatch kiosks | per-unit assembly scans (dead-wax code against jacket barcode) |
| 10 | Customer portal | reads the customer's records above, scoped to the ERPNext customer; PDF export of the trace | the portal | reads the machine data of the customer's own orders |
| 11 | Reports and signals | ERPNext reports for money, stock and work orders | yield per stamper, reject-rate drift, audio score versus play count (the automatic retirement signal), energy per record, environment excursions over runs | the curves from VictoriaMetrics for the run's window |
Core entities: `customer`, `order`, `release`, `side`, `audio_asset`,
`gate_approval`, `session`, `lacquer`, `father`, `mother`, `stamper`,
`stamper_measurement`, `press`, `press_run`, `press_cycle`, `record`,
`optical_result`, `audio_result`, `pvc_lot`, `regrind_batch`, `label_lot`,
`carton_lot`, `lab_result`, `packaging_check`, `shipment`, `operator`,
`shift`, `event` (the hash chain).
The public front of order intake (price calculator, uploads with
automatic checks, fan-funded campaigns) is planned in
[artist platform](artist-platform.md), including why its public side
should not depend on the plant's WAN link.
Where a module touches a business document, the document is ERPNext's
and the module holds its production side: the order is an ERPNext sales
order, a run is a work order, each station step is a job card, a PVC lot
is a batch with its quality inspection, a shipment is a delivery note
([ERPNext](#erpnext-the-plants-erp)).
The machine-data store has the only tables we own: `press_cycle`,
`record`, `optical_result`, `audio_result`, `packaging_scan`,
`instrument_file`, `event` (the hash chain), each carrying the ERPNext
names it belongs to (job card, batch, serial number). In ERPNext the
`cnx_erp` app adds the custom document types Release, Side, Audio Asset
and Artist Gate, and custom fields on Job Card, Serial No, Batch and
Quality Inspection; everything else is a standard ERPNext document type.
Stations use the same application in kiosk mode: an operator taps a badge
(the same card the access-control system issues, so one ID) and scans
whatever the step asks for. No forms longer than one screen.
whatever the step asks for; each confirmation is a time log or a
completed quantity on the station's ERPNext job card. No forms longer
than one screen. The office works in ERPNext's own desk (purchasing,
accounts, stock counts, planning); we build an interface only where the
desk does not fit the work.
## ERPNext: the plant's ERP
Decided October 2026: **the whole plant runs ERPNext**, the open-source ERP
on the Frappe framework (GPLv3, no licence fee; version 15 is the current
stable line). It closes the item this plan had left for after launch, and
it sets a rule for everything we build: **every tool has to interact with
ERPNext**, through the integration described here.
it sets the rule for everything we build: **ERPNext is the system of
record, and what we build are tools and interfaces that interact with
it**, through the integration described here. Invoices, stock and every
other record of the business and of production are kept in ERPNext; only
machine data (telemetry and the other machine-speed data of decision 2)
is kept outside it.
### Who owns what
| Object | Master | The other side keeps |
|---|---|---|
| Customers, contacts, addresses | ERPNext | the factory application scopes the portal by the ERPNext customer; the artist platform links each account to one |
| Price list, item prices, pricing rules | ERPNext | the artist-platform calculator reads them; the demos' price list becomes an ERPNext price list |
| Quotations, sales orders, invoices, payments (fan pre-orders in the ring-fenced account included) | ERPNext | the artist platform creates them; the factory application reads the order |
| Items and BOMs: one item per release and format (record, sleeves, jacket, labels, compound per copy), raw materials and packaging | ERPNext | the factory application reads the BOM of the run |
| Work order per press run; job cards per operation (cutting, plating, stamper prep, test pressings, pressing, packing); workstations (presses, lathe, plating cells, Sibert line, packing) | ERPNext | the stations' work orders are these job cards: kiosk scans and times post back as time logs and completed quantity |
| Stock: compound lots as batches, label and carton lots, finished goods, warehouses including the archive | ERPNext | the factory application knows which lot sat in which hopper for every cycle and posts the consumption |
| Incoming lab gate per compound lot | Quality Inspection in ERPNext, with a template carrying the parameters and limits of [quality automation](quality-automation.md) | instrument files and the CoA scan in the factory application |
| Metal parts: lacquers, fathers, mothers, stampers | serial numbers in ERPNext for location and value (warehouse: archive, rack, press) | genealogy, metrology, play counts and stamper sets per mother in the factory application |
| Gates, per-cycle rows, per-record optical results, audio scores, telemetry, environment, the hash-chained event log, client audio | factory application and VictoriaMetrics only: thousands of rows a day are not ERP documents | ERPNext gets the totals: good, rejected and scrap to regrind per job card and run |
| Stops | Downtime Entry in ERPNext per stop (workstation, reason, from, to) | the PLC detail |
| Deliveries | delivery notes in ERPNext | carrier and tracking per consignment on both sides |
| Assets: presses, lathe, galvanics, Sibert line, utilities, PV and BESS, IT | ERPNext asset register, depreciation, maintenance schedules | telemetry and run hours |
| Purchasing, suppliers, accounting, Thai VAT and withholding tax, payroll | ERPNext, with the HR app for payroll | nothing |
| Object | In ERPNext | Outside ERPNext (machine data) | Our tools |
|---|---|---|---|
| Customers, contacts, addresses (fans who buy included) | Customer, Contact, Address | none | the portal is scoped to the ERPNext customer; the artist platform links each account to one |
| Price list, item prices, pricing rules | Price List, Item Price, Pricing Rule | none | the artist-platform calculator reads them; the demos' price list becomes an ERPNext price list |
| Quotations, sales orders, invoices, payments (fan pledges in the ring-fenced account included) | Quotation, Sales Order, Sales Invoice, Payment Entry | none | the artist platform creates them |
| Releases, audio versions, the three artist gates | custom Release, Side, Audio Asset and Artist Gate documents | the audio files, in the client vault | portal upload and approval |
| Items and BOMs: one item per release and format (record, sleeves, jacket, labels, compound per copy), raw materials, packaging, spares | Item, BOM | none | none |
| Work orders, job cards per operation (mastering, cutting, plating, stamper prep, test pressings, pressing, packing), workstations | Work Order, Job Card with time logs and quantities, Operation, Workstation | none | the station kiosks work the job cards |
| Stock: compound lots, regrind, label and carton lots, finished goods, spares, warehouses including the archive | Batch, Purchase Receipt, Stock Entry, Warehouse | which lot sat in which hopper for each cycle | lab and goods-in stations, the machine-data service posts consumption |
| Lab gates and inspections | Quality Inspection per batch, run, stamper and test pressing, with templates carrying the parameters and limits of [quality automation](quality-automation.md); CoA attached | instrument raw files and images | instrument adapters create the inspections |
| Metal parts: lacquers, fathers, mothers, stampers | Serial No with its parent, location (archive box and shelf, rack, press), play count, retirement, sets per mother | metrology raw files | plating, prep and archive kiosks |
| Press runs and stops | Job Card per run (good, rejected, scrap to regrind), Downtime Entry per stop (workstation, reason, from, to) | per-cycle rows, PLC telemetry | the machine-data service posts the totals |
| Per-record inspection, audio samples, packaging scans | totals and verdicts per run, the engineer's verdict on each flagged sample | every record's optical result and image, audio captures and scores, per-unit scans | QC views |
| Environment, energy, utilities | energy per record in reports, from totals | VictoriaMetrics time series | Grafana, alerting |
| Deliveries | Delivery Note, Shipment (carrier, tracking) | none | dispatch kiosk |
| Assets: presses, lathe, galvanics, Sibert line, utilities, PV and BESS, IT | Asset, depreciation, Asset Maintenance, maintenance schedules | run hours, alarms | none |
| Purchasing, suppliers, accounting, Thai VAT and withholding tax, payroll | ERPNext, with the HR app for payroll | none | none |
### How every tool interacts with it
@@ -634,9 +644,10 @@ ERPNext**, through the integration described here.
3. **Business-sized postings.** Per job card, per run, per lot, per
stop, per shift. Never per record or per cycle.
4. **ERPNext names are the shared keys** (sales order, work order, job
card, batch, serial number). The factory application keeps its own IDs
for records, cycles and parts and stores the ERPNext name beside them;
the record key on the sleeve never changes.
card, batch, serial number). The machine-data store has keys of its
own only for cycles and records (press + counter, and the record key
on the sleeve, which never changes) and stores the ERPNext names
beside them.
5. **Customisation as code.** Custom fields, document types, print
formats and webhooks ship as one Frappe app in our Gitea (working name
`cnx_erp`), installed and upgraded by the deployment, never clicked
@@ -650,8 +661,10 @@ ERPNext**, through the integration described here.
same outbox. No ERPNext endpoint is published.
8. **New tools follow the same rule.** A dashboard, a script or a kiosk
app built later uses the same client and an integration user of its
own. A tool that cannot read from or write to ERPNext this way is not
finished.
own, and keeps its records in ERPNext. A tool that cannot read from or
write to ERPNext this way is not finished; a tool with its own
database of business records is not allowed. Machine data is the only
exception.
### Hosting on NixOS
@@ -707,16 +720,21 @@ ERPNext**, through the integration described here.
build's cost entries in proplan (project CNX-01) are the source for
capitalising the plant at handover.
- **Commissioning and launch:** items, BOMs, workstations, inspection
templates, work orders and job cards; stations post job cards.
- **Expand:** serial numbers for in-house metal parts; payroll if it did
not start earlier.
templates, releases and artist gates, work orders and job cards, serial
numbers for every metal part (bought stampers as well as our own);
stations work the job cards.
- **Expand:** payroll if it did not start earlier.
Estimates: no licence; `vinyl-erp` 2,000 to 4,000 USD of hardware (none
if it runs as a VM); ERPNext configuration (chart of accounts, Thai tax,
items, BOMs, workstations, inspection templates, print formats) 1 to 2
person-months or a partner quote; the integration and the `cnx_erp` app
1.5 to 2.5 person-months; Nix packaging and the clan module 0.5 to 1
person-month.
(custom documents for releases, sides, audio assets and gates; custom
fields on job cards, serial numbers, batches and inspections) 2 to 3
person-months; Nix packaging and the clan module 0.5 to 1 person-month.
The factory application's own estimate shrinks by what ERPNext now holds
(orders, stock, genealogy, inspections, shipping); re-estimate both once
the dev ERPNext runs.
## Observability and alerting
@@ -917,7 +935,7 @@ options, which come back with the quotes. Fleet pieces already paid for
| off-site backup storage, per year | 100 to 500 |
| **Hardware total** | **~34,000 to 68,000** |
| `cnx-factory` to v1 (orders through shipments, stations, portal) | 4 to 6 person-months |
| ERPNext: configuration with Thai tax, the integration and the `cnx_erp` app, Nix packaging | 3 to 5.5 person-months, or a partner quote for the configuration |
| ERPNext: configuration with Thai tax, the integration and the `cnx_erp` app, Nix packaging | 3.5 to 6 person-months, or a partner quote for the configuration |
| Clan modules, router extensions, collectors, dashboards and rules to commissioning | 1 to 2 person-months |
| Vision, metrology and audio pipeline integration (Launch and Expand) | 3 to 5 person-months, plus integrator fees in the vision quote |