Commit Graph

707 Commits

Author SHA1 Message Date
ce486f35ca Перенос встроенных стилей из шаблона detail.html в отдельный CSS-файл transformation_detail.css 2026-01-15 15:09:38 +03:00
2ef537fff6 Добавлена возможность выбора анонимного системного клиента в форме заказа
- Убрана фильтрация системного клиента из результатов поиска (api_search_customers)
- Добавлен флаг is_system_customer в результаты API поиска
- Создан новый API endpoint api_get_system_customer для быстрого получения системного клиента
- Добавлена кнопка 'Аноним' для быстрого выбора системного клиента
- Системный клиент выделяется жёлтым цветом и иконкой инкогнито в выпадающем списке
- Улучшена компактность результатов поиска (уменьшен шрифт до 13px)
- Изменены пропорции полей: клиент 9 колонок, статус 3 колонки (было 6:6)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 12:54:56 +03:00
c7e03d258b Обновление админки и представлений для интеграций 2026-01-15 12:20:39 +03:00
fb3074a2ed Обновление конфигурации и зависимостей для AI сервисов 2026-01-15 12:20:25 +03:00
607c5ac8f4 Обновление структуры моделей интеграций 2026-01-15 12:19:44 +03:00
a23d714128 Добавление интеграции OpenRouter AI 2026-01-15 12:19:29 +03:00
401993526b Обновление GLM моделей до GLM-4 2026-01-15 12:16:56 +03:00
caeb3f80bd refactor(db): консолидация миграций и рефакторинг кода
Объединены изменения из промежуточных миграций в начальные миграции для упрощения истории базы данных.
Удалены миграции: accounts/0002, discounts/0002, orders/0003-0004, products/0002-0005, user_roles/0002, system_settings/0001-0002, integrations/0001-0002.
Добавлена автоматическая creation пользователя при установке пароля.
Обновлен UI страницы установки пароля с кастомным стилем.
Добавлен conditional rendering для кнопки синхронизации Recommerce.
Исправлены редиректы с 'index' на '/' в accounts views.
Добавлена проверка request.tenant в navbar и authenticate метод в auth backend.
2026-01-14 16:30:28 +03:00
e7672588c6 refactor: rename primary_category to external_category 2026-01-14 02:59:11 +03:00
1fb280607a feat(integrations): добавить поле primary_category и маппинг категорий для интеграций
Добавлена поддержка выбора основной категории (primary_category) для товаров и наборов, а также новая модель IntegrationCategoryMapping для связи категорий с внешними площадками. Теперь можно указать категорию товара, которая будет использоваться при экспорте на внешние площадки (Recommerce, WooCommerce и др.), с возможностью настройки маппинга категорий для каждого типа интеграции.
2026-01-14 01:53:38 +03:00
7fd361aaf8 docs(products): обновить описание синхронизации флагов
Уточнена инструкция в модалке: акцент на выборе флагов для
синхронизации, а не на изменении значений.
Удалены временные скрипты отладки API.
2026-01-13 22:55:12 +03:00
06a9cc05ca feat(products): добавить пояснение к маркетинговым флагам в модалке синхронизации
Добавлен информационный блок с объяснением, что флаги синхронизируются
с текущими значениями из системы на удалённый сайт.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 15:47:40 +03:00
eff9778539 fix(recommerce): использовать in_stock для определения наличия в API
- Добавить константу RECOMMERCE_INFINITY_COUNT = 999999 в mappers.py
- Изменить логику: product.in_stock определяет count (0 или 999999)
- Добавить test_count.py для тестирования поля count
- Обновить документацию recommerce_api.md с секцией Product Availability

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:35:10 +03:00
36090382c1 feat(products): улучшить интерфейс массовой синхронизации с Recommerce
- Добавить секцию маркетинговых флагов в модалку синхронизации
- Добавить кнопки "Выбрать все" для групп полей
- Улучшить UX отображения списка товаров

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:21:08 +03:00
3cffa9b05d fix(recommerce): исправить имена полей маркетинговых флагов для API
- is_new → new (API ожидает 'new', не 'is_new')
- is_popular → popular (API ожидает 'popular', не 'is_popular')
- добавить тестовый скрипт test_is_new.py для проверки флагов

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:06:39 +03:00
2aa3de7bfa feat(products): добавить интерфейс маркетинговых флагов
Добавлены поля is_new, is_popular, is_special в форму продукта.
Настроено отображение полей в виде переключателей (switch).
Добавлено отображение бейджей флагов в списке товаров
и на странице детализации продукта.
2026-01-13 10:04:48 +03:00
ec9fd1c78b feat(products): маркетинговые флаги is_new, is_popular, is_special
- Добавлены поля в BaseProductEntity (наследуются в Product, ProductKit)
- Исправлен формат флагов в Recommerce mappers (1/0 вместо true/false)
- Добавлены чекбоксы в админку Product и ProductKit
- special = is_special OR has_discount (ручное + автоматическое)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 00:27:04 +03:00
52422ee8df feat(recommerce): флаг special для акционных товаров
- Исправлен формат флага: special=1/0 вместо is_special="true"/"false"
- Добавлен тестовый скрипт test_is_special.py для отладки API

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 00:04:35 +03:00
74d7d1186a fix(recommerce): сброс зачеркнутой цены через price_old=0
- Передаем price_old[amount]="0" для сброса старой цены
- Добавлены флаги is_new и is_popular в маппер
- Добавлен debug логгер для отладки типов данных

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 23:26:29 +03:00
707b45b16d feat: добавлена интеграция синхронизации с Recommerce 2026-01-12 21:45:31 +03:00
a5ab216934 feat(integrations): добавлена полная интеграция с Recommerce
Реализован клиент для работы с API Recommerce, включая:
- Клиент с методами для работы с товарами и заказами
- Сервисный слой для высокоуровневых операций
- Мапперы данных между форматами
- Обработку исключений

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 17:56:53 +03:00
9fceab9de1 feat(integrations): реализованы методы работы с API Recommerce
Добавлены методы для управления категориями и товарами (CRUD), а также
получение списка заказов с поддержкой пагинации и фильтрации.
2026-01-12 03:51:08 +03:00
b1b56fbb2e feat(integrations): добавлена проверка соединения для Recommerce
- Добавлен endpoint /test/<integration_id>/ для тестирования соединений
- RecommerceService упрощён под реальное API (x-auth-token + store_url)
- Кнопка "Проверить подключение" в UI с обработкой статусов
- Миграция для удаления IntegrationConfig и обновления полей

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 00:57:35 +03:00
37394121e1 feat(integrations): архитектура включения/выключения интеграций
- Удалена лишняя модель IntegrationConfig из system_settings
- Singleton-паттерн: одна запись на интеграцию с is_active тумблером
- Добавлено шифрование токенов (EncryptedCharField с Fernet AES-128)
- UI: тумблеры слева, форма настроек справа
- API endpoints: toggle, settings, form_data
- Модель Recommerce: store_url + api_token (x-auth-token)
- Модель WooCommerce: store_url + consumer_key/secret

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 00:29:04 +03:00
4629369823 feat(integrations): добавлена заготовка интеграции Recommerce
- Создана структура marketplaces/ для маркетплейсов
- Модели: MarketplaceIntegration, WooCommerceIntegration, RecommerceIntegration
- Сервисы: MarketplaceService, WooCommerceService, RecommerceService
- RecommerceService содержит методы для работы с API:
  - test_connection(), sync(), fetch_products()
  - push_product(), update_stock(), update_price()
