SERIALWORKS Inventory Control Source of truth

Today

What needs somebody, read off the same screens that fix it

Stock

Raw materials, accessories and finished silencers
SKUDescriptionTypeOn hand WebsiteDriftState

Website stock

Runs by itself. This screen is the record of what it did.
Checking…

Sync log

Reconciliation

Four systems, one part at a time, and a person deciding.

What is being compared, and against what

These systems do not count the same thing, and pretending they do is how a reconciliation screen ends up permanently, arithmetically wrong. This system distinguishes what is owned (including a pallet at the anodiser), what is on the premises, what is sellable, and what is available after reservations. Each source is compared against the one that means the same thing it does.

The sources

A system with nothing to say says so. It is never a zero.
SystemCompared againstHow it arrived CapturedRowsState

Load what a system says

The spreadsheet has no live connection and this product is not building one — export it and drop the file here. QuickBooks and the storefront are read through their connectors when they are configured; until then an export works the same way. The first row must be a header, and one column has to be a part code.
Nothing is overwritten by either button.

Matches waiting on a person

Confirm once and no run asks again. A refusal is remembered too.
SystemThey call itProposed part They sayWe sayDecide

In one system and nowhere else

A part that lives only in the Sheet was never set up here.
SystemCodeDescription They sayWhy it did not matchSay which part

Every part, biggest money first

Because that is the one that gets fixed first.
SystemPartThey call itMatchedCompared on We sayThey sayGap WorthStateDecide

Is the gap closing

Every run is kept. That is the only way to answer this.
RunWhenDiffersOnly there Only hereAmbiguousMoney apart

Movements

Every change ever made. Corrections are new rows — nothing is edited or deleted.
WhenSKUChangeWhyBinRecorded by

Bins and shelves

One bin, one part. That is what lets the floor scan once instead of twice.
LocationBinAssigned partOn hand Parts in itChange
A bin can only be re-assigned when it is empty, so the sticker on the shelf and the contents of the shelf can never disagree. Re-assigning tells you to reprint the label — do that before anything goes back in.

Labels

QR encodes an internal token, never the SKU text — rename without reprinting.

Build

A build consumes components and produces the finished unit in one movement.

Start a build

Nothing moves from here. This reads back what the build would consume and what is short, and the commit button lives on that answer.
Components come out of stock at this location, so the location is part of the question, not a detail.

Open a work order

A work order is the intention to build. It moves no stock — the build does that, later, against this order.

Shop load

Minutes of committed work against the hours each machine actually has

Open orders and when they are due

OrderPartLeft to makeMinutes DuePrioritySet byChange

What we make

PartDescriptionComponents OperationsUnit costAt a run of On hand
Unit cost is the STORED cost, computed at the run size in the column beside it. The cost in the build panel below is for the run you are about to make, at the quantity you typed — setup is charged once per run, so those two numbers differ and neither is wrong. "Cost & BOM" opens the part on the Costing screen, where the components, the operations and the minutes are, and where they are edited.

Unit Register

Every numbered unit, where it is now, and what has happened to it.
SerialPartStateWrite-up WhereMarkedBy

Marking setup

The shop’s own marking procedure and marking address, as data.

Lots and Heats

Which melt the metal came from, and what it turned into

A vendor says a heat is bad. What did we ship out of it?

Type the heat number off the mill cert. This follows the metal forward through every build it went into — including through a blank that went into a can — and lists the serials that contain it, plus what is still on the shelf.

How much has a heat behind it

Stock counted in at go-live has no mill cert and never will.
PartDescriptionOn hand With a heatNo heat on record Heats

Record a heat

Use this when the mill cert turns up after the delivery, or when somebody walks the bar rack and writes down what is actually on each shelf. It moves no stock — it says which of the stock already in that bin is this heat.

Every lot

Spent ones stay in the list — they are what a recall is about.
HeatPartKindCertVendor ReceivedOn handWhere
A lot marked untraced is not a melt. It is this system's word for stock with no heat number on record — counted in at go-live, or received before the mill cert arrived. It is listed rather than hidden, because a trace that quietly left it out would be claiming coverage this system does not have.

Transfers and counts

Stock between buildings, counts held for review, and corrections with a reason

Move stock to another building

A transfer is one document with two legs. Shipping takes the stock off the shelf at one end and puts it in this shipment's own bin, which is owned but not available — it is not sellable, not pickable, and it is still on the balance sheet. Receiving takes it out of there and puts it on a shelf at the other end. Between the two it is somewhere, which is the whole point.
Raising it moves nothing. The van leaves when somebody presses Ship.

