def test_realocates_batch_if_nessesary_when_available_quantity_reduces(
    messagebus, ):
    history = [
        commands.CreateBatch(reference="batch1",
                             sku="INDIFFERENT-TABLE",
                             qty=100),
        commands.CreateBatch(
            reference="batch2",
            sku="INDIFFERENT-TABLE",
            qty=100,
            eta=date.today(),
        ),
        commands.Allocate(orderid="order1", sku="INDIFFERENT-TABLE", qty=50),
        commands.Allocate(orderid="order2", sku="INDIFFERENT-TABLE", qty=50),
    ]
    for message in history:
        messagebus.handle(message)
    [batch1, batch2] = messagebus.uow.products.get("INDIFFERENT-TABLE").batches

    assert batch1.available_quantity == 0
    assert batch2.available_quantity == 100

    message = commands.ChangeBatchQuantity(reference="batch1", qty=55)
    messagebus.handle(message)

    assert batch1.available_quantity == 5
    assert batch2.available_quantity == 50
Beispiel #2
0
def test_allocations_view(sqlite_bus):
    # uow = unit_of_work.SqlAlchemyUnitOfWork(sqlite_session_factory)
    sqlite_bus.handle(commands.CreateBatch('sku1batch', 'sku1', 50, None))
    sqlite_bus.handle(commands.CreateBatch('sku2batch', 'sku2', 50, None))
    sqlite_bus.handle(commands.Allocate(
        'order1',
        'sku1',
        20,
    ))
    sqlite_bus.handle(commands.Allocate(
        'order1',
        'sku2',
        20,
    ))

    sqlite_bus.handle(
        commands.CreateBatch('sku1batch-later', 'sku1', 50, today))
    sqlite_bus.handle(commands.Allocate('other-order', 'sku1', 30))
    sqlite_bus.handle(commands.Allocate('other-order', 'sku2', 10))

    assert views.allocations('order1', sqlite_bus.uow) == [
        {
            'sku': 'sku1',
            'batchref': 'sku1batch'
        },
        {
            'sku': 'sku2',
            'batchref': 'sku2batch'
        },
    ]
Beispiel #3
0
    def test_sends_email_on_out_of_stock_error(self):
        bus = bootstrap_test_app()
        bus.handle(commands.CreateBatch("b1", "POPULAR-CURTAINS", 9, None))
        bus.handle(commands.Allocate("o1", "POPULAR-CURTAINS", 10))

        with mock.patch(
                "allocation.adapters.notifications.EmailNotifications.send"
        ) as mock_send_mail:
            bus.handle(commands.Allocate("o1", "POPULAR-CURTAINS", 10))
            assert mock_send_mail.call_args == mock.call(
                ['*****@*****.**'], "缺货啦,货号POPULAR-CURTAINS")
Beispiel #4
0
def test_allocations_view(sqlite_bus):
    sqlite_bus.handle(commands.CreateBatch("sku1batch", "sku1", 50, None))
    sqlite_bus.handle(commands.CreateBatch("sku2batch", "sku2", 50, today))
    sqlite_bus.handle(commands.Allocate("order1", "sku1", 20))
    sqlite_bus.handle(commands.Allocate("order1", "sku2", 20))
    # add a spurious batch and order to make sure we're getting the right ones
    sqlite_bus.handle(commands.CreateBatch("sku1batch-later", "sku1", 50, today))
    sqlite_bus.handle(commands.Allocate("otherorder", "sku1", 30))
    sqlite_bus.handle(commands.Allocate("otherorder", "sku2", 10))

    assert views.allocations("order1", sqlite_bus.uow) == [
        {"sku": "sku1", "batchref": "sku1batch"},
        {"sku": "sku2", "batchref": "sku2batch"},
    ]
Beispiel #5
0
def test_allocations_view(sqlite_session_factory):
    uow = unit_of_work.SqlAlchemyUnitOfWork(sqlite_session_factory)
    messagebus.handle(commands.CreateBatch("sku1batch", "sku1", 50, None), uow)
    messagebus.handle(commands.CreateBatch("sku2batch", "sku2", 50, today), uow)
    messagebus.handle(commands.Allocate("order1", "sku1", 20), uow)
    messagebus.handle(commands.Allocate("order1", "sku2", 20), uow)
    # add a spurious batch and order to make sure we're getting the right ones
    messagebus.handle(commands.CreateBatch("sku1batch-later", "sku1", 50, today), uow)
    messagebus.handle(commands.Allocate("otherorder", "sku1", 30), uow)
    messagebus.handle(commands.Allocate("otherorder", "sku2", 10), uow)

    assert views.allocations("order1", uow) == [
        {"sku": "sku1", "batchref": "sku1batch"},
        {"sku": "sku2", "batchref": "sku2batch"},
    ]
