shop_system_models 0.0.1.dev26587__tar.gz → 0.0.1.dev27337__tar.gz

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 (85) hide show
  1. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/PKG-INFO +1 -1
  2. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/pyproject.toml +1 -1
  3. shop_system_models-0.0.1.dev27337/shop_system_models/consts/languages.py +4 -0
  4. shop_system_models-0.0.1.dev27337/shop_system_models/consts/languages.pyi +4 -0
  5. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/authorization.py +6 -0
  6. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/deployment_api/request/processes.py +1 -0
  7. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/services.py +36 -0
  8. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/shop_categories.py +9 -0
  9. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/shop_content/blocks.py +21 -0
  10. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/shop_content/delivery_types.py +51 -0
  11. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/shop_content/payment_methods.py +32 -0
  12. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/shop_templates.py +18 -0
  13. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/shops.py +102 -0
  14. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/tasks.py +24 -0
  15. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/users.py +53 -0
  16. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/request/web_app_url.py +14 -0
  17. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/response/general.py +23 -0
  18. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/response/permissions.py +6 -0
  19. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/response/premium.py +15 -0
  20. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/response/shops.py +51 -0
  21. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/response/simple_responses.py +61 -0
  22. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/response/web_app_url.py +5 -0
  23. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/shared.pyi +34 -0
  24. shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/users.pyi +37 -0
  25. shop_system_models-0.0.1.dev27337/shop_system_models/shop_api/shop/request/details.py +19 -0
  26. shop_system_models-0.0.1.dev27337/shop_system_models/shop_api/shop/request/orders.py +171 -0
  27. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/extra_product_options.py +1 -0
  28. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/products.py +1 -0
  29. shop_system_models-0.0.1.dev26587/shop_system_models/deployment_api/request/authorization.py +0 -1
  30. shop_system_models-0.0.1.dev26587/shop_system_models/deployment_api/request/services.py +0 -0
  31. shop_system_models-0.0.1.dev26587/shop_system_models/shop_api/shop/request/details.py +0 -37
  32. shop_system_models-0.0.1.dev26587/shop_system_models/shop_api/shop/request/orders.py +0 -143
  33. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/README.md +0 -0
  34. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/__init__.py +0 -0
  35. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/__init__.pyi +0 -0
  36. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/__init__.py +0 -0
  37. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/__init__.pyi +0 -0
  38. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/country_codes.py +0 -0
  39. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/country_codes.pyi +0 -0
  40. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/enums.py +0 -0
  41. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/enums.pyi +0 -0
  42. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/messages/admin.py +0 -0
  43. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/messages/locales/en.json +0 -0
  44. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/messages/locales/ru.json +0 -0
  45. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/consts/messages/mapping.py +0 -0
  46. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/deployment_api/__init__.py +0 -0
  47. /shop_system_models-0.0.1.dev26587/shop_system_models/deployment_api/request/servers.py → /shop_system_models-0.0.1.dev27337/shop_system_models/deployment_api/__init__.pyi +0 -0
  48. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/deployment_api/request/bot.py +0 -0
  49. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/deployment_api/request/nocodb.py +0 -0
  50. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/deployment_api/request/premium.py +0 -0
  51. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/deployment_api/shared.py +0 -0
  52. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/deployment_api/users.py +0 -0
  53. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/py.typed +0 -0
  54. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/__init__.py +0 -0
  55. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/__init__.pyi +0 -0
  56. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/bot/__init__.py +0 -0
  57. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/bot/request.py +0 -0
  58. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/bot/response.py +0 -0
  59. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/commands/__init__.py +0 -0
  60. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/commands/request.py +0 -0
  61. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/commands/response.py +0 -0
  62. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/links.py +0 -0
  63. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/processes/__init__.py +0 -0
  64. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/processes/request.py +0 -0
  65. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/processes/response.py +0 -0
  66. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shared.py +0 -0
  67. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/__init__.py +0 -0
  68. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/__init__.py +0 -0
  69. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/baskets.py +0 -0
  70. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/categories.py +0 -0
  71. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/coupons.py +0 -0
  72. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/payment_methods.py +0 -0
  73. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/products.py +0 -0
  74. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/review.py +0 -0
  75. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/request/shop.py +0 -0
  76. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/__init__.py +0 -0
  77. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/basic.py +0 -0
  78. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/baskets.py +0 -0
  79. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/categories.py +0 -0
  80. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/coupons.py +0 -0
  81. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/initialization_data.py +0 -0
  82. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/orders.py +0 -0
  83. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/payment_methods.py +0 -0
  84. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/review.py +0 -0
  85. {shop_system_models-0.0.1.dev26587 → shop_system_models-0.0.1.dev27337}/shop_system_models/shop_api/shop/response/users.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: shop_system_models
