def test_add_batch_for_existing_product(): uow = FakeUnitOfWork() services.add_batch("b1", "GARISH-RUG", 100, None, uow) services.add_batch("b2", "GARISH-RUG", 99, None, uow) assert "b2" in [ b.reference for b in uow.products.get("GARISH-RUG").batches ]
def test_allocate_errors_for_invalid_sku(): uow = FakeUnitOfWork() services.add_batch("b1", "AREALSKU", 100, None, uow) with pytest.raises(services.InvalidSku, match="Invalid sku NONEXISTENTSKU"): services.allocate("o1", "NONEXISTENTSKU", 10, uow)
def test_does_allocate_if_available_equal_to_required(): uow = FakeUnitOfWork() services.add_batch(BATCH_REF, SKU, QUANTITY, None, uow) ref = services.allocate(ORDER_1, SKU, QUANTITY, uow) batch = uow.batches.get(ref) assert batch.available_qty == 0
def test_error_for_invalid_sku(): uow = FakeUnitOfWork() services.add_batch(BATCH_1, REAL_SKU, HIGH_NUM, None, uow) with pytest.raises(services.InvalidSKU, match=f"Invalid SKU: {UNREAL_SKU}"): services.allocate(ORDER_1, UNREAL_SKU, LOW_NUM, uow)
def add_batch(): uow = unit_of_work.SqlAlchemyUnitOfWork() eta = request.json["eta"] if eta is not None: eta = datetime.fromisoformat(eta).date() services.add_batch(request.json["ref"], request.json["sku"], request.json["qty"], eta, uow) return "OK", 201
def test_does_allocate_if_available_greater_than_required(): uow = FakeUnitOfWork() services.add_batch(BATCH_REF, SKU, GREATER, None, uow) ref = services.allocate(ORDER_REF, SKU, QUANTITY, uow) batch = uow.batches.get(ref) assert batch.available_qty == QUANTITY - SMALLER
def test_raises_out_of_stock_exception_if_cannot_allocate(): uow = FakeUnitOfWork() services.add_batch(BATCH1, FORK, 10, today, uow) services.allocate(ORDER1, FORK, 10, uow) with pytest.raises(model.OutOfStock, match=FORK): services.allocate(ORDER2, FORK, 1, uow)
def test_returns_allocated_batch_ref(): uow = FakeUnitOfWork() services.add_batch("in-stock-batch-ref", POSTER, 100, None, uow) services.add_batch("shipment-batch-ref", POSTER, 100, tomorrow, uow) allocation = services.allocate(OREF, POSTER, 10, uow) assert allocation == "in-stock-batch-ref"
def test_trying_to_deallocate_unallocated_sku(): uow = FakeUnitOfWork() services.add_batch(BATCH_1, REAL_SKU, HIGH_NUM, None, uow) with pytest.raises(model.UnallocatedSKU, match=f"Unallocated SKU: {UNREAL_SKU}"): services.deallocate(ORDER_1, REAL_SKU, LOW_NUM, UNREAL_SKU, uow)
def test_returns_allocation(): """ Tests that the allocation service is able to allocate an OrderLine. """ uow = FakeUnitOfWork() services.add_batch(BATCH_1, REAL_SKU, HIGH_NUM, None, uow) result = services.allocate(ORDER_1, REAL_SKU, LOW_NUM, uow) assert result == BATCH_1
def test_deallocate_decrements_available_quantity(): uow = FakeUnitOfWork() services.add_batch(BATCH_1, REAL_SKU, HIGH_NUM, None, uow) batch_ref = services.allocate(ORDER_1, REAL_SKU, LOW_NUM, uow) batch = uow.batches.get(batch_ref) services.deallocate(ORDER_1, REAL_SKU, LOW_NUM, batch_ref, uow) assert batch.available_qty == HIGH_NUM
def test_allocation_is_idempotent(): uow = FakeUnitOfWork() services.add_batch(BATCH_REF, SKU, QUANTITY, None, uow) services.allocate(ORDER_REF, SKU, SMALLER, uow) services.allocate(ORDER_REF, SKU, SMALLER, uow) batch = uow.batches.get(BATCH_REF) assert batch.available_qty == QUANTITY - SMALLER
def add_batch(): uow = unit_of_work.SQLAlchemyUnitOfWork() eta = request.json['eta'] if eta is not None: eta = datetime.date.fromisoformat(eta) r, s, q = request.json['ref'], request.json['sku'], request.json['qty'] services.add_batch(r, s, q, eta, uow) return 'OK', 201
def test_prefers_current_stock_batches_to_shipments(): uow = FakeUnitOfWork() services.add_batch(IN_STOCK, CLOCK, 100, today, uow) services.add_batch(SHIPMENT, CLOCK, 100, tomorrow, uow) services.allocate(ORDER_1, CLOCK, 10, uow) b1, b2 = uow.batches.get(IN_STOCK), uow.batches.get(SHIPMENT) assert b1.available_qty == 90 assert b2.available_qty == 100
def test_prefers_warehouse_batches_to_shipments(): uow = FakeUnitOfWork() services.add_batch("in-stock-batch", "RETRO-CLOCK", 100, None, uow) services.add_batch("shipment-batch", "RETRO-CLOCK", 100, tomrrow, uow) in_stock_batch = uow.batches.get("in-stock-batch") shipment_batch = uow.batches.get("shipment-batch") services.allocate("oref", "RETRO-CLOCK", 10, uow) assert in_stock_batch.available_quantity == 90 assert shipment_batch.available_quantity == 100
def test_can_only_deallocate_allocated_lines(): uow = FakeUnitOfWork() services.add_batch(BATCH_REF, REAL_SKU, QUANTITY, None, uow) batch = None # avoid batch being possibly unbound try: services.deallocate(ORDER_REF, SKU, SMALLER, BATCH_REF, uow) except model.UnallocatedSKU: batch = uow.batches.get(BATCH_REF) assert batch.available_qty == QUANTITY
def test_doesnt_allocate_if_available_smaller_than_required(): uow = FakeUnitOfWork() services.add_batch(BATCH_REF, SKU, QUANTITY, None, uow) ref = services.allocate(ORDER_REF, SKU, SMALLER, uow) batch = None try: services.allocate(ORDER_REF, SKU, QUANTITY, uow) except model.OutOfStock: batch = uow.batches.get(ref) assert batch.available_qty == QUANTITY - SMALLER
def test_doesnt_allocate_if_skus_do_not_match(): uow = FakeUnitOfWork() services.add_batch(BATCH_REF, REAL_SKU, QUANTITY, None, uow) ref = services.allocate(ORDER_REF, REAL_SKU, SMALLER, uow) batch = None # avoid batch being possibly unbound try: services.allocate(ORDER_REF, UNREAL_SKU, SMALLER, uow) except services.InvalidSKU or model.UnallocatedSKU: batch = uow.batches.get(ref) assert batch.available_qty == QUANTITY - SMALLER
def test_change_batch_qty(): uow = FakeUnitOfWork() services.add_batch(BATCH_REF, REAL_SKU, 100, None, uow) services.allocate(ORDER_REF, REAL_SKU, 70, uow) batch = uow.batches.get(BATCH_REF) assert batch.available_qty == 100 - 70 services.change_batch_quantity(BATCH_REF, 30, uow) assert batch.available_qty > 0
def add_batch(): eta = request.json['eta'] if eta is not None: eta = datetime.fromisoformat(eta).date() services.add_batch( request.json['ref'], request.json['sku'], request.json['qty'], eta, unit_of_work.SqlAlchemyUnitOfWork(), ) return 'OK', 201
def on_post_add_batch(self, req, res): print("POST REQUESTED") eta = req.media['eta'] ref = req.media['ref'] sku = req.media['sku'] qty = req.media['qty'] if eta is not None: eta = datetime.fromisoformat(eta).date() services.add_batch(ref, sku, qty, eta, unit_of_work.SqlAlchemyUnitOfWork()) res.body = "OK" res.status = falcon.HTTP_201 return None
def test_prefer_earlier_batches(): uow = FakeUnitOfWork() services.add_batch(SPEEDY, SPOON, 100, today, uow) services.add_batch(NORMAL, SPOON, 100, tomorrow, uow) services.add_batch(SLOW, SPOON, 100, later, uow) services.allocate(ORDER_1, SPOON, 10, uow) b1, b2, b3 = uow.batches.get(SPEEDY), uow.batches.get( NORMAL), uow.batches.get(SLOW) assert b1.available_qty == 90 assert b2.available_qty == 100 assert b3.available_qty == 100
def test_allocate_commits(): uow = FakeUnitOfWork() services.add_batch("b1", "OMINOUS-MIRROR", 100, None, uow) services.allocate("o1", "OMINOUS-MIRROR", 10, uow) assert uow.committed
def test_allocate_returns_allocation(): uow = FakeUnitOfWork() services.add_batch("batch1", "COMPLICATED-LAMP", 100, None, uow) result = services.allocate("o1", "COMPLICATED-LAMP", 10, uow) assert result == "batch1"
def test_add_batch(): uow = FakeUnitOfWork() services.add_batch("b1", "CRUNCHY-ARMCHAIR", 100, None, uow) assert uow.batches.get("b1") is not None assert uow.committed
def test_add_batch_for_new_product(): uow = FakeUnitOfWork() services.add_batch("b1", "CRUNCHY-ARMCHAIR", 100, None, uow) assert uow.products.get("CRUNCHY-ARMCHAIR") is not None assert uow.committed
def test_add_batch(): uow = FakeUnitOfWork() services.add_batch(BATCH_1, REAL_SKU, 100, None, uow) assert uow.batches.get(BATCH_1) is not None assert uow.committed
def test_commits(): uow = FakeUnitOfWork() services.add_batch(BATCH_1, REAL_SKU, HIGH_NUM, None, uow) services.allocate(ORDER_1, REAL_SKU, LOW_NUM, uow) assert uow.committed is True