Aleksey Filippov [Fri, 27 Feb 2026 21:38:15 +0000 (00:38 +0300)]
fix(ERP-245): prevent TypeError when Domru XML has single count element
When XML response contains only one count element, json_decode(json_encode($xml))
produces a flat array instead of nested, causing $arr to be a string.
Skip non-array entries to avoid "Cannot access offset of type string on string".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aleksey Filippov [Fri, 27 Feb 2026 15:06:41 +0000 (18:06 +0300)]
fix(ERP-244): fix CSRF validation error in ShiftReminderController
- Disable CSRF validation on ShiftReminderController: endpoint is
protected by session authentication (AccessControl, roles=['@']).
CSRF cookies may be absent in browsers with strict privacy settings,
causing false 400 errors for legitimate authenticated users.
- Stop retrying on 400/401/403 responses in shift-reminder.js to prevent
cascading error floods in logs when auth/validation fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aleksey Filippov [Thu, 26 Feb 2026 19:58:14 +0000 (22:58 +0300)]
fix(ERP-243): catch all exceptions in TimetableService transaction rollback
catch (Exception) only caught yii\db\Exception, missing
InvalidArgumentException from validation/upload errors. This left
orphaned timetable records with tabel=1 but no timetable_fact entry,
blocking shift reopening.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aleksey Filippov [Thu, 26 Feb 2026 18:19:45 +0000 (21:19 +0300)]
fix(ERP-242): validate XML response from Domru API before parsing
- Skip iteration on empty curl response instead of writing empty file
- Use libxml_use_internal_errors to catch invalid XML gracefully
- Auto-create log/text/ directory if missing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aleksey Filippov [Thu, 26 Feb 2026 16:43:48 +0000 (19:43 +0300)]
fix: correct bubble.png path in minified CSS
Minified CSS in web/min/ referenced ../images/png/bubble.png which
resolved to a non-existent web/images/png/ directory, causing 404.
Fixed to ../azea/assets/images/png/bubble.png where the file actually exists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aleksey Filippov [Thu, 26 Feb 2026 15:47:41 +0000 (18:47 +0300)]
fix(ERP-241): use InvalidArgumentException in TimetableService for proper error display
TimetableService threw generic \Exception which EventBehavior couldn't
handle, causing "Произошла неизвестная ошибка" in mobile app instead of
actual validation messages. Changed to InvalidArgumentException (matching
pattern used by all other api3 services) and switched from Json::encode
to firstErrors[0] for human-readable messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Filter by entity=write_offs_products_erp_video (only write-off videos, not all files)
- Add --min-age=2h param: skip files younger than 2h (queue still processing)
- Reduce default --days from 10 to 2 (cron safety net for queue failures)
- Fix PHP hanging: switch from exec/system to proc_open with /dev/null pipes
- Fix timeout: raise from 600s to 1800s for large files
- Update actionStatus: show write-off video stats only (MOV+AVI / MP4)
- Update WriteOffsErp: change border date from -2 month to -1 month
- Add WriteOffsAttachmentsController: sync border_date comment
- Add erp24/docs/diagrams/convert-video-controller.html
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aleksey Filippov [Fri, 20 Feb 2026 13:47:30 +0000 (16:47 +0300)]
feat(BR-132): add is_promo_balance flag to promocode
Boolean field to distinguish promo codes that credit separate promo
balance vs regular bonuses. Propagated to child codes on generation
and bulk update. UI toggle added to edit form.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aleksey Filippov [Fri, 20 Feb 2026 13:33:10 +0000 (16:33 +0300)]
feat(BR-132): add alphanumeric promo code format PROMO-XXXX-XXXX
Add format switcher for promo code generation: legacy digits (CODE123)
and new alphanumeric (CODE-XXXX-XXXX) without confusing chars (0/O/1/l/I).
Expand code column from VARCHAR(13) to VARCHAR(20).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aleksey Filippov [Thu, 19 Feb 2026 16:50:01 +0000 (19:50 +0300)]
auto-claude: subtask-4-3 - Add Plyr JS init and CSS styles via registerCss
- Added registerCss with video-plyr-wrap wrapper styles
- Wrapped video elements in div.video-plyr-wrap for proper Plyr styling
- Plyr initialization already present from previous subtask
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Aleksey Filippov [Thu, 19 Feb 2026 16:48:41 +0000 (19:48 +0300)]
auto-claude: subtask-4-2 - Заменить блок видео на Plyr.js плеер + карточку скачивания
- Добавлен класс write-offs-video для инициализации Plyr.js плеера
- Для AVI файлов создана карточка скачивания с классом video-download-card
- MP4/MOV воспроизводятся через Plyr.js с кастомными контролами
- MOV файлы имеют дополнительную ссылку на скачивание
- Добавлена JS инициализация Plyr плееров при загрузке страницы
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Aleksey Filippov [Thu, 19 Feb 2026 16:47:21 +0000 (19:47 +0300)]
auto-claude: subtask-4-1 - Подключить Plyr.js CSS и JS через registerCssFile/registerJsFile
- Added Plyr.js CSS from CDN (https://cdn.plyr.io/3.7.8/plyr.css)
- Added Plyr.js JS from CDN (https://cdn.plyr.io/3.7.8/plyr.min.js)
- CSS registered with POS_HEAD position for proper styling
- JS registered with POS_END position for optimal page loading
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Aleksey Filippov [Thu, 19 Feb 2026 16:43:10 +0000 (19:43 +0300)]
auto-claude: subtask-2-3 - Добавить авто-конвертацию MOV/AVI → MP4 в saveUploadedFile()
- Добавлена авто-конвертация MOV/AVI файлов в MP4 после saveAs()
- При успешной конвертации оригинальный файл удаляется
- URL в записи Files обновляется на MP4 версию
- Если FFmpeg недоступен, файл сохраняется в оригинальном формате
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Aleksey Filippov [Thu, 19 Feb 2026 16:41:23 +0000 (19:41 +0300)]
auto-claude: subtask-2-2 - Реализовать метод FileService::convertToMp4()
Добавлен метод для конвертации видео MOV/AVI в MP4 через FFmpeg:
- Проверка наличия FFmpeg через `which ffmpeg`
- Проверка существования исходного файла
- Использование безопасного escapeshellarg() для shell-команд
- Флаг -y для перезаписи без подтверждения
- Флаг -movflags +faststart для быстрого старта воспроизведения
- Graceful fallback: возвращает null при ошибках без исключений
- Логирование через Yii::warning() с категорией 'video'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>