Transfers

TransferFromToReferenceState ShippedReceivedOn the truck ValueAge

Counts waiting for review

A count that moves less than the threshold posts on the handset the moment the counter presses save, exactly as it always has. This queue is only the big ones. The person who counted cannot approve their own count: the server refuses it whichever door the request comes through, and the floor credential cannot reach the review at all. Both names are on the record afterwards.

Count variance

Counted against expected, by part and by counter
CounterCountsWith a variance Units outValue out
PartDescriptionCounts Units outValue moved

Corrections

Every one of them, with the reason it was posted under
Corrections are posted from the part itself — open a part on the Stock screen and use "Correct the count", where the bin and the standing figure are already in front of you. A reason is required and comes from this shop's own list; change the list under
WhenReasonNotePartBin ChangePosted by

Material plan

On hand, less what is spoken for, plus what is coming — and what to buy

What to buy

A suggestion. Nothing here raises an order.
PartDescriptionBuyBy VendorLast priceRoughly
These are suggestions and nothing else. The quantity clears the shortfall and brings the part back up to its reorder point, so the same part is not short again next week. Raise the order on the Purchasing screen, where a person is looking at it — a planning screen that places orders is a planning screen nobody trusts twice.

The arithmetic

Have Wants it Coming Leaves
PartStateDescription On hand WorkSalesAll of it OrderedMaking TransitVendor ProjectedReorder Needed by
Stock that is already allocated to a customer order is shown on the row it belongs to but is never subtracted here: the order that reserved it is already in the sales-order column, and taking it off twice would paint every part with an order against it red.

Outside processing

Work that leaves the building, what it costs, and what it was supposed to cost

Steps somebody else does

A routing operation, a vendor, and the price it is quoted at
PartOpWhat they doVendor StandardPer unit madeTurnaround Out now
The step itself is written on the Costing screen, in the routing, where the rest of the operations live — an outside step is a step in the routing and not a document beside one. What is set here is who performs it and what they charge. An outside step carries a price and not machine minutes: the vendor's oven is not your capacity, and minutes on it would book somebody else's machine against your own shop-load chart.

Send parts out

This raises a purchase order for the process, moves the parts into the vendor's own location, and keeps their heat numbers on them. They stay yours the whole time: on the balance sheet, off the shelf. Nothing is consumed and nothing is sold.

Jobs

JobPartVendorWhat they doState SentBackStill out Value outAge

Standard against actual

JobPartVendorProcessed StandardActual DifferenceA piece
The standard is what the estimator put on the operation; the actual is what the buyer agreed on the order. The gap is what a quote is out by. The actual charge lands on the parts through the same value ledger the freight vouchers use, so it reaches the cost of the material rather than disappearing into an expense.

Sales

Who ordered what, what is reserved for them, what has gone, what is owed

Raise an order

Prices come from the customer's own price level — a dealer and a distributor pay different numbers for the same can, and typing over a line price is allowed when a deal is a deal. Raising an order reserves nothing: allocation is the next step, and it is deliberately separate.
It starts as a draft. Confirm it when the customer says yes — nothing is reserved before that.

Orders

OrderCustomerHow they buyTheir refState OrderedReservedShipped ValueInvoiced

Free to promise

On the shelf, less what is already reserved against an order
A reservation moves nothing. Stock allocated to an order is still in its bin, still on the count sheet and still on the balance sheet — it is simply not available to the next customer. For a serialised part the number that matters is numbered cans free: a can that has not been marked cannot be promised, because the register cannot say which one it is.
PartDescriptionListOn the shelf ReservedFree to promiseNumbered cans free

Customers

Direct, dealers and distributors — one account, three ways of buying

Add or correct an account

An existing code is corrected rather than duplicated. Accounts are retired, never deleted, and an account with an order still running cannot be retired at all.
CodeNameHow they buyLevelTerms OrdersOpenInvoiced

Invoices

An invoice is raised for what SHIPPED, at the order price — the mirror of the vendor bill a receipt raises on the buying side. A distributor's order going out in three lots produces three invoices for three amounts, and a quantity already invoiced is never invoiced twice. Pressing this twice raises nothing the second time.
InvoiceOrderCustomerTermsDated DueAmountState

Web orders

