shop_system_models 0.0.1.dev26551__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. shop_system_models/__init__.py +5 -0
  2. shop_system_models/consts/__init__.py +0 -0
  3. shop_system_models/consts/country_codes.py +251 -0
  4. shop_system_models/consts/enums.py +56 -0
  5. shop_system_models/consts/messages/admin.py +199 -0
  6. shop_system_models/consts/messages/locales/en.json +43 -0
  7. shop_system_models/consts/messages/locales/ru.json +44 -0
  8. shop_system_models/consts/messages/mapping.py +22 -0
  9. shop_system_models/deployment_api/__init__.py +1 -0
  10. shop_system_models/deployment_api/request/authorization.py +1 -0
  11. shop_system_models/deployment_api/request/bot.py +11 -0
  12. shop_system_models/deployment_api/request/nocodb.py +14 -0
  13. shop_system_models/deployment_api/request/premium.py +15 -0
  14. shop_system_models/deployment_api/request/processes.py +14 -0
  15. shop_system_models/deployment_api/request/servers.py +0 -0
  16. shop_system_models/deployment_api/request/services.py +0 -0
  17. shop_system_models/deployment_api/shared.py +40 -0
  18. shop_system_models/deployment_api/users.py +45 -0
  19. shop_system_models/shop_api/__init__.py +6 -0
  20. shop_system_models/shop_api/bot/__init__.py +1 -0
  21. shop_system_models/shop_api/bot/request.py +49 -0
  22. shop_system_models/shop_api/bot/response.py +11 -0
  23. shop_system_models/shop_api/commands/__init__.py +1 -0
  24. shop_system_models/shop_api/commands/request.py +20 -0
  25. shop_system_models/shop_api/commands/response.py +5 -0
  26. shop_system_models/shop_api/links.py +36 -0
  27. shop_system_models/shop_api/processes/__init__.py +1 -0
  28. shop_system_models/shop_api/processes/request.py +38 -0
  29. shop_system_models/shop_api/processes/response.py +12 -0
  30. shop_system_models/shop_api/shared.py +20 -0
  31. shop_system_models/shop_api/shop/__init__.py +4 -0
  32. shop_system_models/shop_api/shop/request/__init__.py +13 -0
  33. shop_system_models/shop_api/shop/request/baskets.py +38 -0
  34. shop_system_models/shop_api/shop/request/categories.py +24 -0
  35. shop_system_models/shop_api/shop/request/coupons.py +43 -0
  36. shop_system_models/shop_api/shop/request/details.py +37 -0
  37. shop_system_models/shop_api/shop/request/orders.py +143 -0
  38. shop_system_models/shop_api/shop/request/payment_methods.py +17 -0
  39. shop_system_models/shop_api/shop/request/products.py +41 -0
  40. shop_system_models/shop_api/shop/request/review.py +12 -0
  41. shop_system_models/shop_api/shop/request/shop.py +27 -0
  42. shop_system_models/shop_api/shop/response/__init__.py +11 -0
  43. shop_system_models/shop_api/shop/response/basic.py +5 -0
  44. shop_system_models/shop_api/shop/response/baskets.py +36 -0
  45. shop_system_models/shop_api/shop/response/categories.py +31 -0
  46. shop_system_models/shop_api/shop/response/coupons.py +16 -0
  47. shop_system_models/shop_api/shop/response/extra_product_options.py +19 -0
  48. shop_system_models/shop_api/shop/response/initialization_data.py +21 -0
  49. shop_system_models/shop_api/shop/response/orders.py +22 -0
  50. shop_system_models/shop_api/shop/response/pagination.py +17 -0
  51. shop_system_models/shop_api/shop/response/payment_methods.py +12 -0
  52. shop_system_models/shop_api/shop/response/products.py +44 -0
  53. shop_system_models/shop_api/shop/response/review.py +14 -0
  54. shop_system_models/shop_api/shop/response/users.py +6 -0
  55. shop_system_models-0.0.1.dev26551.dist-info/METADATA +38 -0
  56. shop_system_models-0.0.1.dev26551.dist-info/RECORD +57 -0
  57. shop_system_models-0.0.1.dev26551.dist-info/WHEEL +4 -0
