sqlalchemy-connection 2.0.1__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 (33) hide show
  1. sqlalchemy_connection-2.0.1.dist-info/METADATA +26 -0
  2. sqlalchemy_connection-2.0.1.dist-info/RECORD +33 -0
  3. sqlalchemy_connection-2.0.1.dist-info/WHEEL +5 -0
  4. sqlalchemy_connection-2.0.1.dist-info/entry_points.txt +2 -0
  5. sqlalchemy_connection-2.0.1.dist-info/top_level.txt +1 -0
  6. sqlalchemy_connector/__init__.py +3 -0
  7. sqlalchemy_connector/_builder.py +425 -0
  8. sqlalchemy_connector/cli.py +200 -0
  9. sqlalchemy_connector/real_generator.py +2908 -0
  10. sqlalchemy_connector/templates/admin_cart_html_template.html +372 -0
  11. sqlalchemy_connector/templates/admin_html_template.html +364 -0
  12. sqlalchemy_connector/templates/admin_users_html_template.html +82 -0
  13. sqlalchemy_connector/templates/app_template.py +434 -0
  14. sqlalchemy_connector/templates/base_html_template.html +100 -0
  15. sqlalchemy_connector/templates/cart_html_template.html +103 -0
  16. sqlalchemy_connector/templates/catalog_html_template.html +98 -0
  17. sqlalchemy_connector/templates/checkout_html_template.html +70 -0
  18. sqlalchemy_connector/templates/dashboard_html_template.html +121 -0
  19. sqlalchemy_connector/templates/index_html_template.html +91 -0
  20. sqlalchemy_connector/templates/login_html_template.html +59 -0
  21. sqlalchemy_connector/templates/models_template.py +65 -0
  22. sqlalchemy_connector/templates/new_request_html_template.html +49 -0
  23. sqlalchemy_connector/templates/orders_html_template.html +65 -0
  24. sqlalchemy_connector/templates/product_form_html_template.html +142 -0
  25. sqlalchemy_connector/templates/product_html_template.html +131 -0
  26. sqlalchemy_connector/templates/profile_html_template.html +104 -0
  27. sqlalchemy_connector/templates/register_html_template.html +183 -0
  28. sqlalchemy_connector/templates/reviews_html_template.html +104 -0
  29. sqlalchemy_connector/templates/service_detail_html_template.html +67 -0
  30. sqlalchemy_connector/templates/service_form_html_template.html +86 -0
  31. sqlalchemy_connector/templates/services_html_template.html +47 -0
  32. sqlalchemy_connector/templates/slider_js_template.js +99 -0
  33. sqlalchemy_connector/templates/style_css_template.css +502 -0