- IntegrationConfig обновлён с новой интеграцией

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 23:19:42 +03:00
4450e34497 feat(integrations): добавлен фундамент для интеграций с внешними сервисами
- Создано приложение integrations с базовой архитектурой
- BaseIntegration (абстрактная модель) для всех интеграций
- BaseIntegrationService (абстрактный сервисный класс)
- IntegrationConfig модель для тумблеров в system_settings
- Добавлена вкладка "Интеграции" в системные настройки
- Заготовка UI с тумблерами для включения интеграций

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 23:02:42 +03:00
b562eabcaf refactor(admin): удален избыточный admin_access_middleware
- Удален TenantAdminAccessMiddleware (избыточен — Django Admin уже проверяет is_staff)
- CustomUser.create_superuser теперь устанавливает is_staff=False (нет доступа к /admin/)
- PlatformAdmin с is_staff=True сохраняет доступ к админке
- Обновлен комментарий в onboarding.py

Доступ к /admin/ теперь контролируется стандартным механизмом Django Admin
через has_permission() + существующие authentication backends.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 22:00:14 +03:00
a1e81b97bf Update Celery configuration and add customer tasks 2026-01-11 20:59:35 +03:00
2369cfc997 feat(ui): улучшения UX для промокодов и форм заказа
- Добавлена кнопка копирования промокода в клипборд с визуальной обратной связью
- Улучшено отображение ошибок валидации в форме заказа (is-invalid класс)
- Добавлен флаг _draftFieldsFilled для корректной обработки пустого черновика
- Убран value="1" для quantity чтобы избежать конфликтов с draft-data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 19:07:19 +03:00
ed4d509a4e Оптимизация N+1 запросов к ролям пользователей через select_related в middleware 2026-01-11 14:19:28 +03:00
c070e42cab feat(discounts, orders): рефакторинг системы скидок - единый источник правды
- Добавлен combine_mode в форму создания/редактирования скидок
- Добавлена колонка "Объединение" в список скидок с иконками
- Добавлен фильтр по режиму объединения скидок
- Добавлена валидация: только одна exclusive скидка на заказ
- Удалены дублирующие поля из Order и OrderItem:
  - applied_discount, applied_promo_code, discount_amount