@@ -0,0 +1,14 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class NocoDBConfig(BaseModel):
7
+ nocodb_project_id: Optional[str] = None
8
+ nocodb_categories_table: Optional[str] = None
9
+ nocodb_products_table: Optional[str] = None
10
+ nocodb_orders_table: Optional[str] = None
11
+ nocodb_status_table: Optional[str] = None
12
+ nocodb_bot_commands_table: Optional[str] = None
13
+ nocodb_options_table: Optional[str] = ""
14
+ nocodb_options_category_table: Optional[str] = ""
@@ -0,0 +1,15 @@
1
+ import enum
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class PremiumPlanTypes(str, enum.Enum):
7
+ month = '1month'
8
+ three_months = '3months'
9
+ six_months = '6months'
10
+ year = '12months'
11
+
12
+
13
+ class RequestPremiumModel(BaseModel):
14
+ shop_id: str
15
+ premium_type: PremiumPlanTypes
@@ -0,0 +1,14 @@
1
+ from typing import Optional
2
+ from pydantic import BaseModel
3
+
4
+
5
+ class DeployVariables(BaseModel):
6
+ shop_name: str
7
+ shop_id: str
8
+ shop_template_id: str
9
+ orders_chat_id: int
10
+ contact_email: str
11
+ tg_admin_id: int
12
+ contact_phone: Optional[str]
13
+ bot_token: Optional[str]
14
+ invite_user: bool = True
File without changes
File without changes
@@ -0,0 +1,40 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel
5
+
6
+
7
+ class NocoDBConfig(BaseModel):
8
+ nocodb_project_id: str
9
+ nocodb_categories_table: str
10
+ nocodb_products_table: str
11
+ nocodb_orders_table: str
12
+ nocodb_status_table: str
13
+ nocodb_bot_commands_table: str
14
+ nocodb_options_table: Optional[str] = None
15
+ nocodb_options_category_table: Optional[str] = None
16
+
17
+
18
+ class ShopDetailsModel(BaseModel):
19
+ shop_id: str
20
+ shop_name: str
21
+ friendly_name: str
22
+ shop_language: str = "RU"
23
+ shop_api_url: str
24
+ contact_phone: str | None = None
25
+ contact_email: str
26
+ orders_chat_id: int
27
+ orders_history_chat_id: Optional[int] = None
28
+ search_enabled: Optional[bool] = False
29
+ warehouse_accounting: bool = False
30
+ bot_url: str | None = None
31
+ bot_token: str
32
+ payment_token: str | None = None
33
+ placeholder: str
34
+ order_process: str
35
+
36
+ nocodb_config: Optional[NocoDBConfig] = None
37
+
38
+ topic_chat_id: Optional[int] = None
39
+ premium_expiration_date: Optional[datetime] = None
40
+ web_app_url: str
@@ -0,0 +1,45 @@
1
+ # import re
2
+
3
+
4
+ from pydantic import BaseModel
5
+
6
+
7
+ class UserHeadersUpdatingModel(BaseModel):
8
+ tg_id: int
9
+ first_name: str | None = ""
10
+ last_name: str | None = ""
11
+ tg_language: str | None = ""
12
+ username: str | None = None
13
+
14
+
15
+ class UserModel(UserHeadersUpdatingModel):
16
+ password: str | None = None
17
+ preview_url: str | None = None
18
+ rights: str = "user"
19
+ delivery_addresses: list[str] | None = None
20
+
21
+
22
+ class ReferralUser(BaseModel):
23
+ tg_id: int
24
+ first_name: str
25
+ last_name: str | None = None
26
+ username: str | None = None
27
+
28
+
29
+ class InvitedUser(ReferralUser):
30
+ tg_language: str | None = ""
31
+ language: str | None = None
32
+
33
+
34
+ class UserDeploymentModel(BaseModel):
35
+ id: str
36
+ first_name: str
37
+ last_name: str | None = None
38
+ username: str | None = None
39
+ tg_id: int
40
+ tg_language: str = ""
41
+ invited_by_id: str | None = None
42
+ invited_by_user: ReferralUser | None = None
43
+ roles: list[str] | None = None
44
+ shops_available: int = 5
45
+ invited_users: list[InvitedUser] | None
@@ -0,0 +1,6 @@
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class MetaBaseModel(BaseModel):
5
+ """Base model with metadata support for all shop system models."""
6
+ metadata: dict = Field(default_factory=dict, exclude=True)
@@ -0,0 +1 @@
1
+ """Bot-related models for the shop system."""
@@ -0,0 +1,49 @@
1
+ from enum import Enum
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel
5
+ import enum
6
+
7
+
8
+ class OrderStatusTypes(str, enum.Enum):
9
+ CREATED = "CREATED"
10
+ CANCELLED = "CANCELLED"
11
+ PAID = "PAID"
12
+
13
+
14
+ class OrderStatusModel(BaseModel):
15
+ name: str
16
+ message: str
17
+ in_timeline: bool | None = False
18
+ type: Optional[OrderStatusTypes] = None
19
+
20
+ # @field_validator('name', )
21
+ # def validate_name_len(cls, value):
22
+ # if len(value) > 16:
23
+ # return value[:16]
24
+ # return value
25
+
26
+
27
+ class MessagesType(str, Enum):
28
+ admin_order_created = "admin_order_created"
29
+ admin_order_updated = "admin_order_updated"
30
+ user_order_created = "user_order_created"
31
+ user_order_updated = "user_order_updated"
32
+
33
+
34
+ class MessageModel(BaseModel):
35
+ type: MessagesType
36
+ text: str
37
+
38
+
39
+ class ButtonType(str, Enum):
40
+ inline_url = "inline_url"
41
+ inline_payload = "inline_payload"
42
+ app_url = "app_url"
43
+
44
+
45
+ class ButtonModel(BaseModel):
46
+ linked_status: OrderStatusModel | None = None
47
+ type: ButtonType
48
+ name: str
49
+ payload: str | None = ""
@@ -0,0 +1,11 @@
1
+ from shop_system_models.shop_api.bot.request import OrderStatusModel
2
+ from pydantic import BaseModel
3
+
4
+
5
+ class OrderStatusResponseModel(OrderStatusModel):
6
+ id: str
7
+
8
+
9
+ class OrderStatusResponseModelWithShopName(BaseModel):
10
+ shop_name: str
11
+ order_statuses: list[OrderStatusResponseModel]
@@ -0,0 +1 @@
1
+ """Command-related models for the shop system."""
@@ -0,0 +1,20 @@
1
+ from shop_system_models.shop_api.bot.request import ButtonModel
2
+ from pydantic import BaseModel, field_validator
3
+
4
+
5
+ class BotCommandModel(BaseModel):
6
+ name: str
7
+ message: str
8
+
9
+ @field_validator("name", mode="before")
10
+ def command_validation(cls, value):
11
+ if value.startswith("/"):
12
+ return value
13
+ raise ValueError('Bot command should start with "/"')
14
+
15
+
16
+ class NotificationPayloadModel(BaseModel):
17
+ chat_id: int
18
+ message_id: int | None = -1
19
+ text: str
20
+ buttons: list[ButtonModel] = []
@@ -0,0 +1,5 @@
1
+ from shop_system_models.shop_api.commands.request import BotCommandModel
2
+
3
+
4
+ class BotCommandResponseModel(BotCommandModel):
5
+ id: str
@@ -0,0 +1,36 @@
1
+ from typing import Optional, Dict, Any
2
+ from pydantic import Field, HttpUrl
3
+ from fastapi import HTTPException
4
+ from pydantic import BaseModel, field_validator
5
+
6
+
7
+
8
+ from shop_system_models.shop_api import MetaBaseModel
9
+
10
+
11
+ class ServiceLink(MetaBaseModel):
12
+ """Model representing a link to another service."""
13
+ service_name: str
14
+ url: HttpUrl
15
+ resource_id: str
16
+ link_metadata: Optional[Dict[str, Any]] = Field(default_factory=lambda: {})
17
+
18
+
19
+ class ServiceLinkResponse(MetaBaseModel):
20
+ """Response model for service link operations."""
21
+ link_id: str
22
+ service_name: str
23
+ resource_id: str
24
+ success: bool = True
25
+ error: Optional[str] = None
26
+
27
+
28
+ class LinkBlocksModel(BaseModel):
29
+ contacts: str | None = "https://teletype.in/@tg-shops/09hOkoJjizN" # Teletype link
30
+ info: str | None = "https://teletype.in/@tg-shops/2vZa_0ykcCF" # Teletype link
31
+
32
+ @field_validator("contacts", "info", mode="before")
33
+ def link_validation(cls, value):
34
+ if value and (not value.startswith("http://") and not value.startswith("https://")):
35
+ raise HTTPException(status_code=400, detail=f'Invalid link: "{value}"')
36
+ return value
@@ -0,0 +1 @@
1
+ """Process-related models for the shop system."""
@@ -0,0 +1,38 @@
1
+ from shops_payment_processing.models.invoice import InvoiceWithPaymentLinkMessageModel # type: ignore
2
+
3
+ from shop_system_models.shop_api.commands.request import NotificationPayloadModel
4
+ from shop_system_models.shop_api.shop.request.orders import InvoiceTGMessageModel, InvoiceTONMessageModel
5
+ from shop_system_models.shop_api.shop.request.orders import InvoiceWithPaymentLinkMessageModel as InvoiceWithPaymentLinkMessageModelLocal
6
+ from pydantic import BaseModel
7
+
8
+
9
+ class SetAdminMessageIdProcess(BaseModel):
10
+ admin_message_id: int | None = None
11
+
12
+
13
+ class SetProcessStatus(BaseModel):
14
+ message: str | None = None
15
+ success: bool | None = None
16
+
17
+
18
+ class ProcessModel(SetAdminMessageIdProcess, SetProcessStatus):
19
+ name: str
20
+ process_key: int
21
+ order_id: str
22
+
23
+
24
+ class ProcessVariables(BaseModel):
25
+ order_id: str
26
+ shop_url: str
27
+ shop_id: str
28
+ shop_api_url: str
29
+ shop_bot_url: str
30
+ user_order_info: NotificationPayloadModel
31
+ admin_order_info: NotificationPayloadModel
32
+ payment_info: (InvoiceTGMessageModel
33
+ | InvoiceTONMessageModel
34
+ | InvoiceWithPaymentLinkMessageModel
35
+ | InvoiceWithPaymentLinkMessageModelLocal
36
+ | None) = None
37
+ send_to_admin_dm: bool = False
38
+ shop_language: str
@@ -0,0 +1,12 @@
1
+ from shop_system_models.shop_api.processes.request import ProcessModel
2
+ from pydantic import BaseModel
3
+
4
+
5
+ class ProcessResponseModel(ProcessModel):
6
+ id: str
7
+
8
+
9
+ class UpdateMessageResponseModel(BaseModel):
10
+ text: str
11
+ status: str
12
+ order_number: str
@@ -0,0 +1,20 @@
1
+ from typing import Dict, Optional
2
+ from pydantic import BaseModel
3
+
4
+ class Thumbnail(BaseModel):
5
+ signedUrl: Optional[str] = None
6
+ path: Optional[str] = None
7
+
8
+ class Thumbnails(BaseModel):
9
+ tiny: Optional[Thumbnail]
10
+ small: Optional[Thumbnail]
11
+ card_cover: Optional[Thumbnail]
12
+
13
+ class ImageMetadata(BaseModel):
14
+ id: Optional[str] = None
15
+ url: Optional[str] = None
16
+ title: Optional[str] = None
17
+ mimetype: Optional[str] = None
18
+ thumbnails: Optional[Thumbnails]
19
+ path: Optional[str] = None
20
+ signedUrl: Optional[str] = None
@@ -0,0 +1,4 @@
1
+ """Shop-related models for the shop system."""
2
+
3
+ # from shop_system_models.shop_api.shop.request import * # noqa
4
+ # from shop_system_models.shop_api.shop.response import * # noqa
@@ -0,0 +1,13 @@
1
+ """Shop request models for API communication."""
2
+
3
+ from shop_system_models.shop_api.shop.request.orders import (
4
+ OrderModel,
5
+ DeliveryTypeModel,
6
+ CreateOrderModel,
7
+ BookingOrderModel,
8
+ OrderDeliveryTypeModel,
9
+ ExtraField,
10
+ AddressModel,
11
+ Coordinates,
12
+ ExtraFieldPayload,
13
+ )
@@ -0,0 +1,38 @@
1
+ from typing import Annotated
2
+
3
+ from annotated_types import Ge
4
+ from pydantic import BaseModel
5
+ from typing_extensions import Doc
6
+
7
+
8
+ class DBProductInBasket(BaseModel):
9
+ id: str # ID продукта
10
+ count: int # его кол-во
11
+
12
+
13
+ class BasketModel(BaseModel):
14
+ user_id: str | None = None # Not uses in request
15
+ order_id: str | None = None # Not uses in request
16
+ products_id: list[DBProductInBasket] = []
17
+ amount: float | None = 0 # Not uses in request
18
+ preview_url: str = ""
19
+
20
+
21
+ class DBProductInBasketV2(BaseModel):
22
+ id: str # product ID
23
+ unique_id: str # unique product ID in the basket, used it for product deleting
24
+ extra_option_ids: list[str] = []
25
+
26
+
27
+ class BasketModelV2(BaseModel):
28
+ user_id: str | None = None
29
+ order_id: str | None = None
30
+ products_id: list[DBProductInBasketV2] = []
31
+ coupon: str | None = None
32
+ coupon_discount: Annotated[float, Doc("The amount of discount from attached coupon, if any.")] = 0
33
+ amount: Annotated[float, Ge(0)] = 0 # this amount already includes discount
34
+ preview_url: str = ""
35
+
36
+
37
+ class CouponInputData(BaseModel):
38
+ code: str
@@ -0,0 +1,24 @@
1
+ from typing import List
2
+
3
+ from pydantic import BaseModel, Field, field_validator
4
+
5
+ from shop_system_models.shop_api.shared import ImageMetadata
6
+
7
+
8
+ class SubmitParentCategoryModel(BaseModel):
9
+ parent_category: list[int] = Field(default_factory=list)
10
+
11
+
12
+ class SubmitCategoryModel(BaseModel):
13
+ name: str
14
+ preview_url: str = ""
15
+
16
+ @field_validator("name", mode="before")
17
+ def name_validation(cls, value):
18
+ if not value:
19
+ raise ValueError("Name cannot be an empty string.")
20
+ return value
21
+
22
+
23
+ class CategoryModel(SubmitCategoryModel, SubmitParentCategoryModel):
24
+ images: List[ImageMetadata] = []
@@ -0,0 +1,43 @@
1
+ import datetime
2
+ from typing import Annotated
3
+
4
+ from annotated_types import Ge, Le
5
+ from pydantic import BaseModel, model_validator, StringConstraints
6
+
7
+
8
+ class SubmitCouponModel(BaseModel):
9
+ exp_date: datetime.datetime | None = None
10
+ amount: Annotated[float, Ge(0)] | None = None
11
+ discount: Annotated[float, Ge(0), Le(100)] | None = None
12
+ available_qty: Annotated[int, Ge(0)]
13
+ code: Annotated[str, StringConstraints(min_length=1, max_length=10)]
14
+
15
+ @model_validator(mode="after")
16
+ def amount_xor_discount_validator(self):
17
+ if self.amount is None and self.discount is None:
18
+ raise ValueError("amount or discount must be specified")
19
+
20
+ if self.amount is not None and self.discount is not None:
21
+ raise ValueError("only one of amount and discount must be specified")
22
+
23
+ return self
24
+
25
+
26
+ class CouponModel(SubmitCouponModel):
27
+ def get_discount_amount(self, basket_amount: float) -> float:
28
+ """
29
+ Calculate the discount amount.
30
+
31
+ It is guaranteed that the discount amount will be less than basket amount,
32
+ i.e. final basket amount won't go below zero.
33
+ """
34
+
35
+ if self.amount is not None:
36
+ discount_amount = self.amount
37
+ else:
38
+ assert self.discount is not None, "amount and discount are both None" # for mypy
39
+
40
+ # Round down discount_amount with precision of 2 digits after point
41
+ discount_amount = int(self.discount * basket_amount) / 100
42
+
43
+ return min(discount_amount, basket_amount - 1)
@@ -0,0 +1,37 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, Field
5
+
6
+
7
+
8
+
9
+ class ShopDetailsModel(BaseModel):
10
+ shop_id: str
11
+ shop_name: str
12
+ friendly_name: str
13
+ shop_language: str = "RU"
14
+ shop_api_url: str = "https://marketplace-api-dev.tg-shops.com"
15
+ contact_phone: str | None = None
16
+ contact_email: str
17
+ orders_chat_id: int
18
+ orders_history_chat_id: Optional[int] = None
19
+ search_enabled: Optional[bool] = False
20
+ warehouse_accounting: bool = False
21
+ bot_url: str | None = None
22
+ bot_token: str
23
+ payment_token: str | None = None
24
+ placeholder: str
25
+ order_process: str
26
+ nocodb_project_id: str
27
+ nocodb_categories_table: str
28
+ nocodb_products_table: str
29
+ nocodb_orders_table: str
30
+ nocodb_status_table: str
31
+ nocodb_bot_commands_table: str
32
+ nocodb_options_table: Optional[str] = ""
33
+ nocodb_options_category_table: Optional[str] = ""
34
+ topic_chat_id: Optional[int] = None
35
+ premium_expiration_date: Optional[datetime] = None
36
+ web_app_url: str = ""
37
+
@@ -0,0 +1,143 @@
1
+ from datetime import datetime
2
+ from typing import Optional, List, Dict, Any, Union
3
+ from pydantic import Field, field_validator, BaseModel
4
+
5
+ from shop_system_models.shop_api import MetaBaseModel
6
+ from shop_system_models.shop_api.shop.response.baskets import UserBasketResponseModelV2
7
+ from shop_system_models.shop_api.shop.response.products import ProductResponseModel
8
+
9
+
10
+ class ExtraFieldPayload(MetaBaseModel):
11
+ """Model for extra field data in orders."""
12
+ name: str
13
+ value: str
14
+
15
+
16
+ class OrderDeliveryTypeModel(MetaBaseModel):
17
+ """Model for order delivery details."""
18
+ name: str
19
+ address: Optional[str] = ""
20
+ amount: Optional[float] = 0.0
21
+ extra_fields_payload: Optional[List[ExtraFieldPayload]] = Field(default_factory=lambda: [])
22
+
23
+
24
+ class Coordinates(MetaBaseModel):
25
+ """Geographic coordinates."""
26
+ latitude: Optional[float] = None
27
+ longitude: Optional[float] = None
28
+
29
+
30
+ class AddressModel(MetaBaseModel):
31
+ """Address model with optional coordinates."""
32
+ coordinates: Optional[Coordinates] = None
33
+ address: Optional[str] = None
34
+
35
+
36
+ class ExtraField(MetaBaseModel):
37
+ """Model for defining extra fields."""
38
+ name: str
39
+ description: str
40
+ is_required: Optional[bool] = None
41
+
42
+
43
+ class DeliveryTypeModel(MetaBaseModel):
44
+ """Delivery type configuration model."""
45
+ name: str
46
+ amount: float = 0.0
47
+ is_address_required: Optional[bool] = False
48
+ address_hint: Optional[str] = ""
49
+ extra_fields: List[ExtraField] = Field(default_factory=list)
50
+ is_timepicker_required: bool = False
51
+ details: Optional[str] = None
52
+ country: Optional[str] = None
53
+ country_code: Optional[str] = None # ISO format, ex.: RU, KZ, BY...
54
+ city: Optional[str] = None
55
+ delivery_location: Optional[Coordinates] = None
56
+ delivery_radius: Optional[int] = None
57
+ delivery_min_hour: Optional[int] = None
58
+ delivery_max_hour: Optional[int] = None
59
+ delivery_minutes_interval: Optional[int] = None
60
+ delivery_min_day: Optional[int] = None
61
+ delivery_max_day: Optional[int] = None
62
+
63
+
64
+ class BookingOrderModel(MetaBaseModel):
65
+ """Details for a booking order."""
66
+ booking_id: str
67
+ from_date: datetime
68
+ till_date: datetime
69
+ item_id: str
70
+
71
+
72
+ class CreateOrderModel(MetaBaseModel):
73
+ """Model for creating a new order."""
74
+ delivery: Optional[OrderDeliveryTypeModel] = None
75
+ delivery_date_from: datetime = Field(default_factory=datetime.now)
76
+ comment: Optional[str] = None
77
+ user_contact_number: Optional[str] = None
78
+ payment_type_id: Optional[str] = None
79
+ booking_details: Optional[BookingOrderModel] = None
80
+ preview_url: Optional[str] = ""
81
+
82
+
83
+ class ProductsInBasket(ProductResponseModel):
84
+ count_in_basket: int = 1
85
+
86
+
87
+ # This depends on UserBasketResponseModelV2 which we'll define in a separate file
88
+ # For now, we'll create a placeholder class that can be updated later
89
+ class OrderModel(CreateOrderModel):
90
+ """Complete order model."""
91
+ basket: UserBasketResponseModelV2 # This will be implemented in basket models
92
+ user_id: Optional[str] = None
93
+ basket_id: Optional[str] = None
94
+ status: Optional[str] = None
95
+ client_coordinates: Optional[AddressModel] = None
96
+ created: datetime = Field(default_factory=datetime.now)
97
+ updated: datetime = Field(default_factory=datetime.now)
98
+ order_number: str = "#0001"
99
+ process_key: Optional[int] = None
100
+ coupon: Optional[str] = None
101
+ admin_message_id: str | None = None
102
+
103
+
104
+ class LabeledPrice(BaseModel):
105
+ label: str
106
+ amount: int
107
+
108
+
109
+ class InvoiceBaseModel(BaseModel):
110
+ chat_id: int
111
+ order_id: str
112
+ order_number: str # order_number
113
+ payload: str # <basket_id>_<order_id>_<order_number> from OrderResponseModel --> its subscription key
114
+ amount: float
115
+ currency: str # fiat
116
+ payment_address: str
117
+ payment_timeout: int | None = None
118
+
119
+
120
+ class InvoiceTGMessageModel(InvoiceBaseModel):
121
+ description: str # order_products
122
+ provider_data: str | None = None
123
+ prices: list[LabeledPrice] # label and amount in coins!
124
+ need_name: bool | None = False
125
+ need_phone_number: bool | None = False
126
+ need_email: bool | None = False
127
+ send_phone_number_to_provider: bool | None = False
128
+ send_email_to_provider: bool | None = False
129
+ is_flexible: bool | None = False
130
+ reply_markup: bool | None = None
131
+
132
+
133
+ class InvoiceWithPaymentLinkMessageModel(InvoiceBaseModel):
134
+ payment_link: str
135
+
136
+
137
+ class InvoiceTONMessageModel(InvoiceBaseModel):
138
+ approved_addresses: list[str] = []
139
+ ton_amount: float
140
+
141
+
142
+ class PaidContentMessage(BaseModel):
143
+ message: str