Beispiel #6
0
    def test_allocates(self):
        bus = bootstrap_test_app()

        bus.handle(commands.CreateBatch('b1', '黑桌子', 20, None))
        bus.handle(commands.Allocate('o1', '黑桌子', 10))
        [batch] = bus.uow.products.get('黑桌子').batches
        assert batch.available_quantity == 10
    def test_commits(self):
        bus = bootstrap_test_app()
        bus.handle(commands.CreateBatch("batch01", "OMINOUS-MIRROR", 100,
                                        None))
        bus.handle(commands.Allocate("o1", "OMINOUS-MIRROR", 10))

        assert bus.uow.committed
Beispiel #8
0
 def test_allocates(self):
     uow = FakeUnitOfWork()
     messagebus.handle(
         commands.CreateBatch("batch1", "COMPLICATED-LAMP", 100, None), uow)
     messagebus.handle(commands.Allocate("o1", "COMPLICATED-LAMP", 10), uow)
     [batch] = uow.products.get("COMPLICATED-LAMP").batches
     assert batch.available_quantity == 90
Beispiel #9
0
 def test_allocates(self):
     bus = bootstrap_test_app()
     bus.handle(
         commands.CreateBatch("batch1", "COMPLICATED-LAMP", 100, None))
     bus.handle(commands.Allocate("o1", "COMPLICATED-LAMP", 10))
     [batch] = bus.uow.products.get("COMPLICATED-LAMP").batches
     assert batch.available_quantity == 90
def test_deallocation(sqlite_bus):
    sqlite_bus.handle(commands.CreateBatch('b1', 'sku1', 50, None))
    sqlite_bus.handle(commands.CreateBatch('b2', 'sku1', 50, today))
    sqlite_bus.handle(commands.Allocate('o1', 'sku1', 40))
    sqlite_bus.handle(commands.ChangeBatchQuantity('b1', 10))

    assert views.allocations('o1') == [{'sku': 'sku1', 'batchref': 'b2'}]
Beispiel #11
0
    def test_errors_for_invalid_sku(self):
        bus = bootstrap_test_app()
        bus.handle(commands.CreateBatch("b1", "AREALSKU", 100, None))

        with pytest.raises(handlers.InvalidSku,
                           match="Invalid sku NONEXISTENTSKU"):
            bus.handle(commands.Allocate("o1", "NONEXISTENTSKU", 10))
Beispiel #12
0
def reallocate(
    event: events.Deallocated, uow: unit_of_work.AbstractUnitOfWork
):
    with uow:
        product = uow.products.get(sku=event.sku)
        product.events.append(commands.Allocate(**asdict(event)))
        uow.commit()
Beispiel #13
0
    def test_errors_for_invalid_sku(self):
        uow = FakeUnitOfWork()
        messagebus.handle(commands.CreateBatch("b1", "AREALSKU", 100, None), uow)

        with pytest.raises(handlers.InvalidSku, match="Invalid sku NONEXISTENTSKU"):
            messagebus.handle(
                commands.Allocate("o1", "NONEXISTENTSKU", 10), uow
            )
Beispiel #14
0
def test_out_of_stock_email(bus):
    sku = random_sku()
    bus.handle(commands.CreateBatch('batch1', sku, 9, None))
    bus.handle(commands.Allocate('order1', sku, 10))
    email = get_email_from_mailhog(sku)
    assert email['Raw']['From'] == '*****@*****.**'
    assert email['Raw']['To'] == ['*****@*****.**']
    assert f'Out of stock for {sku}' in email['Raw']['Data']
Beispiel #15
0
    def test_commits(self):
        bus = bootstrap_test_app()

        bus.handle(commands.CreateBatch('b1', 'OMINOUS-MIRROR', 100, None))

        bus.handle(commands.Allocate('o1', 'OMINOUS-MIRROR', 10))

        assert bus.uow.committed is True
Beispiel #16
0
def test_out_of_stock_email(bus):
    sku = random_sku()
    bus.handle(commands.CreateBatch("batch1", sku, 9, None))
    bus.handle(commands.Allocate("order1", sku, 10))
    email = get_email_from_mailhog(sku)
    assert email["Raw"]["From"] == "*****@*****.**"
    assert email["Raw"]["To"] == ["*****@*****.**"]
    assert f"Out of stock for {sku}" in email["Raw"]["Data"]