- Скидки теперь хранятся только в DiscountApplication
- Добавлены свойства для обратной совместимости

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 13:46:02 +03:00
cd758a0645 feat(user_roles): обновлены choices для поля code в модели Role 2026-01-11 13:02:50 +03:00
f57e639dbe feat(discounts): добавлено комбинирование скидок по режимам
Добавлено поле combine_mode с тремя режимами:
- stack - складывать с другими скидками
- max_only - применять только максимальную
- exclusive - отменяет все остальные скидки

Изменения:
- Модель Discount: добавлено поле combine_mode
- Calculator: новый класс DiscountCombiner, методы возвращают списки скидок
- Applier: создание нескольких DiscountApplication записей
- Admin: отображение combine_mode с иконками
- POS API: возвращает списки применённых скидок
- POS UI: отображение нескольких скидок с иконками режимов

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 12:56:38 +03:00
293f3b58cb fix(pos): добавлено предупреждение при частичной оплате
При выборе способа оплаты \"Одним способом\" и вводе суммы меньше
полной стоимости заказа теперь показывается подтверждение с
предложением вернуться и выбрать смешанную оплату.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 02:21:15 +03:00
42d8c34e8c feat(pos): добавлен полноценный интерфейс скидок в модальное окно продажи
- Добавлен API endpoint /pos/api/discounts/available/ для получения списка доступных скидок
- Добавлен метод DiscountApplier.apply_manual_discount() для применения ручных скидок
- Обновлен POS checkout для обработки manual_discount_id
- Расширена секция скидок в модальном окне:
  * Отображение автоматических скидок (read-only)
  * Dropdown для выбора скидки вручную
  * Подробная детализация: подитог, общая скидка, скидки на позиции
  * Поле промокода с иконкой
- Увеличен размер модального окна и изменено соотношение колонок (5/7)
- Убрана вертикальная прокрутка из модального окна

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 01:59:43 +03:00
6313b8f6e7 fix(pos): исправлена проблема с CSRF токеном при API запросах
- Заменен getCookie('csrftoken') на getCsrfToken() во всех fetch запросах
  (checkAutoDiscounts, applyPromoCode, handleCheckoutSubmit и др.)
- Это исправляет ошибку 403 Forbidden, возникающую из-за CSRF_USE_SESSIONS=True

fix(discounts): исправлен фильтр товаров в CRUD скидок

- Изменен фильтр с is_active=True на status='active' для корректной
  работы с моделью Product

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 01:41:17 +03:00
b48e6c810d feat(discounts): добавлен CRUD интерфейс для скидок в настройках
- Добавлена вкладка "Скидки" в страницу настроек
- Созданы views для управления скидками и промокодами с проверкой прав:
  * owner/manager/superuser - полный CRUD
  * florist - только просмотр
  * courier - нет доступа
- Созданы шаблоны: список скидок, форма, подтверждение удаления
- Созданы шаблоны: список промокодов, форма, подтверждение удаления
- Добавлены фильтры по типу, области действия, активности
- Добавлена пагинация

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 01:19:26 +03:00
f50b47736d feat(orders): добавлено отображение скидок в админке заказов
- Добавлен DiscountApplicationInline для просмотра истории скидок на странице заказа
- OrderAdmin: добавлены колонки subtotal_display и discount_display
- OrderAdmin: добавлен фильтр по applied_discount
- OrderAdmin: добавлена секция "Скидки" в fieldsets
- OrderItemInline: добавлено отображение скидки в inline
- OrderItemAdmin: добавлена колонка и фильтр по скидкам

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 00:43:26 +03:00
6978f4e59f feat(pos): интеграция системы скидок в POS терминал
API endpoints:
- POST /api/discounts/validate-promo/: валидация промокода
- POST /api/discounts/calculate/: расчёт скидок для корзины

