From 07ecc0eda3aaed309728540e7b7be6810d9c2404 Mon Sep 17 00:00:00 2001 From: Sam Debruyn Date: Sat, 7 Sep 2024 15:50:14 +0200 Subject: [PATCH] feat: add OrderItem and generate correct schema for items dataset --- jafgen/customers/customers.py | 19 ++++++++------- jafgen/customers/order.py | 13 ++++------ jafgen/customers/order_id.py | 4 ++++ jafgen/customers/order_item.py | 43 ++++++++++++++++++++++++++++++++++ jafgen/simulation.py | 2 +- jafgen/stores/inventory.py | 5 ++-- tests/test_order_totals.py | 10 ++++---- 7 files changed, 70 insertions(+), 26 deletions(-) create mode 100644 jafgen/customers/order_id.py create mode 100644 jafgen/customers/order_item.py diff --git a/jafgen/customers/customers.py b/jafgen/customers/customers.py index 9328756..9d55165 100644 --- a/jafgen/customers/customers.py +++ b/jafgen/customers/customers.py @@ -7,6 +7,7 @@ from faker import Faker from jafgen.customers.order import Order +from jafgen.customers.order_item import OrderItem from jafgen.customers.tweet import Tweet from jafgen.stores.inventory import Inventory from jafgen.stores.item import Item, ItemType @@ -46,7 +47,7 @@ def p_tweet(self, day: Day) -> float: return self.p_tweet_persona(day) def get_order(self, day: Day) -> Order | None: - items = self.get_order_items(day) + items = [OrderItem(item=item) for item in self.get_order_items(day)] order_minute = self.get_order_minute(day) order_day = day.at_minute(order_minute) @@ -127,9 +128,9 @@ def get_order_items(self, day: Day): num_drinks = 2 if fake.random.random() > 0.7: - food = Inventory.get_item_type(ItemType.JAFFLE, 1) + food = Inventory.get_order_item_type(ItemType.JAFFLE, 1) - return Inventory.get_item_type(ItemType.BEVERAGE, num_drinks) + food + return Inventory.get_order_item_type(ItemType.BEVERAGE, num_drinks) + food class BrunchCrowd(Customer): @@ -150,7 +151,7 @@ def get_order_minute(self, day: Day) -> int: def get_order_items(self, day: Day): num_customers = 1 + int(self.favorite_number / 20) - return Inventory.get_item_type(ItemType.JAFFLE, num_customers) + Inventory.get_item_type(ItemType.BEVERAGE, num_customers) + return Inventory.get_order_item_type(ItemType.JAFFLE, num_customers) + Inventory.get_order_item_type(ItemType.BEVERAGE, num_customers) class Commuter(Customer): @@ -171,7 +172,7 @@ def get_order_minute(self, day: Day) -> int: return max(0, int(order_time)) def get_order_items(self, day: Day): - return Inventory.get_item_type(ItemType.BEVERAGE, 1) + return Inventory.get_order_item_type(ItemType.BEVERAGE, 1) class Student(Customer): @@ -196,9 +197,9 @@ def get_order_minute(self, day: Day) -> int: def get_order_items(self, day: Day): food = [] if fake.random.random() > 0.5: - food = Inventory.get_item_type(ItemType.JAFFLE, 1) + food = Inventory.get_order_item_type(ItemType.JAFFLE, 1) - return Inventory.get_item_type(ItemType.BEVERAGE, 1) + food + return Inventory.get_order_item_type(ItemType.BEVERAGE, 1) + food class Casuals(Customer): @@ -218,7 +219,7 @@ def get_order_minute(self, day: Day) -> int: def get_order_items(self, day: Day): num_drinks = int(fake.random.random() * 10 / 3) num_food = int(fake.random.random() * 10 / 3) - return Inventory.get_item_type(ItemType.BEVERAGE, num_drinks) + Inventory.get_item_type(ItemType.JAFFLE, num_food) + return Inventory.get_order_item_type(ItemType.BEVERAGE, num_drinks) + Inventory.get_order_item_type(ItemType.JAFFLE, num_food) class HealthNut(Customer): @@ -239,4 +240,4 @@ def get_order_minute(self, day: Day) -> int: return max(0, int(order_time)) def get_order_items(self, day: Day): - return Inventory.get_item_type(ItemType.BEVERAGE, 1) + return Inventory.get_order_item_type(ItemType.BEVERAGE, 1) diff --git a/jafgen/customers/order.py b/jafgen/customers/order.py index 5d59e87..df5e4d6 100644 --- a/jafgen/customers/order.py +++ b/jafgen/customers/order.py @@ -1,24 +1,22 @@ -import uuid from dataclasses import dataclass, field -from typing import Any, NewType +from typing import Any from faker import Faker import jafgen.customers.customers as customer -from jafgen.stores.item import Item +from jafgen.customers.order_id import OrderId +from jafgen.customers.order_item import OrderItem from jafgen.stores.store import Store from jafgen.time import Day fake = Faker() -OrderId = NewType("OrderId", uuid.UUID) - @dataclass class Order: customer: "customer.Customer" day: Day store: Store - items: list[Item] + items: list[OrderItem] id: OrderId = field(default_factory=lambda: OrderId(fake.uuid4())) subtotal: float = field(init=False) @@ -46,6 +44,3 @@ def to_dict(self) -> dict[str, Any]: # "order_total": int(self.order_total * 100), "order_total": int(int(self.subtotal * 100) + int(self.tax_paid * 100)), } - - def items_to_dict(self) -> list[dict[str, Any]]: - return [item.to_dict() for item in self.items] diff --git a/jafgen/customers/order_id.py b/jafgen/customers/order_id.py new file mode 100644 index 0000000..a1c0e33 --- /dev/null +++ b/jafgen/customers/order_id.py @@ -0,0 +1,4 @@ +import uuid +from typing import NewType + +OrderId = NewType("OrderId", uuid.UUID) diff --git a/jafgen/customers/order_item.py b/jafgen/customers/order_item.py new file mode 100644 index 0000000..c420f4d --- /dev/null +++ b/jafgen/customers/order_item.py @@ -0,0 +1,43 @@ +import uuid +from dataclasses import dataclass, field +from typing import Any, NewType + +from faker import Faker + +from jafgen.customers.order_id import OrderId +from jafgen.stores.item import Item +from jafgen.stores.supply import StorageKeepingUnit + +fake = Faker() + +OrderItemId = NewType("OrderItemId", uuid.UUID) + +@dataclass(frozen=True) +class OrderItem: + item: Item + id: OrderItemId = field(default_factory=lambda: OrderItemId(fake.uuid4())) + + @property + def name(self) -> str: + return self.item.name + + @property + def price(self) -> float: + return self.item.price + + @property + def sku(self) -> StorageKeepingUnit: + return self.item.sku + + def __str__(self): + return f"<{self.name} @ ${self.price}>" + + def __repr__(self): + return self.__str__() + + def to_dict(self, order_id: OrderId) -> dict[str, Any]: + return { + "id": str(self.id), + "order_id": str(order_id), + "sku": str(self.sku), + } diff --git a/jafgen/simulation.py b/jafgen/simulation.py index 873f9b4..379bbc6 100644 --- a/jafgen/simulation.py +++ b/jafgen/simulation.py @@ -80,7 +80,7 @@ def save_results(self) -> None: entities: dict[str, list[dict[str, Any]]] = { "customers": [customer.to_dict() for customer in self.customers.values()], "orders": [order.to_dict() for order in self.orders], - "items": [item.to_dict() for order in self.orders for item in order.items], + "items": [item.to_dict(order.id) for order in self.orders for item in order.items], "stores": [market.store.to_dict() for market in self.markets], "supplies": stock.to_dict(), "products": inventory.to_dict(), diff --git a/jafgen/stores/inventory.py b/jafgen/stores/inventory.py index 009054f..fdf44b0 100644 --- a/jafgen/stores/inventory.py +++ b/jafgen/stores/inventory.py @@ -2,6 +2,7 @@ from faker import Faker +from jafgen.customers.order_item import OrderItem from jafgen.stores.item import Item, ItemType from jafgen.stores.supply import StorageKeepingUnit as SKU @@ -19,8 +20,8 @@ def update(cls, inventory_list: list[Item]): cls.inventory[item.type].append(item) @classmethod - def get_item_type(cls, type: ItemType, count: int = 1): - return [fake.random.choice(cls.inventory[type])for _ in range(count)] + def get_order_item_type(cls, type: ItemType, count: int = 1): + return [OrderItem(item=item) for item in [fake.random.choice(cls.inventory[type])for _ in range(count)]] @classmethod def to_dict(cls) -> list[dict[str, Any]]: diff --git a/tests/test_order_totals.py b/tests/test_order_totals.py index 90c0d32..001eb0a 100644 --- a/tests/test_order_totals.py +++ b/tests/test_order_totals.py @@ -1,9 +1,9 @@ -from jafgen.time import Day -from jafgen.customers.customers import Customer, BrunchCrowd, RemoteWorker, Student +from jafgen.customers.customers import BrunchCrowd, Customer, RemoteWorker, Student from jafgen.customers.order import Order -from jafgen.stores.item import ItemType from jafgen.stores.inventory import Inventory +from jafgen.stores.item import ItemType from jafgen.stores.store import Store +from jafgen.time import Day def test_order_totals(default_store: Store): @@ -17,8 +17,8 @@ def test_order_totals(default_store: Store): Order( customer=CustType(store=default_store), items= - inventory.get_item_type(ItemType.JAFFLE, 2) + - inventory.get_item_type(ItemType.BEVERAGE, 1), + inventory.get_order_item_type(ItemType.JAFFLE, 2) + + inventory.get_order_item_type(ItemType.BEVERAGE, 1), store=default_store, day=Day(date_index=i), )