diff --git a/README.md b/README.md index ad74af7..f505f69 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,44 @@ * [documentation](https://psychic-broccoli-r4ome5j.pages.github.io/) -Implementation of a digital twin of a retail corporation that operates a chain of grocery stores will be described. The implementation is of course limited but comprehensive enough to get some key insights about why corporate IT looks the way it looks. If anyone intends to create antifragile data systems it's important to study how fragile systems come to be on the first place. \ No newline at end of file +Implementation of a digital twin of a retail corporation that operates a chain of grocery stores will be described. The implementation is of course limited but comprehensive enough to get some key insights about why corporate IT looks the way it looks. If anyone intends to create antifragile data systems it's important to study how fragile systems come to be on the first place. + +## Bootstrap the database + +First create a postgresql database. + +```bash +createdb -h localhost -U postgresuser retail +``` + +In this case we decided to call the database `retail` and we created it in the same computer we will be running the digital twin. Then sync the data models in the freshly created database with: + +```bash +retailtwin.exe init postgresql://postgresuser:password@localhost/retail +``` + +Then we can populate the database with dummy data with the `bootstrap` subcommand: + +```bash +retailtwin.exe bootstrap postgresql://postgresuser:password@localhost/retail +``` + +Finally we can create all the necessary functions, procedures, and triggers with + +```bash +retailtwin.exe sync postgresql://postgresuser:password@localhost/retail +``` + +## Terminals + +There are currently three available terminals to operate with the digital twin: + +### Stocking terminal + +```bash +stock [DB_URI] [Store location] +``` + +```bash +stock postgresql://postgresuser:password@localhost/retail 1 +``` diff --git a/pyproject.toml b/pyproject.toml index a908c12..936bb9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,15 +11,18 @@ dependencies = [ "duckdb", "pydantic", "typer", + "rich", "pyyaml", "pydantic-settings", "polars", + "pandas", "pyarrow", "sqlalchemy[asyncio] > 2.0.13", "adbc-driver-postgresql", "adbc-driver-sqlite", "prompt_toolkit", "asyncpg", + "psycopg2-binary", "pydantic-settings" ] diff --git a/src/retailtwin/bootstrap.py b/src/retailtwin/bootstrap.py index 215174e..244b062 100644 --- a/src/retailtwin/bootstrap.py +++ b/src/retailtwin/bootstrap.py @@ -24,7 +24,7 @@ from retailtwin.models import ( ) # Some configuration parameters. -PACKAGE_ROOT = Path(retailtwin.__file__).parent / "retail" +PACKAGE_ROOT = Path(retailtwin.__file__).parent PRODUCT_LIST_FILE = "data/products.csv" DISCOUNT_LIST_FILE = "data/discounts.csv" RANDOM_PEOPLE_FILE = "data/random_people.csv" diff --git a/src/retailtwin/cli/stock.py b/src/retailtwin/cli/stock.py index 4ec3b43..0eed9e4 100644 --- a/src/retailtwin/cli/stock.py +++ b/src/retailtwin/cli/stock.py @@ -64,14 +64,14 @@ def handle_command(command: str, **kwargs): pl.col("upc"), pl.col("name"), pl.col("package"), - pl.col("price"), + pl.col("unitprice"), pl.col("best_until"), pl.col("quantity"), ] ).filter(pl.col("upc") == upc) console.print( df_to_table( - df.with_columns(pl.col("price").cast(str)), + df.with_columns(pl.col("unitprice").cast(str)), title=f"Item {upc} on location {location}", ) ) diff --git a/src/retailtwin/sql/add_item_to_cart.sql b/src/retailtwin/sql/add_item_to_cart.sql index a254586..07bd9d5 100644 --- a/src/retailtwin/sql/add_item_to_cart.sql +++ b/src/retailtwin/sql/add_item_to_cart.sql @@ -1,9 +1,9 @@ -create or replace procedure add_item_to_cart(cart integer, sku integer, quantity integer) +create or replace procedure add_item_to_cart(cart integer, upc integer, quantity integer) language sql as $$ INSERT INTO itemsoncart -("cart", "sku", "quantity") +("cart", "upc", "quantity") values ($1, $2, $3); $$; \ No newline at end of file diff --git a/src/retailtwin/sql/sync.py b/src/retailtwin/sql/sync.py index 941e015..dc9afd0 100644 --- a/src/retailtwin/sql/sync.py +++ b/src/retailtwin/sql/sync.py @@ -3,7 +3,7 @@ from sqlalchemy import create_engine, text from sqlalchemy.orm import Session import retailtwin -PACKAGE_ROOT = Path(retailtwin.__file__).parent / "retail" +PACKAGE_ROOT = Path(retailtwin.__file__).parent def funcandproc(db_uri: str): @@ -29,7 +29,7 @@ def funcandproc(db_uri: str): view_name = predicate.stem.removesuffix(".sql") with predicate.open() as sql: # First remove the view - session.execute(text(f"drop view {view_name}")) + session.execute(text(f"drop view if exists {view_name}")) session.commit() # And sync it