def test_change_batch_quantity_leading_to_reallocation(): # start with two batches and an order allocated to one of them orderid, sku = random_orderid(), random_sku() earlier_batch, later_batch = random_batchref('old'), random_batchref( 'newer') api_client.post_to_add_batch(earlier_batch, sku, qty=10, eta='2011-01-01') api_client.post_to_add_batch(later_batch, sku, qty=10, eta='2011-01-02') response = api_client.post_to_allocate(orderid, sku, 10) assert response.ok response = api_client.get_allocation(orderid) assert response.json()[0]['batchref'] == earlier_batch subscription = redis_client.subscribe_to('line_allocated') # change quantity on allocated batch so it's less than our order redis_client.publish_message('change_batch_quantity', { 'batchref': earlier_batch, 'qty': 5 }) # wait until we see a message saying the order has been reallocated messages = [] for attempt in Retrying(stop=stop_after_delay(3), reraise=True): with attempt: message = subscription.get_message(timeout=1) if message: messages.append(message) logger.info("%s", messages) data = json.loads(messages[-1]['data']) assert data['orderid'] == orderid assert data['batchref'] == later_batch
def test_happy_path_returns_201_and_allocated_batch(): sku, othersku = random_sku(), random_sku("other") earlybatch = random_batchref(1) laterbatch = random_batchref(2) otherbatch = random_batchref(3) post_to_add_batch(laterbatch, sku, 100, "2011-01-02") post_to_add_batch(earlybatch, sku, 100, "2011-01-01") post_to_add_batch(otherbatch, othersku, 100, None) data = {"orderid": random_orderid(), "sku": sku, "qty": 3} url = config.get_api_url() r = requests.post(f"{url}/allocate", json=data) assert r.status_code == 201 assert r.json()["batchref"] == earlybatch
def test_happy_path_returns_202_and_batch_is_allocated(): orderid = random_orderid() sku, othersku = random_sku(), random_sku('other') earlybatch = random_batchref(1) laterbatch = random_batchref(2) otherbatch = random_batchref(3) api_client.post_to_add_batch(laterbatch, sku, 100, '2011-01-02') api_client.post_to_add_batch(earlybatch, sku, 100, '2011-01-01') api_client.post_to_add_batch(otherbatch, othersku, 100, None) r = api_client.post_to_allocate(orderid, sku, qty=3) assert r.status_code == 202 r = api_client.get_allocation(orderid) assert r.ok assert r.json() == [ { 'sku': sku, 'batchref': earlybatch }, ]
def test_concurrent_updates_to_version_are_not_allowed( postgres_session_factory): sku, batch = random_sku(), random_batchref() session = postgres_session_factory() insert_batch(session, batch, sku, 100, eta=None, product_version=1) session.commit() order1, order2 = random_orderid(1), random_orderid(2) exceptions = [] # type: List[Exception] try_to_allocate_order1 = lambda: try_to_allocate(order1, sku, exceptions, postgres_session_factory) try_to_allocate_order2 = lambda: try_to_allocate(order2, sku, exceptions, postgres_session_factory) thread1 = threading.Thread(target=try_to_allocate_order1) thread2 = threading.Thread(target=try_to_allocate_order2) thread1.start() thread2.start() thread1.join() thread2.join() [[version]] = session.execute( "SELECT version_number FROM products WHERE sku=:sku", dict(sku=sku), ) assert version == 2 [exception] = exceptions assert 'could not serialize access due to concurrent update' in str( exception) orders = list( session.execute( "SELECT orderid FROM allocations" " JOIN batches ON allocations.batch_id = batches.id" " JOIN order_lines ON allocations.orderline_id = order_lines.id" " WHERE order_lines.sku=:sku", dict(sku=sku), )) assert len(orders) == 1 with unit_of_work.SqlAlchemyUnitOfWork(postgres_session_factory) as uow: uow.session.execute('select 1')