fomichev [Wed, 3 Jun 2026 06:50:03 +0000 (09:50 +0300)]
ERP-396: убрать индексы из миграций store_type/city_store_params, добавить идемпотентность
Таблицы небольшие — индексы не дают выигрыша.
Проверка существования колонки в safeUp/safeDown предотвращает
падение при повторных накатах и откатах миграций.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fomichev [Tue, 2 Jun 2026 14:53:16 +0000 (17:53 +0300)]
ERP-389: блок Каналы (ассортиментные лейблы) в управлении магазином
- StoreDynamic: константа CATEGORY_ASSORTMENT_LABELS = 5
- CityStoreManagementController: загрузка/сохранение лейблов через
StoreDynamic category 5 (value_string = "1,3,7"); recordStoreDynamicStr();
save(true, $validateFields) вместо полной валидации — фикс ошибки
required для null SEO-полей при сохранении с Операционного таба
- JS: панель Каналы в renderOps(), теги в renderHero(), модал выбора,
openCombo() показывает полный список без фильтра по текущему тексту
- CSS: стили lbl-tag, tag-add, btn-panel-link, lbl-modal-*, hero-labels
- index.php: модальное окно + URL assortmentLabels
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fomichev [Tue, 2 Jun 2026 13:22:44 +0000 (16:22 +0300)]
ERP-389: is_active в city_store_params + новый интерфейс управления магазином
- Разделены поля visible (CityStore) и is_active (CityStoreParams):
visible больше не меняется при смене is_active
- Неактивные магазины остаются в списке /city-store-params с оранжевым фоном
- Добавлены константы категорий в StoreDynamic (CATEGORY_IS_ACTIVE=4 и др.)
- История активности: изменение is_active записывается в store_dynamic (category=4)
- Новый интерфейс /city-store-management на основе мокапа v8:
4 вкладки (Карточка, Операционное, SEO, Сервисная), комбобокс выбора магазина,
AJAX-сохранение, dirty-tracking, RBAC на вкладку Сервисная (Директор + IT)
- Миграции: store_type.code (slug) и city_store_params.is_active
- StoreService зарегистрирован как singleton в DI-контейнере
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
deploy: рестарт yii-queue воркеров после reload php-fpm
Воркеры yii queue/listen читают .env один раз при старте и кэшируют
vendor/autoload в памяти. Без принудительного рестарта они продолжают
работать с прежними токенами/кодом задач — и любое изменение в .env
или коде джоб до них не доедет.
Инцидент 2026-05-07: после ротации TELEGRAM_BOT_TOKEN_PROD в @BotFather
воркеры с uptime 68 дней (last restart Feb27) продолжали слать с
отозванным токеном, выдавая 401 Unauthorized — ERP молча терял все
уведомления клиентам с 21.04 по 07.05.
Дополнительно убиваются orphan-процессы yii queue/listen с PPID=1:
такие появляются, если supervisor когда-то рестартовали без graceful
stop детей — supervisorctl restart их НЕ трогает, а они продолжают
слушать очередь со старым окружением. На erpp 2026-05-07 жили ровно
10 таких orphan'ов от Feb27 параллельно с новыми воркерами.
fix(ERP-372): синхронизировать фильтры getSalesCountSum с getSalesSum
На дашборде /dashboard/sales для магазинов с большой долей доставки
(например, 07 Аэродромная 28) средний чек расходился с суммой продаж:
avg = sum_count_query / cnt_count_query, при этом колонка «сумма продаж»
показывала результат другого запроса (getSalesSum) с более узким
фильтром.
Привожу getSalesCountSum к тем же условиям:
- LEFT JOIN sales sc ON sc.id = s.sales_check
- sc.order_id IS NULL OR IN ('','0') — отбрасываем строки, привязанные
через sales_check к доставочной продаже;
- s.marketplace_order_id IS NULL OR ='' — отбрасываем продажи маркетплейсов.
После фикса avg = sum / cnt совпадает с тем, что выводится в колонке
«сумма продаж».
Тесты (9/9 GREEN): unit на структуру SQL и биндинг параметров +
интеграционные на реальной БД (insert/rollback в транзакции),
проверяющие исключение маркетплейс- и доставочно-связанных продаж.
test(ERP-372): добавить тесты для getSalesCountSum
Unit-тесты на SQL-структуру, биндинг параметров, payType-ветку
и пустой результат. Интеграционный тест на реальной БД проверяет,
что метод исключает маркетплейс-продажи и записи, связанные через
sales_check с доставкой. На текущем (нефиксенном) коде воспроизводят
баг — RED-состояние перед применением правки.
fix(task_22): расширить окно выборки админов с 1 до 4 месяцев
Сотрудники с пустым guid выпадали из синхронизации с 1С после месяца —
расширяем окно date_add до 4 месяцев. Добавлена документация по каналу
ERP→1С create_employee (pull через API2 DataController::actionRequest).
Реализован CRUD справочника поставщиков с модальными окнами (AJAX),
GridView + PJAX и каскадной деактивацией связанных записей.
Компоненты:
- Supplier (AR модель с TimestampBehavior + BlameableBehavior)
- SupplierSearch (search модель без пагинации)
- SupplierController (AJAX CRUD, наследует BaseController)
- views/supplier/index.php (GridView + модалка + JS)
- views/supplier/_form.php (форма для модалки)
- BuyerReferenceController + view (контейнер с табами)
Бейджи типа и статуса — по UI-guideline из spec-supplier-reference.html.
Валидация: name unique varchar(200), lead_time >= 0, type/currency enum.
Soft delete через is_active=false с каскадом на markings и product_mappings.
Write-операции обёрнуты в DB-транзакции.
Артефакты workflow: docs/jira/ERP-318/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>