From 16be0f0fbe6244cd280985b3d9a1ae684b5d1d3f Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 9 Dec 2025 15:46:46 +0900 Subject: [PATCH] fixup! WIP --- dibbler/models/Transaction.py | 32 ++++++++++++++ dibbler/models/User.py | 9 ++-- dibbler/queries/joint_buy_product.py | 7 +++ tests/queries/test_current_penalty.py | 6 +-- tests/queries/test_transaction_log.py | 61 ++++++++++++++------------- 5 files changed, 79 insertions(+), 36 deletions(-) diff --git a/dibbler/models/Transaction.py b/dibbler/models/Transaction.py index 0d6df69..05da1f1 100644 --- a/dibbler/models/Transaction.py +++ b/dibbler/models/Transaction.py @@ -11,6 +11,7 @@ from sqlalchemy import ( Text, and_, column, + func, or_, ) from sqlalchemy.orm import ( @@ -104,6 +105,37 @@ class Transaction(Base): ), name="trx_type_transfer_no_self_transfers", ), + CheckConstraint( + func.coalesce(column("product_count"), 1) != 0, + name="trx_product_count_non_zero", + ), + CheckConstraint( + func.coalesce(column("penalty_multiplier_percent"), 100) >= 100, + name="trx_penalty_multiplier_percent_min_100", + ), + CheckConstraint( + func.coalesce(column("interest_rate_percent"), 0) >= 0, + name="trx_interest_rate_percent_non_negative", + ), + CheckConstraint( + func.coalesce(column("amount"), 1) != 0, + name="trx_amount_non_zero", + ), + CheckConstraint( + func.coalesce(column("per_product"), 1) > 0, + name="trx_per_product_positive", + ), + CheckConstraint( + func.coalesce(column("penalty_threshold"), 0) <= 0, + name="trx_penalty_threshold_max_0", + ), + CheckConstraint( + or_( + column("joint_transaction_id").is_(None), + column("joint_transaction_id") != column("id"), + ), + name="trx_joint_transaction_id_not_self", + ), # Speed up product count calculation Index("product_user_time", "product_id", "user_id", "time"), # Speed up product owner calculation diff --git a/dibbler/models/User.py b/dibbler/models/User.py index 8f7ca93..0f86bc7 100644 --- a/dibbler/models/User.py +++ b/dibbler/models/User.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Self +from typing import Self from sqlalchemy import ( Integer, @@ -19,12 +19,13 @@ class User(Base): """Internal database ID""" name: Mapped[str] = mapped_column(String(20), unique=True) - """ - The PVV username of the user. - """ + """The PVV username of the user.""" card: Mapped[str | None] = mapped_column(String(20)) + """The NTNU card number of the user.""" + rfid: Mapped[str | None] = mapped_column(String(20)) + """The RFID tag of the user (if they have any, rare these days).""" # name_re = r"[a-z]+" # card_re = r"(([Nn][Tt][Nn][Uu])?[0-9]+)?" diff --git a/dibbler/queries/joint_buy_product.py b/dibbler/queries/joint_buy_product.py index 9ece96c..c2c05e3 100644 --- a/dibbler/queries/joint_buy_product.py +++ b/dibbler/queries/joint_buy_product.py @@ -21,6 +21,13 @@ def joint_buy_product( """ Create buy product transactions for multiple users at once. """ + + if instigator not in users: + raise ValueError("Instigator must be in the list of users buying the product.") + + if product_count <= 0: + raise ValueError("Product count must be positive.") + joint_transaction = Transaction.joint( user_id=instigator.id, product_id=product.id, diff --git a/tests/queries/test_current_penalty.py b/tests/queries/test_current_penalty.py index 6910070..81fe975 100644 --- a/tests/queries/test_current_penalty.py +++ b/tests/queries/test_current_penalty.py @@ -25,13 +25,13 @@ def test_current_penalty_with_history(sql_session: Session) -> None: transactions = [ Transaction.adjust_penalty( time=datetime(2023, 10, 1, 10, 0, 0), - penalty_threshold=200, + penalty_threshold=-200, penalty_multiplier_percent=150, user_id=user.id, ), Transaction.adjust_penalty( time=datetime(2023, 10, 2, 10, 0, 0), - penalty_threshold=300, + penalty_threshold=-300, penalty_multiplier_percent=200, user_id=user.id, ), @@ -39,4 +39,4 @@ def test_current_penalty_with_history(sql_session: Session) -> None: sql_session.add_all(transactions) sql_session.commit() - assert current_penalty(sql_session) == (300, 200) + assert current_penalty(sql_session) == (-300, 200) diff --git a/tests/queries/test_transaction_log.py b/tests/queries/test_transaction_log.py index 14da292..58efad7 100644 --- a/tests/queries/test_transaction_log.py +++ b/tests/queries/test_transaction_log.py @@ -83,7 +83,7 @@ def insert_default_test_transactions( return transactions -def test_user_transactions_no_transactions(sql_session: Session): +def test_user_transactions_no_transactions(sql_session: Session) -> None: insert_test_data(sql_session) transactions = transaction_log(sql_session) @@ -91,7 +91,7 @@ def test_user_transactions_no_transactions(sql_session: Session): assert len(transactions) == 0 -def test_transaction_log_filtered_by_user(sql_session: Session): +def test_transaction_log_filtered_by_user(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -99,7 +99,7 @@ def test_transaction_log_filtered_by_user(sql_session: Session): assert len(transaction_log(sql_session, user=user2)) == 3 -def test_transaction_log_filtered_by_product(sql_session: Session): +def test_transaction_log_filtered_by_product(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -107,7 +107,7 @@ def test_transaction_log_filtered_by_product(sql_session: Session): assert len(transaction_log(sql_session, product=product2)) == 2 -def test_transaction_log_after_datetime(sql_session: Session): +def test_transaction_log_after_datetime(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -122,7 +122,7 @@ def test_transaction_log_after_datetime(sql_session: Session): ) -def test_transaction_log_after_datetime_no_transactions(sql_session: Session): +def test_transaction_log_after_datetime_no_transactions(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) assert ( @@ -136,7 +136,7 @@ def test_transaction_log_after_datetime_no_transactions(sql_session: Session): ) -def test_transaction_log_after_datetime_exclusive(sql_session: Session): +def test_transaction_log_after_datetime_exclusive(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -152,7 +152,7 @@ def test_transaction_log_after_datetime_exclusive(sql_session: Session): ) -def test_transaction_log_after_transaction_id(sql_session: Session): +def test_transaction_log_after_transaction_id(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -166,7 +166,7 @@ def test_transaction_log_after_transaction_id(sql_session: Session): ) == len(transactions) -def test_transaction_log_after_transaction_id_one_transaction(sql_session: Session): +def test_transaction_log_after_transaction_id_one_transaction(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -183,7 +183,7 @@ def test_transaction_log_after_transaction_id_one_transaction(sql_session: Sessi ) -def test_transaction_log_after_transaction_id_exclusive(sql_session: Session): +def test_transaction_log_after_transaction_id_exclusive(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -201,7 +201,7 @@ def test_transaction_log_after_transaction_id_exclusive(sql_session: Session): ) -def test_transaction_log_before_datetime(sql_session: Session): +def test_transaction_log_before_datetime(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -216,7 +216,7 @@ def test_transaction_log_before_datetime(sql_session: Session): ) -def test_transaction_log_before_datetime_no_transactions(sql_session: Session): +def test_transaction_log_before_datetime_no_transactions(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -231,7 +231,7 @@ def test_transaction_log_before_datetime_no_transactions(sql_session: Session): ) -def test_transaction_log_before_datetime_exclusive(sql_session: Session): +def test_transaction_log_before_datetime_exclusive(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -247,7 +247,7 @@ def test_transaction_log_before_datetime_exclusive(sql_session: Session): ) -def test_transaction_log_before_transaction_id(sql_session: Session): +def test_transaction_log_before_transaction_id(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -264,7 +264,7 @@ def test_transaction_log_before_transaction_id(sql_session: Session): ) -def test_transaction_log_before_transaction_id_one_transaction(sql_session: Session): +def test_transaction_log_before_transaction_id_one_transaction(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -281,7 +281,7 @@ def test_transaction_log_before_transaction_id_one_transaction(sql_session: Sess ) -def test_transaction_log_before_transaction_id_exclusive(sql_session: Session): +def test_transaction_log_before_transaction_id_exclusive(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -299,7 +299,7 @@ def test_transaction_log_before_transaction_id_exclusive(sql_session: Session): ) -def test_transaction_log_before_after_datetime_combined(sql_session: Session): +def test_transaction_log_before_after_datetime_combined(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -318,7 +318,7 @@ def test_transaction_log_before_after_datetime_combined(sql_session: Session): ) -def test_transaction_log_before_after_transaction_id_combined(sql_session: Session): +def test_transaction_log_before_after_transaction_id_combined(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -337,7 +337,7 @@ def test_transaction_log_before_after_transaction_id_combined(sql_session: Sessi ) -def test_transaction_log_before_date_after_transaction_id(sql_session: Session): +def test_transaction_log_before_date_after_transaction_id(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -356,7 +356,7 @@ def test_transaction_log_before_date_after_transaction_id(sql_session: Session): ) -def test_transaction_log_before_transaction_id_after_date(sql_session: Session): +def test_transaction_log_before_transaction_id_after_date(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -375,7 +375,7 @@ def test_transaction_log_before_transaction_id_after_date(sql_session: Session): ) -def test_transaction_log_after_product_and_user_not_allowed(sql_session: Session): +def test_transaction_log_after_product_and_user_not_allowed(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -388,7 +388,9 @@ def test_transaction_log_after_product_and_user_not_allowed(sql_session: Session ) -def test_transaction_log_after_datetime_and_transaction_id_not_allowed(sql_session: Session): +def test_transaction_log_after_datetime_and_transaction_id_not_allowed( + sql_session: Session, +) -> None: user, user2, product, product2 = insert_test_data(sql_session) insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -401,7 +403,7 @@ def test_transaction_log_after_datetime_and_transaction_id_not_allowed(sql_sessi ) -def test_transaction_log_limit(sql_session: Session): +def test_transaction_log_limit(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -409,7 +411,7 @@ def test_transaction_log_limit(sql_session: Session): assert len(transaction_log(sql_session, limit=len(transactions) + 3)) == len(transactions) -def test_transaction_log_filtered_by_transaction_type(sql_session: Session): +def test_transaction_log_filtered_by_transaction_type(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -442,7 +444,7 @@ def test_transaction_log_filtered_by_transaction_type(sql_session: Session): ) -def test_transaction_log_filtered_by_transaction_type_negated(sql_session: Session): +def test_transaction_log_filtered_by_transaction_type_negated(sql_session: Session) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -480,7 +482,7 @@ def test_transaction_log_filtered_by_transaction_type_negated(sql_session: Sessi def test_transaction_log_combined_filter_user_datetime_transaction_type_limit( sql_session: Session, -): +) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -501,7 +503,7 @@ def test_transaction_log_combined_filter_user_datetime_transaction_type_limit( def test_transaction_log_combined_filter_user_transaction_id_transaction_type_limit( sql_session: Session, -): +) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -522,7 +524,7 @@ def test_transaction_log_combined_filter_user_transaction_id_transaction_type_li def test_transaction_log_combined_filter_product_datetime_transaction_type_limit( sql_session: Session, -): +) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -543,7 +545,7 @@ def test_transaction_log_combined_filter_product_datetime_transaction_type_limit def test_transaction_log_combined_filter_product_transaction_id_transaction_type_limit( sql_session: Session, -): +) -> None: user, user2, product, product2 = insert_test_data(sql_session) transactions = insert_default_test_transactions(sql_session, user, user2, product, product2) @@ -562,4 +564,5 @@ def test_transaction_log_combined_filter_product_transaction_id_transaction_type assert len(result) == 2 -def test_transaction_log_filtered_by_user_joint_transactions(sql_session: Session): ... +# NOTE: how should this work? Do we includ the entire JOINT transaction, or only the part relevant to the user? +def test_transaction_log_filtered_by_user_joint_transactions(sql_session: Session) -> None: ...