A storefront order arrives as an order, not as a number going down
The stock sync reads quantities and writes them back; that half is unchanged and still on the Website stock screen. This is the other half. A wc/v3 order webhook posts straight to /api/woo/orders and lands as a sales order with the customer, the lines and the price they actually paid. Set the webhook's Secret in WooCommerce > Settings > Advanced > Webhooks and give the same value to this instance as WOO_WEBHOOK_SECRET. WooCommerce signs every delivery with it, and that signature is how this door tells your store from a stranger — a delivery that arrives without one is refused, because an unsigned order is an order anyone on the internet can place. Pull is the backstop, because WooCommerce disables a webhook after seven consecutive failed deliveries and says nothing. An order that arrives twice is one order.

Reports

Rows, not dashboards. Everything here opens in Excel.

Purchasing

Raise an order, or let a vendor PDF be read into one. Nothing becomes an order until somebody confirms it.
Order acknowledgements, invoices, packing lists. Scans are read with OCR.

Purchase orders

OrderVendorTheir refOrdered LinesValueStatus

Costing

Material plus machine time plus labour plus overhead. Setup is charged per run.

What a part costs, and why

The total, then the lines that produced it — this component, this many, this much scrap; this operation, this machine, these minutes, at this rate. Both are editable.
A second run size to price beside the part's own, so you can see what the setup is worth spread thinner. Put the run you are actually being asked to quote.
Setup is charged once per run, so the run size is most of the answer. The part's own standard lot is used when it has one.

Inventory value

The run size the re-cost assumes for every part that has no standard lot of its own. Raise it and setup spreads over more units, so stored unit costs and the value of the stock on the shelf fall with nothing physical having changed. Set it to the run the shop actually builds at.
PartDescriptionTypeOn hand Unit costAt a run ofSourceValue

Did the rates come back?

What the rates collected, against what the shop actually spent.

Record what the shop actually spent

Typed by hand, because that is the only version that works today — the QuickBooks connector is in stub mode. Anything automatic later adds rows beside these; it never replaces them.
What left the bank in this period for that category, off the invoice or the bookkeeping. One row per category per period, so a 6,500 rent quarter and a 1,200 insurance quarter stay tellable apart.
Absorbed is never typed — it is derived from what was actually built, through the same decomposition the quote came off. Only the spending side needs a human.

Open a period

A period records the plantwide basis and rate it is measured on, as they stand today. Change the rate afterwards and this period still reports on the one the quotes actually came off.
Periods may not overlap. Two periods over the same week would each claim the same builds and each report a variance on them.

The machinery behind those numbers

Machine rates, overhead, and the freight that arrives two weeks late.

Overhead: the two pools, and the line between them

Tier one is each machine's own hour rate, recorded below. Tier two is this plantwide rate, for cost no machine can be blamed for. A cost belongs to exactly one of them — charged in both, it is absorbed twice and every quote goes out heavy.
Pick whichever one moves when the shop gets busier. Where the machines do the work, that is machine hours. A shop that is mostly hand assembly is on labour hours.
A year of the cost ticked below, divided by a year of that basis — the same basis hours, added up across every machine. A four-machine suppressor shop with 5,600 basis hours and a 78,400 plantwide pool is 14.00 an hour.
Margin, not markup. price = cost ÷ (1 − margin), so 40 here on a cost of 100.00 lists at 166.67, not 140.00. 38 is a normal target for a suppressor shop and makes the list price cost ÷ 0.62.
Margin or markup, and which of them this is

This box is margin. Margin is measured against the price; markup is measured against the cost. A part costing 100 sold at 150 is a 50% markup and a 33.3% margin — same transaction, two numbers, and they are never equal.

Type a markup in here and the list price comes out low, every time, by more the higher the number: intending 40% markup and typing 40 gives a price of 166.67 instead of 140. Nothing on any screen will look wrong. You will simply be about 16% cheaper than you meant to be, on everything, until somebody works out why the year was flat.

If you think in markup, convert once: margin = markup ÷ (1 + markup). A 40% markup is a 28.6% margin. A 100% markup — doubling the cost — is a 50% margin.

It drives ONE number: the list price. Dealers and distributors buy at a discount off that list, so what they pay and what you really earn on them is different again, and it is printed per channel on the part panel above rather than implied by this one percentage.

On machine or labour hours the rate is per hour; on material cost it is a multiplier of material. The margin does ONE job — it is what the LIST price is worked back from. What each channel actually pays and actually earns is on the part panel above, because dealers and distributors buy at a discount off that list and their margins are not this number.
What the plantwide rate covers
Tick what this rate is meant to recover. A category already inside a machine's pool cannot be ticked here — that is the double charge, and it is refused rather than warned about.

