FilaOps ERP - Functional Specification
3D Print Farm ERP - Production-grade manufacturing resource planning for additive manufacturing
FilaOps ERP - Functional Specification
#Purpose-Built for 3D Print Farm Operations
Version: 0.2 (Based on operator interview) Last Updated: 2025-12-29 Status: π Core workflows mapped
#Document Purpose
This is THE source of truth for what FilaOps does. Every feature, button, and calculation should trace back to this document.
Rules:
- If it's not documented here, it doesn't exist
- Code implements this spec, not the other way around
- Tests validate this spec
#Design Philosophy
The operator works 20 hrs/day, 7 days/week. This system exists to reduce that.
AUTOMATE: Web orders, MRP calculations, low stock alerts
SIMPLIFY: Morning dashboard, one-click actions, fast decisions
REMEMBER: So the operator doesn't have to hold it all in their head
What FilaOps IS:
- Operations management (quotes, orders, production, inventory, shipping)
- Decision support (what to make, what to buy, what's blocking)
What FilaOps IS NOT:
- Accounting system (QuickBooks does that)
- Full MES/shop floor control (overkill for small print farm)
- Printer firmware (Bambu handles that)
#Operator Profile
Solo print farm owner
βββ Multiple sales channels (web, wholesale, POS, custom quotes)
βββ 6+ printers running daily
βββ MTO (make-to-order) + MTS (make-to-stock) hybrid
βββ One-person: sales, production, QC, shipping, IT
βββ Needs: Less mental load, fewer surprises, faster decisions
PART 1: CORE ENTITIES (Master Data)
#1.1 Items (Products & Materials)
#Item Types (Simple)
#Standard Fields
#Replenishment Fields
Staples (reorder_point): PLA-WHITE, PLA-BLACK, common hardware Specialty (order_driven): TPU, silk filaments, one-off components
#UOM Configuration (The Special Sauce)
Example:
Item: PLA-BLACK
βββ base_uom: grams (what slicer reports, what BOM uses)
βββ purchase_uom: spool
βββ purchase_conversion: 1000 (1 spool = 1000g)
βββ standard_cost: $0.02/gram
βββ replenishment_type: reorder_point
βββ reorder_point: 2000 (grams = 2 spools)
βββ reorder_qty: 5000 (grams = 5 spools)
When you buy: "5 spools" β system adds 5000g to inventory
When BOM says: "47g" β system knows what that means
When low: Alert at 2000g, suggest order 5000g
#Filament-Specific Fields (Optional)
Nice for filtering/reporting, not required for core function.
#1.2 Bill of Materials (BOM)
A recipe. "To make 1 Widget, you need these things."
#BOM Structure
BOM: LAMP-DESK-01
βββ Parent: LAMP-DESK-01 (what we're making)
βββ Makes: 1 ea
β
βββ Components:
βββ Line 1: PLA-BLACK, 235g, $0.02/g = $4.70
βββ Line 2: LED-PUCK, 1 ea, $4.50 = $4.50
βββ Line 3: POWER-CORD, 1 ea, $2.00 = $2.00
βββ Line 4: HARDWARE-KIT, 1 ea, $0.50 = $0.50
βββ Line 5: BOX-LAMP, 1 ea, $1.20 = $1.20
β
βββ Material Cost: $12.90
βββ Runtime: 6 hours Γ $1.50/hr = $9.00
β
βββ TOTAL COST: $21.90
βββ Retail (Γ3.5): $76.65 β $75.99
βββ B2B 10+ (Γ2.5): $54.75 β $52.99
#BOM Fields
#Print-Specific Fields
#Pricing Formula (Brandan's Method)
#1.3 Customers
Keep it simple.
Sources:
- Manual entry (custom quotes, phone orders)
- Auto-created from web orders (Shopify, Etsy, etc.)
#1.4 Vendors (Suppliers)
Who you buy from.
#1.5 Units of Measure (UOM)
Keep the list small.
#Conversions (System-Defined)
#1.6 Inventory Locations
Simple for a home/small print farm.
Many small operations just use MAIN for everything. That's fine.
#1.7 Printers (Future Enhancement)
Not required for core function, but useful for:
- Knowing which printer ran which job
- Status dashboard
- Capacity planning
Bambu Handy already does this. FilaOps integration = nice to have, not essential.
PART 2: CORE WORKFLOWS
#2.1 The Big Picture
HOW WORK FLOWS THROUGH THE SYSTEM
βββββββββββββββββββββββββββββββββ
DEMAND COMES IN SUPPLY GOES OUT
(why are we making stuff?) (how do we fulfill it?)
βββββββββββββββ
β Custom ββββ Quote ββββ
β Request β β
βββββββββββββββ β
βΌ
βββββββββββββββ ββββββββββββββ ββββββββββββββ βββββββββββ
β Web Order ββββββββ SALES ββββββββ PRODUCTION ββββββββ SHIP β
β (auto) β β ORDER β β ORDER β β β
βββββββββββββββ ββββββββββββββ ββββββββββββββ βββββββββββ
β β
βββββββββββββββ β β
β Phone/POS βββββββββββββββ β
β (manual) β β
βββββββββββββββ β
βΌ
βββββββββββββββ ββββββββββββββ
β Low Stock ββββββββββββββββββββββββββββ PRODUCTION β (restock run)
β Alert β β ORDER β
βββββββββββββββ ββββββββββββββ
β
βΌ
ββββββββββββββ
β MRP β
β "What do β
β I need?" β
ββββββββββββββ
β
βββββββββββββ΄ββββββββββββ
βΌ βΌ
ββββββββββββββ ββββββββββββββ
β PURCHASE β β HAVE IT β
β ORDER β β (proceed) β
ββββββββββββββ ββββββββββββββ
β
βΌ
ββββββββββββββ
β RECEIVE ββββ Inventory
ββββββββββββββ
#2.2 Quote (Custom Work)
When: Customer asks "can you make this?"
States:
Quote Document:
Quote Q-2025-0042
βββ Customer: Jane's Craft Shop
βββ Created: 2025-01-10
βββ Valid Until: 2025-01-24
βββ Status: sent
β
βββ Lines:
β βββ CUSTOM-BRACKET-001 Γ 50 @ $4.99 = $249.50
β βββ (includes: 23g PLA, 45min print, Γ3.5 markup)
β
βββ Notes: "Customer provided STL, wants matte black"
βββ Total: $249.50
Key Action: Convert to Sales Order
WHEN: Customer says "yes, let's do it"
1. Create Sales Order from quote
- Copy customer
- Copy lines
- Link SO back to quote
2. Update quote.status = 'converted'
3. Navigate to new SO
#2.3 Sales Order (Commitment to Deliver)
When: Customer wants something and you've agreed to make/ship it
Sources:
- Converted quote (custom)
- Web order import (Shopify, Etsy, etc.)
- Manual entry (phone, wholesale, POS)
States:
Sales Order Document:
Sales Order SO-2025-0089
βββ Customer: Acme Corp
βββ Order Date: 2025-01-15
βββ Ship By: 2025-01-22
βββ Source: Q-2025-0042 (or "Shopify #1234", or "Manual")
βββ Status: in_production
β
βββ Lines:
β βββ Line 1: WIDGET-PRO Γ 10 @ $12.99 = $129.90
β β βββ Qty Ready: 6
β β βββ Production: WO-0112 (60% complete)
β β
β βββ Line 2: GADGET-MINI Γ 5 @ $6.99 = $34.95
β βββ Qty Ready: 5 β
β βββ Production: WO-0113 (complete)
β
βββ Subtotal: $164.85
βββ Shipping: $8.50
βββ Total: $173.35
BLOCKING ISSUES:
βββ WO-0112 needs 47g PLA-RED (out of stock)
βββ [Order Missing Material] button
Key Actions:
Confirm Order:
WHEN: Order is complete and you're committing to it
1. Validate has lines
2. Set status = 'confirmed'
3. Trigger MRP check (do we have material?)
Create Production Order:
WHEN: Confirmed order has items that need to be made
For each line:
1. Check if product has BOM (if not, skip or error)
2. Create Production Order:
- Product = line.product
- Quantity = line.qty
- Due date = SO.ship_by
- Link back to SO line
3. Set SO status = 'in_production'
Order Missing Material:
WHEN: Blocking issues show material shortages
1. Gather all material shortages across linked WOs
2. Open Purchase Order dialog pre-filled:
- Suggested vendor (from item.preferred_vendor)
- Items and quantities needed
3. On submit: Create PO, link to demand
4. Blocking issues now show "Incoming: PO-xxxx, ETA: date"
Ship Order:
WHEN: All lines ready (or partial ship)
1. Create Shipment record
2. Deduct inventory
3. Set SO status = 'shipped'
4. (Future: create QB invoice, notify customer)
#2.4 Production Order (Work Order)
When: You need to make something
Sources:
- Created from Sales Order (MTO)
- Created manually for restocking (MTS)
- Suggested by MRP/low stock alert
States:
Production Order Document:
Production Order WO-2025-0112
βββ Product: WIDGET-PRO
βββ Quantity: 10
βββ Due Date: 2025-01-22
βββ Status: in_progress
β
βββ Demand Source:
β βββ Sales Order: SO-2025-0089, Line 1
β βββ Customer: Acme Corp
β
βββ Progress:
β βββ Completed: 6
β βββ Scrapped: 1
β βββ Remaining: 3
β
βββ Material Requirements:
β βββ PLA-BLACK: 470g needed (47g Γ 10)
β β βββ Available: 2,500g
β β βββ Status: β OK
β βββ SPRING-CLIP: 20 ea needed (2 Γ 10)
β β βββ Available: 45 ea
β β βββ Status: β OK
β
βββ Print Time: 4.5 hrs total (27 min Γ 10)
Key Actions:
Release:
WHEN: WO is planned and materials are checked
1. Set status = 'released'
2. Materials are now "allocated" (reserved for this job)
Record Completion:
WHEN: Prints come off the printer
INPUT: quantity_good, quantity_scrapped
1. Update WO.qty_completed += quantity_good
2. Update WO.qty_scrapped += quantity_scrapped
3. Add finished goods to inventory
4. If qty_completed >= qty_ordered: status = 'complete'
5. Update linked SO line qty_ready
Scrap:
WHEN: Print fails, bad quality, etc.
INPUT: quantity, reason
1. Update WO.qty_scrapped += quantity
2. (Material was consumed but no output)
3. Log reason for review
#2.5 Purchase Order
When: You need to buy materials
Sources:
- Manual ("I need to order filament")
- From "Order Missing Material" button on SO
- From MRP suggestion
- From low stock alert
States:
Purchase Order Document:
Purchase Order PO-2025-0034
βββ Vendor: Bambu Lab
βββ Order Date: 2025-01-15
βββ Expected: 2025-01-20
βββ Status: sent
β
βββ Lines:
β βββ PLA-BLACK Γ 5 spools @ $19.99 = $99.95
β β βββ Qty Received: 0
β βββ PLA-WHITE Γ 3 spools @ $19.99 = $59.97
β βββ Qty Received: 0
β
βββ Total: $159.92
LINKED DEMAND:
βββ WO-0112 (needs PLA-BLACK for SO-0089)
βββ Low stock replenishment
Key Action: Receive
WHEN: Package arrives
For each line:
1. Enter qty received
2. Convert to base UOM: 5 spools Γ 1000g = 5000g
3. Add to inventory (location: MAIN)
4. Update PO line qty_received
If all lines fully received:
5. Set PO status = 'received'
6. (Future: create QB bill)
#2.6 Inventory Transactions
Every time inventory changes, record it.
#Transaction Types
#Running Balance Example
Item: PLA-BLACK
Location: MAIN
Date | Type | Reference | Qty | Balance
---------|----------|------------|---------|--------
01/01 | - | Opening | - | 3,000g
01/10 | issue | WO-0098 | -235g | 2,765g
01/12 | issue | WO-0101 | -470g | 2,295g
01/15 | receive | PO-0034 | +5,000g | 7,295g
01/16 | issue | WO-0112 | -282g | 7,013g
#2.7 Shipment
When: Order is ready to go out the door
Shipment Document:
Shipment SH-2025-0067
βββ Sales Order: SO-2025-0089
βββ Customer: Acme Corp
βββ Ship Date: 2025-01-22
βββ Carrier: USPS
βββ Tracking: 9400111899223456789012
β
βββ Items Shipped:
β βββ WIDGET-PRO Γ 10
β βββ GADGET-MINI Γ 5
β
βββ Status: shipped
On Ship:
- Deduct inventory for each line
- Update SO status
- Record tracking number
- (Future: notify customer, sync to Pirateship)
#2.8 Returns (Edge Case)
Happens rarely, but need to handle.
Process:
- Create Return record linked to original SO/Shipment
- Receive items back
- Inspect: restock or scrap?
- Adjust inventory accordingly
- (Refund handled in QuickBooks)
PART 3: MRP (The Brain)
MRP answers: "What do I need, and when?"
#3.1 How It Works
DEMAND SUPPLY
(what I need to make/ship) (what I have or is coming)
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
Sales Order lines (confirmed) On-hand inventory
+ Restock needs (below reorder) + Open PO lines (not received)
+ Safety stock + Open WO completions
= GROSS REQUIREMENT = AVAILABLE SUPPLY
GROSS - AVAILABLE = NET REQUIREMENT
If NET > 0 β You need to buy or make something
#3.2 Simple MRP Check (Per Item)
#3.3 MRP Suggestions
When you confirm a Sales Order:
For each line:
1. Can we ship from stock?
- If yes: reserve inventory, done
- If no: need to produce
2. To produce, check materials:
- For each BOM component:
- Is there enough available?
- If no: suggest PO
3. Show user:
- "Ready to go" (have everything)
- "Need to order: X, Y, Z" (shortages)
- "Waiting for: PO-123" (already ordered)
#3.4 Reorder Point Alerts
Nightly (or on-demand):
For each item where replenishment_type = 'reorder_point':
if on_hand < reorder_point:
create_alert(
item=item,
on_hand=on_hand,
reorder_point=reorder_point,
suggested_qty=reorder_qty,
severity='critical' if on_hand < (reorder_point / 2) else 'warning'
)
PART 4: DASHBOARDS
#4.1 Morning Dashboard
Purpose: What do I need to DO today?
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π¦ SHIP TODAY 3 orders β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β SO-0089 β Acme Corp β 2 items β β
READY β [Ship] β
β SO-0091 β Jane Doe β 1 item β β
READY β [Ship] β
β SO-0092 β Bob's Shop β 3 items β β οΈ 2 of 3 β [View] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π¨οΈ PRINT TODAY 5 jobs β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β WO-0112 β Widget Pro Γ10 β Due Today β β
Mat Ready β
β WO-0113 β Gadget Γ5 β Due Today β β
Mat Ready β
β WO-0114 β Custom Γ1 β Due Today β β οΈ Need PLA-RED β
β WO-0115 β Lamp Γ2 β Due Tmrw β β
Mat Ready β
β WO-0116 β Stand Γ20 β Due Tmrw β β
Mat Ready β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π NEED TO ORDER 2 items β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β PLA-RED β Have: 200g β Need: 450g β Short: 250g β
β SPRING-CLIP β Have: 12 β Need: 40 β Short: 28 β
β β
β [Create PO for All Shortages] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π¨οΈ PRINTERS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β P1S-01: π’ Idle β P1S-02: π΅ Printing 67% β
β A1-01: π’ Idle β A1-02: π’ Idle β
β A1-03: π΄ Error β A1-04: π’ Idle β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π¬ QUOTES PENDING RESPONSE 2 quotes β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Q-0156 β Jane's Crafts β Custom bracket β Sent 3d ago β
β Q-0158 β Wholesale Co β 50Γ widgets β Sent 1d ago β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#4.2 Evening Dashboard
Purpose: What do I need to PLAN?
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π NEED TO ORDER 4 items β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β PLA-WHITE β 800g β Min: 2kg β π΄ CRITICAL β
β PLA-BLACK β 1.5kg β Min: 2kg β π‘ LOW β
β LED-PUCK β 4 ea β Min: 10 β π‘ LOW β
β BOX-SMALL β 18 ea β Min: 25 β π‘ LOW β
β β
β [Create PO - Bambu Lab] [Create PO - Amazon] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π¬ ARRIVING SOON 2 POs β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β PO-0034 β Bambu Lab β 5Γ PLA spools β ETA: Tomorrow β
β PO-0036 β Amazon β LED pucks, wire β ETA: Friday β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π OVERNIGHT SUGGESTIONS 3 jobs β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β These items are below reorder point and material ready β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β WIDGET-PRO Γ10 β 8hr print β PLA-BLK β
β
β β PHONE-STAND Γ15 β 6hr print β PLA-BLK β
β
β β GADGET-MINI Γ20 β 4hr print β PLA-WHT β οΈ low β
β β
β [Create WO for Selected] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π STOCK LEVELS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Finished Goods Below Reorder: β
β β’ WIDGET-PRO: 3 ea (min: 10) β
β β’ PHONE-STAND: 5 ea (min: 15) β
β β’ GADGET-MINI: 8 ea (min: 20) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
PART 5: INTEGRATIONS (Future)
#5.1 Priority Order
#5.2 QuickBooks Integration
What to sync:
- Shipped orders β QB Invoices
- Received POs β QB Bills
- Customers β QB Customers
- Vendors β QB Vendors
What NOT to sync:
- Inventory (let QB do its own thing or sync periodically)
- Anything in draft status
#5.3 Web Order Import
Shopify/Etsy/TikTok flow:
1. Order placed on platform (payment collected there)
2. FilaOps polls or receives webhook
3. Create Customer (if new)
4. Create Sales Order (status: confirmed)
5. Trigger normal fulfillment flow
6. On ship: send tracking back to platform
PART 6: DATA INTEGRITY RULES
#6.1 What Must Always Be True
These are assertions. If any is false, something is broken.
#6.2 State Machine Rules
Quote: draft β sent β [converted | expired | cancelled]
β
(no going back from converted/expired/cancelled)
Sales Order: draft β confirmed β in_production β ready β shipped
β
cancelled (only from draft/confirmed)
Production Order: draft β released β in_progress β complete
β
cancelled (only from draft/released)
Purchase Order: draft β sent β [partial β] received
β
cancelled (only before receiving)
#6.3 Referential Integrity
Delete Rules:
- Can't delete Customer with open SOs
- Can't delete Item with inventory > 0
- Can't delete Item used in open orders
- Can't delete Vendor with open POs
Cascade Rules:
- Archive Item β archives BOMs using it (soft delete)
- Cancel SO β releases any material allocations
PART 7: TESTING REQUIREMENTS
#7.1 Critical Path Tests
Before ANY release, these must pass:
#7.2 Integration Tests by Workflow
APPENDIX: OPEN QUESTIONS
Decisions to make as we build:
- Partial shipments? Can we ship 8 of 10 and ship 2 later?
- Lot/serial tracking? Needed for traceability?
- Multi-location? Or just MAIN for now?
- Approval workflows? Or trust the operator?
- Audit log? How detailed?
- Seasonal forecasting? Or just reorder points?
APPENDIX: GLOSSARY
END OF SPECIFICATION v0.2
Quick Actions
Details
- Type
- Functional Spec
- Author
- Blb3D
- Slug
- blb3d/docs-filaops-erp-functional-specification