Обновлён pos_checkout:
- добавлен параметр promo_code в payload
- автоматическое применение скидок к заказу

UI (terminal.html):
- секция скидок в модальном окне оплаты
- поле ввода промокода
- отображение автоматических скидок
- кнопки применения/удаления промокода

JavaScript (terminal.js):
- переменные состояния скидок
- функции applyPromoCode, removePromoCode
- checkAutoDiscounts: проверка автоматических скидок
- updateCheckoutTotalWithDiscounts: пересчёт итога
- обработчики кнопок промокода

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 00:30:55 +03:00
9960590dcc feat(orders): добавлены поля скидок в Order и OrderItem
Интеграция системы скидок с моделями заказов:

Order:
- applied_discount: ForeignKey на Discount
- discount_amount: сумма скидки на заказ
- applied_promo_code: использованный промокод
- calculate_total(): обновлён с учётом скидки

OrderItem:
- applied_discount: ForeignKey на Discount
- discount_amount: сумма скидки на позицию
- get_total_price(): обновлён с учётом скидки

Миграция:
- 0003_order_applied_discount... добавляет новые поля

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 00:30:34 +03:00
241625eba7 feat(discounts): добавлено приложение скидок
Создано новое Django приложение для управления скидками:

Модели:
- BaseDiscount: абстрактный базовый класс с общими полями
- Discount: основная модель скидки (процент/фикс, на заказ/товар/категорию)
- PromoCode: промокоды для активации скидок
- DiscountApplication: история применения скидок

Сервисы:
- DiscountCalculator: расчёт скидок для корзины и заказов
- DiscountApplier: применение скидок к заказам (атомарно)
- DiscountValidator: валидация промокодов и условий

Админ-панель:
- DiscountAdmin: управление скидками
- PromoCodeAdmin: управление промокодами
- DiscountApplicationAdmin: история применения (только чтение)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 00:30:14 +03:00
27cb9ba09d fix signals 2026-01-10 23:43:19 +03:00
4ea01b8269 fix(inventory, orders, pos): удалена зависимость от django-simple-history для tenant-моделей
- Добавлен pre_save сигнал для Order вместо django-simple-history
- Переписаны все функции signals.py без использования instance.history
- Заменены .username на .name|default:.email для CustomUser в шаблонах
- Исправлен CSRF-токен в POS для работы с CSRF_USE_SESSIONS=True

Теперь создание заказов работает корректно в мультитенантной архитектуре.
2026-01-10 17:21:00 +03:00
8f3c90c11a fix(inventory): enforce consistent date format in document forms and views
- Add explicit date input format '%Y-%m-%d' to WriteOffDocumentForm and IncomingDocumentForm
- Disable localization for date fields to ensure yyyy-MM-dd format is used
- Set initial date value to current date in WriteOffDocumentCreateView's get_initial method
- Restrict warehouse queryset to active warehouses in forms initialization
- Improve date widget consistency by adding format parameter to DateInput widgets
2026-01-10 11:45:25 +03:00
5f565555e3 fix(products): improve bulk category modal behavior and initialization
- Move default date initialization from form to view initial data
- Add checks for DOM elements existence before event listener attachment
- Handle 'clear' mode in bulk category modal with confirmation and API call
- Improve CSRF token usage and error handling during bulk update requests
- Remove deprecated handleClearAll function and integrate logic into handleApply
- Reset modal state properly including input fields and radio button modes
- Update modal JS file version reference in products list template
2026-01-10 11:41:37 +03:00
0d6d62d1ad fix(products): improve bulk category modal and batch selection handling
- Add null check for selectAllCheckbox to avoid errors in batch-selection.js
- Replace clear existing categories toggle with radio buttons for add, replace, and clear modes
- Disable category search input and fade category list when 'clear' mode is selected
- Update mode hint text dynamically based on selected mode with explanatory messages
- Enable apply button when 'clear' mode is selected regardless of category selection
- Remove clear all categories button from modal footer
- Add event listeners for mode radio buttons to update UI and error states on change
- Initialize mode UI and apply button state on modal setup
- Bump static JS files versions for batch-selection and bulk-category-modal to 1.2 and 1.4 respectively
2026-01-10 00:47:42 +03:00
b63162b1cb Рефакторинг: убрана зависимость от Django Groups/Permissions для CustomUser
- CustomUser теперь наследуется от AbstractBaseUser (вместо AbstractUser)
- Удалены поля groups и user_permissions из CustomUser
- Все authentication backends (TenantUserBackend, PlatformAdminBackend, RoleBasedPermissionBackend) больше НЕ наследуются от ModelBackend
- Добавлены методы has_perm() и has_module_perms() в CustomUser для делегирования проверки прав кастомным backends
- Полная изоляция: CustomUser использует только систему ролей (UserRole), PlatformAdmin использует только is_superuser
- Удалён весь старый код, связанный с Django permissions
- Нет обратной совместимости (не требуется)
- Чистая архитектура для multi-tenant приложения
2026-01-10 00:10:25 +03:00
d90b0162c5 fix: Исправлена вторая ошибка - отключен ModelBackend для CustomUser
Проблема:
После первого исправления ошибка продолжалась, но теперь в другом месте.
Django's ModelBackend пытался проверить permissions для CustomUser через
Permission.objects.filter(group__user=user_obj), что вызывало ошибку
"Cannot query 'chupa@chus.by': Must be 'PlatformAdmin' instance"