What each machine's pool covers

The annual fixed pool below is a number with no explanation attached to it. This is the explanation, and it is what makes the boundary checkable instead of remembered.
Rent is the one that catches people. The square metres a machine stands on belong in that machine's pool; the rest of the building belongs to the plantwide rate. Those are two different costs, so they are two different categories here — and a shop that splits its rent ticks both, in different tiers, without being refused.

Machine rates

Basis hours are productive hours, not calendar hours.
Work centreMachineAnnual poolBasis hrs Variable/hrLabour/hrAttend. Machine rateAll-in

New machine rate

Records a rate from a date forward. The rate it replaces is closed, not overwritten — nothing already costed changes.
A year of this ONE machine's fixed cost: finance payment or depreciation, its service contract, the floor it stands on. Tick what is in it in the panel above. A financed turning centre lands near 48,000 a year, a finishing bench nearer 9,000.
Hours it actually cuts. Take the control's run-time hours for last year, or job cards. Not 2,080. A machine open 2,080 hours and cutting 1,400 has a basis of 1,400.
Only what stops when the spindle stops — power, air, coolant. Last year's spend divided by the basis hours above. Usually 1 to 8 an hour; a big machining centre sits at the top of that.
What the hour costs the company: wage plus payroll tax, insurance and benefits. Not what lands in the pay packet. A 22 an hour machinist costs the shop nearer 27.50.
How much of an operator this machine needs while it runs. One person tending three machines is 0.33. One machine, one person, is 1. A lights-out night on a bar feeder is 0.
Basis hours are the hours the machine actually cuts, not the hours it is available. Using calendar hours under-recovers the pool and every quote that comes off it is quietly too cheap. Tick tooling only if it is already inside the pool — charged there and per unit, it is counted twice.
How the five numbers become an hour rate

Machine rate = pool ÷ basis hours + variable per hour. That is what one hour of this machine costs to own and run, before anybody is stood at it. The table above prints it back as Machine rate so you can check it against the number in your head.

All-in rate = machine rate + labour per hour × attendance factor. Attendance is the one that is usually left at 1 by accident. A shop where one person runs three machines that are all cutting is paying one wage across three rates — put 1 in all three and every quote carries three wages for one person, and the shop looks unprofitable on paper while the bank account says otherwise.

Where to find basis hours if nobody has ever counted them. Most controls keep a lifetime and a since-reset spindle-run counter; read it, reset it, read it again in a month, multiply. Failing that, take the weeks you actually run, the hours a week the machine has work in front of it, and knock off holidays, maintenance and the weeks it sat waiting on material. A machine available 2,080 hours a year and cutting 1,400 is normal, not bad.

A rate is never edited. Recording one closes the rate it replaces from the date forward and keeps it, so re-costing March still uses March's rate. That is why this is a form and not an editable cell.

Freight and duty

Raises the value of stock already counted. It never adds a unit.

Not sure what belongs in a box?

The long version of every number on this screen, worked through on one part from raw material to a price.

How costing works

One suppressor, from raw bar to a price, with the arithmetic at every step.

What this is

This carries one part all the way through. A 7.62 titanium can: one tube, seven baffles, an end cap and a QD mount, cut on four machines. Every figure is printed as the product computes it, to four decimals, so you can check any line against the number in your head.

It is a worked example, not a reading of your catalogue. The rates below belong to one shop and were typed in once. Your own machines will produce different money. The arithmetic does not change, and every step names the box on the Costing screen the number comes from.

The run size used throughout is 10, with a run of 200 beside it. Setup is charged once per run, so the run size is most of the answer. Step 7 is where that shows up.

Read it in order the first time. Steps 1 and 2 are the machinery, set up once and then left alone. Steps 3 to 6 are one part. Steps 7 to 9 are the three things shops get wrong with real money on them.
Step 1 of 10

The machine hour rate, one per machine

What one hour of one machine costs to own and run, before anybody is stood at it. It is entered on Costing → New machine rate.

machine hour rate = annual fixed pool / annual basis hours + variable per hour

The annual fixed pool is a year of what this one machine costs whether it cuts or not. The finance payment or its depreciation, its service contract, the floor space it stands on, insurance carried on the machine itself. Cost that belongs to one machine goes in that machine's pool and nowhere else.

