Skip to content

Commit

Permalink
Remove beartype (breaks Mypy again); use generics
Browse files Browse the repository at this point in the history
  • Loading branch information
jace committed Mar 5, 2024
1 parent c6cc7ba commit 313c0f6
Show file tree
Hide file tree
Showing 11 changed files with 33 additions and 52 deletions.
3 changes: 2 additions & 1 deletion boxoffice/models/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
from uuid import UUID

from . import BaseScopedNameMixin, Mapped, Model, relationship, sa
from .user import User

__all__ = ['Category']


class Category(BaseScopedNameMixin, Model):
class Category(BaseScopedNameMixin[int, User], Model):
__tablename__ = 'category'
__table_args__ = (
sa.UniqueConstraint('item_collection_id', 'name'),
Expand Down
8 changes: 3 additions & 5 deletions boxoffice/models/discount_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
sa,
)
from .enums import DiscountTypeEnum, LineItemStatus
from .user import Organization, User

__all__ = ['DiscountPolicy', 'DiscountCoupon', 'item_discount_policy']

Expand All @@ -49,15 +50,14 @@
)


class DiscountPolicy(BaseScopedNameMixin, Model):
class DiscountPolicy(BaseScopedNameMixin[UUID, User], Model):
"""
Consists of the discount rules applicable on tickets.
`title` has a GIN index to enable trigram matching.
"""

