Passed
Push — main ( 854eb5...57d628 )
by Jochen
05:03
created

  A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
"""
2
byceps.services.shop.order.dbmodels.order
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2021 Jochen Kupperschmidt
6
:License: Revised BSD (see `LICENSE` file for details)
7
"""
8
9 1
from datetime import datetime
10 1
from typing import Optional
11
12 1
from sqlalchemy.ext.hybrid import hybrid_property
13
14 1
from .....database import BaseQuery, db, generate_uuid
15 1
from .....typing import UserID
16 1
from .....util.instances import ReprBuilder
17
18 1
from ....user.dbmodels.user import User
19
20 1
from ...shop.transfer.models import ShopID
21
22 1
from ..transfer.models import OrderNumber, PaymentMethod, PaymentState
23
24
25 1
class OrderQuery(BaseQuery):
26
27 1
    def for_shop(self, shop_id: ShopID) -> BaseQuery:
28 1
        return self.filter_by(shop_id=shop_id)
29
30 1
    def placed_by(self, user_id: UserID) -> BaseQuery:
31 1
        return self.filter_by(placed_by_id=user_id)
32
33
34 1
class Order(db.Model):
35
    """An order for articles, placed by a user."""
36
37 1
    __tablename__ = 'shop_orders'
38 1
    query_class = OrderQuery
39
40 1
    id = db.Column(db.Uuid, default=generate_uuid, primary_key=True)
41 1
    created_at = db.Column(db.DateTime, nullable=False)
42 1
    shop_id = db.Column(db.UnicodeText, db.ForeignKey('shops.id'), index=True, nullable=False)
43 1
    order_number = db.Column(db.UnicodeText, unique=True, nullable=False)
44 1
    placed_by_id = db.Column(db.Uuid, db.ForeignKey('users.id'), index=True, nullable=False)
45 1
    placed_by = db.relationship(User, foreign_keys=[placed_by_id])
46 1
    first_names = db.Column(db.UnicodeText, nullable=False)
47 1
    last_name = db.Column(db.UnicodeText, nullable=False)
48 1
    country = db.Column(db.UnicodeText, nullable=False)
49 1
    zip_code = db.Column(db.UnicodeText, nullable=False)
50 1
    city = db.Column(db.UnicodeText, nullable=False)
51 1
    street = db.Column(db.UnicodeText, nullable=False)
52 1
    total_amount = db.Column(db.Numeric(7, 2), nullable=False)
53 1
    invoice_created_at = db.Column(db.DateTime, nullable=True)
54 1
    _payment_method = db.Column('payment_method', db.UnicodeText, nullable=True)
55 1
    _payment_state = db.Column('payment_state', db.UnicodeText, index=True, nullable=False)
56 1
    payment_state_updated_at = db.Column(db.DateTime, nullable=True)
57 1
    payment_state_updated_by_id = db.Column(db.Uuid, db.ForeignKey('users.id'), nullable=True)
58 1
    payment_state_updated_by = db.relationship(User, foreign_keys=[payment_state_updated_by_id])
59 1
    cancelation_reason = db.Column(db.UnicodeText, nullable=True)
60 1
    shipping_required = db.Column(db.Boolean, nullable=False)
61 1
    shipped_at = db.Column(db.DateTime, nullable=True)
62
63 1
    def __init__(
64
        self,
65
        shop_id: ShopID,
66
        order_number: OrderNumber,
67
        placed_by_id: UserID,
68
        first_names: str,
69
        last_name: str,
70
        country: str,
71
        zip_code: str,
72
        city: str,
73
        street,
74
        *,
75
        created_at: Optional[datetime] = None,
76
    ) -> None:
77 1
        if created_at is None:
78 1
            created_at = datetime.utcnow()
79 1
        self.created_at = created_at
80 1
        self.shop_id = shop_id
81 1
        self.order_number = order_number
82 1
        self.placed_by_id = placed_by_id
83 1
        self.first_names = first_names
84 1
        self.last_name = last_name
85 1
        self.country = country
86 1
        self.zip_code = zip_code
87 1
        self.city = city
88 1
        self.street = street
89 1
        self.payment_state = PaymentState.open
90
91 1
    @hybrid_property
92 1
    def payment_method(self) -> Optional[PaymentMethod]:
93 1
        if self._payment_method is None:
94 1
            return None
95
96 1
        return PaymentMethod[self._payment_method]
97
98 1
    @payment_method.setter
99 1
    def payment_method(self, method: PaymentMethod) -> None:
100 1
        assert method is not None
101 1
        self._payment_method = method.name
102
103 1
    @hybrid_property
104 1
    def payment_state(self) -> PaymentState:
105 1
        return PaymentState[self._payment_state]
106
107 1
    @payment_state.setter
108 1
    def payment_state(self, state: PaymentState) -> None:
109 1
        assert state is not None
110 1
        self._payment_state = state.name
111
112 1
    def __repr__(self) -> str:
113
        item_count = len(self.items)
114
115
        return ReprBuilder(self) \
116
            .add_with_lookup('id') \
117
            .add('shop', self.shop_id) \
118
            .add_with_lookup('order_number') \
119
            .add('placed_by', self.placed_by.screen_name) \
120
            .add_custom(f'{item_count:d} items') \
121
            .add_custom(self.payment_state.name) \
122
            .build()
123