Annual basis hours are the hours it actually cuts. Not 2,080, and not the hours it is available. A machine open 2,080 hours a year and cutting 1,400 has a basis of 1,400. Use 2,080 and the pool is recovered over 49% more hours than the shop ever bills, so every quote off that rate is quietly too cheap.

Variable per hour is only what stops when the spindle stops. Power, air, coolant. Last year's spend on it, divided by the basis hours above.

MachineAnnual poolBasis hours Variable /hrMachine rate /hr
Doosan Lynx 2100 turning centre48,000.001,4006.0040.285714
Haas VF-2 machining centre61,000.001,5007.2547.916667
Rotary welding cell22,000.001,1004.1024.100000
Finishing and assembly bench9,000.001,6001.206.825000
Haas: 61,000.00 / 1,500 = 40.666667 + 7.25 variable = 47.916667 an hour Bench: 9,000.00 / 1,600 = 5.625000 + 1.20 variable = 6.825000 an hour

The rate is held to six decimals and the screen prints it back in the Machine rate column, so you can check it the moment you save. The dearest hour on this list is seven times the cheapest. That gap is not an accounting curiosity, and step 9 is what it costs a shop that ignores it.

Labour is charged separately, not inside the rate. Each rate carries a labour per hour and an attendance factor beside it. Labour per hour is what the hour costs the company, wage plus payroll tax plus insurance and benefits, not what lands in the pay packet. Attendance is how much of an operator the machine needs while it runs: one person tending two machines is 0.5, one machine with somebody stood at it is 1.

Why labour is separate. A lights-out night shift on the Haas costs the same machine hour and no wage. Keep them in one number and that job is quoted with an operator who was at home.
Step 2 of 10

The plantwide rate, for everything no machine can be blamed for

The front office. The bookkeeper and the accountant's fee. Quality control that is not a routed operation. Shipping boxes and foam. The building rent left over after each machine's own footprint. Software. The owner's own hours spent running the business rather than cutting metal. All of it is real, all of it has to be recovered, and none of it can be traced to a machine.

plantwide rate = annual plantwide pool / a year of the chosen basis

The basis is set on Costing → Overhead. Machine hours is the default and is right where the machines do the work. Labour hours suits a shop that is mostly hand assembly. Material cost turns the rate into a multiplier of material, which suits a shop that mostly buys and resells. Pick whichever one moves when the shop gets busier.

This shop is on machine hours at 14.00 an hour. Its four rated machines carry 5,600 basis hours between them, so:

14.00 x 5,600 hours = 78,400.00 recovered in a year

If the pool is bigger than 78,400 the rate is too low and the year ends short. That is not a guess you have to live with: step 10 shows where the product measures it.

The one rule that costs real money. A cost belongs to exactly one pool. Put building rent in each machine's annual pool and in the plantwide rate and it is absorbed twice, every quote goes out heavy, and nothing on any screen looks wrong. So the boundary is declared: What the plantwide rate covers and What each machine's pool covers are tick lists on the Costing screen, and a category ticked in both tiers is refused rather than warned about. Rent is the one that catches people. The square metres a machine stands on belong to that machine. The rest of the building belongs to the plant, and they are two separate categories for exactly this reason.
Step 3 of 10

Material

Entered on the part itself, under What a part costs, and why, on the components table. Quantity per is for one finished unit, never for the run: seven baffles a can is 7, whether the order is for one or a hundred.

line cost = ( quantity per x run size + fixed quantity ) / ( 1 - scrap ) x unit cost

Scrap is what you expect to lose forever, not what went wrong last month. It is typed as a percentage and the model holds it as a fraction, so 5 on the screen means five per cent. At 5% on the baffles the cost carries 73.68 blanks to get 70 good ones out of a run of ten cans.

ComponentQty perScrap Blanks for 10Unit costCost for 10
Titanium tube stock, 7.6212%10.20408211.125654113.5271
Baffle blank, 7.6275%73.6842116.200000456.8421
End cap10%10.0000008.75000087.5000
QD mount10%31.00000031.000000310.0000
Material for a run of 10967.8692
baffles: 7 x 10 = 70 good ones, 70 / 0.95 = 73.684211 blanks, x 6.20 = 456.8421 material per unit: 967.8692 / 10 = 96.7869

The unit cost of a bought part is the moving average of what you actually paid, weighted by what is on the shelf. That is why the tube is 11.125654 and not a round number. It moves when a receipt lands at a new price, and a freight invoice that turns up two weeks later moves it again without adding a single unit to stock.