3
- Version: 0.0.1.dev26587
3
+ Version: 0.0.1.dev27337
4
4
  Summary: Shared model definitions for shop system services
5
5
  Author: Pavel Mulin
6
6
  Author-email: pavel@tg-shops.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "shop_system_models"
3
- version = "0.0.1.dev26587"
3
+ version = "0.0.1.dev27337"
4
4
  description = "Shared model definitions for shop system services"
5
5
  authors = ["Pavel Mulin <pavel@tg-shops.com>"]
6
6
  readme = "README.md"
@@ -0,0 +1,4 @@
1
+ TG_LANGUAGES_MAPPING = {'ru': 'RU',
2
+ 'en': 'EN'}
3
+
4
+ LANGUAGES = {value: key for key, value in TG_LANGUAGES_MAPPING.items()} # reverse TG_LANGUAGES
@@ -0,0 +1,4 @@
1
+ from _typeshed import Incomplete
2
+
3
+ TG_LANGUAGES_MAPPING: Incomplete
4
+ LANGUAGES: Incomplete
@@ -0,0 +1,6 @@
1
+ from shop_system_models.deployment_api.request.users import User
2
+
3
+
4
+ class Token(User):
5
+ initData: str
6
+
@@ -12,3 +12,4 @@ class DeployVariables(BaseModel):
12
12
  contact_phone: Optional[str]
13
13
  bot_token: Optional[str]
14
14
  invite_user: bool = True
