def test_allocating_to_a_batch_reduces_the_available_quantity() -> None: batch = Batch("batch-001", "SMALL-TABLE", qty=20, eta=today) line = OrderLine("order-ref", "SMALL-TABLE", 2) batch.allocate(line) assert batch.available_quantity == 18
def test_prefers_current_stock_batches_to_shipments() -> None: in_stock_batch = Batch("in-stock-batch", "RETRO-CLOCK", 100, eta=None) shipment_batch = Batch("shipment-batch", "RETRO-CLOCK", 100, eta=tomorrow) line = OrderLine("oref", "RETRO-CLOCK", 10) allocate(line, [in_stock_batch, shipment_batch]) assert in_stock_batch.available_quantity == 90 assert shipment_batch.available_quantity == 100
def test_prefers_warehouse_batches_to_shipments(): in_stock_batch = Batch("in-stock-batch", "RETRO-CLOCK", 100, eta=None) shipment_batch = Batch("shipment-batch", "RETRO-CLOCK", 100, eta=tomorrow) product = Product(sku="RETRO-CLOCK", items=[in_stock_batch, shipment_batch]) line = OrderLine("oref", "RETRO-CLOCK", 10) product.allocate(line) assert in_stock_batch.available_quantity == 90 assert shipment_batch.available_quantity == 100
def test_prefers_earlier_batches() -> None: earliest = Batch("speedy-batch", "MINIMALIST-SPOON", 100, eta=today) medium = Batch("normal-batch", "MINIMALIST-SPOON", 100, eta=tomorrow) latest = Batch("slow-batch", "MINIMALIST-SPOON", 100, eta=later) line = OrderLine("order1", "MINIMALIST-SPOON", 10) allocate(line, [medium, earliest, latest]) assert earliest.available_quantity == 90 assert medium.available_quantity == 100 assert latest.available_quantity == 100
def test_returns_allocated_batch_ref() -> None: in_stock_batch = Batch("in-stock-batch-ref", "HIGHBROW-POSTER", 100, eta=None) shipment_batch = Batch("shipment-batch-ref", "HIGHBROW-POSTER", 100, eta=tomorrow) line = OrderLine("oref", "HIGHBROW-POSTER", 10) allocation = allocate(line, [in_stock_batch, shipment_batch]) assert allocation == in_stock_batch.reference
def test_returns_allocated_batch_ref(): in_stock_batch = Batch("in-stock-batch-ref", "HIGHBROW-POSTER", 100, eta=None) shipment_batch = Batch("shipment-batch-ref", "HIGHBROW-POSTER", 100, eta=tomorrow) line = OrderLine("oref", "HIGHBROW-POSTER", 10) product = Product(sku="HIGHBROW-POSTER", items=[in_stock_batch, shipment_batch]) allocation = product.allocate(line) assert allocation == in_stock_batch.reference
def test_increments_version_number(): line = OrderLine("oref", "SCANDI-PEN", 10) product = Product(sku="SCANDI-PEN", items=[Batch("b1", "SCANDI-PEN", 100, eta=None)]) product.version_number = 7 product.allocate(line) assert product.version_number == 8
def test_error_for_invalid_sku() -> None: batch = Batch("b1", "AREALSKU", 100, eta=None) product = Product(batch.sku, [batch]) uow = FakeUnitOfWork({Product: "sku"}, [product]) with pytest.raises(services.allocation.InvalidSku, match="Invalid sku NONEXISTENTSKU"): services.allocation.allocate("o1", "NONEXISTENTSKU", 10, uow)
def test_records_out_of_stock_event_if_cannot_allocate(): batch = Batch("batch1", "SMALL-FORK", 10, eta=today) product = Product(sku="SMALL-FORK", items=[batch]) product.allocate(OrderLine("order1", "SMALL-FORK", 10)) allocation = product.allocate(OrderLine("order2", "SMALL-FORK", 1)) assert product.messages[-1] == events.OutOfStock(sku="SMALL-FORK") assert allocation is None
def add_batch(e: commands.CreateBatch, uow: AbstractUnitOfWork): """UOW를 이용해 배치를 추가합니다.""" with uow: product = uow[Product].get(e.sku) if not product: product = Product(e.sku, items=[]) uow[Product].add(product) product.items.append(Batch(e.ref, e.sku, e.qty, e.eta)) uow.commit()
def add_batch( ref: str, sku: str, qty: int, eta: Optional[datetime], uow: AbstractUnitOfWork ) -> None: """UOW를 이용해 배치를 추가합니다.""" with uow: product = uow[Product].get(sku) if not product: product = Product(sku, items=[]) uow[Product].add(product) product.items.append(Batch(ref, sku, qty, eta)) uow.commit()
def test_repository_can_save_a_batch(session: Session) -> None: batch = Batch("batch1", "RUSTY-SOAPDISH", 100, eta=None) product = Product(batch.sku, [batch]) repo = SqlAlchemyRepository(Product, session) repo.add(product) session.commit() rows = list( session.execute( "SELECT reference, sku, _purchased_quantity, eta FROM batch")) assert rows == [("batch1", "RUSTY-SOAPDISH", 100, None)]
def test_repository_can_retrieve_a_batch_with_allocations( session: Session) -> None: orderline_id = insert_order_line(session) batch1_id = insert_batch(session, "batch1", "GENERIC-SOFA") insert_product(session, "GENERIC-SOFA") insert_batch(session, "batch2", "GENERIC-TABLE") insert_product(session, "GENERIC-TABLE") insert_allocation(session, orderline_id, batch1_id) repo = SqlAlchemyRepository(Product, session) product = repo.get("GENERIC-SOFA") retrieved = product.items[0] if product else None expected = Batch("batch1", "GENERIC-SOFA", 100, eta=None) assert retrieved == expected # Batch.__eq__ only compares reference assert retrieved.sku == expected.sku assert retrieved._purchased_quantity == expected._purchased_quantity assert retrieved._allocations == { OrderLine("order1", "GENERIC-SOFA", 12), }
def test_cannot_allocate_if_skus_do_not_match() -> None: batch = Batch("batch-001", "UNCOMFORTABLE-CHAIR", 100, eta=None) different_sku_line = OrderLine("order-123", "EXPENSIVE-TOASTER", 10) assert batch.can_allocate(different_sku_line) is False
def make_batch_and_line(sku: str, batch_qty: int, line_qty: int) -> tuple[Batch, OrderLine]: return ( Batch("batch-001", sku, batch_qty, eta=today), OrderLine("order-123", sku, line_qty), )
def test_commits() -> None: batch = Batch("b1", "OMINOUS-MIRROR", 100, eta=None) product = Product(batch.sku, [batch]) uow = FakeUnitOfWork({Product: "sku"}, [product]) services.allocation.allocate("o1", "OMINOUS-MIRROR", 10, uow) assert uow.committed is True
def test_returns_allocation() -> None: batch = Batch("b1", "COMPLICATED-LAMP", 100, eta=None) product = Product(batch.sku, [batch]) uow = FakeUnitOfWork({Product: "sku"}, [product]) result = services.allocation.allocate("o1", "COMPLICATED-LAMP", 10, uow) assert result == "b1"
def test_batch_equality() -> None: batch1 = Batch("batch-001", "SIMPLE-TABLE", 10, eta=today) batch2 = Batch("batch-001", "SIMPLE-CHAIR", 5, eta=today) assert batch1 == batch2