Beispiel #17
0
def create_and_allocate_batch(uow: unit_of_work.AbstractUnitOfWork) -> tuple:
    sku = helpers.random_sku()
    orderid = helpers.random_orderid()
    batchref = helpers.random_batchref()

    message_bus.handle(commands.CreateBatch(batchref, sku, 100, None), uow)
    message_bus.handle(commands.Allocate(orderid, sku, 30), uow)

    return batchref, orderid, sku
def test_allocations_view(sqlite_bus):
    sqlite_bus.handle(commands.CreateBatch('sku1batch', 'sku1', 50, None))
    sqlite_bus.handle(commands.CreateBatch('sku2batch', 'sku2', 50, today))
    sqlite_bus.handle(commands.Allocate('order1', 'sku1', 20))
    sqlite_bus.handle(commands.Allocate('order1', 'sku2', 20))
    # add s spurious batch and order to make sure we're getting the right ones
    sqlite_bus.handle(
        commands.CreateBatch('sku1batch-later', 'sku1', 50, today))
    sqlite_bus.handle(commands.Allocate('otherorder', 'sku1', 30))
    sqlite_bus.handle(commands.Allocate('otherorder', 'sku2', 10))

    assert views.allocations('order1') == [{
        'sku': 'sku1',
        'batchref': 'sku1batch'
    }, {
        'sku': 'sku2',
        'batchref': 'sku2batch'
    }]
Beispiel #19
0
def allocate_endpoint():
    try:
        command = commands.Allocate(request.json['orderid'],
                                    request.json['sku'], request.json['qty'])
        bus.handle(command)
    except handlers.InvalidSku as e:
        return jsonify({'message': str(e)}), 400

    return 'OK', 202
Beispiel #20
0
    def test_returns_allocation(self):
        bus = bootstrap_test_app()

        bus.handle(commands.CreateBatch('b1', 'COMPLICATED-LAMP', 100, None))

        bus.handle(commands.Allocate('o1', 'COMPLICATED-LAMP', 10))

        [batch] = bus.uow.products.get('COMPLICATED-LAMP').batches
        assert batch.available_quantity == 90
Beispiel #21
0
def allocate_endpoint():
    try:
        cmd = commands.Allocate(request.json["orderid"], request.json["sku"],
                                request.json["qty"])
        bus.handle(cmd)
    except InvalidSku as e:
        return {"message": str(e)}, 400

    return "OK", 202
Beispiel #22
0
 def test_sends_email_on_out_of_stock_error(self):
     uow = FakeUnitOfWork()
     messagebus.handle(
         commands.CreateBatch("b1", "POPULAR-CURTAINS", 9, None), uow)
     with mock.patch("allocation.adapters.email.send") as mock_send_mail:
         messagebus.handle(commands.Allocate("o1", "POPULAR-CURTAINS", 10),
                           uow)
         assert mock_send_mail.call_args == mock.call(
             "*****@*****.**", f"Out of stock for POPULAR-CURTAINS")
def test_allocations_view(sqlite_session_factory):
    uow = unit_of_work.SqlAlchemyUnitOfWork(sqlite_session_factory)
    messagebus.handle(commands.CreateBatch('sku1batch', 'sku1', 50, None), uow)
    messagebus.handle(commands.CreateBatch('sku2batch', 'sku2', 50, today),
                      uow)
    messagebus.handle(commands.Allocate('order1', 'sku1', 20), uow)
    messagebus.handle(commands.Allocate('order1', 'sku2', 20), uow)

    assert views.allocations('order1', uow) == [
        {
            'sku': 'sku1',
            'batchref': 'sku1batch'
        },
        {
            'sku': 'sku2',
            'batchref': 'sku2batch'
        },
    ]
Beispiel #24
0
 def test_commits(self):
     uow = FakeUnitOfWork()
     messagebus.handle(
         commands.CreateBatch("b1", "OMINOUS-MIRROR", 100, None), uow
     )
     messagebus.handle(
         commands.Allocate("o1", "OMINOUS-MIRROR", 10), uow
     )
     assert uow.committed
