]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Фикс по js
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 17 Apr 2026 09:23:38 +0000 (12:23 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 17 Apr 2026 09:23:38 +0000 (12:23 +0300)
docs/jira/ERP-300J/test-plan.md [new file with mode: 0644]
erp24/views/buyer-reference/index.php
erp24/views/product-mapping/index.php
erp24/web/js/product-mapping/index.js

diff --git a/docs/jira/ERP-300J/test-plan.md b/docs/jira/ERP-300J/test-plan.md
new file mode 100644 (file)
index 0000000..d7c6ccd
--- /dev/null
@@ -0,0 +1,389 @@
+План ручного тестирования — ERP-300J / Справочник закупщика
+
+Ветка: feature_fomichev_ERP-300J_suppliers_dict                                                                                                                                                                         
+Разделы: Поставщики · Производители + Плантации · Маркировка · Маппинг товаров
+                                                                                                                                                                                                                          
+---                                                                                                                                                                                                                     
+0. Предусловия
+
+- Миграции применены: m260408_* (5 таблиц) + m260408_100500_* (junction) + m260409_120000_* (RBAC)
+- Пользователь авторизован и имеет права на раздел buyer-reference
+- Есть тестовые данные в products_1c_nomenclature (несколько товаров с category/subcategory/species)
+
+  ---                                                                                                                                                                                                                     
+1. Главная страница — 4 вкладки
+
+┌─────┬───────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┐                                                                     
+│  #  │            Действие            │                                            Ожидаемый результат                                            │
+├─────┼────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤                                                                  
+│ 1.1 │ Открыть /buyer-reference       │ Страница загружается, видны 4 таба: Поставщики / Производители и плантации / Маркировка / Маппинг товаров │                                                                    
+├─────┼────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
+│ 1.2 │ Переключаться между вкладками  │ Каждая вкладка подгружает контент без перезагрузки страницы                                               │                                                                    
+├─────┼────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤                                                                  
+│ 1.3 │ Обновить страницу на вкладке N │ Активная вкладка остаётся активной (если сохраняется в URL-хэше)                                          │                                                                    
+└─────┴────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+                                                                                                                                                                                                                          
+---                                                                                                                                                                                                                     
+2. Вкладка «Поставщики»
+
+2.1 Создание
+
+┌───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────┐                                          
+│   #   │                                                 Действие                                                  │                 Ожидаемый результат                  │                                            
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤
+│ 2.1.1 │ Нажать «Добавить поставщика», заполнить все поля корректно (name, тип, валюта, срок поставки) → Сохранить │ Запись появляется в таблице, тост «Поставщик создан» │                                            
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤
+│ 2.1.2 │ Создать поставщика с существующим именем                                                                  │ Ошибка: «Поставщик уже существует»                   │
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤                                          
+│ 2.1.3 │ Отправить форму с пустым именем                                                                           │ Ошибка валидации на поле name                        │                                            
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤                                            
+│ 2.1.4 │ Ввести lead_time_days = -1                                                                                │ Ошибка: «Срок поставки должен быть >= 0»             │                                            
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤                                            
+│ 2.1.5 │ Проверить дропдауны Тип (2 опции) и Валюта (3 опции)                                                      │ Варианты: local/international; RUB/EUR/USD           │                                          
+└───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────┘
+
+2.2 Редактирование
+
+┌───────┬───────────────────────────────────────────────────┬─────────────────────────────────────────────┐                                                                                                             
+│   #   │                         Действие                          │             Ожидаемый результат             │
+├───────┼───────────────────────────────────────────────────────────┼─────────────────────────────────────────────┤
+│ 2.2.1 │ Нажать «Редактировать» на существующем поставщике         │ Модалка открывается с заполненными данными  │
+├───────┼───────────────────────────────────────────────────────────┼─────────────────────────────────────────────┤
+│ 2.2.2 │ Изменить name → Сохранить                                 │ Таблица обновляется, новое имя отображается │
+├───────┼───────────────────────────────────────────────────────────┼─────────────────────────────────────────────┤                                                                                                   
+│ 2.2.3 │ Попытаться сохранить имя другого существующего поставщика │ Ошибка уникальности                         │                                                                                                     
+└───────┴───────────────────────────────────────────────────────────┴─────────────────────────────────────────────┘
+
+2.3 Деактивация (soft delete + каскад)
+
+┌───────┬─────────────────────────────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────┐                                                    
+│   #   │                                        Действие                                         │                          Ожидаемый результат                           │
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
+│ 2.3.1 │ Деактивировать поставщика без связанных маркировок и маппингов                          │ Тост: «деактивирован. Связанных записей: маркировки — 0, маппинги — 0» │
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
+│ 2.3.2 │ Деактивировать поставщика у которого есть активные маркировки (создать заранее)         │ Тост с корректным счётчиком: «маркировки — N»                          │
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤                                          
+│ 2.3.3 │ Проверить в БД / вкладке «Маркировка», что связанные маркировки стали is_active = false │ Маркировки деактивированы                                              │                                            
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤                                            
+│ 2.3.4 │ Деактивировать уже неактивного поставщика                                               │ Ошибка: «Поставщик уже деактивирован»                                  │                                            
+└───────┴─────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────┘
+
+2.4 Фильтрация
+
+┌───────┬────────────────────────────────────────┬────────────────────────────────────────────┐                                                                                                                         
+│   #   │                Действие                │            Ожидаемый результат             │              
+├───────┼────────────────────────────────────────┼────────────────────────────────────────────┤                                                                                                                         
+│ 2.4.1 │ Ввести текст в поле поиска по name     │ Таблица фильтруется                        │              
+├───────┼────────────────────────────────────────┼────────────────────────────────────────────┤
+│ 2.4.2 │ Фильтр по типу (local / international) │ Показываются только соответствующие записи │
+└───────┴────────────────────────────────────────┴────────────────────────────────────────────┘
+                                                                                                                                                                                                                          
+---                             
+3. Вкладка «Производители и плантации»
+
+3.1 Производители — Создание / Редактирование
+
+┌───────┬──────────────────────────────────────────────┬──────────────────────────────────────────────────────────┐
+│   #   │                   Действие                   │                   Ожидаемый результат                    │
+├───────┼──────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
+│ 3.1.1 │ Создать производителя с уникальным именем    │ Запись в таблице, тост «Производитель создан»            │
+├───────┼──────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
+│ 3.1.2 │ Создать производителя с дублирующимся именем │ Ошибка: «Производитель с таким названием уже существует» │
+├───────┼──────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
+│ 3.1.3 │ Отредактировать имя                          │ Таблица обновляется                                      │                                                                                                   
+└───────┴──────────────────────────────────────────────┴──────────────────────────────────────────────────────────┘
+
+3.2 Производители — Деактивация (блокировка)
+
+┌───────┬───────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────┐                                                  
+│   #   │                              Действие                               │                                        Ожидаемый результат                                         │
+├───────┼─────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────┤
+│ 3.2.1 │ Деактивировать производителя без активных маркировок                │ Тост с количеством деактивированных плантаций                                                      │                                  
+├───────┼─────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────┤                                    
+│ 3.2.2 │ Деактивировать производителя с активными маркировками               │ Ошибка: «Нельзя деактивировать производителя: есть активные маркировки. Сначала деактивируйте их.» │
+├───────┼─────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────┤                                    
+│ 3.2.3 │ В БД проверить, что плантации производителя стали is_active = false │ Каскад сработал корректно                                                                          │                                    
+└───────┴─────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────┘
+
+3.3 Плантации
+
+┌───────┬────────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────┐                                                                                     
+│   #   │                          Действие                          │                    Ожидаемый результат                     │
+├───────┼────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
+│ 3.3.1 │ Создать плантацию через кнопку «Добавить плантацию»        │ В форме доступен выпадающий список активных производителей │                                                                                   
+├───────┼────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤                                                                                     
+│ 3.3.2 │ Создать плантацию через кнопку «+» на строке производителя │ Поле producer_id предзаполнено                             │
+├───────┼────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤                                                                                     
+│ 3.3.3 │ Редактировать плантацию                                    │ Данные сохраняются                                         │                                                                                     
+├───────┼────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤                                                                                     
+│ 3.3.4 │ Деактивировать плантацию без связанных маркировок          │ Тост «Плантация деактивирована»                            │                                                                                     
+├───────┼────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤                                                                                     
+│ 3.3.5 │ Деактивировать уже неактивную плантацию                    │ Ошибка: «Плантация уже деактивирована»                     │                                                                                   
+└───────┴────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘
+                                  
+---                                                                                                                                                                                                                     
+4. Вкладка «Маркировка»
+
+4.1 Создание
+
+┌───────┬───────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────┐
+│   #   │                         Действие                          │                       Ожидаемый результат                        │
+├───────┼───────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
+│ 4.1.1 │ Создать маркировку с корректным кодом (напр. SCH-RP-RN50) │ Запись создана                                                   │
+├───────┼───────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
+│ 4.1.2 │ Ввести код строчными буквами (напр. sch-rp)               │ Код сохраняется в верхнем регистре (SCH-RP) благодаря strtoupper │
+├───────┼───────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤                                                                              
+│ 4.1.3 │ Ввести код с недопустимым символом (напр. SCH_RP)         │ Ошибка: «Код: 3-12 символов, только A-Z, 0-9 и дефис»            │                                                                                
+├───────┼───────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤                                                                                
+│ 4.1.4 │ Ввести код короче 3 символов (напр. AB)                                                                │ Ошибка валидации                                                 │                                   
+├───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤                                   
+│ 4.1.5 │ Ввести код длиннее 12 символов                                                                         │ Ошибка валидации                                                 │                                 
+├───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤                                   
+│ 4.1.6 │ Создать маркировку с дублирующимся кодом                                                               │ Ошибка: «Маркировка с таким кодом уже существует»                │                                 
+├───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤                                   
+│ 4.1.7 │ Создать маркировку с такой же комбинацией (producer_id + plantation_id + product_name) при другом коде │ Ошибка уникального индекса                                       │                                 
+├───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤                                   
+│ 4.1.8 │ Выбрать производителя — проверить, что в дропдауне «Плантация» появились только его плантации          │ Каскадный AJAX-запрос /marking/plantations-by-producer работает  │                                 
+└───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘
+
+4.2 Деактивация (блокировка)
+
+┌───────┬─────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┐                                                        
+│   #   │                      Действие                       │                                      Ожидаемый результат                                       │                                                      
+├───────┼─────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤                                                        
+│ 4.2.1 │ Деактивировать маркировку без привязанных маппингов │ Тост «Маркировка деактивирована»                                                               │
+├───────┼─────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤                                                        
+│ 4.2.2 │ Деактивировать маркировку с привязанными маппингами │ Ошибка: «Нельзя деактивировать маркировку: есть N привязанных маппингов. Сначала отвяжите их.» │
+└───────┴─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┘
+                                                                                                                                                                                                                          
+---                                                                                                                                                                                                                     
+5. Вкладка «Маппинг товаров»
+
+5.1 Список и пагинация
+
+┌───────┬───────────────────────────────────┬───────────────────────────────────────────────────────┐                                                                                                                 
+│   #   │             Действие              │                  Ожидаемый результат                  │                                                                                                                   
+├───────┼───────────────────────────────────┼───────────────────────────────────────────────────────┤
+│ 5.1.1 │ Открыть вкладку                   │ Отображаются карточки товаров, блок аналитики в шапке │                                                                                                                   
+├───────┼───────────────────────────────────┼───────────────────────────────────────────────────────┤        
+│ 5.1.2 │ Сменить per-page (50 / 100 / 500) │ Количество карточек на странице меняется              │
+├───────┼───────────────────────────────────┼───────────────────────────────────────────────────────┤                                                                                                                 
+│ 5.1.3 │ Перейти на страницу 2             │ Корректная пагинация, другие товары                   │                                                                                                                   
+└───────┴───────────────────────────────────┴───────────────────────────────────────────────────────┘
+
+5.2 Фильтры
+
+┌───────┬──────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────┐                                                                                             
+│   #   │                             Действие                             │             Ожидаемый результат              │
+├───────┼──────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────┤                                                                                             
+│ 5.2.1 │ Выбрать категорию → дропдаун «Подкатегория» заполняется (каскад) │ AJAX-запрос /product-mapping/cascade-filters                    │
+├───────┼──────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
+│ 5.2.2 │ Выбрать подкатегорию → дропдаун «Вид» заполняется                │ Каскад второго уровня                                                   │
+├───────┼──────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤                                                                
+│ 5.2.3 │ Ввести текст в поиск → применить фильтр                          │ Показываются только товары, содержащие текст                            │                                                                  
+├───────┼──────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤                                                                  
+│ 5.2.4 │ Фильтр по поставщику                                             │ Показываются только товары с маппингом на выбранного поставщика         │                                                                  
+├───────┼──────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤                                                                  
+│ 5.2.5 │ Фильтр по маркировке                                             │ Показываются только товары с маппингом, содержащим выбранную маркировку │                                                                
+├───────┼──────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤                                                                  
+│ 5.2.6 │ Фильтр «Только без маппинга»                                     │ Показываются только товары без записей в product_mappings               │                                                                
+├───────┼──────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤                                                                  
+│ 5.2.7 │ Комбинация 2+ фильтров                                           │ Результат пересечения условий                                           │
+├───────┼──────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤                                                                  
+│ 5.2.8 │ Сбросить фильтры                                                 │ Показываются все товары                                                 │                                                                
+└───────┴──────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────┘
+
+5.3 Аналитика
+
+┌───────┬─────────────────────────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────┐                                                        
+│   #   │                                  Действие                                   │                          Ожидаемый результат                           │
+├───────┼─────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤                                                        
+│ 5.3.1 │ Применить фильтр                                                            │ Блок аналитики пересчитывается через AJAX (/product-mapping/analytics) │
+├───────┼─────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
+│ 5.3.2 │ Проверить корректность % (with_supplier, single_supplier, without_producer) │ Значения математически согласованы с данными таблицы                   │
+└───────┴─────────────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────┘
+
+5.4 Создание маппинга
+
+┌───────┬────────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────┐                                                                   
+│   #   │                                          Действие                                          │             Ожидаемый результат              │                                                                 
+├───────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────┤                                                                   
+│ 5.4.1 │ Нажать «+» на карточке товара → заполнить форму (поставщик, название, квант=1) → Сохранить │ Маппинг появляется в таблице внутри карточки │
+├───────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────┤                                                                   
+│ 5.4.2 │ Указать квант = 0                                                                             │ Ошибка: «Кратность должна быть >= 1»         │
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────┤                                                              
+│ 5.4.3 │ Не заполнить «Название у поставщика»                                                          │ Ошибка обязательного поля                    │                                                                
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────┤                                                                
+│ 5.4.4 │ Создать дублирующий маппинг (тот же товар + поставщик + без плантации)                        │ Ошибка уникальности                                  │                                                        
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤                                                        
+│ 5.4.5 │ Создать маппинг с плантацией, создать ещё один с тем же товаром + поставщик + та же плантация │ Ошибка уникальности                                  │                                                      
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤                                                        
+│ 5.4.6 │ Создать маппинг с тем же товаром + поставщик, но разными плантациями                          │ Успешно (разные partial-unique индексы)              │                                                      
+├───────┼───────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤                                                        
+│ 5.4.7 │ Создать маппинг с несколькими маркировками (multiselect)                                      │ В БД записи в mapping_markings для всех выбранных ID │                                                      
+└───────┴───────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────┘
+
+5.5 Редактирование маппинга
+
+┌───────┬─────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────┐                                                                                        
+│   #   │                        Действие                         │                    Ожидаемый результат                     │
+├───────┼─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
+│ 5.5.1 │ Открыть форму редактирования                            │ Форма заполнена, в multiselect отмечены текущие маркировки │
+├───────┼─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤
+│ 5.5.2 │ Изменить поставщика, убрать одну маркировку → Сохранить │ Данные обновляются, в mapping_markings убрана запись       │
+├───────┼─────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤                                                                                      
+│ 5.5.3 │ Снять все маркировки → Сохранить                        │ В mapping_markings нет записей для этого mapping_id        │                                                                                        
+└───────┴─────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘
+
+5.6 Удаление маппинга
+
+┌───────┬──────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐                                                                       
+│   #   │                       Действие                       │                              Ожидаемый результат                               │
+├───────┼──────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
+│ 5.6.1 │ Удалить маппинг с привязанными маркировками          │ Маппинг удалён, записи в mapping_markings удалены каскадно (ON DELETE CASCADE) │
+├───────┼──────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
+│ 5.6.2 │ Повторный запрос на удаление уже удалённого маппинга │ 404 или ошибка «Маппинг не найден»                                             │
+└───────┴──────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
+
+5.7 Экспорт в XLSX
+
+┌───────┬─────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐                                                           
+│   #   │                                        Действие                                         │                   Ожидаемый результат                   │
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤                                                           
+│ 5.7.1 │ Нажать «Экспорт» без фильтров                                                           │ Файл product-mapping-YYYY-MM-DD_HHmmss.xlsx скачивается │
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
+│ 5.7.2 │ Открыть файл: проверить заголовки (12 столбцов), жирный + серый фон, заморозка строки 1 │ Форматирование соответствует                            │
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤                                                         
+│ 5.7.3 │ Товар без маппинга в выборке                                                            │ В файле строка с пустыми полями маппинга                │                                                           
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤                                                           
+│ 5.7.4 │ Товар с 2 маппингами → в файле 2 строки                                                 │ Разворачивание маппингов корректно                      │                                                           
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤                                                           
+│ 5.7.5 │ Экспорт с активным фильтром (напр. по поставщику)                                       │ В файле только отфильтрованные товары                   │                                                         
+├───────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤                                                           
+│ 5.7.6 │ Проверить, что temp-файл удалён после отправки                                          │ Файл в @runtime отсутствует (хук EVENT_AFTER_SEND)      │                                                         
+└───────┴─────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘
+                                                                                                                                                                                                                        
+---                                                                                                                                                                                                                     
+6. Консольная команда — ProductMappingCommand
+
+┌─────┬────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────┐
+│  #  │                                    Команда                                     │                                   Ожидаемый результат                                   │                                      
+├─────┼────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤                                    
+│ 6.1 │ php yii product-mapping/find-orphans                                           │ Выводит список маппингов без товара в 1С (или «Orphan-маппинги не найдены»)             │                                      
+├─────┼────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤
+│ 6.2 │ php yii product-mapping/delete-orphans (предварительно создать orphan вручную) │ Удаляет orphan-маппинги, выводит количество; в mapping_markings каскадно удалены записи │                                      
+└─────┴────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────┘
+                                                                                                                                                                                                                          
+---                                                                                                                                                                                                                     
+7. RBAC / Права доступа
+
+┌─────┬─────────────────────────────────────────────────────────────────────┬─────────────────────┐                                                                                                                   
+│  #  │                              Сценарий                               │  Ожидаемый результат   │                                                                                                                  
+├─────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤
+│ 7.1 │ Пользователь без прав на buyer-reference открывает /buyer-reference │ 403 или редирект       │                                                                                                                  
+├─────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤       
+│ 7.2 │ Пользователь без прав на supplier/create выполняет POST             │ 403                    │
+├─────┼─────────────────────────────────────────────────────────────────────┼────────────────────────┤                                                                                                                
+│ 7.3 │ Пользователь с правами — все действия доступны                      │ Нет лишних ограничений │                                                                                                                  
+└─────┴─────────────────────────────────────────────────────────────────────┴────────────────────────┘
+                                                                                                                                                                                                                          
+---                                                                                                                                                                                                                     
+8. Регрессия — вкладка «Бюджет» (style.css / index.js изменены)
+
+┌─────┬────────────────────────────────────────────┬───────────────────────────────────────────────────┐                                                                                                              
+│  #  │                  Действие                  │                Ожидаемый результат                │                                                                                                                
+├─────┼────────────────────────────────────────────┼───────────────────────────────────────────────────┤                                                                                                              
+│ 8.1 │ Открыть раздел «Бюджет»                    │ Страница отображается корректно, стили не сломаны │                                                                                                                
+├─────┼────────────────────────────────────────────┼───────────────────────────────────────────────────┤     
+│ 8.2 │ Интерактивные элементы бюджета (если есть) │ Работают как прежде                               │                                                                                                                
+└─────┴────────────────────────────────────────────┴───────────────────────────────────────────────────┘
+                                                                                                                                                                                                                          
+---                                                                                                                                                                                                                     
+Критические сценарии (приоритет 1)
+
+1. Каскадная деактивация поставщика → маркировки + маппинги деактивируются
+2. Блокировка деактивации производителя при наличии активных маркировок
+3. Блокировка деактивации маркировки при наличии привязанных маппингов
+4. Уникальность partial-индекса маппинга (с плантацией / без плантации)
+5. syncMarkings корректно удаляет старые связи и создаёт новые
+6. Экспорт XLSX удаляет temp-файл после отправки    
+
+
+Миграции БД
+
+erp24/migrations/m260408_100000_create_suppliers_table.php
+erp24/migrations/m260408_100100_create_producers_table.php
+erp24/migrations/m260408_100200_create_plantations_table.php
+erp24/migrations/m260408_100300_create_markings_table.php
+erp24/migrations/m260408_100400_create_product_mappings_table.php
+erp24/migrations/m260408_100500_create_mapping_markings_table.php
+erp24/migrations/m260409_120000_add_erp300_rbac_permissions.php
+
+Модели (Records)
+
+erp24/records/Supplier.php
+erp24/records/SupplierSearch.php
+erp24/records/Producer.php
+erp24/records/ProducerSearch.php
+erp24/records/Plantation.php
+erp24/records/Marking.php
+erp24/records/MarkingSearch.php
+erp24/records/ProductMapping.php
+erp24/records/MappingMarking.php
+
+Контроллеры
+
+erp24/controllers/BuyerReferenceController.php
+erp24/controllers/SupplierController.php
+erp24/controllers/ProducerController.php
+erp24/controllers/MarkingController.php
+erp24/controllers/ProductMappingController.php
+erp24/commands/ProductMappingController.php
+
+Сервисы и формы
+
+erp24/services/ProductMappingService.php
+erp24/forms/ProductMappingFilterForm.php
+
+Views
+
+erp24/views/buyer-reference/index.php
+erp24/views/supplier/index.php
+erp24/views/supplier/_form.php
+erp24/views/producer/index.php
+erp24/views/producer/_producer_form.php
+erp24/views/producer/_plantation_form.php
+erp24/views/marking/index.php
+erp24/views/marking/_form.php
+erp24/views/product-mapping/index.php
+erp24/views/product-mapping/_card.php
+erp24/views/product-mapping/_form.php
+erp24/views/product-mapping/_filters.php
+erp24/views/product-mapping/_analytics.php
+
+Frontend
+
+erp24/web/js/product-mapping/index.js
+erp24/web/js/budget/index.js
+erp24/web/css/budget/style.css
+
+Тесты
+
+erp24/tests/unit/records/SupplierTest.php
+erp24/tests/unit/records/ProducerTest.php
+erp24/tests/unit/records/PlantationTest.php
+erp24/tests/unit/records/MarkingTest.php
+erp24/tests/unit/records/ProductMappingTest.php
+erp24/tests/unit/forms/ProductMappingFilterFormTest.php
+erp24/tests/unit/services/ProductMappingServiceTest.php
+erp24/tests/unit/commands/ProductMappingCommandTest.php
+erp24/tests/unit/controllers/Erp300ControllersTest.php
+erp24/tests/unit/migrations/Erp300RbacMigrationTest.php
+
+Документация
+
+docs/jira/ERP-318/debate-log.md
+docs/jira/ERP-318/interview.md
+docs/jira/ERP-318/plan.md
+docs/jira/ERP-318/prd.md
+docs/jira/ERP-318/spec.md
index b5cd03abfc65579b25c5c9d42029be1bc7d1e0ab..6e6368c8c52805eb068c945250ab08bb0aaf5abf 100644 (file)
@@ -167,4 +167,5 @@ $js = <<<JS
 JS;
 
 $this->registerJs($js);
+$this->registerJsFile('/js/product-mapping/index.js', ['position' => \yii\web\View::POS_END]);
 ?>
index 70b27b093cbcc2cdd138d97adf38bde9f7062802..71c58820ac4d7b13391ef21b6c8c0d563f957213 100644 (file)
@@ -109,7 +109,7 @@ use yii\widgets\LinkPager;
 </div>
 
 <?php
-$this->registerJs('window.pmCfg = ' . \yii\helpers\Json::encode([
+$this->registerJs('if (typeof window.pmInit === "function") { window.pmInit(' . \yii\helpers\Json::encode([
     'urls' => [
         'createForm' => Url::to(['/product-mapping/create-form']),
         'updateForm' => Url::to(['/product-mapping/update-form']),
@@ -121,7 +121,5 @@ $this->registerJs('window.pmCfg = ' . \yii\helpers\Json::encode([
         'cascade'    => Url::to(['/product-mapping/cascade-filters']),
         'export'     => Url::to(['/product-mapping/export']),
     ],
-]) . ';');
-
-$this->registerJsFile('/js/product-mapping/index.js', ['position' => \yii\web\View::POS_END]);
+]) . '); }');
 ?>
index 099558263731657a6dbcd4cfd3f4135757eb1898..4feb775356bc5615784a97167a540331a334b74a 100644 (file)
@@ -1,6 +1,5 @@
 /* global bootstrap, yii */
-(function () {
-    var cfg = window.pmCfg;
+window.pmInit = function (cfg) {
     if (!cfg) return;
 
     // Снимаем все предыдущие обработчики этого модуля с document,
         $(this).removeClass('is-invalid');
         $(this).next('.invalid-feedback').remove();
     });
-}());
+};