Finance · Fulfillment
Inventory Accounting
A hardware purchase crosses three systems before it becomes cost of goods sold: it's ordered and received in Inflow, paid through Ramp, and booked in QuickBooks. Almost all the bookkeeping posts itself. This playbook is in two parts: first the short list of what a person actually does, then what happens automatically underneath so those few steps make sense.
The one rule everything follows: no payable before receipt. Money paid before goods arrive is a prepayment (asset); inventory and what we owe are recognized only when goods are received. Inflow is the warehouse truth, Ramp is the AP system of record, and QuickBooks sees only journal entries — never bills.
What you do by hand
Most of the ledger posts itself. Here's the entire list of human steps, by role — do these and the journal entries follow automatically (Part 2 shows how). The one step that trips people up is starred.
Fulfillment Team
Owns the PO from placement through goods receipt — all in Inflow.
- Place the PO with line items, quantities, and unit costs. Record the vendor's PO number and payment terms (deposit %, balance %, expected delivery date), then send it to the supplier. Inflow assigns the KISS PO number (e.g. PO-001234).
- Mark the receipt against that PO when goods arrive — inspect, count, and flag any shortfall, damage, or partial receipt. This is the trigger: marking receipt in Inflow is what recognizes the inventory and the payable (Event 4 below). You do not wait for the supplier's balance invoice.
AP Team
Routes inventory bills through Ramp. You don't code them or pick GL accounts — you just make the bill findable.
- Make sure the vendor is in the Inventory Vendor Group in Ramp. Any bill citing a KISS PO number is inventory by definition — if its vendor isn't tagged yet, flag it to add them.
- ★ Put the KISS PO number in the Ramp bill's Memo as PO-001234 — literally PO- followed by the 6-digit number Inflow assigned. This is the one step that matters most: it's how the bill auto-links to the right PO so every entry posts itself.
- Pay the bill as normal. The PO match carries from the bill to the payment automatically — there's nothing extra to type when you pay.
- If a freight, customs, or duty bill arrives separately from the supplier (rare — most bundle it in), don't code it. Route it to Fulfillment for the related PO/lot, then to the Accountant.
Accountant
Owns the ledger. With the workflows posting the routine entries, the job is mostly reviewing the audit trail and clearing exceptions in the Accounting app (/accounting).
- One-time per vendor: in the Vendors view, set the supplier's
qbo_vendor_idandramp_vendor_id. Without them, JEs post untagged and the vendor's bills land unmatched. - Ramp Inbox: match any bill that arrived without a clean PO-001234 to its PO (the view pre-selects a likely one). The match just records the link — then open that PO's audit trail and click Catch up JEs to post the queued JEs and back-write any missed payments to Inflow (F11c).
- PO Checks: post the recognitions the automation skipped (overpaid, or invoice > PO), and resolve invoice-vs-PO discrepancies by adjusting the Inflow PO up to the actual amount — the true-up then posts itself.
- Book landed-cost add-on bills (the separate freight/duty case) by hand.
- Monthly at close: post the adjustment batch (cycle counts, scrap, returns) and run the tie-out in PO Checks / SO Checks.
What happens underneath
You did the few things above; here's what the system does in response. The whole design serves one principle — recognize a payable (and inventory) only when goods are received — which is why deposits sit apart from what we owe.
No payable before receipt.
Money paid to a supplier before goods arrive is parked in 1350 Prepaid Inventory (an asset), never in Accounts Payable. 1360 Inventory and 2100 Accounts Payable are recognized only at receipt — at that moment we book the inventory at full landed value, clear the prepaid, and owe the unpaid remainder. That's why inventory invoices are booked as journal entries, never QuickBooks bills: a QBO bill would post AP the instant it's entered — before receipt — collapsing the two states (prepaid vs. received-and-owed) we keep apart. Ask "what do we owe a supplier?" in QuickBooks, not Ramp's bill-pay report.
The lifecycle, entry by entry
Eight events, in order. The two that move the ledger most are Event 4 (receipt) and Event 7 (shipment). The Posted by line on each step names the workflow that fires it — almost everything is automatic. Dashed steps are exceptions, not the everyday path.
PO placed with supplier
manual · InflowFulfillment creates the PO in Inflow (lines, qty, unit costs), records the vendor PO# and terms, and sends it. A KISS PO number is assigned.
Deposit paid
Ramp → QBOThe supplier sends a deposit invoice (typically 40–50% of PO value for Shanghai Lijin). It flows through Ramp; paid before goods arrive, it's a prepayment to 1350 — no AP.
Intermediate payment
exceptionAn interim invoice (e.g. 30% at shipment). Usually waived for Shanghai Lijin; documented in case it occurs. Treated exactly like the deposit — another prepayment to 1350.
Goods received at the warehouse
Inflow → QBOFulfillment marks the receipt against the KISS PO in Inflow. Receipt alone triggers recognition. A single JE recognizes the inventory at full PO value, clears the prepaid, and books the unpaid remainder as AP.
Cr 1350 Prepaid Inventory — prepaid-to-date on this PO
Cr 2100 Accounts Payable — PO value − prepaid (the unpaid remainder)
Final supplier invoice paid
Ramp → QBOThe balance is paid (~15 days after delivery for Shanghai Lijin). Goods are already received, so the payment pays down the AP created at receipt — it doesn't touch 1350.
Landed-cost add-on
manual · exceptionA freight, customs, duty, broker, or insurance bill that arrives separately from the primary supplier. AP escalates to Fulfillment for the PO/lot, then to the Accountant, who books it by hand.
Already shipped: Dr Cost of Hardware (5101) / Cr 2100 AP
COGS recognition
Inflow → QBOWhen the order is fulfilled (shipped) in Inflow, inventory leaves 1360 and becomes cost of goods sold, matched to the revenue recognized at the same moment. The inventory-side pair:
products.cogs)products.cogs — the two drift, which the monthly tie-out catches.Adjustments, scrap & returns
manual · monthly batchCycle-count adjustments, scrap/damage write-offs, customer returns inbound, and returns to supplier. These hit Inflow but are not automated yet — the Accountant logs them in a tracker and posts one batch JE at monthly close, each memo citing the Inflow event IDs. Templates below.
| Adjustment event | What it is | Journal entry |
|---|---|---|
| Cycle count — down | Physical count lower than Inflow | Dr Inventory Variance / Cr 1360 |
| Cycle count — up | Physical count higher than Inflow | Dr 1360 / Cr Inventory Variance |
| Scrap / damage | Item destroyed or unsalable | Dr Scrap Expense / Cr 1360 |
| Customer return (restockable) | Good-condition unit comes back | Dr 1360 / Cr 5101 (+ revenue side) |
| Return to supplier | Defective unit, supplier credit | Dr 2100 AP / Cr 1360 |
What posts automatically
| Workflow | Fires on | What it posts |
|---|---|---|
| F11 · Ramp Bill Received | Ramp bill created | Parses PO-###### from the memo, matches the PO, logs the bill; posts Dr 1360 / Cr 2100 AP only if goods are already received. |
| F12 · Ramp Bill Paid | Ramp payment | Pre-receipt → Dr 1350 / Cr Cash; post-receipt → Dr 2100 AP / Cr Cash. Negative = refund (reversed). Also writes the payment back onto the matched Inflow PO as a payment-line. |
| F17 · Post Receipt JE | F10, on receipt | Event 4 recognition at full PO value: Dr 1360 / Cr 1350 / Cr 2100 AP. Self-guards. |
| F18 · Post True-Up JE | F10, every sync | Trues 1360 + AP to a revised PO total after receipt. No-ops unless a delta is owed. |
| F3 · Revenue Recognition | Inflow fulfillment | Event 7: Dr 5101 / Cr 1360 at products.cogs, plus the revenue/commission/royalty pairs. |
What the system handles for you
A few things the automation does silently that used to be manual — worth knowing so no one duplicates them — plus the one case it deliberately leaves for a human.
| Handled automatically | So you don't need to… |
|---|---|
| Payments flow back to Inflow | Re-key payment dates/amounts into Inflow. When a matched bill is paid, F12 writes the payment onto the Inflow PO as a payment-line. |
| PO-total corrections self-true-up | Hand-post an adjustment when a received PO's total changes. Fix the number in Inflow and F18 posts the 1360/AP delta on the next sync. |
| New suppliers appear on their own | Create the supplier record. F10 adds it on the first PO sync — you only map its QBO + Ramp ids in the Vendors view (manual step above). |
| The payment forecast builds itself | Hand-build a payment schedule. A new PO inherits the vendor's terms policy and the Cash Flow 13-week forecast schedules the tranches (forecast only — not the GL). |
Where to watch it — the Accounting app
The Accounting app in Hive (/accounting) is where you both do the
Accountant's manual steps and verify everything else. It's read-only except the Ramp
Inbox match, and it links every external ID (KISS PO# · Vendor PO# · Vendor invoice# ·
Ramp IDs · Inflow event IDs · QBO JE IDs) into one timeline per PO.
| View | What it shows / what you do there |
|---|---|
| PO Audit Trail | Every PO with rolled-up Prepaid (1350) / AP (2100) / Inventory (1360) balances; click a row for the full per-PO event timeline and Dr/Cr lines. |
| PO Checks | The confidence layer: a balanced ΣDr = ΣCr badge, a paste-in QBO tie-out, and pass/fail checks (received with no recognition · prepaid stuck on a received PO · recognized 1360 ≠ current PO total). The monthly tie-out, in-app. |
| Ramp Inbox | Bills not yet matched to a PO (a missing or malformed PO-######). Picking the PO only records the link — then open that PO's audit trail and click Catch up JEs to post the queued JEs and back-write any missed payments to Inflow (fires F11c). The match alone posts nothing. |
| Vendors | Supplier directory. Flags vendors missing qbo_vendor_id / ramp_vendor_id — set both so JEs tag and bills auto-match. |
| SO Ledger / SO Checks | The sales-side twin (deferred revenue 2200 / customer deposits 2300, COGS recognized this month). Where inventory and revenue tie out together. |
The accounts
Four accounts carry the inventory story. If one ever holds something other than what's listed here, that's a process exception worth investigating.
| Account | Should contain |
|---|---|
| 1350 Prepaid Inventory | Deposits and interim payments on POs whose goods have not yet been received. A growing, stale 1350 signals delayed shipments worth a look at close. |
| 1360 Inventory | On-hand goods at landed cost; ties to Inflow's physical valuation. |
| 2100 Accounts Payable | Balances owed for goods received but not yet paid. Never holds a deposit. |
| 5101 Cost of Hardware | Landed cost of goods that have shipped to customers. |
Landed cost
Inventory is valued at landed cost — every dollar it took to get the goods to the warehouse ready to sell. Selling price would massively overstate the asset and net income.
Capitalize to inventory include
Do not capitalize exclude
Manufacturing orders are GL-neutral
KISS assembles finished locks from component parts via Manufacturing Orders in Inflow. These produce no QBO entry — both components and finished goods are inventory, so the cost just shifts within Inflow and total 1360 value is unchanged. The risk is drift: if a finished good's unit cost ≠ the sum of consumed components, 1360 slowly desyncs. Sample one MO at close to confirm it's value-neutral; the monthly tie-out catches drift in aggregate.
Monthly tie-out
The goal: confirm 1360 Inventory in QBO equals Inflow's physical on-hand value at cost. Most of this lives in the Accounting app's PO Checks (and SO Checks for the revenue side) — the implied balances, the balanced-JE badge, and a paste-in QBO tie-out are right there. Use it first; drop to SQL only to dig into a flagged variance.
- Open PO Checks; paste the QBO month-end 1360 / 2100 / 1350 balances into the tie-out. Anything over the threshold is flagged.
- Cross-check Inflow on-hand × unit cost (
products.cogstoday) against the implied 1360. - If a variance exceeds threshold, investigate before closing. If it's genuinely unattributable, post to 3990 Cleanup Suspense with a clear memo.
Where drift usually comes from
| Cause | How to spot it |
|---|---|
| Missed F3 JE | A fulfillment happened in Inflow but no COGS JE posted — the most common. Surfaces as a fulfilled order with no rev-rec entry. |
| Missed adjustment | A cycle count or scrap event never made it into the monthly batch JE. |
| MO costing drift | A manufacturing order produced a finished unit cost ≠ sum of components. |
| Stale cost basis | products.cogs is out of date vs. actual Inflow cost layers (the known receipts-vs-fulfillments gap). |
| Off-flow manual JE | Someone touched 1360 outside the standard flow. |
Decisions & history
The policy calls that shaped this system, with the dates they were made.
| Date | Decision | Why |
|---|---|---|
| 2026-05-01 | Capitalize at receipt | Hardware sits on the balance sheet as 1360 until it ships. Required for revenue/COGS matching under the deferred-revenue model. |
| 2026-05-01 | Landed cost is the value | Supplier price + inbound freight + duties + broker + insurance. Reflects what it took to make the item sellable. |
| 2026-05-01 | Inflow-event audit trail | Every JE touching 1360 or COGS references the Inflow event that triggered it. The April phantom-COGS issue went undetected for weeks without this. |
| 2026-05-27 | Accountant owns inventory entries | Receipts move 1350/1360/AP at once — too much judgment for routine AP coding. Centralizing prevents mis-coding. |
| 2026-06-04 | Recognize at receipt, full PO value; no payable before receipt | At receipt: Dr 1360 (full PO) / Cr 1350 (prepaid) / Cr 2100 AP (remainder). Deposits are direct JEs to 1350, never bills. Keeps prepaid and received-and-owed on separate tracks. |
| 2026-06-05 | Receipt recognition & true-ups automated | F10 fires F17 on receipt and F18 on every sync; the manual review queue and F13 sweep were retired. Guard-skipped cases surface in PO Checks. |
The April 2026 cutover
On April 1, 2026 KISS switched from QBO inventory items (which auto-book COGS at invoice creation) to non-inventory items + F3 automation (COGS via JE at fulfillment), so revenue and COGS recognize at the same moment. On April 9–10, inactivating the old inventory items — which still carried on-hand quantities — triggered QBO's automatic adjustment and dumped $743,535 of phantom credits into Cost of Hardware, distorting net income to ~$768K against a reality of ~$25K. It was reversed with a single JE on 04/30 (Dr 5101 / Cr 1360 $743,535). A one-time cutover bridge JE (offset to 3990 Cleanup Suspense) is still pending to align 1360 to Inflow's physical value at the cutover moment.
What's still being worked through
- Cost basis (high priority). Receipts hit 1360 at actual bill amount; fulfillments leave at static
products.cogs. They drift. Leaning toward making Inflow's weighted-average cost canonical at fulfillment — pending confirmation the Inflow API exposes it cleanly. - Adjustment automation. A poller (planned as F14) to read Inflow's cycle-count / scrap / return history and queue JEs, replacing the manual monthly batch — with a review queue for events needing judgment.
- Variance threshold for the tie-out — set after a few months of real data.
- Inventory Variance / Scrap Expense accounts — confirm or create in QBO before the first adjustment batch.
- Cutover bridge JE — post the one-time 1360 alignment to close out the April cutover.
Keep this playbook in sync with
- Accounting app (
apps/accounting/README.md) — the five-rule JE model, the views (PO Audit Trail / PO Checks / Ramp Inbox / Vendors / SO Ledger), and the data model. - Ramp bill → PO matching — F11 parses
PO-\d{6}from the bill's reference/memo; if your KISS PO numbering changes, update the regex and this playbook's "putPO-######in the Memo" step together. - Receipt & true-up posting — F17 (
n8n/f17-post-receipt-je.json) and F18 (n8n/f18-post-true-up-je.json), both fired by F10 (Inflow PO Sync). - Ramp side — F11 (bill received) and F12 (bill paid / refund), and the Inventory Vendor Group + vendor mapping.
- COGS / rev-rec — F3 (
n8n/f3-revenue-recognition.json) and the Hardware Revenue playbook for the revenue, commission, and royalty side. - Cost source — Supabase
products.cogs(the static basis fulfillments use today).