__tablename__ = 'discount_policy'
__uuid_primary_key__ = True
__table_args__ = (
sa.UniqueConstraint('organization_id', 'name'),
sa.UniqueConstraint('organization_id', 'discount_code_base'),
Expand Down Expand Up @@ -305,9 +305,8 @@ def generate_coupon_code(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(secrets.choice(chars) for _ in range(size))


class DiscountCoupon(IdMixin, Model):
class DiscountCoupon(IdMixin[UUID], Model):
__tablename__ = 'discount_coupon'
__uuid_primary_key__ = True
__table_args__ = (sa.UniqueConstraint('discount_policy_id', 'code'),)

def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -370,4 +369,3 @@ class PolicyCoupon:

if TYPE_CHECKING:
from .item import Item, Price
from .user import Organization, User
5 changes: 2 additions & 3 deletions boxoffice/models/invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from . import BaseMixin, Mapped, Model, UuidMixin, relationship, sa, timestamptz
from .enums import InvoiceStatus
from .user import Organization, User
from .utils import get_fiscal_year

__all__ = ['Invoice']
Expand All @@ -25,9 +26,8 @@ def gen_invoice_no(organization, jurisdiction, invoice_dt):
)


class Invoice(UuidMixin, BaseMixin, Model):
class Invoice(UuidMixin, BaseMixin[UUID, User], Model):
__tablename__ = 'invoice'
__uuid_primary_key__ = True
__table_args__ = (
sa.UniqueConstraint(
'organization_id', 'fy_start_at', 'fy_end_at', 'invoice_no'
Expand Down Expand Up @@ -143,4 +143,3 @@ def validate_immutable_final_invoice(self, key, val):

if TYPE_CHECKING:
from .order import Order
from .user import Organization
8 changes: 3 additions & 5 deletions boxoffice/models/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
from .category import Category
from .discount_policy import item_discount_policy
from .enums import LineItemStatus
from .user import User

__all__ = ['Item', 'Price']


class Item(BaseScopedNameMixin, Model):
class Item(BaseScopedNameMixin[UUID, User], Model):
__tablename__ = 'item'
__uuid_primary_key__ = True
__table_args__ = (sa.UniqueConstraint('item_collection_id', 'name'),)

description = MarkdownColumn('description', default='', nullable=False)
Expand Down Expand Up @@ -219,9 +219,8 @@ def demand_curve(self) -> Sequence[sa.engine.Row[tuple[Decimal, int]]]:
).fetchall()


class Price(BaseScopedNameMixin, Model):
class Price(BaseScopedNameMixin[UUID, User], Model):
__tablename__ = 'price'
__uuid_primary_key__ = True
__table_args__ = (
sa.UniqueConstraint('item_id', 'name'),
sa.CheckConstraint('start_at < end_at', 'price_start_at_lt_end_at_check'),
Expand Down Expand Up @@ -289,4 +288,3 @@ def tense(self):
if TYPE_CHECKING:
from .discount_policy import DiscountPolicy
from .item_collection import ItemCollection
from .user import User
6 changes: 3 additions & 3 deletions boxoffice/models/item_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from decimal import Decimal
from typing import TYPE_CHECKING, cast
from uuid import UUID

from sqlalchemy.ext.orderinglist import ordering_list

Expand All @@ -17,17 +18,16 @@
)
from .enums import LineItemStatus, TransactionTypeEnum
from .payment import PaymentTransaction
from .user import Organization
from .user import Organization, User
from .utils import HeadersAndDataTuple

__all__ = ['ItemCollection']


class ItemCollection(BaseScopedNameMixin, Model):
class ItemCollection(BaseScopedNameMixin[UUID, User], Model):
"""Represent a collection of tickets."""

__tablename__ = 'item_collection'
__uuid_primary_key__ = True
__table_args__ = (sa.UniqueConstraint('organization_id', 'name'),)

description = MarkdownColumn('description', default='', nullable=False)
Expand Down
7 changes: 3 additions & 4 deletions boxoffice/models/line_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
timestamptz,
)
from .enums import LineItemStatus
from .user import User

__all__ = ['LineItem', 'Assignee']

Expand All @@ -46,7 +47,7 @@ class LineItemDict(TypedDict):
ticket_id: str


class Assignee(BaseMixin, Model):
class Assignee(BaseMixin[int, User], Model):
__tablename__ = 'assignee'
__table_args__ = (
sa.UniqueConstraint('line_item_id', 'current'),
Expand All @@ -67,7 +68,7 @@ class Assignee(BaseMixin, Model):
current: Mapped[bool | None] = sa.orm.mapped_column()


class LineItem(BaseMixin, Model):
class LineItem(BaseMixin[UUID, User], Model):
"""
A line item in a sale receipt.
Expand All @@ -76,7 +77,6 @@ class LineItem(BaseMixin, Model):
"""

__tablename__ = 'line_item'
__uuid_primary_key__ = True
__table_args__ = (
sa.UniqueConstraint('customer_order_id', 'line_item_seq'),
sa.UniqueConstraint('previous_id'),
Expand Down Expand Up @@ -393,4 +393,3 @@ def sales_delta(user_tz: tzinfo, ticket_ids: Sequence[str]):
from .discount_policy import DiscountCoupon, DiscountPolicy
from .item_collection import ItemCollection
from .order import Order
from .user import User
10 changes: 0 additions & 10 deletions boxoffice/models/line_item_discounter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@
from uuid import UUID
import itertools

from beartype import beartype

from .discount_policy import DiscountCoupon, DiscountPolicy, PolicyCoupon
from .line_item import LineItemTuple

__all__ = ['LineItemDiscounter']


class LineItemDiscounter:
@beartype
def get_discounted_line_items(
self,
line_items: Sequence[LineItemTuple],
Expand All @@ -36,7 +33,6 @@ def get_discounted_line_items(
return self.apply_discount(valid_discounts[0], line_items)
return line_items

@beartype
def get_valid_discounts(
self, line_items: Sequence[LineItemTuple], coupons: Sequence[str]
) -> Sequence[PolicyCoupon]:
Expand All @@ -51,7 +47,6 @@ def get_valid_discounts(

return DiscountPolicy.get_from_ticket(ticket, len(line_items), coupons)

@beartype
def calculate_discounted_amount(
self, discount_policy: DiscountPolicy, line_item: LineItemTuple
) -> Decimal:
Expand All @@ -73,11 +68,9 @@ def calculate_discounted_amount(
return line_item.base_amount - discounted_price.amount
return (discount_policy.percentage or 0) * line_item.base_amount / Decimal(100)

@beartype
def is_coupon_usable(self, coupon: DiscountCoupon, applied_to_count: int) -> bool:
return (coupon.usage_limit - coupon.used_count) > applied_to_count

@beartype
def apply_discount(
self,
policy_coupon: PolicyCoupon,
Expand Down Expand Up @@ -134,7 +127,6 @@ def apply_discount(
discounted_line_items.append(line_item)
return discounted_line_items

@beartype
def apply_combo_discount(
self,
discounts: list[PolicyCoupon],
Expand All @@ -149,7 +141,6 @@ def apply_combo_discount(
[discounts[0]], self.apply_combo_discount(discounts[1:], line_items)
)

@beartype
def apply_max_discount(
self,
discounts: list[PolicyCoupon | Sequence[PolicyCoupon]],
Expand Down Expand Up @@ -184,7 +175,6 @@ def apply_max_discount(
),
)

@beartype
def get_combos(
self, discounts: list[PolicyCoupon], qty: int
) -> list[list[PolicyCoupon]]:
Expand Down
25 changes: 10 additions & 15 deletions boxoffice/models/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from decimal import Decimal
from functools import partial
from typing import TYPE_CHECKING
from uuid import UUID, uuid4
from uuid import UUID
import secrets

from sqlalchemy.ext.orderinglist import ordering_list
Expand All @@ -24,6 +24,7 @@
)
from .enums import LineItemStatus, OrderStatus, TransactionTypeEnum
from .line_item import LineItem
from .user import Organization, User

__all__ = ['Order', 'OrderSession']

Expand All @@ -42,17 +43,13 @@ def gen_receipt_no(organization):
)


class Order(BaseMixin, Model):
class Order(BaseMixin[UUID, User], Model):
__tablename__ = 'customer_order'
__uuid_primary_key__ = True
__table_args__ = (
sa.UniqueConstraint('organization_id', 'invoice_no'),
sa.UniqueConstraint('access_token'),
)

id: Mapped[UUID] = sa.orm.mapped_column( # type: ignore[assignment] # noqa: A003
primary_key=True, default=uuid4
)
user_id: Mapped[int | None] = sa.orm.mapped_column(sa.ForeignKey('user.id'))
user: Mapped[User | None] = relationship(back_populates='orders')
menu_id: Mapped[UUID] = sa.orm.mapped_column(
Expand Down Expand Up @@ -99,17 +96,17 @@ class Order(BaseMixin, Model):

confirmed_line_items: DynamicMapped[LineItem] = relationship(
lazy='dynamic',
primaryjoin=sa.and_(
LineItem.customer_order_id == id,
primaryjoin=lambda: sa.and_(
LineItem.customer_order_id == Order.id,
LineItem.status == LineItemStatus.CONFIRMED,
),
viewonly=True,
)

confirmed_and_cancelled_line_items: DynamicMapped[LineItem] = relationship(
lazy='dynamic',
primaryjoin=sa.and_(
LineItem.customer_order_id == id,
primaryjoin=lambda: sa.and_(
LineItem.customer_order_id == Order.id,
LineItem.status.in_(
[LineItemStatus.CONFIRMED.value, LineItemStatus.CANCELLED.value]
),
Expand All @@ -119,8 +116,8 @@ class Order(BaseMixin, Model):

initial_line_items: DynamicMapped[LineItem] = relationship(
lazy='dynamic',
primaryjoin=sa.and_(
LineItem.customer_order_id == id,
primaryjoin=lambda: sa.and_(
LineItem.customer_order_id == Order.id,
LineItem.previous_id.is_(None),
LineItem.status.in_(
[
Expand Down Expand Up @@ -221,11 +218,10 @@ def net_amount(self) -> Decimal:
return self.paid_amount - self.refunded_amount


class OrderSession(BaseMixin, Model):
class OrderSession(BaseMixin[UUID, User], Model):
"""Records the referrer and utm headers for an order."""

__tablename__ = 'order_session'
__uuid_primary_key__ = True

customer_order_id: Mapped[UUID] = sa.orm.mapped_column(
sa.ForeignKey('customer_order.id'), index=True, unique=False
Expand Down Expand Up @@ -256,4 +252,3 @@ class OrderSession(BaseMixin, Model):
from .invoice import Invoice
from .item_collection import ItemCollection
from .payment import OnlinePayment, PaymentTransaction
from .user import Organization, User
7 changes: 3 additions & 4 deletions boxoffice/models/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
TransactionMethodEnum,
TransactionTypeEnum,
)
from .user import User

__all__ = ['OnlinePayment', 'PaymentTransaction']


class OnlinePayment(BaseMixin, Model):
class OnlinePayment(BaseMixin[UUID, User], Model):
"""Represents payments made through a payment gateway. Supports Razorpay only."""

__tablename__ = 'online_payment'
__uuid_primary_key__ = True
customer_order_id: Mapped[UUID] = sa.orm.mapped_column(
sa.ForeignKey('customer_order.id')
)
Expand All @@ -60,15 +60,14 @@ def fail(self) -> None:
self.failed_at = func.utcnow()


class PaymentTransaction(BaseMixin, Model):
class PaymentTransaction(BaseMixin[UUID, User], Model):
"""
Models transactions made by a customer.
A transaction can be one of type 'Payment', 'Refund', 'Credit'.
"""

__tablename__ = 'payment_transaction'
__uuid_primary_key__ = True

customer_order_id: Mapped[UUID] = sa.orm.mapped_column(
sa.ForeignKey('customer_order.id')
Expand Down
5 changes: 4 additions & 1 deletion boxoffice/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ def permissions(self, actor, inherited=None):

def fetch_invoices(self):
"""Return invoices for an organization as a tuple of (row_headers, rows)."""
from .order import Order # pylint: disable=import-outside-toplevel

headers = [
'order_id',
'receipt_no',
Expand Down Expand Up @@ -135,9 +137,10 @@ def fetch_invoices(self):

# Tail imports
from .invoice import Invoice # isort:skip
from .order import Order # isort:skip


if TYPE_CHECKING:
from .discount_policy import DiscountPolicy
from .item_collection import ItemCollection
from .line_item import Assignee
from .order import Order
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
git+https://github.com/hasgeek/baseframe#egg=baseframe
beartype
click
git+https://github.com/hasgeek/coaster#egg=coaster
Flask
Expand Down

0 comments on commit 313c0f6

Please sign in to comment.