Available stock counts drift from reality
Done- Plan (done)
- Code (done)
- Test (done)
- Review (done)
- Finish (done)
Cost
$0.0078
Tests
Passed
Iterations
1
Re-plans
0
LLM calls
12
Prompt read from cache
70%
Usage by agent
- Cache read
- Cache write
- Input
- Output
View as table
| Agent | Cost | Cache read | Cache write | Input | Output |
|---|---|---|---|---|---|
| planner | $0.0013 | 6,188 | 1,835 | 8 | 2,102 |
| coder | $0.0040 | 27,559 | 9,454 | 12 | 5,047 |
| tester | $0.0013 | 8,045 | 4,715 | 6 | 1,310 |
| reviewer | $0.0012 | 7,189 | 4,942 | 6 | 966 |
Timeline
-
planner iteration 1 Finished 3 calls · 10.1K tokens · $0.0013 · 11.7s
Loading…
-
coder iteration 1 Finished 5 calls · 42.1K tokens · $0.0040 · 23.7s
Loading…
-
tester iteration 1 Finished 2 calls · 14.1K tokens · $0.0013 · 8.3s
Loading…
-
verify iteration 1 Passed 0.5s
........... [100%] 11 passed in 0.02s
-
reviewer iteration 1 Finished 2 calls · 13.1K tokens · $0.0012 · 7.7s
Loading…
Final diff
diff --git a/orders.py b/orders.py index 3c6e298..640b4d4 100644 --- a/orders.py +++ b/orders.py @@ -1,4 +1,4 @@ -from stock import Stock +from stock import OutOfStock, Stock class OrderError(Exception): @@ -11,7 +11,17 @@ class Orders: self._orders: dict[int, dict] = {} self._next_id = 1 + def _get(self, order_id: int) -> dict: + if order_id not in self._orders: + raise OrderError(f"unknown order id {order_id}") + return self._orders[order_id] + def place(self, lines: dict[str, int]) -> int: + # Check every line before reserving anything so a failed order + # leaves stock untouched. + for sku, qty in lines.items(): + if self.stock.available(sku) < qty: + raise OutOfStock(sku) for sku, qty in lines.items(): self.stock.reserve(sku, qty) order_id = self._next_id @@ -20,10 +30,19 @@ class Orders: return order_id def ship(self, order_id: int) -> None: - self._orders[order_id]["status"] = "shipped" + order = self._get(order_id) + if order["status"] == "cancelled": + raise OrderError(f"order {order_id} is cancelled and cannot be shipped") + if order["status"] == "shipped": + raise OrderError(f"order {order_id} has already been shipped") + order["status"] = "shipped" def cancel(self, order_id: int) -> None: - order = self._orders[order_id] + order = self._get(order_id) + if order["status"] == "cancelled": + return + if order["status"] == "shipped": + raise OrderError(f"order {order_id} has already shipped and cannot be cancelled") for sku, qty in order["lines"].items(): self.stock.release(sku, qty) order["status"] = "cancelled" diff --git a/test_orders.py b/test_orders.py index 149497c..00f4f7c 100644 --- a/test_orders.py +++ b/test_orders.py @@ -1,5 +1,7 @@ -from orders import Orders -from stock import Stock +import pytest + +from orders import OrderError, Orders +from stock import OutOfStock, Stock def test_place_reserves(): @@ -13,3 +15,75 @@ def test_cancel_releases(): orders = Orders(stock) orders.cancel(orders.place({"a": 2})) assert stock.available("a") == 5 + + +def test_double_cancel_releases_once(): + stock = Stock({"a": 5}) + orders = Orders(stock) + oid = orders.place({"a": 2}) + orders.cancel(oid) + orders.cancel(oid) + assert stock.available("a") == 5 + + +def test_failed_place_leaves_stock_unchanged(): + stock = Stock({"a": 5, "b": 1}) + orders = Orders(stock) + with pytest.raises(OutOfStock): + orders.place({"a": 2, "b": 3}) + assert stock.available("a") == 5 + assert stock.available("b") == 1 + + +def test_failed_place_does_not_consume_order_id(): + stock = Stock({"a": 5, "b": 1}) + orders = Orders(stock) + with pytest.raises(OutOfStock): + orders.place({"a": 2, "b": 3}) + assert orders.place({"a": 1}) == 1 + + +def test_place_unknown_sku_raises_out_of_stock(): + stock = Stock({"a": 5}) + with pytest.raises(OutOfStock): + Orders(stock).place({"a": 1, "zzz": 1}) + assert stock.available("a") == 5 + + +def test_cancel_shipped_raises_and_changes_nothing(): + stock = Stock({"a": 5}) + orders = Orders(stock) + oid = orders.place({"a": 2}) + orders.ship(oid) + with pytest.raises(OrderError): + orders.cancel(oid) + assert stock.available("a") == 3 + assert orders._orders[oid]["status"] == "shipped" + + +def test_ship_cancelled_raises_and_stays_cancelled(): + stock = Stock({"a": 5}) + orders = Orders(stock) + oid = orders.place({"a": 2}) + orders.cancel(oid) + with pytest.raises(OrderError): + orders.ship(oid) + assert orders._orders[oid]["status"] == "cancelled" + assert stock.available("a") == 5 + + +def test_ship_twice_raises(): + stock = Stock({"a": 5}) + orders = Orders(stock) + oid = orders.place({"a": 2}) + orders.ship(oid) + with pytest.raises(OrderError): + orders.ship(oid) + assert orders._orders[oid]["status"] == "shipped" + + +@pytest.mark.parametrize("method", ["ship", "cancel"]) +def test_unknown_order_id_raises_order_error(method): + orders = Orders(Stock({"a": 5})) + with pytest.raises(OrderError): + getattr(orders, method)(999)