Material per unit does not care about the run size. 96.7869 at a run of 10, and 96.7869 at a run of 200. Hold that thought for step 7, because everything else on this part moves.

Step 4 of 10

Machine time, labour and tooling

The three numbers the shop enters per operation, on the same panel as the components, under How it is made.

minutes for the run = setup minutes + cycle minutes x run size machine cost = minutes / 60 x machine hour rate labour cost = minutes / 60 x labour per hour x attendance tooling cost = tooling per unit x run size

Setup minutes are per run and they are the clock on the wall. From the last good part of the last job to the first good part of this one. Tearing down, fixturing, tool changes, touching off, the first article, and the walk to the crib for the tool that was not on the cart. Time the person, not the spindle.

Cycle minutes are one part, door close to door open, and they are charged on every part. Take it off the control if it shows a cycle timer, or run three parts and divide. Then decide once, for the whole shop, whether load and unload sit inside that number, and hold to it on every operation of every part.

Tooling per unit is the consumable, over the parts it survives. An insert at 18.00 with four usable edges, each edge good for 30 parts, is 18.00 / 120 = 0.15 a part. Not the machine, not the fixture, not the holder. Count the edges you actually get rather than the ones on the box.

OpOperationSetupCycle Minutes for 10MachineLabourTooling
10Turn tube, thread both ends4522265177.928660.729218.5000
20Profile and port baffles6041470375.3472107.708324.0000
30Stack and weld2035370148.6167191.16670.0000
40Finish and assemble101819021.612576.00000.0000
For a run of 101351,295723.5050435.604242.5000
op 20: 60 + 41 x 10 = 470 minutes 470 / 60 x 47.916667 = 375.3472 of machine 470 / 60 x 27.50 x 0.5 = 107.7083 of labour (one operator across two machines) 2.40 x 10 = 24.0000 of tooling

1,295 minutes is 21.5833 machine hours for the run. That figure is about to be used again, so it is worth reading twice.

Why the weld cell shows zero tooling. Its machine rate has Tooling is inside this rate ticked, so the perishable tooling is already inside the pool it charges. Enter tooling per unit as well and it is the same insert paid for twice. The product refuses that save rather than letting every quote go out heavy. Put tooling in one place. Per unit is the more accurate of the two, and inside the rate is the easier.
Step 5 of 10

Overhead, the second tier only

Tier one is already paid. Every machine minute above was charged at that machine's own hour rate, so the Doosan's finance payment and the Haas's service contract are inside the 723.5050 of machine cost. Nothing more is owed on them.

Tier two is applied here, once, on the whole run:

plantwide overhead = 21.5833 machine hours x 14.00 = 302.1667

On a labour hours basis it would be the attended hours instead, which for this run is 15.4583 rather than 21.5833. On a material cost basis it is a multiplier of the 967.8692. Same pool, three ways of spreading it, and the one to pick is the measure that actually moves when the shop gets busier.

Step 6 of 10

The total

BucketFor a run of 10Per unit
Material967.869296.7869
Machine time723.505072.3505
Labour435.604243.5604
Tooling42.50004.2500
Overhead, plantwide302.166730.2167
Cost2,471.6450247.1645

That is the whole model. Five buckets, one lot size, and a stored unit cost that always has the run it was costed at printed beside it. A unit cost with no run size next to it cannot be reproduced by anybody, which is why the screen never shows one on its own.

The run column adds by hand to 2,471.6451 and the product prints 2,471.6450. The product adds the exact figures and rounds once at the end, rather than adding five numbers that have each already been rounded, so a hand total off the printed lines can land a hundredth of a cent away from it. The per unit column happens to add exactly here.
Step 7 of 10

Why ten cost more each than two hundred

The same part, the same rates, the same day. Only the run size changed.

Per unitRun of 10Run of 200Cheaper by
Material96.786996.78690.0000
Machine time72.350564.05688.2937
Labour43.560439.91283.6476
Tooling4.25004.25000.0000
Overhead30.216727.22422.9925
Cost a unit247.1645232.230714.9338

Material did not move, because every can eats the same metal. Tooling did not move, because every part indexes the same insert. What moved is the setup, and here is the whole of it:

