feat: add initial workflow master views, UI features

This commit is contained in:
Lance Edgar 2025-01-22 21:32:15 -06:00
parent 9d378a0c5f
commit 7167c6a7cc
10 changed files with 2364 additions and 22 deletions

View file

@ -9,6 +9,7 @@ class TestOrderHandler(DataTestCase):
def make_config(self, **kwargs):
config = super().make_config(**kwargs)
config.setdefault('wutta.model_spec', 'sideshow.db.model')
config.setdefault('wutta.enum_spec', 'sideshow.enum')
return config
@ -58,3 +59,361 @@ class TestOrderHandler(DataTestCase):
self.assertEqual(handler.item_status_to_variant(enum.ORDER_ITEM_STATUS_RESTOCKED), 'warning')
self.assertEqual(handler.item_status_to_variant(enum.ORDER_ITEM_STATUS_EXPIRED), 'warning')
self.assertEqual(handler.item_status_to_variant(enum.ORDER_ITEM_STATUS_INACTIVE), 'warning')
def test_process_placement(self):
model = self.app.model
enum = self.app.enum
handler = self.make_handler()
# sample data
user = model.User(username='barney')
self.session.add(user)
order = model.Order(order_id=42, customer_name="Fred Flintstone", created_by=user)
item1 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_READY)
order.items.append(item1)
item2 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_READY)
order.items.append(item2)
item3 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_READY)
order.items.append(item3)
self.session.add(order)
self.session.flush()
# two items are updated
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_READY)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_READY)
self.assertEqual(len(item1.events), 0)
self.assertEqual(len(item2.events), 0)
handler.process_placement([item1, item2], user,
vendor_name="Acme Dist", po_number='ACME123')
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item1.events), 1)
self.assertEqual(len(item2.events), 1)
self.assertEqual(item1.events[0].note, "PO ACME123 for vendor Acme Dist")
self.assertEqual(item2.events[0].note, "PO ACME123 for vendor Acme Dist")
self.assertEqual(item1.events[0].type_code, enum.ORDER_ITEM_EVENT_PLACED)
self.assertEqual(item2.events[0].type_code, enum.ORDER_ITEM_EVENT_PLACED)
# update last item, without vendor name but extra note
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_READY)
self.assertEqual(len(item3.events), 0)
handler.process_placement([item3], user, po_number="939234", note="extra note")
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item3.events), 2)
self.assertEqual(item3.events[0].note, "PO 939234")
self.assertEqual(item3.events[1].note, "extra note")
self.assertEqual(item3.events[0].type_code, enum.ORDER_ITEM_EVENT_PLACED)
self.assertEqual(item3.events[1].type_code, enum.ORDER_ITEM_EVENT_NOTE_ADDED)
def test_process_receiving(self):
model = self.app.model
enum = self.app.enum
handler = self.make_handler()
# sample data
user = model.User(username='barney')
self.session.add(user)
order = model.Order(order_id=42, customer_name="Fred Flintstone", created_by=user)
item1 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item1)
item2 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item2)
item3 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item3)
item4 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item4)
item5 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item5)
self.session.add(order)
self.session.flush()
# all info provided
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item1.events), 0)
handler.process_receiving([item1], user, vendor_name="Acme Dist",
invoice_number='INV123', po_number='123')
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item1.events), 1)
self.assertEqual(item1.events[0].note, "invoice INV123 (PO 123) from vendor Acme Dist")
self.assertEqual(item1.events[0].type_code, enum.ORDER_ITEM_EVENT_RECEIVED)
# missing PO number
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item2.events), 0)
handler.process_receiving([item2], user, vendor_name="Acme Dist", invoice_number='INV123')
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item2.events), 1)
self.assertEqual(item2.events[0].note, "invoice INV123 from vendor Acme Dist")
self.assertEqual(item2.events[0].type_code, enum.ORDER_ITEM_EVENT_RECEIVED)
# missing invoice number
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item3.events), 0)
handler.process_receiving([item3], user, vendor_name="Acme Dist", po_number='123')
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item3.events), 1)
self.assertEqual(item3.events[0].note, "PO 123 from vendor Acme Dist")
self.assertEqual(item3.events[0].type_code, enum.ORDER_ITEM_EVENT_RECEIVED)
# vendor name only
self.assertEqual(item4.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item4.events), 0)
handler.process_receiving([item4], user, vendor_name="Acme Dist")
self.assertEqual(item4.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item4.events), 1)
self.assertEqual(item4.events[0].note, "from vendor Acme Dist")
self.assertEqual(item4.events[0].type_code, enum.ORDER_ITEM_EVENT_RECEIVED)
# no info; extra note
self.assertEqual(item5.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item5.events), 0)
handler.process_receiving([item5], user, note="extra note")
self.assertEqual(item5.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item5.events), 2)
self.assertIsNone(item5.events[0].note)
self.assertEqual(item5.events[0].type_code, enum.ORDER_ITEM_EVENT_RECEIVED)
self.assertEqual(item5.events[1].note, "extra note")
self.assertEqual(item5.events[1].type_code, enum.ORDER_ITEM_EVENT_NOTE_ADDED)
def test_process_reorder(self):
model = self.app.model
enum = self.app.enum
handler = self.make_handler()
# sample data
user = model.User(username='barney')
self.session.add(user)
order = model.Order(order_id=42, customer_name="Fred Flintstone", created_by=user)
item1 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item1)
item2 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item2)
item3 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_PLACED)
order.items.append(item3)
self.session.add(order)
self.session.flush()
# two items are updated
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item1.events), 0)
self.assertEqual(len(item2.events), 0)
handler.process_reorder([item1, item2], user)
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_READY)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_READY)
self.assertEqual(len(item1.events), 1)
self.assertEqual(len(item2.events), 1)
self.assertIsNone(item1.events[0].note)
self.assertIsNone(item2.events[0].note)
self.assertEqual(item1.events[0].type_code, enum.ORDER_ITEM_EVENT_REORDER)
self.assertEqual(item2.events[0].type_code, enum.ORDER_ITEM_EVENT_REORDER)
# update last item, with extra note
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_PLACED)
self.assertEqual(len(item3.events), 0)
handler.process_reorder([item3], user, note="extra note")
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_READY)
self.assertEqual(len(item3.events), 2)
self.assertIsNone(item3.events[0].note)
self.assertEqual(item3.events[1].note, "extra note")
self.assertEqual(item3.events[0].type_code, enum.ORDER_ITEM_EVENT_REORDER)
self.assertEqual(item3.events[1].type_code, enum.ORDER_ITEM_EVENT_NOTE_ADDED)
def test_process_contact_success(self):
model = self.app.model
enum = self.app.enum
handler = self.make_handler()
# sample data
user = model.User(username='barney')
self.session.add(user)
order = model.Order(order_id=42, customer_name="Fred Flintstone", created_by=user)
item1 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item1)
item2 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item2)
item3 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item3)
self.session.add(order)
self.session.flush()
# two items are updated
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item1.events), 0)
self.assertEqual(len(item2.events), 0)
handler.process_contact_success([item1, item2], user)
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_CONTACTED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_CONTACTED)
self.assertEqual(len(item1.events), 1)
self.assertEqual(len(item2.events), 1)
self.assertIsNone(item1.events[0].note)
self.assertIsNone(item2.events[0].note)
self.assertEqual(item1.events[0].type_code, enum.ORDER_ITEM_EVENT_CONTACTED)
self.assertEqual(item2.events[0].type_code, enum.ORDER_ITEM_EVENT_CONTACTED)
# update last item, with extra note
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item3.events), 0)
handler.process_contact_success([item3], user, note="extra note")
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_CONTACTED)
self.assertEqual(len(item3.events), 2)
self.assertIsNone(item3.events[0].note)
self.assertEqual(item3.events[1].note, "extra note")
self.assertEqual(item3.events[0].type_code, enum.ORDER_ITEM_EVENT_CONTACTED)
self.assertEqual(item3.events[1].type_code, enum.ORDER_ITEM_EVENT_NOTE_ADDED)
def test_process_contact_failure(self):
model = self.app.model
enum = self.app.enum
handler = self.make_handler()
# sample data
user = model.User(username='barney')
self.session.add(user)
order = model.Order(order_id=42, customer_name="Fred Flintstone", created_by=user)
item1 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item1)
item2 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item2)
item3 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item3)
self.session.add(order)
self.session.flush()
# two items are updated
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item1.events), 0)
self.assertEqual(len(item2.events), 0)
handler.process_contact_failure([item1, item2], user)
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_CONTACT_FAILED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_CONTACT_FAILED)
self.assertEqual(len(item1.events), 1)
self.assertEqual(len(item2.events), 1)
self.assertIsNone(item1.events[0].note)
self.assertIsNone(item2.events[0].note)
self.assertEqual(item1.events[0].type_code, enum.ORDER_ITEM_EVENT_CONTACT_FAILED)
self.assertEqual(item2.events[0].type_code, enum.ORDER_ITEM_EVENT_CONTACT_FAILED)
# update last item, with extra note
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item3.events), 0)
handler.process_contact_failure([item3], user, note="extra note")
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_CONTACT_FAILED)
self.assertEqual(len(item3.events), 2)
self.assertIsNone(item3.events[0].note)
self.assertEqual(item3.events[1].note, "extra note")
self.assertEqual(item3.events[0].type_code, enum.ORDER_ITEM_EVENT_CONTACT_FAILED)
self.assertEqual(item3.events[1].type_code, enum.ORDER_ITEM_EVENT_NOTE_ADDED)
def test_process_delivery(self):
model = self.app.model
enum = self.app.enum
handler = self.make_handler()
# sample data
user = model.User(username='barney')
self.session.add(user)
order = model.Order(order_id=42, customer_name="Fred Flintstone", created_by=user)
item1 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item1)
item2 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item2)
item3 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item3)
self.session.add(order)
self.session.flush()
# two items are updated
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item1.events), 0)
self.assertEqual(len(item2.events), 0)
handler.process_delivery([item1, item2], user)
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_DELIVERED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_DELIVERED)
self.assertEqual(len(item1.events), 1)
self.assertEqual(len(item2.events), 1)
self.assertIsNone(item1.events[0].note)
self.assertIsNone(item2.events[0].note)
self.assertEqual(item1.events[0].type_code, enum.ORDER_ITEM_EVENT_DELIVERED)
self.assertEqual(item2.events[0].type_code, enum.ORDER_ITEM_EVENT_DELIVERED)
# update last item, with extra note
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item3.events), 0)
handler.process_delivery([item3], user, note="extra note")
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_DELIVERED)
self.assertEqual(len(item3.events), 2)
self.assertIsNone(item3.events[0].note)
self.assertEqual(item3.events[1].note, "extra note")
self.assertEqual(item3.events[0].type_code, enum.ORDER_ITEM_EVENT_DELIVERED)
self.assertEqual(item3.events[1].type_code, enum.ORDER_ITEM_EVENT_NOTE_ADDED)
def test_process_restock(self):
model = self.app.model
enum = self.app.enum
handler = self.make_handler()
# sample data
user = model.User(username='barney')
self.session.add(user)
order = model.Order(order_id=42, customer_name="Fred Flintstone", created_by=user)
item1 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item1)
item2 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item2)
item3 = model.OrderItem(order_qty=1, order_uom=enum.ORDER_UOM_UNIT,
status_code=enum.ORDER_ITEM_STATUS_RECEIVED)
order.items.append(item3)
self.session.add(order)
self.session.flush()
# two items are updated
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item1.events), 0)
self.assertEqual(len(item2.events), 0)
handler.process_restock([item1, item2], user)
self.assertEqual(item1.status_code, enum.ORDER_ITEM_STATUS_RESTOCKED)
self.assertEqual(item2.status_code, enum.ORDER_ITEM_STATUS_RESTOCKED)
self.assertEqual(len(item1.events), 1)
self.assertEqual(len(item2.events), 1)
self.assertIsNone(item1.events[0].note)
self.assertIsNone(item2.events[0].note)
self.assertEqual(item1.events[0].type_code, enum.ORDER_ITEM_EVENT_RESTOCKED)
self.assertEqual(item2.events[0].type_code, enum.ORDER_ITEM_EVENT_RESTOCKED)
# update last item, with extra note
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_RECEIVED)
self.assertEqual(len(item3.events), 0)
handler.process_restock([item3], user, note="extra note")
self.assertEqual(item3.status_code, enum.ORDER_ITEM_STATUS_RESTOCKED)
self.assertEqual(len(item3.events), 2)
self.assertIsNone(item3.events[0].note)
self.assertEqual(item3.events[1].note, "extra note")
self.assertEqual(item3.events[0].type_code, enum.ORDER_ITEM_EVENT_RESTOCKED)
self.assertEqual(item3.events[1].type_code, enum.ORDER_ITEM_EVENT_NOTE_ADDED)