@@ -0,0 +1,26 @@
1
+ Metadata-Version: 2.4
2
+ Name: sqlalchemy-connection
3
+ Version: 2.0.1
4
+ Summary: Утилита для подключения к локальным SQLite базам данных
5
+ Author: SQLAlchemy Tools
6
+ Author-email: support@sqlalchemy-tools.dev
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Topic :: Database :: Front-Ends
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/plain
13
+ Requires-Dist: flask>=2.0.0
14
+ Requires-Dist: flask-sqlalchemy>=3.0.0
15
+ Requires-Dist: werkzeug>=2.0.0
16
+ Requires-Dist: flask-session>=0.5.0
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: description
21
+ Dynamic: description-content-type
22
+ Dynamic: requires-dist
23
+ Dynamic: requires-python
24
+ Dynamic: summary
25
+
26
+ SQLAlchemy Localhost Connector — лёгкая утилита командной строки для быстрого подключения к локальным SQLite/PostgreSQL базам данных. Позволяет просматривать схему, таблицы и записи без необходимости устанавливать тяжёлые GUI-клиенты. Поддерживает SQLAlchemy 2.x, автоматическое определение драйвера и вывод структуры БД в табличном формате.
@@ -0,0 +1,33 @@
1
+ sqlalchemy_connector/__init__.py,sha256=8kHDFwREh2xhTkBrlYYyMKcRM8DiIMUSdC4lSHI5CwM,136
2
+ sqlalchemy_connector/_builder.py,sha256=IZXLxA2IxqKYBYym4AVgSs9-Ht5wUuShGs5lo2VqFUc,25466
3
+ sqlalchemy_connector/cli.py,sha256=Pofuy056s8W6ujzVaY9IRIShoOEBbbTUv_vCKHnQ8D4,7717
4
+ sqlalchemy_connector/real_generator.py,sha256=ScT0ky52v2aSQsGt2DCWwxeV_cj-glg-la_o95IUOZE,163775
5
+ sqlalchemy_connector/templates/admin_cart_html_template.html,sha256=8AEikVUM08CJhUA7CPBJ5AL6AoVbWYCM8V90XJ4vZtM,15962
6
+ sqlalchemy_connector/templates/admin_html_template.html,sha256=oHinzOthUtBLAz2XDvFXVlqcB05oowZt9rdM0WrFsTE,17164
7
+ sqlalchemy_connector/templates/admin_users_html_template.html,sha256=QFjWJOFCL2ZgXrvsgKAXGiZLKcCQeHuIupJos62CVvs,4358
8
+ sqlalchemy_connector/templates/app_template.py,sha256=If5HSXzmyk09yAjbnZyb6SggoEnwYLLhZ5y7uor1Nnw,19922
9
+ sqlalchemy_connector/templates/base_html_template.html,sha256=OxTxro_tL8Lqj9jeJU8vq368dM4LOGmsuPuIvNf4kE4,4763
10
+ sqlalchemy_connector/templates/cart_html_template.html,sha256=BE3wFmKLR1Jx71hN33_6v22VUa2Zpi9FsT_nI3Nnnyw,5242
11
+ sqlalchemy_connector/templates/catalog_html_template.html,sha256=E0F_xCscWIviXuzFIu4Iv1n2CvcM66LWh4MXfaJ-6nk,5007
12
+ sqlalchemy_connector/templates/checkout_html_template.html,sha256=TCCO-fNLbsK0OUMQFw-TllMoFO87tH4Trh4JP9ihqfo,2842
13
+ sqlalchemy_connector/templates/dashboard_html_template.html,sha256=W8Ud98E2HpWzBvyShtCSOr09Gw_aEQJJhxEpAP4Y0F8,4011
14
+ sqlalchemy_connector/templates/index_html_template.html,sha256=dBrC33eVLgDitm-T9DJo8Q9AwzPpUBYYBXc9eUkgK-A,3402
15
+ sqlalchemy_connector/templates/login_html_template.html,sha256=USyQq2J9sOwhgwpvxGgk6E3kL3i6UTBzpemjCy_vDAw,2699
16
+ sqlalchemy_connector/templates/models_template.py,sha256=1HIolAKYmgYDu4sxWUw71zvqLsHfAd_qvL2GU_Rn9gQ,2200
17
+ sqlalchemy_connector/templates/new_request_html_template.html,sha256=R8JpBpI3bLQoVidda5Ol5JI_l3ofmuvmoMpP9UzL5aQ,1799
18
+ sqlalchemy_connector/templates/orders_html_template.html,sha256=1gdFgx2ss_SInX765XFa3M3FhQhHagoIq02Y4iLrIXA,2876
19
+ sqlalchemy_connector/templates/product_form_html_template.html,sha256=11FWMsEd5-CIfUvmC_GKg1FVV-vNI8fefRaoFdEl4OI,8612
20
+ sqlalchemy_connector/templates/product_html_template.html,sha256=oeoT3tDmY1rz1W9xM4H9P0sl-IiaJijXKjMhvMb1-8A,5977
21
+ sqlalchemy_connector/templates/profile_html_template.html,sha256=N3mh8D3fFmIZXZClq2umpUhMSHW1yB9r2X7DCpITbkA,5149
22
+ sqlalchemy_connector/templates/register_html_template.html,sha256=D0cSNUj7f7YBDpqrAFsvvjgg1d3VP9NjvwZpA1SwWh4,8767
23
+ sqlalchemy_connector/templates/reviews_html_template.html,sha256=YEVqDK_kQdl1e-7g-TUEu_1DvXRETfPAkdPIXYkvX-Y,5321
24
+ sqlalchemy_connector/templates/service_detail_html_template.html,sha256=BGp1Unhv9uNvnOY5wt-PCj-KjR9Pw_NWtI_tzgGumdA,2769
25
+ sqlalchemy_connector/templates/service_form_html_template.html,sha256=qiDrNCNW7kza6pPup4LW_nPFGJPr6OFrCoF5Zk2G9jw,3364
26
+ sqlalchemy_connector/templates/services_html_template.html,sha256=Yqrpu5tuZKLJTGeIw95sBMnarEp4w3ly_6_LoGH0SRI,2106
27
+ sqlalchemy_connector/templates/slider_js_template.js,sha256=Mpbmijga3fn8uEdyE8K9UWsvyDM4Vju9yJj0NaDmF7w,4257
28
+ sqlalchemy_connector/templates/style_css_template.css,sha256=OmOC2qSzZRAEZ-0GFvNjcLWmMnrK0ZokYy5IgvXY2wA,12608
29
+ sqlalchemy_connection-2.0.1.dist-info/METADATA,sha256=h4IRMveG83EfQFQ96poT5eqlXr7ZOvEXrx4qTK2-FZ0,1407
30
+ sqlalchemy_connection-2.0.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
31
+ sqlalchemy_connection-2.0.1.dist-info/entry_points.txt,sha256=IVrTKidNfqZDvxWHPxb5GuFBsclKN1ATFSAv0FvwfJ0,67
32
+ sqlalchemy_connection-2.0.1.dist-info/top_level.txt,sha256=Kz0UwgoF8pTlT2fXUyCx4hHmrK4bjgZ_xvxBexjYsTM,21
33
+ sqlalchemy_connection-2.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ start-sqlalchemy = sqlalchemy_connector.cli:main
@@ -0,0 +1 @@
1
+ sqlalchemy_connector
@@ -0,0 +1,3 @@
1
+ """SQLAlchemy Localhost Connector - утилита для работы с SQLite базами данных"""
2
+
3
+ __version__ = "2.0.0"
@@ -0,0 +1,425 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Модуль сбора конфигурации для генератора.
5
+ """
6
+ import sys
7
+ import os
8
+
9
+
10
+ def ask(prompt, default=None):
11
+ """Задаёт вопрос и возвращает ответ. Если пустой — возвращает default."""
12
+ if default is not None:
13
+ full_prompt = f"{prompt} [{default}]: "
14
+ else:
15
+ full_prompt = f"{prompt}: "
16
+ answer = input(full_prompt).strip()
17
+ return answer if answer else default
18
+
19
+
20
+ def ask_yes_no(prompt, default="нет"):
21
+ """Задаёт вопрос да/нет. Возвращает True/False."""
22
+ hint = " [да/нет]" if default is None else (f" [да/нет, по умолчанию {default}]")
23
+ while True:
24
+ answer = input(prompt + hint + ": ").strip().lower()
25
+ if not answer and default is not None:
26
+ return default in ("да", "yes", "y", "д")
27
+ if answer in ("да", "yes", "y", "д", "+", "1"):
28
+ return True
29
+ if answer in ("нет", "no", "n", "н", "-", "0"):
30
+ return False
31
+ print(" Введите 'да' или 'нет'")
32
+
33
+
34
+ def ask_choice(prompt, choices, default=None):
35
+ """Предлагает выбор из списка. Возвращает выбранный элемент."""
36
+ print(prompt)
37
+ for i, c in enumerate(choices, 1):
38
+ marker = " (по умолчанию)" if c == default else ""
39
+ print(f" {i}. {c}{marker}")
40
+ while True:
41
+ raw = input("Ваш выбор (номер): ").strip()
42
+ if not raw and default is not None:
43
+ return default
44
+ if raw.isdigit() and 1 <= int(raw) <= len(choices):
45
+ return choices[int(raw) - 1]
46
+ print(f" Введите число от 1 до {len(choices)}")
47
+
48
+
49
+ # ─────────────────────────────────────────────
50
+ # Типы полей для кастомных полей
51
+ # ─────────────────────────────────────────────
52
+ FIELD_TYPES = [
53
+ ("text", "Текстовое поле (строка)"),
54
+ ("textarea", "Многострочный текст"),
55
+ ("email", "Email"),
56
+ ("phone", "Телефон"),
57
+ ("date", "Дата"),
58
+ ("time", "Время"),
59
+ ("datetime", "Дата и время"),
60
+ ("number", "Число"),
61
+ ("select", "Выпадающий список (выбор из вариантов)"),
62
+ ]
63
+
64
+
65
+ def ask_custom_fields(section_name):
66
+ """Интерактивный ввод произвольных полей. Возвращает список словарей."""
67
+ fields = []
68
+ print(f"\n Добавление полей для: {section_name}")
69
+ print(" (Введите пустое название чтобы закончить)\n")
70
+
71
+ while True:
72
+ label = ask(f" Название поля (отображаемое)")
73
+ if not label:
74
+ break
75
+
76
+ # Предлагаем имя для БД
77
+ suggested_name = label.lower().replace(" ", "_")
78
+ # Транслитерация кириллицы
79
+ translit_map = {
80
+ 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo',
81
+ 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm',
82
+ 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u',
83
+ 'ф': 'f', 'х': 'kh', 'ц': 'ts', 'ч': 'ch', 'ш': 'sh', 'щ': 'shch',
84
+ 'ъ': '', 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya',
85
+ }
86
+ transliterated = ""
87
+ for ch in suggested_name:
88
+ if ch in translit_map:
89
+ transliterated += translit_map[ch]
90
+ elif ch.isascii():
91
+ transliterated += ch
92
+ else:
93
+ transliterated += "_"
94
+ # Убираем двойные подчёркивания
95
+ while "__" in transliterated:
96
+ transliterated = transliterated.replace("__", "_")
97
+ transliterated = transliterated.strip("_")
98
+
99
+ db_name = ask(f" Имя в БД (латиница)", transliterated)
100
+
101
+ # Тип поля
102
+ print(" Тип поля:")
103
+ for i, (code, desc) in enumerate(FIELD_TYPES, 1):
104
+ print(f" {i}. {desc}")
105
+ while True:
106
+ type_raw = input(" Номер типа [1]: ").strip()
107
+ if not type_raw:
108
+ field_type = "text"
109
+ break
110
+ if type_raw.isdigit() and 1 <= int(type_raw) <= len(FIELD_TYPES):
111
+ field_type = FIELD_TYPES[int(type_raw) - 1][0]
112
+ break
113
+ print(f" Введите число от 1 до {len(FIELD_TYPES)}")
114
+
115
+ # Варианты для select
116
+ options = []
117
+ if field_type == "select":
118
+ opts_raw = ask(" Варианты через запятую")
119
+ if opts_raw:
120
+ options = [o.strip() for o in opts_raw.split(",") if o.strip()]
121
+
122
+ required = ask_yes_no(" Обязательное поле?", "нет")
123
+
124
+ fields.append({
125
+ "label": label,
126
+ "name": db_name,
127
+ "type": field_type,
128
+ "required": required,
129
+ "options": options,
130
+ })
131
+ print(f" ✔ Поле «{label}» ({field_type}) добавлено\n")
132
+
133
+ return fields
134
+
135
+
136
+ def collect_config():
137
+ """Собирает конфигурацию проекта через диалог с пользователем."""
138
+ print("\n" + "=" * 60)
139
+ print(" 🏗️ Генератор сайтов на Flask")
140
+ print("=" * 60 + "\n")
141
+
142
+ config = {}
143
+
144
+ # ── Основные параметры ──────────────────────────────────────
145
+ config["project_name"] = ask("Название проекта (папка)", "mysite")
146
+ config["output_path"] = ask("Путь для создания проекта", os.getcwd())
147
+
148
+ # ── Авторизация ─────────────────────────────────────────────
149
+ print("\n── Авторизация ──")
150
+ auth_type = ask_choice(
151
+ "Авторизация пользователей по:",
152
+ ["Логин + пароль", "Email + пароль"],
153
+ default="Логин + пароль"
154
+ )
155
+ config["auth_by_email"] = ("Email" in auth_type)
156
+
157
+ # ── Поля пользователя ────────────────────────────────────────
158
+ print("\n── Поля пользователя ──")
159
+ print("Стандартные поля (логин/email, пароль, роль) уже включены.")
160
+ print("Добавьте дополнительные поля для профиля пользователя:")
161
+
162
+ # Предлагаем популярные поля
163
+ config["user_full_name"] = ask_yes_no("Добавить поле ФИО", "да")
164
+ if not config["auth_by_email"]:
165
+ config["user_email"] = ask_yes_no("Добавить поле Email", "да")
166
+ else:
167
+ config["user_email"] = True # email уже есть как логин
168
+ config["user_phone"] = ask_yes_no("Добавить поле Телефон", "да")
169
+ config["user_birth_date"] = ask_yes_no("Добавить поле Дата рождения", "да")
170
+ config["user_address"] = ask_yes_no("Добавить поле Адрес", "нет")
171
+ config["user_gender"] = ask_yes_no("Добавить поле Пол", "нет")
172
+ config["user_city"] = ask_yes_no("Добавить поле Город", "нет")
173
+ config["user_workplace"] = ask_yes_no("Добавить поле Место работы/учёбы", "нет")
174
+ config["user_passport"] = ask_yes_no("Добавить поле Паспортные данные (серия/номер)", "нет")
175
+ config["user_inn"] = ask_yes_no("Добавить поле ИНН", "нет")
176
+ config["user_snils"] = ask_yes_no("Добавить поле СНИЛС", "нет")
177
+ config["user_education"] = ask_yes_no("Добавить поле Образование", "нет")
178
+ config["user_position"] = ask_yes_no("Добавить поле Должность", "нет")
179
+ config["user_telegram"] = ask_yes_no("Добавить поле Telegram", "нет")
180
+
181
+ # Кастомные поля пользователя
182
+ print("\n Хотите добавить ещё поля пользователя?")
183
+ print(" (Например: отдел, должность, ИНН, СНИЛС и т.д.)")
184
+ add_custom_user = ask_yes_no(" Добавить дополнительные поля?", "нет")
185
+ if add_custom_user:
186
+ config["custom_user_fields"] = ask_custom_fields("Пользователь")
187
+ else:
188
+ config["custom_user_fields"] = []
189
+
190
+ # ── Корзина и товары ────────────────────────────────────────
191
+ print("\n── Корзина и товары ──")
192
+ print("Если включить корзину — будет создан каталог товаров,")
193
+ print("пользователи смогут добавлять товары в корзину и оформлять заказы.")
194
+ config["cart"] = ask_yes_no("Добавить функционал корзины с товарами?", "нет")
195
+ if config["cart"]:
196
+ config["cart_type"] = "products" # всегда товары
197
+ print("\n Стандартные поля товара: Название, Описание, Цена, Кол-во на складе, Фото.")
198
+ print(" Также будет поле «Активен» (можно снять товар с продажи).\n")
199
+ print(" Хотите добавить дополнительные атрибуты товара?")
200
+ print(" (Например: размер, цвет, материал, вес, бренд и т.д.)")
201
+ add_product_attrs = ask_yes_no(" Добавить доп. атрибуты товара?", "нет")
202
+ if add_product_attrs:
203
+ config["custom_product_fields"] = ask_custom_fields("Товар")
204
+ else:
205
+ config["custom_product_fields"] = []
206
+ else:
207
+ config["cart_type"] = None
208
+ config["custom_product_fields"] = []
209
+
210
+ # ── Если корзина включена — заявки и услуги не нужны ─────────
211
+ if config["cart"]:
212
+ # Корзина заменяет заявки и услуги
213
+ config["custom_request_fields"] = []
214
+ config["services"] = False
215
+ for k in ["svc_name","svc_description","svc_price","svc_duration","svc_category",
216
+ "svc_image","svc_max_clients","svc_location","svc_requirements","svc_is_active"]:
217
+ config[k] = False
218
+ # ── Статусы заказов ───────────────────────────────────────────
219
+ print("\n── Статусы заказов ──")
220
+ print("По умолчанию: Новый, Оплачен, Отправлен, Доставлен, Отменён")
221
+ custom_statuses = ask_yes_no("Изменить статусы?", "нет")
222
+ if custom_statuses:
223
+ raw = ask("Введите статусы через запятую")
224
+ config["statuses"] = [s.strip() for s in raw.split(",") if s.strip()]
225
+ else:
226
+ config["statuses"] = ["Новый", "Оплачен", "Отправлен", "Доставлен", "Отменён"]
227
+
228
+ # ── Поля оформления заказа ─────────────────────────────────
229
+ print("\n── Поля оформления заказа ──")
230
+ print("Когда пользователь оформляет заказ из корзины,")
231
+ print("можно запросить дополнительные данные (адрес доставки и т.д.).")
232
+ print("Если не добавить ни одного поля — заказ оформится сразу по кнопке.\n")
233
+
234
+ config["checkout_fields"] = []
235
+ # Предложим стандартные поля
236
+ if ask_yes_no(" Добавить поле 'Адрес доставки'?", "да"):
237
+ config["checkout_fields"].append({
238
+ "label": "Адрес доставки", "name": "delivery_address",
239
+ "type": "text", "required": True, "options": []
240
+ })
241
+ if ask_yes_no(" Добавить поле 'Получатель (ФИО)'?", "да"):
242
+ config["checkout_fields"].append({
243
+ "label": "Получатель (ФИО)", "name": "recipient_name",
244
+ "type": "text", "required": True, "options": []
245
+ })
246
+ if ask_yes_no(" Добавить поле 'Телефон для связи'?", "да"):
247
+ config["checkout_fields"].append({
248
+ "label": "Телефон для связи", "name": "contact_phone",
249
+ "type": "phone", "required": True, "options": []
250
+ })
251
+ if ask_yes_no(" Добавить поле 'Комментарий к заказу'?", "нет"):
252
+ config["checkout_fields"].append({
253
+ "label": "Комментарий к заказу", "name": "comment",
254
+ "type": "textarea", "required": False, "options": []
255
+ })
256
+ if ask_yes_no(" Добавить поле 'Способ доставки'?", "нет"):
257
+ config["checkout_fields"].append({
258
+ "label": "Способ доставки", "name": "delivery_method",
259
+ "type": "select", "required": True,
260
+ "options": ["Самовывоз", "Курьер", "Почта"]
261
+ })
262
+ if ask_yes_no(" Добавить поле 'Желаемая дата доставки'?", "нет"):
263
+ config["checkout_fields"].append({
264
+ "label": "Желаемая дата доставки", "name": "delivery_date",
265
+ "type": "date", "required": False, "options": []
266
+ })
267
+
268
+ # Кастомные поля оформления
269
+ add_custom_checkout = ask_yes_no(" Добавить другие поля оформления?", "нет")
270
+ if add_custom_checkout:
271
+ config["checkout_fields"].extend(ask_custom_fields("Оформление заказа"))
272
+
273
+ else:
274
+ # ── Поля заявки ──────────────────────────────────────────────
275
+ print("\n── Поля заявки ──")
276
+ print("Стандартные поля (ID, пользователь, статус, дата) уже включены.")
277
+ print("Добавьте поля, которые пользователь заполняет при создании заявки:")
278
+ print("(Например: категория проблемы, описание, автомобиль, дата бронирования...)\n")
279
+
280
+ config["custom_request_fields"] = ask_custom_fields("Заявка")
281
+
282
+ if not config["custom_request_fields"]:
283
+ # Если ничего не добавили — предложим базовые
284
+ print("\n Вы не добавили ни одного поля. Добавить стандартные?")
285
+ if ask_yes_no(" Добавить поле 'Описание'?", "да"):
286
+ config["custom_request_fields"].append({
287
+ "label": "Описание",
288
+ "name": "description",
289
+ "type": "textarea",
290
+ "required": True,
291
+ "options": [],
292
+ })
293
+
294
+ # ── Модуль услуг ─────────────────────────────────────────────
295
+ print("\n── Модуль услуг ──")
296
+ print("Услуги — это позиции, которые создаёт администратор.")
297
+ print("Пользователи могут просматривать услуги и подавать на них заявки.")
298
+ config["services"] = ask_yes_no("Добавить модуль услуг?", "нет")
299
+ if config["services"]:
300
+ print("\n Поля услуги (администратор заполняет при создании):")
301
+ config["svc_name"] = True # название — всегда
302
+ config["svc_description"] = ask_yes_no(" Добавить поле 'Описание'", "да")
303
+ config["svc_price"] = ask_yes_no(" Добавить поле 'Цена'", "да")
304
+ config["svc_duration"] = ask_yes_no(" Добавить поле 'Продолжительность'", "нет")
305
+ config["svc_category"] = ask_yes_no(" Добавить поле 'Категория'", "нет")
306
+ config["svc_image"] = ask_yes_no(" Добавить фотографию услуги (физический файл)?", "да")
307
+ config["svc_max_clients"] = ask_yes_no(" Добавить поле 'Макс. кол-во клиентов'", "нет")
308
+ config["svc_location"] = ask_yes_no(" Добавить поле 'Место проведения'", "нет")
309
+ config["svc_requirements"]= ask_yes_no(" Добавить поле 'Требования к клиенту'", "нет")
310
+ config["svc_is_active"] = ask_yes_no(" Добавить поле 'Активна (вкл/выкл)'", "да")
311
+ else:
312
+ # Заполняем дефолтами чтобы generator не падал
313
+ for k in ["svc_name","svc_description","svc_price","svc_duration","svc_category",
314
+ "svc_image","svc_max_clients","svc_location","svc_requirements","svc_is_active"]:
315
+ config[k] = False
316
+
317
+ # ── Статусы заявок ───────────────────────────────────────────
318
+ print("\n── Статусы заявок ──")
319
+ print("По умолчанию: Новая, В работе, Завершена")
320
+ custom = ask_yes_no("Изменить статусы?", "нет")
321
+ if custom:
322
+ raw = ask("Введите статусы через запятую")
323
+ config["statuses"] = [s.strip() for s in raw.split(",") if s.strip()]
324
+ else:
325
+ config["statuses"] = ["Новая", "В работе", "Завершена"]
326
+
327
+ # ── Администратор ────────────────────────────────────────────
328
+ print("\n── Администратор ──")
329
+ print("Введите данные администратора:")
330
+ if config["auth_by_email"]:
331
+ config["admin_login"] = ask("Email администратора", "admin@example.com")
332
+ else:
333
+ config["admin_login"] = ask("Логин администратора", "admin")
334
+ config["admin_password"] = ask("Пароль администратора", "admin123")
335
+ # Заполняем поля админа теми же полями что и у пользователя
336
+ config["admin_extra"] = {}
337
+ if config.get("user_full_name"):
338
+ config["admin_extra"]["full_name"] = ask(" ФИО администратора", "Администратор")
339
+ if config.get("user_email") and not config["auth_by_email"]:
340
+ config["admin_extra"]["email"] = ask(" Email администратора", "admin@example.com")
341
+ if config.get("user_phone"):
342
+ config["admin_extra"]["phone"] = ask(" Телефон администратора", "+7 (999) 000-00-00")
343
+ if config.get("user_birth_date"):
344
+ config["admin_extra"]["birth_date"] = ask(" Дата рождения администратора", "")
345
+ if config.get("user_address"):
346
+ config["admin_extra"]["address"] = ask(" Адрес администратора", "")
347
+ if config.get("user_city"):
348
+ config["admin_extra"]["city"] = ask(" Город администратора", "")
349
+ if config.get("user_telegram"):
350
+ config["admin_extra"]["telegram"] = ask(" Telegram администратора", "")
351
+
352
+ # ── Отзывы ───────────────────────────────────────────────────
353
+ print("\n── Отзывы ──")
354
+ config["reviews"] = ask_yes_no("Добавить отзывы на товары/услуги?", "нет")
355
+
356
+ # ── Фото до/после ────────────────────────────────────────────
357
+ print("\n── Фото «до/после» для заявок ──")
358
+ config["photo_before_after"] = ask_yes_no("Добавить фото «до/после» для заявок?", "нет")
359
+
360
+ # ── Анимации ─────────────────────────────────────────────────
361
+ print("\n── Анимации ──")
362
+ config["animations"] = ask_yes_no("Добавить анимации на сайт?", "да")
363
+
364
+ # ── Демо-данные ──────────────────────────────────────────────
365
+ print("\n── Демонстрационные данные ──")
366
+ config["demo_data"] = ask_yes_no("Создать скрипт с демонстрационными данными?", "нет")
367
+
368
+ return config
369
+
370
+
371
+ def print_summary(config):
372
+ """Выводит итоговую конфигурацию перед генерацией."""
373
+ print("\n" + "=" * 60)
374
+ print(" 📋 Итоговая конфигурация")
375
+ print("=" * 60)
376
+ print(f" Проект: {config['project_name']}")
377
+ print(f" Путь: {config['output_path']}")
378
+ auth_mode = "Email + пароль" if config.get("auth_by_email") else "Логин + пароль"
379
+ print(f" Авторизация: {auth_mode}")
380
+
381
+ # Поля пользователя
382
+ user_fields_str = []
383
+ if config.get("user_full_name"):
384
+ user_fields_str.append("ФИО")
385
+ if config.get("user_email"):
386
+ user_fields_str.append("Email")
387
+ if config.get("user_phone"):
388
+ user_fields_str.append("Телефон")
389
+ if config.get("user_birth_date"):
390
+ user_fields_str.append("Дата рождения")
391
+ if config.get("user_address"):
392
+ user_fields_str.append("Адрес")
393
+ if config.get("user_gender"):
394
+ user_fields_str.append("Пол")
395
+ if config.get("user_city"):
396
+ user_fields_str.append("Город")
397
+ if config.get("user_workplace"):
398
+ user_fields_str.append("Место работы/учёбы")
399
+ if config.get("user_passport"):
400
+ user_fields_str.append("Паспортные данные")
401
+ for f in config.get("custom_user_fields", []):
402
+ user_fields_str.append(f["label"])
403
+ print(f" Поля User: {', '.join(user_fields_str) if user_fields_str else '(нет доп. полей)'}")
404
+
405
+ # Поля заявки
406
+ req_fields_str = []
407
+ for f in config.get("custom_request_fields", []):
408
+ req_fields_str.append(f"{f['label']} ({f['type']})")
409
+ print(f" Поля заявки: {', '.join(req_fields_str) if req_fields_str else '(нет доп. полей)'}")
410
+
411
+ print(f" Статусы: {', '.join(config['statuses'])}")
412
+ print(f" Администратор: {config['admin_login']}")
413
+ svc_info = "да" if config.get("services") else "нет"
414
+ print(f" Модуль услуг: {svc_info}")
415
+ cart_info = "нет"
416
+ if config.get("cart"):
417
+ cart_info = f"да ({config.get('cart_type', '')})"
418
+ print(f" Корзина: {cart_info}")
419
+ print(f" Отзывы: {config['reviews']}")
420
+ print(f" Фото до/после: {config['photo_before_after']}")
421
+ print(f" Анимации: {config['animations']}")
422
+ print(f" Демо-данные: {config['demo_data']}")
423
+ print("=" * 60)
424
+
425
+