Beispiel #25
0
def test_deallocation(sqlite_bus):
    sqlite_bus.handle(commands.CreateBatch("b1", "sku1", 50, None))
    sqlite_bus.handle(commands.CreateBatch("b2", "sku1", 50, today))
    sqlite_bus.handle(commands.Allocate("o1", "sku1", 40))
    sqlite_bus.handle(commands.ChangeBatchQuantity("b1", 10))

    assert views.allocations("o1", sqlite_bus.uow) == [
        {"sku": "sku1", "batchref": "b2"},
    ]
def test_allocate_errors_for_invalid_sku(messagebus):
    message = commands.CreateBatch(reference="batch1", sku="AREALSKU", qty=100)
    messagebus.handle(message)

    with pytest.raises(handlers.InvalidSku,
                       match="Invalid sku NON-EXISTENTSKU"):
        message = commands.Allocate(orderid="order1",
                                    sku="NON-EXISTENTSKU",
                                    qty=10)
        messagebus.handle(message)
Beispiel #27
0
    def test_reallocates_if_necessary(self):
        bus = bootstrap_test_app()
        event_history = [
            commands.CreateBatch('批次1', '桌子', 50),
            commands.CreateBatch('批次2', '桌子', 50, date.today()),
            commands.Allocate('订单1', '桌子', 20),
            commands.Allocate('订单2', '桌子', 20),
        ]
        for e in event_history:
            bus.handle(e)
        [batch1, batch2] = bus.uow.products.get(sku='桌子').batches
        assert batch1.available_quantity == 10  # 下了两单 现在库存10
        assert batch2.available_quantity == 50  # 这个不变

        # bus.handle(
        #     commands.ChangeBatchQuantity('批次1', 25), uow)
        bus.handle(commands.ChangeBatchQuantity('批次1', 25))
        assert batch1.available_quantity == 5  # 批次1泡水了 库存25 所以要退下的单子给批次2
        assert batch2.available_quantity == 30  # 批次2 减少20
Beispiel #28
0
def test_deallocation(sqlite_session_factory):
    uow = unit_of_work.SqlAlchemyUnitOfWork(sqlite_session_factory)
    messagebus.handle(commands.CreateBatch("b1", "sku1", 50, None), uow)
    messagebus.handle(commands.CreateBatch("b2", "sku1", 50, today), uow)
    messagebus.handle(commands.Allocate("o1", "sku1", 40), uow)
    messagebus.handle(commands.ChangeBatchQuantity("b1", 10), uow)

    assert views.allocations("o1", uow) == [
        {"sku": "sku1", "batchref": "b2"},
    ]
Beispiel #29
0
    def test_reallocates_if_necessary(self):
        uow = FakeUnitOfWork()
        history = [
            commands.CreateBatch("batch1", "INDIFFERENT-TABLE", 50, None),
            commands.CreateBatch("batch2", "INDIFFERENT-TABLE", 50, date.today()),
            commands.Allocate("order1", "INDIFFERENT-TABLE", 20),
            commands.Allocate("order2", "INDIFFERENT-TABLE", 20),
        ]
        for msg in history:
            messagebus.handle(msg, uow)
        [batch1, batch2] = uow.products.get(sku="INDIFFERENT-TABLE").batches
        assert batch1.available_quantity == 10
        assert batch2.available_quantity == 50

        messagebus.handle(commands.ChangeBatchQuantity("batch1", 25), uow)

        # order1 or order2 will be deallocated, so we'll have 25 - 20
        assert batch1.available_quantity == 5
        # and 20 will be reallocated to the next batch
        assert batch2.available_quantity == 30
Beispiel #30
0
def test_allocations_view(session_factory):
    uow = unit_of_work.SqlAlchemyUnitOfWork(session_factory)
    messagebus.handle(commands.CreateBatch('sku1batch', 'sku1', 50, None), uow)
    messagebus.handle(
        commands.CreateBatch('sku2batch', 'sku2', 50, date.today()), uow)
    messagebus.handle(commands.Allocate('vieworder1', 'sku1', 20), uow)
    messagebus.handle(commands.Allocate('vieworder1', 'sku2', 20), uow)
    # add a spurious batch and order to make sure we're getting the right ones
    messagebus.handle(
        commands.CreateBatch('sku1batch-later', 'sku1', 50, date.today()), uow)
    messagebus.handle(commands.Allocate('otherorder', 'sku1', 30), uow)
    messagebus.handle(commands.Allocate('otherorder', 'sku2', 10), uow)

    assert views.allocations('vieworder1', uow) == [{
        'sku': 'sku1',
        'batchref': 'sku1batch'
    }, {
        'sku': 'sku2',
        'batchref': 'sku2batch'
    }]