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.
- shop_system_models/__init__.py +5 -0
- shop_system_models/consts/__init__.py +0 -0
- shop_system_models/consts/country_codes.py +251 -0
- shop_system_models/consts/enums.py +56 -0
- shop_system_models/consts/messages/admin.py +199 -0
- shop_system_models/consts/messages/locales/en.json +43 -0
- shop_system_models/consts/messages/locales/ru.json +44 -0
- shop_system_models/consts/messages/mapping.py +22 -0
- shop_system_models/deployment_api/__init__.py +1 -0
- shop_system_models/deployment_api/request/authorization.py +1 -0
- shop_system_models/deployment_api/request/bot.py +11 -0
- shop_system_models/deployment_api/request/nocodb.py +14 -0
- shop_system_models/deployment_api/request/premium.py +15 -0
- shop_system_models/deployment_api/request/processes.py +14 -0
- shop_system_models/deployment_api/request/servers.py +0 -0
- shop_system_models/deployment_api/request/services.py +0 -0
- shop_system_models/deployment_api/shared.py +40 -0
- shop_system_models/deployment_api/users.py +45 -0
- shop_system_models/shop_api/__init__.py +6 -0
- shop_system_models/shop_api/bot/__init__.py +1 -0
- shop_system_models/shop_api/bot/request.py +49 -0
- shop_system_models/shop_api/bot/response.py +11 -0
- shop_system_models/shop_api/commands/__init__.py +1 -0
- shop_system_models/shop_api/commands/request.py +20 -0
- shop_system_models/shop_api/commands/response.py +5 -0
- shop_system_models/shop_api/links.py +36 -0
- shop_system_models/shop_api/processes/__init__.py +1 -0
- shop_system_models/shop_api/processes/request.py +38 -0
- shop_system_models/shop_api/processes/response.py +12 -0
- shop_system_models/shop_api/shared.py +20 -0
- shop_system_models/shop_api/shop/__init__.py +4 -0
- shop_system_models/shop_api/shop/request/__init__.py +13 -0
- shop_system_models/shop_api/shop/request/baskets.py +38 -0
- shop_system_models/shop_api/shop/request/categories.py +24 -0
- shop_system_models/shop_api/shop/request/coupons.py +43 -0
- shop_system_models/shop_api/shop/request/details.py +37 -0
- shop_system_models/shop_api/shop/request/orders.py +143 -0
- shop_system_models/shop_api/shop/request/payment_methods.py +17 -0
- shop_system_models/shop_api/shop/request/products.py +41 -0
- shop_system_models/shop_api/shop/request/review.py +12 -0
- shop_system_models/shop_api/shop/request/shop.py +27 -0
- shop_system_models/shop_api/shop/response/__init__.py +11 -0
- shop_system_models/shop_api/shop/response/basic.py +5 -0
- shop_system_models/shop_api/shop/response/baskets.py +36 -0
- shop_system_models/shop_api/shop/response/categories.py +31 -0
- shop_system_models/shop_api/shop/response/coupons.py +16 -0
- shop_system_models/shop_api/shop/response/extra_product_options.py +19 -0
- shop_system_models/shop_api/shop/response/initialization_data.py +21 -0
- shop_system_models/shop_api/shop/response/orders.py +22 -0
- shop_system_models/shop_api/shop/response/pagination.py +17 -0
- shop_system_models/shop_api/shop/response/payment_methods.py +12 -0
- shop_system_models/shop_api/shop/response/products.py +44 -0
- shop_system_models/shop_api/shop/response/review.py +14 -0
- shop_system_models/shop_api/shop/response/users.py +6 -0
- shop_system_models-0.0.1.dev26551.dist-info/METADATA +38 -0
- shop_system_models-0.0.1.dev26551.dist-info/RECORD +57 -0
- 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 @@
|
|
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,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,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
|