1
|
|
|
""" |
2
|
|
|
byceps.services.shop.order.dbmodels.order |
3
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4
|
|
|
|
5
|
|
|
:Copyright: 2014-2022 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, TYPE_CHECKING |
11
|
|
|
|
12
|
1 |
|
from moneyed import Currency, get_currency, Money |
13
|
|
|
|
14
|
|
|
if TYPE_CHECKING: |
15
|
1 |
|
hybrid_property = property |
16
|
|
|
else: |
17
|
1 |
|
from sqlalchemy.ext.hybrid import hybrid_property |
18
|
1 |
|
|
19
|
1 |
|
from .....database import db, generate_uuid |
20
|
|
|
from .....typing import UserID |
21
|
1 |
|
from .....util.instances import ReprBuilder |
22
|
|
|
|
23
|
1 |
|
from ....user.dbmodels.user import DbUser |
24
|
1 |
|
|
25
|
|
|
from ...shop.transfer.models import ShopID |
26
|
1 |
|
from ...storefront.transfer.models import StorefrontID |
27
|
1 |
|
|
28
|
|
|
from ..transfer.number import OrderNumber |
29
|
|
|
from ..transfer.order import PaymentState |
30
|
1 |
|
|
31
|
|
|
|
32
|
|
|
class DbOrder(db.Model): |
33
|
1 |
|
"""An order for articles, placed by a user.""" |
34
|
|
|
|
35
|
1 |
|
__tablename__ = 'shop_orders' |
36
|
1 |
|
|
37
|
1 |
|
id = db.Column(db.Uuid, default=generate_uuid, primary_key=True) |
38
|
|
|
created_at = db.Column(db.DateTime, nullable=False) |
39
|
|
|
shop_id = db.Column( |
40
|
1 |
|
db.UnicodeText, db.ForeignKey('shops.id'), index=True, nullable=False |
41
|
|
|
) |
42
|
|
|
storefront_id = db.Column( |
43
|
|
|
db.UnicodeText, |
44
|
|
|
db.ForeignKey('shop_storefronts.id'), |
45
|
|
|
index=True, |
46
|
1 |
|
nullable=False, |
47
|
1 |
|
) |
48
|
|
|
order_number = db.Column(db.UnicodeText, unique=True, nullable=False) |
49
|
|
|
placed_by_id = db.Column( |
50
|
1 |
|
db.Uuid, db.ForeignKey('users.id'), index=True, nullable=False |
51
|
1 |
|
) |
52
|
1 |
|
placed_by = db.relationship(DbUser, foreign_keys=[placed_by_id]) |
53
|
1 |
|
company = db.Column(db.UnicodeText, nullable=True) |
54
|
1 |
|
first_name = db.Column(db.UnicodeText, nullable=False) |
55
|
1 |
|
last_name = db.Column(db.UnicodeText, nullable=False) |
56
|
1 |
|
country = db.Column(db.UnicodeText, nullable=False) |
57
|
1 |
|
zip_code = db.Column(db.UnicodeText, nullable=False) |
58
|
1 |
|
city = db.Column(db.UnicodeText, nullable=False) |
59
|
1 |
|
street = db.Column(db.UnicodeText, nullable=False) |
60
|
1 |
|
_currency = db.Column('currency', db.UnicodeText, nullable=False) |
61
|
1 |
|
_total_amount = db.Column('total_amount', db.Numeric(7, 2), nullable=False) |
62
|
|
|
invoice_created_at = db.Column(db.DateTime, nullable=True) |
63
|
|
|
payment_method = db.Column(db.UnicodeText, nullable=True) |
64
|
1 |
|
_payment_state = db.Column( |
65
|
1 |
|
'payment_state', db.UnicodeText, index=True, nullable=False |
66
|
|
|
) |
67
|
|
|
payment_state_updated_at = db.Column(db.DateTime, nullable=True) |
68
|
1 |
|
payment_state_updated_by_id = db.Column( |
69
|
|
|
db.Uuid, db.ForeignKey('users.id'), nullable=True |
70
|
|
|
) |
71
|
1 |
|
payment_state_updated_by = db.relationship( |
72
|
1 |
|
DbUser, foreign_keys=[payment_state_updated_by_id] |
73
|
1 |
|
) |
74
|
|
|
cancelation_reason = db.Column(db.UnicodeText, nullable=True) |
75
|
1 |
|
processing_required = db.Column(db.Boolean, nullable=False) |
76
|
|
|
processed_at = db.Column(db.DateTime, nullable=True) |
77
|
|
|
|
78
|
|
|
def __init__( |
79
|
|
|
self, |
80
|
|
|
created_at: datetime, |
81
|
|
|
shop_id: ShopID, |
82
|
|
|
storefront_id: StorefrontID, |
83
|
|
|
order_number: OrderNumber, |
84
|
|
|
placed_by_id: UserID, |
85
|
|
|
company: Optional[str], |
86
|
|
|
first_name: str, |
87
|
|
|
last_name: str, |
88
|
|
|
country: str, |
89
|
|
|
zip_code: str, |
90
|
1 |
|
city: str, |
91
|
1 |
|
street: str, |
92
|
1 |
|
currency: Currency, |
93
|
1 |
|
) -> None: |
94
|
1 |
|
self.created_at = created_at |
95
|
1 |
|
self.shop_id = shop_id |
96
|
1 |
|
self.storefront_id = storefront_id |
97
|
1 |
|
self.order_number = order_number |
98
|
1 |
|
self.placed_by_id = placed_by_id |
99
|
1 |
|
self.company = company |
100
|
1 |
|
self.first_name = first_name |
101
|
1 |
|
self.last_name = last_name |
102
|
1 |
|
self.country = country |
103
|
|
|
self.zip_code = zip_code |
104
|
1 |
|
self.city = city |
105
|
1 |
|
self.street = street |
106
|
1 |
|
self.currency = currency |
107
|
|
|
self._total_amount = currency.zero.amount |
108
|
1 |
|
self.payment_state = PaymentState.open |
109
|
1 |
|
|
110
|
1 |
|
@hybrid_property |
111
|
1 |
|
def currency(self) -> Currency: |
112
|
|
|
return get_currency(self._currency) |
113
|
1 |
|
|
114
|
|
|
@currency.setter |
115
|
|
|
def currency(self, currency: Currency) -> None: |
116
|
|
|
self._currency = currency.code |
117
|
|
|
|
118
|
|
|
@property |
119
|
|
|
def total_amount(self) -> Money: |
120
|
|
|
return Money(self._total_amount, self.currency) |
121
|
|
|
|
122
|
|
|
@hybrid_property |
123
|
|
|
def payment_state(self) -> PaymentState: |
124
|
|
|
return PaymentState[self._payment_state] |
125
|
|
|
|
126
|
|
|
@payment_state.setter |
127
|
|
|
def payment_state(self, state: PaymentState) -> None: |
128
|
|
|
assert state is not None |
129
|
|
|
self._payment_state = state.name |
130
|
|
|
|
131
|
|
|
def __repr__(self) -> str: |
132
|
|
|
return ( |
133
|
|
|
ReprBuilder(self) |
134
|
|
|
.add_with_lookup('id') |
135
|
|
|
.add('shop', self.shop_id) |
136
|
|
|
.add_with_lookup('order_number') |
137
|
|
|
.add_custom(self.payment_state.name) |
138
|
|
|
.build() |
139
|
|
|
) |
140
|
|
|
|