Причина:
RoleBasedPermissionBackend наследует ModelBackend, и для CustomUser
все равно вызывался super().has_perm(), который обращался к Django
Permission таблице в public schema, ожидая PlatformAdmin.

Решение:
Полностью отключен вызов super().has_perm() и super().has_module_perms()
для CustomUser. Теперь для CustomUser используется только role-based
permission checking, а для PlatformAdmin - стандартный ModelBackend.

Изменения в user_roles/auth_backend.py:
- has_perm(): добавлена ветка if is_tenant, которая полностью обрабатывает
  CustomUser без вызова super()
- has_module_perms(): аналогичная логика
- Для PlatformAdmin сохранена проверка через super() (ModelBackend)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 23:50:19 +03:00
71ca681073 fix: Исправлена ошибка ForeignKey в products - замена PlatformAdmin на CustomUser
Устранена ошибка ValueError "Cannot query 'email': Must be 'PlatformAdmin' instance"
при доступе CustomUser к странице /products/.

Проблема:
- Модели products (TENANT_APPS) использовали get_user_model() для ForeignKey
- get_user_model() возвращал PlatformAdmin (AUTH_USER_MODEL)
- Но tenant модели должны ссылаться на CustomUser (tenant пользователей)
- Это создавало конфликт типов при запросах от CustomUser

Изменения:

1. products/models/base.py:
   - Убран get_user_model()
   - BaseProductEntity.archived_by теперь ForeignKey('accounts.CustomUser')

2. products/models/categories.py:
   - Убран get_user_model()
   - ProductCategory.deleted_by теперь ForeignKey('accounts.CustomUser')

3. products/models/import_job.py:
   - Убран get_user_model()
   - ProductImportJob.user теперь ForeignKey('accounts.CustomUser')

4. Создана миграция 0002 с data migration:
   - Очистка некорректных ссылок (установка NULL)
   - Изменение типа ForeignKey полей с PlatformAdmin на CustomUser

5. user_roles/auth_backend.py:
   - Добавлена функция _is_tenant_user() для проверки типа пользователя
   - Исправлена логика has_perm() и has_module_perms()
   - CustomUser теперь не проверяется через ModelBackend.has_perm()

6. admin_access_middleware.py:
   - Улучшены сообщения об ошибках доступа
   - Добавлен рендеринг через шаблон access_denied.html

7. templates/errors/access_denied.html:
   - Новый шаблон для красивого отображения ошибок доступа

Результат:
- CustomUser может без ошибок работать со страницей /products/
- Корректная архитектура: tenant модели ссылаются на tenant пользователей
- PlatformAdmin продолжает работать корректно
- Чистое решение без костылей

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 23:47:07 +03:00
256606f2a0 chore: Реорганизация проекта - очистка и структурирование файлов
- Добавлена папка ДОКУМЕНТАЦИЯ с централизованным хранением всех руководств
- Перенесены утилитарные скрипты в myproject/scripts/
- Удалены временные файлы (current_settings.txt, old_settings.txt, nul)
- Добавлены celerybeat-schedule файлы в .gitignore
- Обновлен .env.example (удалены устаревшие настройки PLATFORM_SUPPORT)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 05:50:42 +03:00