Coverage for api/handlers/orders/cancellation.py: 24%
82 statements
« prev ^ index » next coverage.py v7.6.2, created at 2024-10-10 03:02 +0300
« prev ^ index » next coverage.py v7.6.2, created at 2024-10-10 03:02 +0300
1import asyncio
2import datetime
3from typing import Any
5from bson import ObjectId
6from database.integration_1c.savers import remove_from_1c
7from database.orders import move_order_and_return, update_status_and_return
8from exceptions import BadParameterHTTPError, NotFoundHTTPError
9from handlers.authorization.check_role import has_role
10from handlers.authorization.company_employee_access import (
11 flexible_company_assertion_query,
12)
13from mongodb import buf_col, orders_col, trash_orders_col
14from operations.assignment import data_from_assigned, notify_if_assigned
15from operations.orders import fill_carrier_by_oid_company
16from services.notifications.director import notification_api
17from sotrans_models.models.orders.order import (
18 OrderDBModel,
19 OrderStatus,
20 OrderUpdateModel,
21)
22from sotrans_models.models.roles import SotransRole
23from sotrans_models.models.users import SotransOIDCUserModel
24from utils.helper import add_prices_to_update, etag_detalizer, get_org_oid
26cancelled_q = {OrderDBModel.status: OrderStatus.canceled.value}
29async def on_utilize_canceled(
30 order_id: ObjectId,
31) -> dict[str, Any] | OrderDBModel:
32 return await move_order_and_return(
33 order_id,
34 orders_col,
35 trash_orders_col,
36 OrderStatus.archived,
37 cancelled_q,
38 {OrderDBModel.deleted_at: datetime.datetime.utcnow()},
39 )
42async def on_move_to_cancel(
43 order_id: ObjectId,
44 user: SotransOIDCUserModel,
45 order: OrderUpdateModel,
46) -> dict[str, Any] | OrderDBModel:
47 if not order.cancel_reason:
48 raise BadParameterHTTPError("отсутствует cancel_reason")
50 order_found = await orders_col.collection.find_one(
51 {
52 "id": order_id,
53 OrderDBModel.status: {
54 "$in": [
55 os.value
56 for os in (
57 OrderStatus.unverified,
58 OrderStatus.confirmed,
59 OrderStatus.reserved,
60 OrderStatus.active,
61 )
62 ]
63 },
64 }
65 )
66 if not order_found:
67 raise NotFoundHTTPError("заказ")
68 order_model = OrderDBModel(**order_found)
69 if order_model.status == OrderStatus.confirmed and not has_role(
70 user, SotransRole.company_logistician
71 ):
72 org_id = get_org_oid(user)
73 restriction_q = {OrderDBModel.carrier.id: org_id}
74 else:
75 restriction_q = await flexible_company_assertion_query(user)
76 update_data = await data_from_assigned(order)
77 etag_q = {"etag": order.etag} if order.etag else {}
78 updated = await update_status_and_return(
79 order_id,
80 OrderStatus.canceled,
81 set_=update_data
82 | {
83 OrderDBModel.cancel_reason: order.cancel_reason,
84 OrderDBModel.current_stage: None,
85 "completed_stages": None,
86 },
87 restriction=restriction_q | etag_q,
88 )
90 om = OrderDBModel(**updated)
91 asyncio.create_task(notification_api.order_canceled(om))
92 notification_api.company_order_canceled(om, user.sub)
93 asyncio.create_task(remove_from_1c(order_id, orders_col.collection_name))
94 notify_if_assigned(order, om)
95 return updated
98async def on_cancelled_to_exchange(
99 order_id: ObjectId, order: OrderUpdateModel | None
100) -> dict[str, Any] | OrderDBModel:
101 update_data = await data_from_assigned(order)
102 etag_q = {"etag": order.etag} if order and order.etag else {}
103 order_in = await orders_col.collection.find_one(
104 {"id": order_id, OrderDBModel.status: OrderStatus.canceled.value}
105 | etag_q
106 )
107 if order_in is None:
108 await etag_detalizer(
109 orders_col,
110 etag_q,
111 {"id": order_id, OrderDBModel.status: OrderStatus.canceled.value},
112 )
113 raise NotFoundHTTPError("заказ")
114 auction_end_time_setting = order and order.auction_end_time
115 if not (
116 order_in.get(OrderDBModel.auction_end_time) or auction_end_time_setting
117 ):
118 raise BadParameterHTTPError("нет времени завершения аукциона")
119 osp = order and order.start_price
120 if not (order_in.get(OrderDBModel.start_price) or osp):
121 raise BadParameterHTTPError("нет стартовой цены")
122 if auction_end_time_setting:
123 update_data[OrderDBModel.auction_end_time] = auction_end_time_setting
124 update_data[OrderDBModel.start_price] = osp or order_in.get(
125 OrderDBModel.start_price
126 )
127 add_prices_to_update(
128 order_in,
129 update_data,
130 update_data[OrderDBModel.start_price],
131 order and order.end_price,
132 )
133 updated = await update_status_and_return(
134 order_id,
135 OrderStatus.exchange,
136 set_=update_data,
137 restriction=cancelled_q | etag_q,
138 )
139 notify_if_assigned(order, updated)
140 return updated
143async def on_cancelled_to_appointment(
144 order_id: ObjectId, order: OrderUpdateModel | None
145):
146 update_data = await data_from_assigned(order)
147 etag_q = {"etag": order.etag} if order and order.etag else {}
148 updated = await update_status_and_return(
149 order_id,
150 OrderStatus.appointment,
151 update_data,
152 restriction=cancelled_q | etag_q,
153 )
154 notify_if_assigned(order, updated)
157async def on_cancelled_to_confirmed(
158 order_id: ObjectId, order: OrderUpdateModel
159):
160 if not (order.carrier and order.carrier.id):
161 raise BadParameterHTTPError("нет перевозчика")
162 order_data = await data_from_assigned(order)
163 await fill_carrier_by_oid_company(order_data, order)
164 etag_q = {"etag": order.etag} if order and order.etag else {}
165 updated = await update_status_and_return(
166 order_id,
167 OrderStatus.confirmed,
168 order_data,
169 restriction=cancelled_q | etag_q,
170 )
171 um = OrderDBModel(**updated)
172 notify_if_assigned(order, um)
173 asyncio.create_task(notification_api.order_confirmed(um))
176async def on_cancelled_to_buffer(
177 order_id: ObjectId, order: OrderUpdateModel | None
178) -> dict[str, Any] | OrderDBModel:
179 update_data = await data_from_assigned(order)
180 updated = await move_order_and_return(
181 order_id,
182 orders_col,
183 buf_col,
184 OrderStatus.buffer,
185 cancelled_q,
186 update_data,
187 )
188 upm = OrderDBModel(**updated)
189 notify_if_assigned(order, upm)
190 asyncio.create_task(notification_api.new_in_buffer(upm))
191 return upm