OpMachineSetup min MachineLabourOverheadCost of the changeover
10Doosan Lynx 21004530.214310.312510.500051.0268
20Haas VF-26047.916713.750014.000075.6667
30Rotary welding cell208.033310.33334.666723.0333
40Finishing bench101.13754.00002.33337.4708
Setup, once per run13587.301838.395831.5000157.1976
157.1976 / 10 = 15.7198 a unit 157.1976 / 200 = 0.7860 a unit -------- difference 14.9338 a unit, which is the whole gap in the table above

Nothing else moved. The entire difference between a can costing 247.16 and the same can costing 232.23 is one changeover, spread over twenty times as many parts. That is what setup minutes are, and it is why they are the number worth getting right before any other on the screen.

What a wrong setup figure costs. Time the spindle instead of the person and a 45 minute changeover on the lathe gets entered as 15. A run of 10 then quotes 3.40 a unit light, and nothing looks wrong anywhere. Make the same mistake on all four operations, which is what happens when a shop times spindles as a habit, and a run of 10 goes out 10.48 a unit under cost. On short runs that is most of the margin.
Step 8 of 10

Margin, and the price

price = cost / ( 1 - margin )

The Target margin box is margin. It is not markup. Margin is measured against the price you charge. Markup is measured against the cost you paid. They are never equal and the gap grows with the number.

a cost of 100.00 at a 40% MARGIN: 100.00 / 0.60 = 166.67 a cost of 100.00 at a 40% MARKUP: 100.00 x 1.40 = 140.00

Type 40 into that box meaning markup and every price leaves 26.67 on the table on a hundred dollars of cost. Nothing on any screen looks wrong. The year is simply flat.

If you think in markup, convert once: margin = markup / (1 + markup). A 40% markup is a 28.6% margin. Doubling the cost is a 100% markup and a 50% margin.

This shop is set to 38%, so the can works back to:

run of 10: 247.1645 / 0.62 = 398.65 run of 200: 232.2307 / 0.62 = 374.57

The target margin does exactly one job: it sets the list price. What a dealer or a distributor pays is a discount off that list, and what the shop actually earns from them is a different number again. The Costing screen prints it per channel rather than implying it from one percentage. With the list price on file at 1,249.00 and a cost of 247.1645:

ChannelDiscount off listPaysMargin actually earned
Retail, direct and web0%1,249.0080.2%
Dealer25%936.7573.6%
Distributor40%749.4067.0%

The list price on file here is well above the 398.65 a 38% target implies. That is normal and it is not a fault: the target sets a floor to work back from, and what the market pays is a decision the shop makes. The screen prints both figures side by side so nobody mistakes one for the other, and it marks any channel whose price has fallen to or below cost.

Step 9 of 10

Why there are two tiers instead of one rate

Most small shops carry a single blended overhead rate. One number an hour, applied to everything. It is simpler and it is wrong in a way that never shows up on a screen, so it is worth seeing what it would do to the part above.

Roll this shop into one rate. 140,000 of machine pools, 25,705 of variable spend at those machines, 78,400 of plantwide cost, over the 5,600 hours the machines actually cut:

( 140,000 + 25,705 + 78,400 ) / 5,600 = 43.590179 an hour, for every machine
OpMachineMinutes Two tiersOne blended rateError
10Doosan Lynx 2100265239.7619192.523347.2386 light
20Haas VF-2470485.0139341.4564143.5575 light
30Rotary welding cell370234.9500268.806133.8561 heavy
40Finishing bench19065.9458138.035672.0897 heavy
Machine plus overhead, run of 101,2951,025.6716940.821484.8502 light

The Haas hour costs 47.92 to own and the bench hour costs 6.83. One blended rate charges both of them 43.59. So the Haas work comes out 29.6% light and the bench work comes out at 2.09 times what it really costs. The machine-heavy part is being subsidised by the hand work, inside a single number, with nothing on any screen to show it happening.

On this can the two errors partly cancel and it prices 8.49 a unit cheap, which is bad enough. On a part that never leaves the bench nothing cancels at all. Sixty minutes of setup and thirty a piece on the finishing bench, at a run of 10:

two tiers: 12.4950 a unit one blended rate: 26.1541 a unit

The shop would quote that part at more than double its cost, lose the work to somebody who costs properly, and conclude that hand assembly is unprofitable. It is not. The rate was.

So the two tiers each do one job. The machine hour rate charges a part for the machine it actually ran on, which is the only cost that can be traced. The plantwide rate picks up what no machine can be blamed for, spread over a measure of activity. A part that never touches the Doosan carries none of the Doosan, and that is the whole point.
Step 10 of 10

