- Исправлены имена полей времени (time_from/time_to вместо delivery_time_start/end)
- Поля времени сделаны необязательными (дата остается обязательной)
- Добавлен улучшенный UI с быстрыми кнопками для даты и времени
- Поля ввода расположены в один ряд, кнопки быстрого выбора ниже
- Добавлены CSS и JS файлы для улучшенного интерфейса
- Обновлена валидация: время необязательно, но если указано одно - должно быть и другое
- Удалено избыточное поле customer_is_recipient из модели Order
- Добавлено свойство @property is_customer_recipient для обратной совместимости
- Заменены радиокнопки recipient_mode на чекбокс 'Другой получатель' в форме
- Добавлено поле recipient_source для выбора между историей и новым получателем
- Обновлен AddressService.process_recipient_from_form() для работы с чекбоксом
- Обновлены шаблоны: order_form.html (чекбокс вместо радиокнопок) и order_detail.html
- Удалено customer_is_recipient из admin и demo команды
- Создана миграция для удаления поля customer_is_recipient
Логика упрощена: recipient is None = получатель = покупатель, иначе - отдельный получатель
- Добавлены свойства обратной совместимости в модель Order для доступа к полям доставки через связь delivery
- Исправлены фильтры по delivery_date в модели Customer (get_successful_orders_total)
- Исправлены фильтры в orders/filters.py для работы с delivery__delivery_date
- Добавлен select_related('delivery') в customer_detail view для оптимизации запросов
Исправляет ошибку FieldError: Cannot resolve keyword 'delivery_date' into field
- Отделена модель Delivery от Order (OneToOne связь)
- Добавлены обязательные поля delivery_date, time_from, time_to в Delivery
- Delivery обязательна при создании заказа (кроме черновиков)
- Добавлены методы calculate_total() и reset_delivery_cost() в Order
- Добавлена валидация полей доставки в OrderForm
- Исправлено создание доменов - убран порт из домена в БД
- Исправлен редирект после установки пароля (правильный формат URL)
- Исправлена ошибка NoReverseMatch в navbar для public схемы
- Удалены все старые миграции (база создается с нуля)
- Обновлены views для работы с новой моделью Delivery
Moved payment/refund form logic from order_form.html to a dedicated
unified_transaction_form.js module for better code organization.
Changes:
- Created unified_transaction_form.js with initUnifiedTransactionForm() (~233 lines)
- Dual mode: payment and refund switching
- Dynamic form action and field names
- Payment method selection with validation
- Wallet balance limits for account_balance method
- Amount constraints based on mode
- Real-time UI updates and validation
- Updated order_form.html:
- Added unified_transaction_form.js include
- Added initialization call with Django template data
- Removed inline transaction form code (~175 lines)
- Passes URLs and amounts via options
Benefits:
- Cleaner template (175 lines removed)
- Reusable transaction form logic
- Easier to test and maintain
- Configurable via options or data-attributes
- No duplication between payment/refund modes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Moved empty order items cleanup logic from order_form.html to a dedicated
order_form_cleanup.js module for better code organization.
Changes:
- Created order_form_cleanup.js with initOrderFormCleanup() function (~136 lines)
- Automatically removes empty order item forms before submit
- Handles both new and saved forms differently
- Updates TOTAL_FORMS and reindexes remaining forms
- Compatible with Django formsets
- Updated order_form.html:
- Added order_form_cleanup.js include
- Added initialization call for #order-form
- Removed inline cleanup code (~111 lines)
Benefits:
- Cleaner template (111 lines removed)
- Reusable across other formset-based forms
- Easier to test and maintain
- Consistent with other extracted modules
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Moved order item selection logic from order_form.html to select2-product-search.js
for better code reusability and maintainability.
Changes:
- Extended select2-product-search.js with initOrderItemSelect2() function (~87 lines)
- Wraps initProductSelect2 for order item context
- Handles product/kit selection and form field updates
- Manages custom price indicators
- Supports data-ajax-url attribute for URL configuration
- Updated order_form.html:
- Added data-ajax-url to order item select elements
- Removed inline initOrderItemSelect2 function (~73 lines)
- Updated dependency check to use initOrderItemSelect2
Benefits:
- No code duplication - reuses existing initProductSelect2
- Cleaner template (79 lines removed)
- Consistent with existing patterns
- Easy to maintain in one place
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extracted customer selection and creation functionality from order_form.html
to a reusable customer_select2.js module for better maintainability.
Changes:
- Created customer_select2.js (~450 lines) with IIFE pattern
- AJAX customer search with Select2 integration
- Smart parsing of email/phone/name from search input
- Modal-based customer creation with validation
- Toast notifications system
- Auto-initialization via data-attributes
- Global function exports for backward compatibility
- Updated order_form.html:
- Added CSRF meta-tag for token access
- Added data-attributes to customer select element
- Included customer_select2.js script
- Removed ~370 lines of inline JavaScript
Benefits:
- Improved code organization and readability
- Reusable across other pages requiring customer selection
- Better browser caching for static JS
- Consistent with existing select2-product-search.js pattern
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Introduced Recipient model to manage order recipients separately from customers.
- Updated Order model to link to Recipient, replacing recipient_name and recipient_phone fields.
- Enhanced OrderForm to include recipient selection modes: customer, history, and new.
- Added AJAX endpoint to fetch recipient history for customers.
- Updated admin interface to manage recipients and display recipient information in order details.
- Refactored address handling to accommodate new recipient logic.
- Improved demo order creation to include random recipients.
- Добавлены системные статусы partially_assembled и fully_assembled в order_status_service.py
- Создана management команда update_order_statuses для обновления статусов у всех тенантов
- Новые статусы интегрируются в существующую логику резервирования и списания товара
- Статусы располагаются между 'В сборке' и 'В доставке' в естественном порядке процесса
Добавлено:
- Команда clear_tenant_data для полной очистки данных тенанта без удаления схемы
* Очищает все таблицы через TRUNCATE CASCADE
* Сбрасывает ID-последовательности
* Сохраняет схему БД и запись Client
* Поддержка флага --noinput для автоматизации
- Команда init_tenant_data для инициализации системных данных тенанта
* Создаёт системного клиента (АНОНИМНЫЙ ПОКУПАТЕЛЬ для POS)
* Создаёт 8 системных статусов заказов
* Создаёт 5 системных способов оплаты
* Поддержка флага --reset для пересоздания данных
Исправлено:
- Заменены устаревшие фильтры is_active на status='active' для Product и ProductKit
* products/views/category_views.py: исправлены фильтры в build_category_tree и get_context_data
* products/services/kit_pricing.py: исправлены фильтры при получении товаров из variant_group
* products/models/kits.py: исправлен фильтр в get_available_products
* Устранена ошибка FieldError при работе со списком категорий
Улучшено:
- Команда clear_tenant_data теперь предлагает пользователю инициализировать системные данные после очистки
- Добавлена детальная информация о процессе очистки и инициализации данных
Проблема:
На странице списка заказов (order_list) при изменении статуса 'на лету':
- ValidationError показывался через alert() - страшно
- Сообщение содержало служебные элементы
- Статус всё равно менялся визуально (нет отката)
Решение Backend (views.py):
- В set_order_status добавлена обработка ValidationError ПЕРЕД ValueError
- Извлекается чистое сообщение (e.messages[0] или str(e))
- Возвращается JSON: {success: false, error: 'чистое сообщение'}
Решение Frontend (order_list.html):
- Добавлен контейнер для динамических Bootstrap alert
- Создана функция showAlert() для показа красивых alert-danger
- При ошибке:
* Показывается Bootstrap alert с иконкой
* Прокрутка к верху страницы
* Автоскрытие через 5 секунд
* Возврат select к предыдущему значению (откат визуально)
- Больше НЕТ страшных alert()
Теперь пользователь видит:
[красный Bootstrap alert вверху страницы]
⚠️ Заказ 134 был отменён, товары проданы в другом заказе.
Невозможно изменить статус. Для новой продажи создайте новый заказ.
[X]
User-friendly на обеих страницах (форма редактирования + список)!
Проблема:
ValidationError из сигналов отображался как:
'Server error: [\'Заказ 134 был отменён...\']'
со служебными элементами (Server error, квадратные скобки).
Решение:
В order_update добавлена обработка ValidationError перед ValueError:
- Извлекаем чистое сообщение из исключения (e.messages[0] или str(e))
- Показываем через messages.error() — Django автоматически отобразит
красивым Bootstrap alert-danger
- Транзакция откатывается, изменения не сохраняются
Теперь пользователь видит:
[красный Bootstrap alert]
'Заказ 134 был отменён, товары проданы в другом заказе.
Невозможно изменить статус. Для новой продажи создайте новый заказ.'
Без технических префиксов и форматирования - user-friendly.
Проблема: При переводе заказа в статус 'completed' возникала ошибка
"Не удалось создать Sale для заказа", т.к. резервы этого же заказа
блокировали списание товара.
Причина: write_off_by_fifo() считал все резервы со статусом 'reserved'
как занятые, включая резервы текущего заказа, которые ещё не были
переведены в 'converted_to_sale'.
Решение:
- Добавлен параметр exclude_order в write_off_by_fifo() для исключения
резервов конкретного заказа из расчёта занятого товара
- SaleProcessor.create_sale() теперь передаёт order в write_off_by_fifo()
- Добавлены транзакции в views для атомарности операций с заказами:
при ошибке в сигналах статус заказа откатывается вместе со всеми
связанными изменениями
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
При выборе способа оплаты сумма теперь автоматически выделяется,
позволяя пользователю сразу начать вводить новое значение без
необходимости вручную выделять текст.
Улучшение скорости ввода для оператора POS.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Полностью переработан интерфейс смешанной оплаты:
НОВЫЙ UI:
- Построчное добавление платежей с галочкой подтверждения
- Каждая строка: [Способ ▼] [Сумма] [✓] [🗑️]
- Зафиксированные платежи показываются отдельно с зеленой галочкой
- Кнопка "+ Добавить еще часть платежа" (скрывается при остатке = 0)
- Индикатор "Осталось оплатить" / "Оплачено полностью"
ФУНКЦИОНАЛЬНОСТЬ:
✅ Автоподстановка остаточной суммы при выборе способа оплаты
✅ Автофокус на поле суммы после выбора способа
✅ Inline валидация с красными подсказками под полем
✅ Проверка превышения остатка и баланса кошелька
✅ Удаление любого платежа (зафиксированного или нет)
✅ Автодобавление пустой строки при удалении всех платежей
ИЗМЕНЕНИЯ В КОДЕ:
+ Новые методы: addPaymentRow(), renderPaymentRows(), attachPaymentRowEvents()
+ Новые методы: confirmPaymentRow(), removePaymentRow(), updateRemainingHint()
~ Обновлены: render(), getTotalPayments(), validate(), submit(), attachEvents()
~ getTotalPayments() теперь учитывает только зафиксированные платежи (fixed: true)
- Удалены старые методы: addPayment(), removePayment(), updatePaymentsList(), renderPaymentsList()
SINGLE MODE остался без изменений.
Проблема решена: больше невозможно "забыть" добавить последний платеж,
так как каждый платеж фиксируется галочкой явно.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Убрано лишнее поле "Примечание" из PaymentWidget:
- Удалено HTML-поле для ввода примечания
- Убраны все обращения к notesInput в коде
- Примечания теперь передаются как пустая строка
Для POS-терминала это поле избыточно и только замедляет процесс оплаты.
Интерфейс стал проще и быстрее.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
1. Убран параметр версии ?v=4 из подключения terminal.js (для разработки не нужен)
2. Исправлена логика автоподстановки суммы в PaymentWidget:
- Теперь при выборе способа оплаты подставляется ОСТАТОЧНАЯ сумма
- Остаток = amount_due - уже добавленные платежи
- Добавлена подсказка "Осталось оплатить: X руб."
Пример:
- Заказ на 30 руб.
- Добавили платеж 10 руб. наличными
- Выбираем картой → автоматически подставится 20 руб. (а не 30!)
Это предотвращает ошибки и переплаты при смешанной оплате.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Убрана кнопка "Оплатить" внутри PaymentWidget, чтобы избежать путаницы.
Теперь есть только одна кнопка "Подтвердить продажу" внизу модального окна.
При смешанной оплате:
- Кнопка "Добавить платеж" для добавления способов оплаты
- Кнопка "Подтвердить продажу" для завершения (внизу модалки)
Это удобнее и безопаснее - пользователи не будут случайно нажимать
не ту кнопку при добавлении нескольких платежей.
Версия JS: v4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Добавлена интеграция оплаты в POS с поддержкой одиночной и смешанной оплаты,
работой с кошельком клиента и автоматическим созданием заказов.
Backend изменения:
- TransactionService: добавлены методы get_available_payment_methods() и create_multiple_payments()
для фильтрации способов оплаты и атомарного создания нескольких платежей
- POS API: новый endpoint pos_checkout() для создания заказов со статусом "Выполнен"
с обработкой платежей, освобождением блокировок и очисткой корзины
- Template tags: payment_tags.py для получения способов оплаты в шаблонах
Frontend изменения:
- PaymentWidget: переиспользуемый ES6 класс с поддержкой single/mixed режимов,
автоматической валидацией и интеграцией с кошельком клиента
- terminal.html: компактное модальное окно (70vw) с оптимизированной компоновкой,
удален функционал скидок, добавлен показ баланса кошелька
- terminal.js: динамическая загрузка PaymentWidget, интеграция с backend API,
обработка успешной оплаты и ошибок
Поддерживаемые способы оплаты: наличные, карта, онлайн, баланс счёта.
Смешанная оплата позволяет комбинировать несколько способов в одной транзакции.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Заблокировал изменение полей is_positive_end и is_negative_end для
системных статусов заказов, так как эти флаги используются в сигналах
inventory для управления резервированием и списанием товаров со склада.
Что изменено:
- OrderStatusForm: Добавлена блокировка (disabled=True) для полей
is_positive_end и is_negative_end при редактировании системных статусов
- status_form.html: Заменено информационное предупреждение на красное
с детальным описанием заблокированных полей и их влияния на систему
Почему это критично:
Эти флаги проверяются в 3 сигналах inventory/signals.py:
1. rollback_sale_on_status_change - откатывает продажи при уходе от 'completed'
2. release_reservations_on_cancellation - освобождает резервы при отмене
3. reserve_stock_on_uncancellation - резервирует при восстановлении заказа
Случайное изменение флагов может привести к:
- Неправильному освобождению резервов товара
- Двойному резервированию
- Блокировке товара навсегда
- Списанию товара для отмененных заказов
Разрешено редактировать для системных статусов: name, label, color, description
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The cleanup_draft_orders command was no longer needed in the project.
Also updated test output file with latest test results.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Создан файл orders/tests/test_payment_methods.py с комплексными тестами:
1. PaymentMethodCreationTest (6 тестов)
- Проверка создания всех 5 способов оплаты через команду
- Проверка системных флагов и активности
- Проверка правильности порядка сортировки
- Проверка идемпотентности команды
- Критический тест наличия account_balance
2. PaymentMethodMultiTenantTest (2 теста)
- Проверка изоляции данных между тенантами
- Проверка кастомных способов оплаты в разных тенантах
3. PaymentMethodTransactionTest (7 тестов)
- Проверка связи PaymentMethod.transactions
- Проверка создания транзакций
- Проверка изоляции транзакций по способам оплаты
- Проверка защиты от удаления (PROTECT)
- Критический тест использования account_balance
- Исправление бага obj.payments → obj.transactions
4. PaymentMethodOrderingTest (2 теста)
- Проверка сортировки по полю order
- Проверка что account_balance первый (order=0)
Особенности тестирования:
- Использование TenantTestCase для изоляции тенантов
- Использование TransactionTestCase для мультитенантных тестов
- Ручное создание/удаление схем для безопасности
- Проверка изоляции данных между схемами
Результат: 15 тестов, все прошли успешно ✓