Functional Weave
Code in Python

manufacturing.bom-cost@1.0.0

vectors.json

16,300 bytes · view raw

[
  {"name": "a table: material 2545.2p (timber 3.3 m with scrap, screws 8.4 with scrap), labour 525p, overhead 360p", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expect": {"material": {"minor": 2545, "currency": "GBP"}, "labour": {"minor": 525, "currency": "GBP"}, "overhead": {"minor": 360, "currency": "GBP"}, "total": {"minor": 3430, "currency": "GBP"}}},
  {"name": "each element is rounded once from its exact sum: the leg and table labour rounded down one by one would be 194 + 291 = 485, the exact 486.11 gives 486", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}], [{"item": "LEG", "seconds": 100, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "down"], "expect": {"material": {"minor": 2545, "currency": "GBP"}, "labour": {"minor": 486, "currency": "GBP"}, "overhead": {"minor": 333, "currency": "GBP"}, "total": {"minor": 3364, "currency": "GBP"}}},
  {"name": "the same table rounded up: 2545.2p of material is 2546", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "up"], "expect": {"material": {"minor": 2546, "currency": "GBP"}, "labour": {"minor": 525, "currency": "GBP"}, "overhead": {"minor": 360, "currency": "GBP"}, "total": {"minor": 3431, "currency": "GBP"}}},
  {"name": "bought-in parts only: 348.5p rounds half-even to 348", "args": [[{"parent": "KIT", "component": "A", "quantity": {"numerator": 2, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "KIT", "component": "B", "quantity": {"numerator": 1, "denominator": 2}, "scrapBasisPoints": 0}], "KIT", [{"item": "A", "unitCost": {"minor": 150, "currency": "GBP"}}, {"item": "B", "unitCost": {"minor": 97, "currency": "GBP"}}], [], "GBP", "half-even"], "expect": {"material": {"minor": 348, "currency": "GBP"}, "labour": {"minor": 0, "currency": "GBP"}, "overhead": {"minor": 0, "currency": "GBP"}, "total": {"minor": 348, "currency": "GBP"}}},
  {"name": "the same kit rounded half-up is 349", "args": [[{"parent": "KIT", "component": "A", "quantity": {"numerator": 2, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "KIT", "component": "B", "quantity": {"numerator": 1, "denominator": 2}, "scrapBasisPoints": 0}], "KIT", [{"item": "A", "unitCost": {"minor": 150, "currency": "GBP"}}, {"item": "B", "unitCost": {"minor": 97, "currency": "GBP"}}], [], "GBP", "half-up"], "expect": {"material": {"minor": 349, "currency": "GBP"}, "labour": {"minor": 0, "currency": "GBP"}, "overhead": {"minor": 0, "currency": "GBP"}, "total": {"minor": 349, "currency": "GBP"}}},
  {"name": "costing a sub-assembly on its own", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "LEG", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expect": {"material": {"minor": 330, "currency": "GBP"}, "labour": {"minor": 58, "currency": "GBP"}, "overhead": {"minor": 40, "currency": "GBP"}, "total": {"minor": 428, "currency": "GBP"}}},
  {"name": "zero-cost parts and zero-time operations cost nothing", "args": [[{"parent": "KIT", "component": "A", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}], "KIT", [{"item": "A", "unitCost": {"minor": 0, "currency": "EUR"}}], [{"item": "KIT", "seconds": 0, "labourRate": {"minor": 2000, "currency": "EUR"}, "overheadRate": {"minor": 1000, "currency": "EUR"}}], "EUR", "half-up"], "expect": {"material": {"minor": 0, "currency": "EUR"}, "labour": {"minor": 0, "currency": "EUR"}, "overhead": {"minor": 0, "currency": "EUR"}, "total": {"minor": 0, "currency": "EUR"}}},
  {"name": "a bought-in item without a cost is an error", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "no material cost for \"TIMBER\""},
  {"name": "a cost for an item with its own bill is an error", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}, {"item": "LEG", "unitCost": {"minor": 500, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "\"LEG\" is made from its own bill of materials, so its cost is rolled up"},
  {"name": "two costs for one item is an error", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}, {"item": "TOP", "unitCost": {"minor": 1300, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "duplicate material cost for \"TOP\""},
  {"name": "a cost in another currency is an error", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "EUR"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "currency mismatch"},
  {"name": "a negative cost is an error", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": -1, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}], [{"item": "LEG", "seconds": 120, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "TABLE", "seconds": 600, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}, {"item": "CHAIR", "seconds": 900, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "unitCost of \"TOP\" must not be negative"},
  {"name": "negative operation time is an error", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}], [{"item": "LEG", "seconds": -60, "labourRate": {"minor": 1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "seconds of an operation on \"LEG\" must be a whole number, not negative"},
  {"name": "a negative rate is an error", "args": [[{"parent": "TABLE", "component": "TOP", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "LEG", "quantity": {"numerator": 4, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "TABLE", "component": "SCREW", "quantity": {"numerator": 8, "denominator": 1}, "scrapBasisPoints": 500}, {"parent": "LEG", "component": "TIMBER", "quantity": {"numerator": 3, "denominator": 4}, "scrapBasisPoints": 1000}], "TABLE", [{"item": "TOP", "unitCost": {"minor": 1200, "currency": "GBP"}}, {"item": "SCREW", "unitCost": {"minor": 3, "currency": "GBP"}}, {"item": "TIMBER", "unitCost": {"minor": 400, "currency": "GBP"}}, {"item": "PAINT", "unitCost": {"minor": 999, "currency": "GBP"}}], [{"item": "LEG", "seconds": 60, "labourRate": {"minor": -1750, "currency": "GBP"}, "overheadRate": {"minor": 1200, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "the rates of an operation on \"LEG\" must not be negative"},
  {"name": "a cycle in the bill is refused as bom-explode refuses it", "args": [[{"parent": "A", "component": "B", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}, {"parent": "B", "component": "A", "quantity": {"numerator": 1, "denominator": 1}, "scrapBasisPoints": 0}], "A", [], [], "GBP", "half-up"], "expectError": "bill of materials has a cycle: A -> B -> A"}
]