The order to fill it in, and the one check that keeps it honest

  1. A machine rate for every work centre. Pool, basis hours, variable, labour, attendance. An operation routed through a machine with no rate stops the whole part from being costed, on purpose, because time with no rate would otherwise cost nothing while still pulling overhead.
  2. Tick what each pool covers. One list per machine, one for the plant. A category ticked in both tiers is refused.
  3. The plantwide basis and rate.
  4. The target margin. Margin, not markup. Step 8.
  5. Per part: the components. Quantity for one finished unit, and the scrap you actually expect.
  6. Per part: the operations. Setup, cycle, tooling. Step 4.
  7. Press Show me the cost at the run sizes the shop really builds at. Quote everything at a run of one and the shop looks expensive on volume work. Re-cost the catalogue at a run of 1,000 and the value of the stock on the shelf drops for no physical reason.

Then, at the end of a month or a quarter, open a period and record what was actually spent. The Did the rates come back? panel compares what the rates collected into everything that was built against what the shop really paid out.

Absorb 180,000 and spend 220,000 and every quote that came off those rates was 18% too cheap, and the panel says so, per machine, so the fix lands on the rate that was wrong rather than on all of them. That is the difference between a costing system and a costing spreadsheet: the spreadsheet never tells you it was wrong.

An absorption variance is a cost of the period it is found in. Closing a period re-costs nothing and does not change what the stock on the shelf is worth, because the standard cost of everything already built is reproducible from the rate that was in force when it was built.

Accounting

Money goes to QuickBooks. Quantities stay here.

Vendor bills from receipts

BillOrderVendorTermsRaised DueAmountIn the queue
A bill is raised for what ARRIVED, not for what was ordered — a purchase order is a promise and a receipt is a debt. The price is the order's price, so the accrual exists before the vendor's paper does; when the invoice arrives, the difference is a price variance somebody looks at rather than a month-end with nothing in it.

Postings

Both sides of every one — account, debit and credit
ReferenceTypeDateAmount StatusQuickBooks idNote

Sync log

StartedTriggerModeQueued PostedFailedNote

Setup

Parts, vendors, buildings and bins — and the way to load them all at once

Load your parts from a spreadsheet

One row per part. Nothing is written until you have read what it is going to do — the check below reports every new part, every change and every row it will not take, with the line number.
Column names are read the way a spreadsheet writes them: SKU, Part No or Item Code for the part number; Description for the name; Qty, On Hand or Stock for the opening count; Bin, Location, Cost, Type, UoM and Reorder for the rest. Anything it did not recognise is listed back to you before you commit. Running the same file twice cannot post the stock twice. The Type column takes the words these screens print — Raw material, Accessory, Finished — in any capitalisation, singular or plural, and RM, AC and FG as well.

Add or correct a part

Saving against a part number that already exists corrects it. Nothing here is ever deleted — a part with history is retired, and stays readable.
How a part is tracked can only be set before it has moved — it decides what a balance row means.
PartDescriptionTypeUnitTracking Reorder atCostOn hand Change

Buildings and bins

The physical shape of the shop, which changes

Add a building

A building is where stock sits. Bins live inside one and cannot move between them, because the ledger's own foreign key ties a movement to both.
CodeNameKindBins On handStatusChange

Add or re-label a bin

One bin, one part — that is what lets the floor scan once instead of twice. A bound bin can only be re-slotted while it is empty. The QR encodes a token and never the text, so renaming a shelf does not invalidate a printed label.
BuildingBinAssigned partOn hand StatusChange

Vendors

Who you buy from. Their part numbers are learned from their paperwork.

Add or correct a vendor

The Id of this vendor in QuickBooks. Without it no bill for this vendor can be sent, because QuickBooks refuses a Bill with no vendor. Accounting › Match vendors fills these in from your QuickBooks company.
NameContactEmailPhoneTerms StatusChange

Adjustable settings

Every number this system will let you change, and what it changes
A setting you have changed reads set here. One this deployment's hosting is overriding reads environment and cannot be changed from this screen — it is set outside the application. default means nobody has touched it. Every change is written to the log at the bottom of this screen with who made it. Changes take effect within seconds; nothing has to be restarted.

What changed, and who changed it

A number that changed on a Tuesday and a screen that behaved differently on a Tuesday are the same event
WhenSettingFromToWho

System

Health, accounts and the devices on the floor
Prometheus scrape: GET /api/metrics with the same credential. GET /api/livez is the unauthenticated liveness probe — it answers only that this process is running and reads nothing.