Functional Weave
Code in Rust

inventory.valuation-weighted-average@1.0.0

vectors.json

7,636 bytes · view raw

[
  {"name": "two receipts blended, an exact issue, then an issue rounded once: 71000 x 60 / 130 = 32769.23", "args": [[{"date": "2026-01-01", "quantity": 100, "unitCost": {"minor": 500, "currency": "GBP"}}, {"date": "2026-01-05", "quantity": 50, "unitCost": {"minor": 600, "currency": "GBP"}}, {"date": "2026-01-10", "quantity": -120, "unitCost": null}, {"date": "2026-01-15", "quantity": 100, "unitCost": {"minor": 550, "currency": "GBP"}}, {"date": "2026-01-20", "quantity": -60, "unitCost": null}], "GBP", "half-up"], "expect": {"closingQuantity": 70, "closingValue": {"minor": 38231, "currency": "GBP"}, "costOfSales": {"minor": 96769, "currency": "GBP"}, "issueCosts": [{"minor": 64000, "currency": "GBP"}, {"minor": 32769, "currency": "GBP"}], "averageUnitCost": {"minor": 546, "currency": "GBP"}}},
  {"name": "issuing the rest takes exactly what is left: 38231, where 70 x 546p would leave 11p behind", "args": [[{"date": "2026-01-01", "quantity": 100, "unitCost": {"minor": 500, "currency": "GBP"}}, {"date": "2026-01-05", "quantity": 50, "unitCost": {"minor": 600, "currency": "GBP"}}, {"date": "2026-01-10", "quantity": -120, "unitCost": null}, {"date": "2026-01-15", "quantity": 100, "unitCost": {"minor": 550, "currency": "GBP"}}, {"date": "2026-01-20", "quantity": -60, "unitCost": null}, {"date": "2026-01-25", "quantity": -70, "unitCost": null}], "GBP", "half-up"], "expect": {"closingQuantity": 0, "closingValue": {"minor": 0, "currency": "GBP"}, "costOfSales": {"minor": 135000, "currency": "GBP"}, "issueCosts": [{"minor": 64000, "currency": "GBP"}, {"minor": 32769, "currency": "GBP"}, {"minor": 38231, "currency": "GBP"}], "averageUnitCost": {"minor": 0, "currency": "GBP"}}},
  {"name": "rounding up costs the second issue 32770", "args": [[{"date": "2026-01-01", "quantity": 100, "unitCost": {"minor": 500, "currency": "GBP"}}, {"date": "2026-01-05", "quantity": 50, "unitCost": {"minor": 600, "currency": "GBP"}}, {"date": "2026-01-10", "quantity": -120, "unitCost": null}, {"date": "2026-01-15", "quantity": 100, "unitCost": {"minor": 550, "currency": "GBP"}}, {"date": "2026-01-20", "quantity": -60, "unitCost": null}], "GBP", "up"], "expect": {"closingQuantity": 70, "closingValue": {"minor": 38230, "currency": "GBP"}, "costOfSales": {"minor": 96770, "currency": "GBP"}, "issueCosts": [{"minor": 64000, "currency": "GBP"}, {"minor": 32770, "currency": "GBP"}], "averageUnitCost": {"minor": 547, "currency": "GBP"}}},
  {"name": "an exact half, half-up: 2 units worth 1001p, issue 1 costs 501", "args": [[{"date": "2026-02-01", "quantity": 1, "unitCost": {"minor": 500, "currency": "GBP"}}, {"date": "2026-02-01", "quantity": 1, "unitCost": {"minor": 501, "currency": "GBP"}}, {"date": "2026-02-02", "quantity": -1, "unitCost": null}], "GBP", "half-up"], "expect": {"closingQuantity": 1, "closingValue": {"minor": 500, "currency": "GBP"}, "costOfSales": {"minor": 501, "currency": "GBP"}, "issueCosts": [{"minor": 501, "currency": "GBP"}], "averageUnitCost": {"minor": 500, "currency": "GBP"}}},
  {"name": "an exact half, half-even: 2 units worth 1001p, issue 1 costs 500", "args": [[{"date": "2026-02-01", "quantity": 1, "unitCost": {"minor": 500, "currency": "GBP"}}, {"date": "2026-02-01", "quantity": 1, "unitCost": {"minor": 501, "currency": "GBP"}}, {"date": "2026-02-02", "quantity": -1, "unitCost": null}], "GBP", "half-even"], "expect": {"closingQuantity": 1, "closingValue": {"minor": 501, "currency": "GBP"}, "costOfSales": {"minor": 500, "currency": "GBP"}, "issueCosts": [{"minor": 500, "currency": "GBP"}], "averageUnitCost": {"minor": 501, "currency": "GBP"}}},
  {"name": "down: 3 units worth 1000p, issue 1 costs 333 and the remaining 2 are worth 667", "args": [[{"date": "2026-03-01", "quantity": 2, "unitCost": {"minor": 333, "currency": "GBP"}}, {"date": "2026-03-01", "quantity": 1, "unitCost": {"minor": 334, "currency": "GBP"}}, {"date": "2026-03-02", "quantity": -1, "unitCost": null}], "GBP", "down"], "expect": {"closingQuantity": 2, "closingValue": {"minor": 667, "currency": "GBP"}, "costOfSales": {"minor": 333, "currency": "GBP"}, "issueCosts": [{"minor": 333, "currency": "GBP"}], "averageUnitCost": {"minor": 333, "currency": "GBP"}}},
  {"name": "receipts only: the average is for display, 3 at 999p and 2 at 1001p is 999.8, so 1000", "args": [[{"date": "2026-03-01", "quantity": 3, "unitCost": {"minor": 999, "currency": "GBP"}}, {"date": "2026-03-01", "quantity": 2, "unitCost": {"minor": 1001, "currency": "GBP"}}], "GBP", "half-up"], "expect": {"closingQuantity": 5, "closingValue": {"minor": 4999, "currency": "GBP"}, "costOfSales": {"minor": 0, "currency": "GBP"}, "issueCosts": [], "averageUnitCost": {"minor": 1000, "currency": "GBP"}}},
  {"name": "restocking after running out starts a fresh average", "args": [[{"date": "2026-05-01", "quantity": 5, "unitCost": {"minor": 100, "currency": "GBP"}}, {"date": "2026-05-02", "quantity": -5, "unitCost": null}, {"date": "2026-05-03", "quantity": 5, "unitCost": {"minor": 130, "currency": "GBP"}}, {"date": "2026-05-04", "quantity": -2, "unitCost": null}], "GBP", "half-up"], "expect": {"closingQuantity": 3, "closingValue": {"minor": 390, "currency": "GBP"}, "costOfSales": {"minor": 760, "currency": "GBP"}, "issueCosts": [{"minor": 500, "currency": "GBP"}, {"minor": 260, "currency": "GBP"}], "averageUnitCost": {"minor": 130, "currency": "GBP"}}},
  {"name": "an empty ledger is nothing, in the given currency", "args": [[], "EUR", "half-up"], "expect": {"closingQuantity": 0, "closingValue": {"minor": 0, "currency": "EUR"}, "costOfSales": {"minor": 0, "currency": "EUR"}, "issueCosts": [], "averageUnitCost": {"minor": 0, "currency": "EUR"}}},
  {"name": "an issue larger than the stock on hand is an error", "args": [[{"date": "2026-01-01", "quantity": 10, "unitCost": {"minor": 100, "currency": "GBP"}}, {"date": "2026-01-02", "quantity": -11, "unitCost": null}], "GBP", "half-up"], "expectError": "insufficient stock: an issue of 11 on 2026-01-02 exceeds the 10 on hand"},
  {"name": "a ledger out of date order is an error", "args": [[{"date": "2026-01-05", "quantity": 10, "unitCost": {"minor": 100, "currency": "GBP"}}, {"date": "2026-01-04", "quantity": 10, "unitCost": {"minor": 100, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "movements must be in date order"},
  {"name": "a receipt with no unit cost is an error", "args": [[{"date": "2026-01-01", "quantity": 10, "unitCost": null}], "GBP", "half-up"], "expectError": "a receipt needs a unitCost"},
  {"name": "an issue with a unit cost is an error", "args": [[{"date": "2026-01-01", "quantity": 10, "unitCost": {"minor": 100, "currency": "GBP"}}, {"date": "2026-01-02", "quantity": -1, "unitCost": {"minor": 100, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "its unitCost must be null"},
  {"name": "a zero quantity is an error", "args": [[{"date": "2026-01-01", "quantity": 0, "unitCost": null}], "GBP", "half-up"], "expectError": "quantity must be a non-zero whole number"},
  {"name": "a negative unit cost is an error", "args": [[{"date": "2026-01-01", "quantity": 10, "unitCost": {"minor": -100, "currency": "GBP"}}], "GBP", "half-up"], "expectError": "unitCost must not be negative"},
  {"name": "a cost in another currency is an error", "args": [[{"date": "2026-01-01", "quantity": 10, "unitCost": {"minor": 100, "currency": "EUR"}}], "GBP", "half-up"], "expectError": "currency mismatch"},
  {"name": "an unknown rounding mode is an error, even with no issues", "args": [[{"date": "2026-01-01", "quantity": 10, "unitCost": {"minor": 100, "currency": "GBP"}}], "GBP", "nearest"], "expectError": "unknown rounding mode"}
]