Files
portal/docs/deploy/supplier-import-lkomega-runbook.md
T
Дмитрий 26999ca597 chore: working tree cleanup pre-llm-first-router merge
Три группы накопившихся auto-правок (НЕ ручные):

1. markdownlint --fix auto-format (~25 .md в docs/superpowers/, docs/security/marketing-vet.md, docs/adr/015, docs/deploy/lkomega-runbook): MD031/MD032 (blank lines around fence/list) + MD004 (bullet markers `+`→`-`). Содержательных текстовых правок 3: ADR-015 bullet, sprint5d-cleanup bullet, router-discipline trailing space.

2. lefthook 2.1.6 → 2.1.8 (package.json + lock): patch-bump, авто-резолвил npm.

3. Observer runtime (docs/observer/): episodes-2026-05.jsonl +420 строк (текущая активность мозга), STATUS.md regen, .pii-counters / .read-counter тики, +2026-05-24-brain-retro.md note.

Цель — разблокировать merge feat/llm-first-router → main (этап 0 плана постановки в боевой). Содержание ветки не трогает.
2026-05-25 14:23:11 +03:00

100 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Runbook: импорт проектов lkomega → info@lkomega.ru
Разовая операция на боевом liderra.ru (`111.88.246.137`). Усыновляет активные
проекты поставщика crm.bp-gr.ru (аккаунт lkomega) как проекты Лидерры под
тенантом info@lkomega.ru. **Портал не трогается** (никаких save/update/delete).
Plan: `docs/superpowers/plans/2026-05-22-supplier-projects-import-lkomega.md`
Spec: `docs/superpowers/specs/2026-05-22-supplier-projects-import-lkomega-design.md`
## Деплой команды
Скопировать на сервер в `/var/www/liderra/app` (бэкап заменяемого `SupplierRegions.php`):
- `app/Support/SupplierRegions.php` (изменён — добавлен `mapFromSupplier`)
- `app/Services/Supplier/Import/SupplierImportMapper.php` (новый)
- `app/Services/Supplier/Import/SupplierProjectImporter.php` (новый)
- `app/Console/Commands/ImportSupplierProjectsCommand.php` (новый)
```bash
cp /var/www/liderra/app/app/Support/SupplierRegions.php /var/www/liderra/app/app/Support/SupplierRegions.php.bak-$(date +%Y%m%d-%H%M%S)
# scp 4 файла...
cd /var/www/liderra/app && php artisan optimize:clear # сброс кэша команд/конфига
```
Команда — не очередь/воркер, `queue:restart` не нужен.
## Шаг 1 — dry-run (показать план, ничего не пишет)
```bash
cd /var/www/liderra/app && php artisan supplier:import-projects --tenant=info@lkomega.ru
```
Вывод: число проектов к созданию, таблица (тип / идентификатор[маскирован] /
тег / регионы / лимит / площадки B1:id …), список пропусков (`unsupported_source`
для dop2, `regions_exclude`, `sms_unparseable`, `already_exists`).
**Показать заказчику → получить «ок».**
## Шаг 2 — реальный прогон
```bash
cd /var/www/liderra/app && php artisan supplier:import-projects --tenant=info@lkomega.ru --commit
```
Вывод: `Создано: проектов=N, supplier_projects=M, связок=K.`
## Шаг 3 — пост-проверка
```bash
# Число проектов под тенантом (подставить tenant_id info@lkomega.ru):
php artisan tinker --execute="echo App\Models\Project::on('pgsql_supplier')->where('tenant_id', <ID>)->count();"
```
- Выборочно сверить 2–3 проекта: `daily_limit_target` = сумме площадок; регионы корректны (ГИБДД→Лидерра).
- **Проверить целостность площадок каждого проекта** (см. оговорку ниже):
каждый проект должен иметь столько связок `project_supplier_links`, сколько площадок было в группе (обычно 3).
```bash
php artisan tinker --execute="App\Models\Project::on('pgsql_supplier')->where('tenant_id',<ID>)->get()->each(fn(\$p)=>print(\$p->id.': '.\$p->supplierProjects()->count().PHP_EOL));"
```
- Подтвердить, что на портале crm.bp-gr.ru **НЕ появилось новых проектов** (команда его не дёргает).
## Атомарность
`commit()` оборачивает запись **каждого проекта в отдельную транзакцию** на проде
(`DB::connection('pgsql_supplier')->transaction(...)` — Project + все `supplier_projects` +
все pivot-связки группы атомарно). Сбой посреди группы → транзакция откатывается → ни
проекта, ни partial-связок не остаётся, БД консистентна. Уже созданные ДО сбоя проекты
сохраняются (per-group, не per-run).
В прод-команде это включается автоматически: гейт `getPdo()->inTransaction()` — false на
проде → BEGIN/COMMIT per item; true только под тестовым харнессом `SharesSupplierPdo`
(общий PDO уже в транзакции) → внутренний BEGIN пропускается, чтобы избежать
«already active transaction» в Pest.
При ошибке посреди прогона — просто запустить `--commit` повторно: идемпотентность
(`already_exists` по tenant+signal + `firstOrCreate` по `(platform, unique_key,
subject_code)`) пропустит уже импортированные проекты и до-создаст оставшиеся.
## Откат
Импортированные проекты под тенантом — soft-archive через ЛК или:
```php
App\Models\Project::on('pgsql_supplier')->where('tenant_id', <ID>)
->update(['is_active' => false, 'archived_at' => now()]);
```
`supplier_projects`/pivot можно оставить (они указывают на реальные портальные проекты,
их используют и другие потоки).
## NB про среду
- На worktree-сборке 2 теста `SupplierPortalClient*Test` падают из-за отсутствия node-модуля
`playwright` — это известный worktree-only квирк (не регрессия), на боевом/основном
checkout с `node_modules` они зелёные.
- Larastan: production-код чист; test-only `TestCall`/Mockery (квирк #25) добавляются в
`phpstan-baseline.neon` на чистом checkout при интеграции (не из worktree — там дрейф
ide-helper искажает счётчики).