15
+
@@ -0,0 +1,36 @@
1
+ from typing import Optional
2
+
3
+ from shop_system_models.consts.enums import ServiceNames
4
+ from pydantic import BaseModel, computed_field
5
+
6
+
7
+ class ServiceConfig(BaseModel):
8
+ name: ServiceNames
9
+ version: Optional[str] = 'latest'
10
+
11
+ class Config:
12
+ use_enum_values = True
13
+
14
+
15
+ class ProjectConfiguration(BaseModel):
16
+ shop_name: str
17
+
18
+ # Константы для URL — будут задаваться в рантайме
19
+ SHOP_BOT_URL: str = ''
20
+ SHOP_API_URL: str = ''
21
+ SHOP_APP_URL: str = ''
22
+
23
+ @computed_field # type: ignore
24
+ @property
25
+ def shop_bot_url(self) -> str:
26
+ return f"{self.SHOP_BOT_URL}/{self.shop_name}"
27
+
28
+ @computed_field # type: ignore
29
+ @property
30
+ def shop_api_url(self) -> str:
31
+ return f"{self.SHOP_API_URL}/{self.shop_name}"
32
+
33
+ @computed_field # type: ignore
34
+ @property
35
+ def shop_url(self) -> str:
36
+ return f"{self.SHOP_APP_URL}/{self.shop_name}"
@@ -0,0 +1,9 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class ShopCategory(BaseModel):
7
+ name: str
8
+ description: Optional[str] = None
9
+ preview_url: Optional[str] = None
@@ -0,0 +1,21 @@
1
+ from typing import Optional
2
+
3
+ from fastapi import HTTPException
4
+ from pydantic import BaseModel, field_validator
5
+
6
+
7
+ def link_validation(link: str) -> str:
8
+ if not link.startswith('http://') and not link.startswith('https://'):
9
+ raise HTTPException(status_code=400, detail=f'Invalid link: {link}')
10
+ return link
11
+
12
+
13
+ class LinkBlocks(BaseModel):
14
+ contacts: Optional[str] = None
15
+ info: Optional[str] = None
16
+
17
+ @field_validator('contacts', 'info')
18
+ def link_validation(cls, value: str) -> str:
19
+ if value:
20
+ return link_validation(link=value)
21
+ return value
@@ -0,0 +1,51 @@
1
+ from typing import List, Optional
2
+
3
+ from fastapi import HTTPException
4
+ from pydantic import BaseModel, field_validator
5
+
6
+
7
+ class Coordinates(BaseModel):
8
+ latitude: float
9
+ longitude: float
10
+
11
+
12
+ class ExtraField(BaseModel):
13
+ name: str
14
+ description: str
15
+ is_required: bool
16
+
17
+
18
+ # class ExtraFieldPayload(BaseModel):
19
+ # name: str
20
+ # value: str
21
+
22
+
23
+ class DeliveryType(BaseModel):
24
+ name: str
25
+ amount: float = 0.0
26
+ is_address_required: bool = False
27
+ address_hint: Optional[str] = ''
28
+ extra_fields: List[ExtraField] = []
29
+ is_timepicker_required: bool = False
30
+ details: str = ''
31
+ country: Optional[str] = ''
32
+ country_code: Optional[str] = '' # ISO format, ex.: RU, KZ, BY...
33
+ city: Optional[str] = None
34
+ delivery_location: Optional[Coordinates] = None
35
+ delivery_radius: Optional[int] = None
36
+ delivery_min_hour: Optional[int] = None
37
+ delivery_max_hour: Optional[int] = None
38
+ delivery_minutes_interval: Optional[int] = None
39
+ delivery_min_day: Optional[int] = None
40
+ delivery_max_day: Optional[int] = None
41
+
42
+ @field_validator('name')
43
+ def name_validation(cls, name):
44
+ name = name.strip()
45
+ if len(name) <= 2:
46
+ raise HTTPException(status_code=400, detail=f'Invalid delivery name: {name}')
47
+ return name
48
+
49
+
50
+ class DeliveryTypeResponse(DeliveryType):
51
+ id: str
@@ -0,0 +1,32 @@
1
+ from enum import Enum
2
+ from typing import List, Optional
3
+
4
+ from pydantic import BaseModel
5
+
6
+
7
+ class PaymentTypes(str, Enum):
8
+ manual_payment_request = 'ManualPaymentRequest'
9
+ external_card_payment_provider = 'ExternalCardPaymentProvider'
10
+ crypto_ton = 'CryptoTON'
11
+ xtr = 'XTR'
12
+ life_pay = 'LifePay'
13
+ yookassa = "yookassa"
14
+ tkassa = "tkassa"
15
+
16
+ class Metadata(BaseModel):
17
+ key: str
18
+ value: List[str]
19
+
20
+
21
+ class PaymentMethod(BaseModel):
22
+ name: str
23
+ type: PaymentTypes
24
+ payment_data: str # payment_token, TON address etc....
25
+ meta: Optional[List[Metadata]] = []
26
+
27
+ class Config:
28
+ use_enum_values = True
29
+
30
+
31
+ class PaymentMethodResponse(PaymentMethod):
32
+ id: str
@@ -0,0 +1,18 @@
1
+ from typing import Optional
2
+
3
+ from fastapi import HTTPException
4
+ from pydantic import BaseModel, field_validator
5
+
6
+
7
+ class ShopTemplate(BaseModel):
8
+ template_id: str
9
+ name: str
10
+ description: Optional[str] = ''
11
+ bot_url: str
12
+ language: str
13
+
14
+ @field_validator('bot_url')
15
+ def url_validation(cls, bot_url):
16
+ if bot_url.startswith('http://') or bot_url.startswith('https://'):
17
+ return bot_url
18
+ raise HTTPException(status_code=400, detail=f'Invalid bot_url: {bot_url}')
@@ -0,0 +1,102 @@
1
+ import re
2
+ from datetime import datetime
3
+ from typing import Any, List, Optional, Union
4
+
5
+ from pydantic import BaseModel, ValidationError, computed_field, model_validator, Field
6
+ from transliterate import translit # type: ignore
7
+
8
+ from shop_system_models.consts.enums import ShopStatuses
9
+ from shop_system_models.deployment_api.request.nocodb import NocoDBConfig
10
+ from shop_system_models.deployment_api.request.services import ProjectConfiguration
11
+ from shop_system_models.deployment_api.request.tasks import Task
12
+ from shop_system_models.deployment_api.response.shops import ShopCategoryResponse
13
+
14
+
15
+ class Location(BaseModel):
16
+ latitude: float
17
+ longitude: float
18
+ address: str
19
+
20
+
21
+ class CreateShop(BaseModel):
22
+ name: str
23
+ categories: List[ShopCategoryResponse] = []
24
+ locations: Optional[List[Location]] = []
25
+ contact_email: str
26
+ template_id: str
27
+ orders_chat_id: int = 0
28
+ friendly_name: str = ''
29
+ contact_phone: Optional[str] = ''
30
+ bot_token: Optional[str] = ''
31
+ zone: Optional[int] = None
32
+
33
+ @model_validator(mode='before')
34
+ def set_friendly_name_and_format_name(cls, values: dict):
35
+ name = values.get('name', '')
36
+ if len(name) > 35:
37
+ raise ValueError('Shop name too long; must be less than 35 symbols')
38
+
39
+ if not values.get('friendly_name'):
40
+ values['friendly_name'] = name.strip().strip("-")
41
+
42
+ transliterated_name = translit(name, 'ru', reversed=True) if name else ''
43
+ no_whitespaces_and_underscores = transliterated_name.replace(' ', '-').replace('_', '-')
44
+ no_double_dashes = re.sub(r'-{2,}', '-', no_whitespaces_and_underscores)
45
+ to_lowercase = no_double_dashes.lower()
46
+ no_special_characters = re.sub(r'[^a-z0-9_-]', '', to_lowercase)
47
+ formatted_name = re.sub(r'^[^a-z0-9]+|[^a-z0-9]+$', '', no_special_characters)
48
+
49
+ values['name'] = formatted_name
50
+ return values
51
+
52
+
53
+ class Shop(CreateShop):
54
+ # КОНСТАНТЫ ИЗ CONFIG
55
+ WEB_APP_URL: str = ''
56
+ FRONTEND_HOST: str = ''
57
+
58
+ placeholder: Optional[Union[ShopStatuses, Any]] = ShopStatuses.deploying
59
+ tasks: List[Task] = []
60
+ language: str = 'RU'
61
+ nocodb_config: NocoDBConfig = NocoDBConfig()
62
+
63
+ search_enabled: Optional[bool] = False
64
+ warehouse_accounting: Optional[bool] = False
65
+ weekly_reports: Optional[bool] = True
66
+ orders_history_chat_id: Optional[int] = None
67
+ topic_chat_id: Optional[int] = None
68
+ premium_expiration_date: Optional[datetime] = None
69
+ broadcast_messages_count: Optional[int] = 0
70
+ web_app_url: str = Field(default_factory=lambda: Shop.WEB_APP_URL)
71
+
72
+ blocked: bool = False
73
+ block_reason: str = ""
74
+
75
+ @computed_field # type: ignore
76
+ @property
77
+ def sheet_link(self) -> Optional[str]:
78
+ if self.nocodb_config and self.nocodb_config.nocodb_project_id:
79
+ return f"{self.FRONTEND_HOST}/dashboard/#/nc/{self.nocodb_config.nocodb_project_id}"
80
+ return None
81
+
82
+
83
+ class ShopDB(Shop):
84
+ id: str
85
+ tg_admin_id: int = 0
86
+ is_changeable: Optional[bool] = True
87
+ order_process: str = "The-devs.Shop.CreateOrder"
88
+ nocodb_config: NocoDBConfig = NocoDBConfig()
89
+ preview_url: Optional[str] = None
90
+ views_id: List[str] = []
91
+
92
+ @computed_field # type: ignore
93
+ @property
94
+ def configuration(self) -> ProjectConfiguration:
95
+ return ProjectConfiguration(
96
+ shop_name=self.name
97
+ )
98
+
99
+
100
+ class UpdateFromProcess(BaseModel):
101
+ nocodb_config: NocoDBConfig
102
+ language: str
@@ -0,0 +1,24 @@
1
+ from typing import List
2
+
3
+ from shop_system_models.consts.enums import TaskStatuses
4
+ from pydantic import BaseModel
5
+
6
+
7
+ class Task(BaseModel):
8
+ title: str
9
+ assignee_role: List = []
10
+ shop_id: str
11
+ shop_name: str
12
+ submit_url: str = ''
13
+ variables: dict
14
+ element_id: str
15
+ form_json: dict
16
+ job_key: int
17
+ process_id: str
18
+ process_instance_key: int
19
+ process_monitoring_url: str
20
+ deadline: int
21
+ status: TaskStatuses = TaskStatuses.pending
22
+
23
+ class Config:
24
+ use_enum_values = True
@@ -0,0 +1,53 @@
1
+ from typing import List, Optional
2
+
3
+ from shop_system_models.consts.enums import UserRoles
4
+ from shop_system_models.consts.languages import TG_LANGUAGES_MAPPING
5
+ from pydantic import BaseModel, field_validator, model_validator, computed_field
6
+
7
+
8
+ class ReferralUser(BaseModel):
9
+ first_name: str
10
+ last_name: Optional[str] = ''
11
+ username: Optional[str] = ''
12
+ tg_id: int
13
+
14
+
15
+ class User(BaseModel):
16
+ first_name: str
17
+ last_name: Optional[str] = ''
18
+ username: Optional[str] = ''
19
+ tg_id: int
20
+ tg_language: str = '' # language_code from TG
21
+
22
+ @computed_field # type: ignore
23
+ @property
24
+ def language(self) -> str:
25
+ return TG_LANGUAGES_MAPPING.get(self.tg_language, 'EN')
26
+
27
+
28
+ class UserDB(User):
29
+ invited_by_id: Optional[str] = None
30
+ invited_by_user: Optional[ReferralUser] = None
31
+ cache_key: Optional[str] = None
32
+
33
+
34
+ class UserExtended(UserDB):
35
+ SHOPS_LIMIT: int = 0 # сюда потом в рантайме подставишь значение из конфига
36
+
37
+ roles: List[str] = [] # 'shop_admin:<shop_id>' or 'admin'
38
+ shops_available: int = SHOPS_LIMIT
39
+
40
+ @field_validator('roles')
41
+ def if_admin(cls, roles: list):
42
+ for role in roles:
43
+ if role == UserRoles.admin.value:
44
+ return [UserRoles.admin.value]
45
+ return roles
46
+
47
+ @field_validator('shops_available')
48
+ def admin_limit(cls, shops_available, model):
49
+ roles = model.data['roles']
50
+ for role in roles:
51
+ if role == UserRoles.admin.value:
52
+ return 10
53
+ return shops_available
@@ -0,0 +1,14 @@
1
+ import re
2
+
3
+ from pydantic import BaseModel, Field, field_validator
4
+
5
+
6
+ class WebAppUrlUpdateRequest(BaseModel):
7
+ web_app_url: str = Field(..., description="The URL of the telegram web app")
8
+
9
+ @field_validator("web_app_url")
10
+ def validate_web_app_url(cls, value):
11
+ pattern = r"^https://t\.me/[A-Za-z0-9_]+/[A-Za-z0-9_]+$"
12
+ if not re.match(pattern, value):
13
+ raise ValueError("web_app_url must follow the pattern: 'https://t.me/{bot_name}/{webapp_name}', where bot_name and webapp_name can vary.")
14
+ return value
@@ -0,0 +1,23 @@
1
+ import enum
2
+ from pydantic import BaseModel
3
+
4
+
5
+ class PageInfo(BaseModel):
6
+ total_rows: int
7
+ page: int
8
+ page_size: int
9
+ is_first_page: bool
10
+ is_last_page: bool
11
+
12
+
13
+ class ListResponseModel(BaseModel):
14
+ page_info: PageInfo
15
+
16
+
17
+ class ExtraOptionsModel(str, enum.Enum):
18
+ enabled = 'enabled'
19
+ disabled = 'disabled'
20
+
21
+
22
+ class ExtraOptionsStatusResponse(BaseModel):
23
+ status: ExtraOptionsModel
@@ -0,0 +1,6 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class InviteLinkResponse(BaseModel):
5
+ valid_until: int
6
+ link: str
@@ -0,0 +1,15 @@
1
+ from pydantic import BaseModel
2
+
3
+ from shop_system_models.deployment_api.request.premium import PremiumPlanTypes
4
+
5
+
6
+ class PremiumLinkResponseModel(BaseModel):
7
+ shop_name: str
8
+ premium_type: str
9
+ link: str
10
+
11
+
12
+ class PremiumPlanType(BaseModel):
13
+ price: int
14
+ final_price: int
15
+ type: PremiumPlanTypes
@@ -0,0 +1,51 @@
1
+ from datetime import datetime
2
+ from typing import List, Optional
3
+
4
+
5
+ from shop_system_models.deployment_api.request.nocodb import NocoDBConfig
6
+ from shop_system_models.deployment_api.request.shop_categories import ShopCategory
7
+ from shop_system_models.deployment_api.request.shop_content.blocks import LinkBlocks
8
+ from shop_system_models.deployment_api.request.shop_content.delivery_types import DeliveryTypeResponse
9
+ from shop_system_models.deployment_api.request.shop_content.payment_methods import PaymentMethodResponse
10
+ from pydantic import BaseModel, Field
11
+
12
+
13
+ class ContentDataResponseModel(BaseModel):
14
+ blocks: Optional[LinkBlocks]
15
+ delivery_types: Optional[List[DeliveryTypeResponse]]
16
+ payment_methods: Optional[List[PaymentMethodResponse]]
17
+
18
+
19
+ class ShopDetails(BaseModel):
20
+ shop_id: str
21
+ shop_name: str
22
+ friendly_name: str
23
+ shop_language: Optional[str] = 'RU'
24
+ shop_api_url: str
25
+ contact_phone: str
26
+ contact_email: str
27
+ orders_chat_id: int # orders_management_chat_id
28
+ orders_history_chat_id: Optional[int] = None
29
+ topic_chat_id: Optional[int] = None
30
+ bot_url: str
31
+ bot_token: str
32
+ placeholder: str
33
+ order_process: str
34
+ search_enabled: bool = False
35
+ warehouse_accounting: bool = False
36
+ nocodb_config: Optional[NocoDBConfig] = None
37
+ nocodb_project_id: Optional[str] = None
38
+ nocodb_categories_table: Optional[str] = None
39
+ nocodb_products_table: Optional[str] = None
40
+ nocodb_orders_table: Optional[str] = None
41
+ nocodb_status_table: Optional[str] = None
42
+ nocodb_bot_commands_table: Optional[str] = None
43
+ nocodb_options_table: Optional[str] = ""
44
+ nocodb_options_category_table: Optional[str] = ""
45
+ premium_expiration_date: Optional[datetime] = None
46
+ broadcast_messages_count: Optional[int] = 0
47
+ web_app_url: str
48
+
49
+
50
+ class ShopCategoryResponse(ShopCategory):
51
+ id: str
@@ -0,0 +1,61 @@
1
+ from typing import List, Optional
2
+
3
+
4
+ from shop_system_models.deployment_api.request.services import ServiceConfig
5
+ from shop_system_models.deployment_api.request.shop_templates import ShopTemplate
6
+ from shop_system_models.deployment_api.request.shops import CreateShop, Shop, ShopDB
7
+ from shop_system_models.deployment_api.request.tasks import Task
8
+ from shop_system_models.deployment_api.request.users import User, UserExtended
9
+ from pydantic import BaseModel
10
+
11
+ from shop_system_models.deployment_api.response.general import ListResponseModel
12
+
13
+
14
+ class BasicResponse(BaseModel):
15
+ message: str
16
+
17
+
18
+
19
+
20
+
21
+ class ServiceConfigResponse(ServiceConfig):
22
+ id: str
23
+
24
+
25
+ class CreateShopResponse(CreateShop):
26
+ id: str
27
+
28
+
29
+ class ShopResponse(Shop):
30
+ id: str
31
+ preview_url: Optional[str] = None
32
+
33
+
34
+ class ShopResponseId(ShopDB):
35
+ id: str
36
+
37
+
38
+ class ShopsListResponseModel(ListResponseModel):
39
+ shops: List[ShopResponseId]
40
+
41
+
42
+ class ShopDBResponse(ShopDB):
43
+ id: str
44
+
45
+
46
+ class TaskResponse(Task):
47
+ id: str
48
+
49
+
50
+ class UserResponse(UserExtended):
51
+ id: str
52
+ invited_users: Optional[List[User]] = None
53
+ cache_key: Optional[str] = None
54
+
55
+
56
+ class TokenResponse(BaseModel):
57
+ access_token: str
58
+
59
+
60
+ class ShopTemplateResponse(ShopTemplate):
61
+ id: str
@@ -0,0 +1,5 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class WebAppUrlResponse(BaseModel):
5
+ web_app_url: str
@@ -0,0 +1,34 @@
1
+ from datetime import datetime
2
+ from pydantic import BaseModel
3
+
4
+ class NocoDBConfig(BaseModel):
5
+ nocodb_project_id: str
6
+ nocodb_categories_table: str
7
+ nocodb_products_table: str
8
+ nocodb_orders_table: str
9
+ nocodb_status_table: str
10
+ nocodb_bot_commands_table: str
11
+ nocodb_options_table: str | None
12
+ nocodb_options_category_table: str | None
13
+
14
+ class ShopDetailsModel(BaseModel):
15
+ shop_id: str
16
+ shop_name: str
17
+ friendly_name: str
18
+ shop_language: str
19
+ shop_api_url: str
20
+ contact_phone: str | None
21
+ contact_email: str
22
+ orders_chat_id: int
23
+ orders_history_chat_id: int | None
24
+ search_enabled: bool | None
25
+ warehouse_accounting: bool
26
+ bot_url: str | None
27
+ bot_token: str
28
+ payment_token: str | None
29
+ placeholder: str
30
+ order_process: str
31
+ nocodb_config: NocoDBConfig | None
32
+ topic_chat_id: int | None
33
+ premium_expiration_date: datetime | None
34
+ web_app_url: str
@@ -0,0 +1,37 @@
1
+ from pydantic import BaseModel
2
+
3
+ class UserHeadersUpdatingModel(BaseModel):
4
+ tg_id: int
5
+ first_name: str | None
6
+ last_name: str | None
7
+ tg_language: str | None
8
+ username: str | None
9
+
10
+ class UserModel(UserHeadersUpdatingModel):
11
+ password: str | None
12
+ preview_url: str | None
13
+ rights: str
14
+ delivery_addresses: list[str] | None
15
+
16
+ class ReferralUser(BaseModel):
17
+ tg_id: int
18
+ first_name: str
19
+ last_name: str | None
20
+ username: str | None
21
+
22
+ class InvitedUser(ReferralUser):
23
+ tg_language: str | None
24
+ language: str | None
25
+
26
+ class UserDeploymentModel(BaseModel):
27
+ id: str
28
+ first_name: str
29
+ last_name: str | None
30
+ username: str | None
31
+ tg_id: int
32
+ tg_language: str
33
+ invited_by_id: str | None
34
+ invited_by_user: ReferralUser | None
35
+ roles: list[str] | None
36
+ shops_available: int
37
+ invited_users: list[InvitedUser] | None
@@ -0,0 +1,19 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, Field
5
+
6
+
7
+
8
+ class NocoDBConfig(BaseModel):
9
+ nocodb_project_id: Optional[str] = None
10
+ nocodb_categories_table: Optional[str] = None
11
+ nocodb_products_table: Optional[str] = None
12
+ nocodb_orders_table: Optional[str] = None
13
+ nocodb_status_table: Optional[str] = None
14
+ nocodb_bot_commands_table: Optional[str] = None
15
+ nocodb_options_table: Optional[str] = ""
16
+ nocodb_options_category_table: Optional[str] = ""
17
+
18
+
19
+
@@ -0,0 +1,171 @@
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.shop.response.baskets import UserBasketResponseModelV2
6
+ from pydantic_core.core_schema import ValidationInfo
7
+ from shop_system_models.consts.country_codes import ISO3166
8
+
9
+
10
+
11
+ class ExtraFieldPayload(BaseModel):
12
+ name: str
13
+ value: str
14
+
15
+
16
+ class OrderDeliveryTypeModel(BaseModel):
17
+ name: str
18
+ address: str | None = ""
19
+ amount: float | None = 0.0
20
+ extra_fields_payload: list[ExtraFieldPayload] | None = []
21
+
22
+
23
+ class Coordinates(BaseModel):
24
+ latitude: float | None = None
25
+ longitude: float | None = None
26
+
27
+
28
+ class AddressModel(BaseModel):
29
+ coordinates: Coordinates | None = None
30
+ address: str | None = None
31
+
32
+
33
+ class ExtraField(BaseModel):
34
+ name: str
35
+ description: str
36
+ is_required: bool | None
37
+
38
+
39
+ class DeliveryTypeModel(BaseModel):
40
+ name: str
41
+ amount: float = 0.0
42
+ is_address_required: bool | None = False
43
+ address_hint: str | None = ""
44
+ extra_fields: list[ExtraField] = []
45
+ is_timepicker_required: bool = False
46
+ details: str | None = ""
47
+ country: str | None = ""
48
+ country_code: str | None = "" # ISO format, ex.: RU, KZ, BY...
49
+ city: str | None = ""
50
+ delivery_location: Coordinates | None = None
51
+ delivery_radius: int | None = None
52
+ delivery_min_hour: int | None = None
53
+ delivery_max_hour: int | None = None
54
+ delivery_minutes_interval: int | None = None
55
+ delivery_min_day: int | None = None
56
+ delivery_max_day: int | None = None
57
+
58
+ @field_validator("country_code", mode="before")
59
+ def set_country_code(cls, value, values: ValidationInfo):
60
+ country_code_upper = value.upper()
61
+ if ISO3166.get(country_code_upper):
62
+ return country_code_upper
63
+ return "RU"
64
+
65
+
66
+ def format_order_number(order_count: int) -> str:
67
+ return f"#{order_count:04}"
68
+
69
+
70
+ """
71
+ {
72
+ "user_id": 123,
73
+ "basket_id": None,
74
+ "basket": None,
75
+ "status": "booking_request",
76
+ "delivery": None,
77
+ "delivery_date_from": None,
78
+ "user_contact_number": None,
79
+ "client_coordinates": None,
80
+ "comment": "",# НАДО
81
+ "payment_type_id": # НАДО
82
+ "preview_url": ''
83
+ "booking_details": {
84
+ "booking_id": "123123",
85
+ "from_date": datetime.now(),
86
+ "till_date": datetime.now(),
87
+ "item_id": "123123",
88
+ }
89
+ }"""
90
+
91
+
92
+ class BookingOrderModel(BaseModel):
93
+ booking_id: str
94
+ from_date: datetime
95
+ till_date: datetime
96
+ item_id: str
97
+
98
+
99
+ class CreateOrderModel(BaseModel):
100
+ delivery: OrderDeliveryTypeModel | None = None
101
+ delivery_date_from: datetime = Field(default_factory=datetime.now)
102
+ comment: str | None = None
103
+ user_contact_number: str | None = None
104
+ payment_type_id: str | None = None
105
+ booking_details: BookingOrderModel | None = None
106
+ preview_url: str | None = ""
107
+
108
+
109
+ class OrderPaymentDetails(BaseModel):
110
+ title: str
111
+ description: str
112
+ expires_at: datetime
113
+ link: str
114
+
115
+
116
+ class OrderModel(CreateOrderModel):
117
+ basket: UserBasketResponseModelV2
118
+ user_id: str | None = None
119
+ basket_id: str | None = None
120
+ status: str | None = None
121
+ client_coordinates: AddressModel | None = None
122
+ created: datetime = datetime.now()
123
+ updated: datetime = datetime.now()
124
+ order_number: str = "#0001"
125
+ process_key: int | None = None
126
+ coupon: str | None = None
127
+ admin_message_id: str | None = None
128
+
129
+ payment_data: OrderPaymentDetails | None = None
130
+
131
+
132
+ class LabeledPrice(BaseModel):
133
+ label: str
134
+ amount: int
135
+
136
+
137
+ class InvoiceBaseModel(BaseModel):
138
+ chat_id: int
139
+ order_id: str
140
+ order_number: str # order_number
141
+ payload: str # <basket_id>_<order_id>_<order_number> from OrderResponseModel --> its subscription key
142
+ amount: float
143
+ currency: str # fiat
144
+ payment_address: str
145
+ payment_timeout: int | None = None
146
+
147
+
148
+ class InvoiceTGMessageModel(InvoiceBaseModel):
149
+ description: str # order_products
150
+ provider_data: str | None = None
151
+ prices: list[LabeledPrice] # label and amount in coins!
152
+ need_name: bool | None = False
153
+ need_phone_number: bool | None = False
154
+ need_email: bool | None = False
155
+ send_phone_number_to_provider: bool | None = False
156
+ send_email_to_provider: bool | None = False
157
+ is_flexible: bool | None = False
158
+ reply_markup: bool | None = None
159
+
160
+
161
+ class InvoiceWithPaymentLinkMessageModel(InvoiceBaseModel):
162
+ payment_link: str
163
+
164
+
165
+ class InvoiceTONMessageModel(InvoiceBaseModel):
166
+ approved_addresses: list[str] = []
167
+ ton_amount: float
168
+
169
+
170
+ class PaidContentMessage(BaseModel):
171
+ message: str
@@ -17,3 +17,4 @@ class ExtraOptionCategoriesResponseModel(MetaBaseModel):
17
17
  choice_count: int = 0 # How many options user can select from this category, 0 means no limit
18
18
  is_required: bool | None = False # If true, user must select at least one option from this category
19
19
  options: list[ExtraOptionResponseModel] = []
20
+ metadata = {}
@@ -22,6 +22,7 @@ class ProductResponseModel(BaseProductResponseModel):
22
22
  related_products: list["ProductResponseModel"] | None = []
23
23
  secret_urls: list[str] = []
24
24
  checkout_modes: list[ProductCheckoutModes] = []
25
+ metadata = {}
25
26
 
26
27
  @field_validator("checkout_modes")
27
28
  def convert_status(cls, value: list[ProductCheckoutModes]):
@@ -1,37 +0,0 @@
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] = None
33
- nocodb_options_category_table: Optional[str] = None
34
- topic_chat_id: Optional[int] = None
35
- premium_expiration_date: Optional[datetime] = None
36
- web_app_url: str = ""
37
-
@@ -1,143 +0,0 @@
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(BaseModel):
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