fixup! WIP
All checks were successful
Run tests / run-tests (push) Successful in 46s

This commit is contained in:
2025-12-09 15:17:52 +09:00
parent e7453d0fdd
commit 0504cc1a1e
7 changed files with 85 additions and 38 deletions

View File

@@ -63,6 +63,7 @@ def _product_price_query(
TransactionType.BUY_PRODUCT,
TransactionType.ADD_PRODUCT,
TransactionType.ADJUST_STOCK,
TransactionType.JOINT,
]
),
Transaction.product_id == product_id,
@@ -117,6 +118,10 @@ def _product_price_query(
trx_subset.c.type_ == TransactionType.BUY_PRODUCT,
recursive_cte.c.product_count - trx_subset.c.product_count,
),
(
trx_subset.c.type_ == TransactionType.JOINT,
recursive_cte.c.product_count - trx_subset.c.product_count,
),
# Someone adds the product -> product count is increased.
(
trx_subset.c.type_ == TransactionType.ADD_PRODUCT,

View File

@@ -37,6 +37,10 @@ def _product_stock_query(
Transaction.type_ == TransactionType.ADJUST_STOCK,
Transaction.product_count,
),
(
Transaction.type_ == TransactionType.JOINT,
-Transaction.product_count,
),
else_=0,
)
)
@@ -46,6 +50,7 @@ def _product_stock_query(
TransactionType.BUY_PRODUCT,
TransactionType.ADD_PRODUCT,
TransactionType.ADJUST_STOCK,
TransactionType.JOINT,
]
),
Transaction.product_id == product_id,

View File

@@ -80,6 +80,10 @@ def _user_balance_query(
TransactionType.ADJUST_BALANCE,
TransactionType.BUY_PRODUCT,
TransactionType.TRANSFER,
# TODO: join this with the JOINT transactions, and determine
# how much the current user paid for the product.
TransactionType.JOINT_BUY_PRODUCT,
]
),
),

View File

@@ -19,30 +19,6 @@ def insert_test_data(sql_session: Session) -> tuple[User, Product]:
return user, product
def test_transaction_no_duplicate_timestamps(sql_session: Session):
user, _ = insert_test_data(sql_session)
transaction1 = Transaction.adjust_balance(
time=datetime(2023, 10, 1, 12, 0, 0),
user_id=user.id,
amount=100,
)
sql_session.add(transaction1)
sql_session.commit()
transaction2 = Transaction.adjust_balance(
time=transaction1.time,
user_id=user.id,
amount=-50,
)
sql_session.add(transaction2)
with pytest.raises(IntegrityError):
sql_session.commit()
def test_user_not_allowed_to_transfer_to_self(sql_session: Session) -> None:
user, _ = insert_test_data(sql_session)

View File

@@ -0,0 +1,9 @@
from sqlalchemy.orm import Session
def test_joint_buy_product_missing_product(sql_session: Session) -> None: ...
def test_joint_buy_product_missing_user(sql_session: Session) -> None: ...
def test_joint_buy_product_out_of_stock(sql_session: Session) -> None: ...
def test_joint_buy_product(sql_session: Session) -> None: ...
def test_joint_buy_product_duplicate_user(sql_session: Session) -> None: ...
def test_joint_buy_product_non_involved_instigator(sql_session: Session) -> None: ...

View File

@@ -5,7 +5,7 @@ from pprint import pprint
from sqlalchemy.orm import Session
from dibbler.models import Product, Transaction, User
from dibbler.queries import product_price, product_price_log
from dibbler.queries import product_price, product_price_log, joint_buy_product
# TODO: see if we can use pytest_runtest_makereport to print the "product_price_log"s
# only on failures instead of inlining it in every test function
@@ -367,21 +367,27 @@ def test_product_price_joint_transactions(sql_session: Session) -> None:
),
]
transactions += Transaction.buy_joint_product(
time=datetime(2023, 10, 1, 12, 0, 2),
product_count=2,
user_ids=[user1.id, user2.id],
product_id=product.id,
)
sql_session.add_all(transactions)
sql_session.commit()
pprint(product_price_log(sql_session, product))
product_price_ = product_price(sql_session, product)
assert product_price_ == math.ceil((30 * 3 + 20 * 2) / (3 + 2))
joint_buy_product(
sql_session,
time=datetime(2023, 10, 1, 12, 0, 2),
instigator=user1,
users=[user1, user2],
product=product,
product_count=2,
)
pprint(product_price_log(sql_session, product))
old_product_price = product_price_
product_price_ = product_price(sql_session, product)
assert product_price_ == old_product_price, "Joint buy transactions should not affect product price"
transactions = [
Transaction.add_product(
time=datetime(2023, 10, 1, 12, 0, 3),
@@ -399,7 +405,12 @@ def test_product_price_joint_transactions(sql_session: Session) -> None:
pprint(product_price_log(sql_session, product))
product_price_ = product_price(sql_session, product)
expected_product_price = (30 * 3 + 20 * 2) / (3 + 2)
expected_product_price = (expected_product_price * (3 + 2) + 25 * 4) / (3 + 4)
# Expected state:
# Added products:
# Count: 3 + 2 = 5, Price: (30 * 3 + 20 * 2) / 5 = 26
# Joint bought products:
# Count: 5 - 2 = 3, Price: n/a (should not affect price)
# Added products:
# Count: 3 + 4 = 7, Price: (26 * 3 + 25 * 4) / (3 + 4) = 25.57 -> 26
assert product_price_ == math.ceil(expected_product_price)
assert product_price_ == math.ceil((26 * 3 + 25 * 4) / (3 + 4))

View File

@@ -4,7 +4,7 @@ from sqlalchemy import select
from sqlalchemy.orm import Session
from dibbler.models import Product, Transaction, User
from dibbler.queries import product_stock
from dibbler.queries import product_stock, joint_buy_product
def insert_test_data(sql_session: Session) -> None:
@@ -139,3 +139,40 @@ def test_negative_product_stock(sql_session: Session) -> None:
# The stock should be negative because we added and bought the product
assert product_stock(sql_session, product) == 1 - 2 - 1
def test_product_stock_joint_transaction(sql_session: Session) -> None:
insert_test_data(sql_session)
user1 = sql_session.scalars(select(User).where(User.name == "Test User 1")).one()
user2 = User("Test User 2")
sql_session.add(user2)
sql_session.commit()
product = Product("1234567890123", "Test Product")
sql_session.add(product)
sql_session.commit()
transactions = [
Transaction.add_product(
time=datetime(2023, 10, 1, 17, 0, 0),
amount=100,
per_product=100,
user_id=user1.id,
product_id=product.id,
product_count=5,
),
]
sql_session.add_all(transactions)
sql_session.commit()
joint_buy_product(
sql_session,
time=datetime(2023, 10, 1, 17, 0, 1),
instigator=user1,
users=[user1, user2],
product=product,
product_count=3,
)
assert product_stock(sql_session, product) == 5 - 3