docs реклама за показы: заход 3 закрыт — кусок оживления готов, ход работ и снимок состояния
This commit is contained in:
@@ -988,3 +988,71 @@ it('запуск гасит отметку об отданной на почин
|
||||
|
||||
expect($campaign->refresh()->revived_at)->toBeNull();
|
||||
});
|
||||
|
||||
/**
|
||||
* Приёмочный лист замысла, кусок 2: «после правки обычная кнопка "Запустить" доводит
|
||||
* кампанию до модерации». Второго пути запуска мы не делали намеренно — работает
|
||||
* существующий лаунчер, который доигрывает начатое.
|
||||
*
|
||||
* Здесь же проверяется главное денежное следствие: в Яндексе НЕ заводится второй комплект
|
||||
* кампании, группы и сегмента. Заводился бы — клиент платил бы дважды.
|
||||
*/
|
||||
it('после оживления обычный запуск доводит кампанию до модерации и ничего не создаёт заново', function () {
|
||||
configureYandex();
|
||||
|
||||
$calls = [];
|
||||
Http::fake(function ($request) use (&$calls) {
|
||||
$url = $request->url();
|
||||
$key = match (true) {
|
||||
str_contains($url, 'upload_csv_file') => 'segment_upload',
|
||||
str_contains($url, '/confirm') => 'segment_confirm',
|
||||
str_contains($url, '/json/v5/retargetinglists') => 'retargetinglists',
|
||||
str_contains($url, '/json/v5/campaigns') => 'campaigns',
|
||||
str_contains($url, '/json/v5/adgroups') => 'adgroups',
|
||||
str_contains($url, '/json/v5/audiencetargets') => 'audiencetargets',
|
||||
str_contains($url, '/json/v5/creatives') => 'creatives',
|
||||
str_contains($url, '/json/v5/ads') => 'ads',
|
||||
default => 'other',
|
||||
};
|
||||
$calls[$key] = ($calls[$key] ?? 0) + 1;
|
||||
|
||||
return match ($key) {
|
||||
'creatives' => Http::response(['result' => ['Creatives' => creativesOfSeedBanners()]]),
|
||||
'ads' => Http::response(['result' => ['AddResults' => [['Id' => 5561]]]]),
|
||||
default => Http::response([], 404),
|
||||
};
|
||||
});
|
||||
|
||||
$tenant = Tenant::factory()->create();
|
||||
app(AdWalletService::class)->topup($tenant->id, '20000.00', 'yandex', 'тест');
|
||||
|
||||
// Кампания в том виде, в каком её оставляет «Исправить»: черновик с отметкой о починке,
|
||||
// номера Яндекса целы, у баннера новая картинка и ни номера объявления, ни креатива нет.
|
||||
$campaign = makeImpressionCampaign($tenant->id);
|
||||
seedAudience($campaign, 100);
|
||||
seedBanners($campaign, ['300x250' => 4242]);
|
||||
$campaign->update([
|
||||
'status' => AdCampaign::STATUS_DRAFT,
|
||||
'revived_at' => now(),
|
||||
'yandex_segment_id' => 900001,
|
||||
'yandex_retargeting_list_id' => 111,
|
||||
'yandex_campaign_id' => 222,
|
||||
'yandex_ad_group_id' => 333,
|
||||
]);
|
||||
|
||||
app(CampaignLauncher::class)->launch($campaign);
|
||||
|
||||
expect($calls)->not->toHaveKey('segment_upload')
|
||||
->and($calls)->not->toHaveKey('retargetinglists')
|
||||
->and($calls)->not->toHaveKey('campaigns')
|
||||
->and($calls)->not->toHaveKey('adgroups')
|
||||
->and($calls)->not->toHaveKey('audiencetargets')
|
||||
->and($calls['ads'] ?? 0)->toBe(1);
|
||||
|
||||
$campaign->refresh();
|
||||
expect($campaign->status)->toBe(AdCampaign::STATUS_PENDING_MODERATION)
|
||||
->and($campaign->yandex_campaign_id)->toBe(222)
|
||||
->and($campaign->revived_at)->toBeNull();
|
||||
|
||||
expect(AdCampaignBanner::where('campaign_id', $campaign->id)->first()->yandex_ad_id)->toBe(5561);
|
||||
});
|
||||
|
||||
@@ -680,3 +680,109 @@ v9.07. Чинить не в этой ветке.
|
||||
- `npm run type-check` — те же **6 чужих** ошибок, ни одной новой;
|
||||
- робот: **60/60**;
|
||||
- вызовов снятия заморозки — **четыре**, пятого не появилось.
|
||||
|
||||
---
|
||||
|
||||
# Заход 3 закрыт 28.07.2026 — кусок 2 «оживление» готов, кнопка «Исправить» работает
|
||||
|
||||
Задачи 9–12 плана `2026-07-28-yandex-otkazy-okno-peredachi.md`.
|
||||
|
||||
**Задача 9 — удаление отклонённых объявлений** (`abb3941e`). `YandexDirectClient::deleteAds()`
|
||||
шлёт `ads.delete` одним запросом со всеми номерами; пустой список наружу не уходит —
|
||||
Яндекс ответил бы ошибкой на пустое дело, и мы записали бы тревогу на ровном месте.
|
||||
|
||||
**Задача 10 — сервис оживления** (`729a2636`). `CampaignReviveService`: кампания
|
||||
возвращается в черновик, у отклонённых баннеров обнуляются номера креатива и объявления,
|
||||
номера кампании, группы и сегмента Яндекса **уцелевают**. Неудача удаления в кабинете
|
||||
клиента не блокирует. При выключенном рубильнике в Яндекс не ходим вовсе.
|
||||
|
||||
**Задача 11 — ручка «Исправить» и узкое исключение в замке** (`d29f45da`). `POST
|
||||
.../campaigns/{id}/revive`; замок на правке настроек и на наборе баннеров получил одно
|
||||
исключение — по состоянию «чинится после отказа», а не по «есть ли номер кампании».
|
||||
|
||||
**Задача 12 — кнопка на экране** (`89e6a459`). «Исправить» сперва зовёт оживление,
|
||||
и только потом открывает мастер. Не вышло оживить — мастер не открывается, видна ошибка:
|
||||
иначе клиент упёрся бы в непонятный отказ уже внутри мастера.
|
||||
|
||||
**Починка после живой проверки** (`6d34d663`). См. ниже — главная находка захода.
|
||||
|
||||
## 🔴 Главная находка: живая проверка в браузере вскрыла дыру при 337 зелёных тестах
|
||||
|
||||
Кнопка «Исправить» возвращает кампанию в черновик — и **в ту же секунду** исключение
|
||||
из замка переставало действовать: оно было написано по статусу `rejected`, а статуса
|
||||
уже не было. Замок снова смотрел только на «есть номер кампании в Яндексе» и запирал всё.
|
||||
|
||||
Проверено живьём: после «Исправить» смена адреса сайта → 409 «Кампания уже заведена
|
||||
в Яндексе». Перезаливка картинки — тем же признаком. **Кнопка вела в тупик, просто
|
||||
на шаг дальше, чем раньше.**
|
||||
|
||||
Почему тесты молчали: они проверяли правку у кампании, которая **ещё числится
|
||||
отклонённой**, — а кнопка это состояние покидает немедленно. Класс ошибки: тест
|
||||
проверяет состояние, в котором продукт не бывает.
|
||||
|
||||
**Как починено** (решение владельца): отдельная отметка в базе `ad_campaigns.revived_at` —
|
||||
«отдана клиенту на починку». Ставит `CampaignReviveService`, гасит `CampaignLauncher`
|
||||
при следующем запуске. Замок открыт ровно на время починки; черновик после
|
||||
**оборвавшегося** запуска отметки не получает и остаётся запертым — там сегмент
|
||||
и кампания в Яндексе живы, а объявлений может не быть вовсе.
|
||||
|
||||
Почему не «оставить ярлык Отклонено до нового запуска»: клиенту непонятно (нажал —
|
||||
ничего не изменилось), и пришлось бы разрешать запуск прямо из «Отклонено», то есть
|
||||
трогать путь запуска, где заморозка денег.
|
||||
|
||||
Запись в журнале схемы — `db/CHANGELOG_schema.md`, v9.11. `rls-reviewer` — чисто:
|
||||
табличные гранты покрывают новую колонку, поколоночный `UPDATE (yandex_creative_id)`
|
||||
для админки к ней отношения не имеет, `db/03_service_bypass_policies.sql` перезапускать
|
||||
не надо (новых таблиц нет).
|
||||
|
||||
## Что проверено вырезанием
|
||||
|
||||
- Отказ от пустого списка в `deleteAds` → покраснел «пустой список в Яндекс не уходит». ✅
|
||||
- Проверка статуса в сервисе оживления → покраснел «оживить можно только отклонённую». ✅
|
||||
- Обнуление номеров кампании → покраснел «номера кампании, группы и сегмента уцелевают». ✅
|
||||
- Фильтр «только отклонённые баннеры» → покраснел «принятый баннер оживление не трогает». ✅
|
||||
- Исключение в замке настроек → покраснела правка отклонённой кампании. ✅
|
||||
- Замок баннеров распахнут настежь → покраснели три теста про работающую кампанию. ✅
|
||||
- Сервис не ставит отметку `revived_at` → покраснели оба теста живой находки. ✅
|
||||
- Отметка заменена на «любой черновик» → покраснел «оборвавшийся запуск заперт». ✅
|
||||
- Запуск не гасит отметку → покраснел «запуск гасит отметку». ✅
|
||||
- Лаунчер заводит кампанию Яндекса заново → покраснел «после оживления ничего
|
||||
не создаётся заново». ✅
|
||||
|
||||
## Приёмочный лист замысла §8, кусок 2 — закрыт целиком
|
||||
|
||||
| Строка | Чем закрыта |
|
||||
|---|---|
|
||||
| «Исправить» у отклонённой возвращает её в черновик | `CampaignReviveServiceTest`, `AdvertisingCampaignEndpointTest` |
|
||||
| Номера кампании, группы и сегмента уцелевают | `CampaignReviveServiceTest` |
|
||||
| У отклонённых баннеров номера креатива и объявления обнулены | `CampaignReviveServiceTest` |
|
||||
| Правка картинок и настроек у отклонённой разрешена | `AdvertisingCampaignEndpointTest`, `CampaignBannerEndpointsTest` — и **после нажатия «Исправить»** тоже |
|
||||
| У работающей кампании правка по-прежнему заперта | `AdvertisingCampaignEndpointTest`, `CampaignBannerEndpointsTest` |
|
||||
| После правки обычный «Запустить» доводит до модерации | `CampaignLauncherTest` — и ничего не создаётся в Яндексе заново |
|
||||
| Второй «Исправить» получает отказ 409 | `AdvertisingCampaignEndpointTest` |
|
||||
| Мест разморозки денег по-прежнему четыре | `grep -rn -- "->release(" app/app` |
|
||||
| Не хватило денег — обычный отказ запуска | прежние тесты лаунчера, особого случая для оживления нет |
|
||||
|
||||
## Живая проверка глазами, 28.07.2026
|
||||
|
||||
Портал поднят на тестовой базе `liderra_testing_reklama`, вход клиентом, экран
|
||||
«Яндекс Аудитория»: карточка «Отклонено» с причиной → «Исправить» → кампания стала
|
||||
черновиком, открылся мастер «Изменить кампанию» → смена адреса сайта прошла (200),
|
||||
номера Яндекса на месте (555/666/777), у баннера номера обнулены, отметка о починке стоит.
|
||||
|
||||
🪤 Синтетические клики Playwright по кнопке Vuetify не срабатывали (запрос не уходил
|
||||
вовсе), а `element.click()` в самой странице — срабатывал. Проверять поведение через
|
||||
`browser_evaluate`, иначе можно принять живой продукт за сломанный.
|
||||
|
||||
## Зелёная отметка на конец захода 3
|
||||
|
||||
- портал: **342/342, 1133 проверки** (было 322/322 — 20 новых тестов);
|
||||
- фронт: **227 файлов, 1671 тест** зелёные (посторонняя ошибка в чужом `autopodbor` — та же);
|
||||
- `npm run type-check` — те же **6 чужих** ошибок, ни одной новой;
|
||||
- робот: **60/60**;
|
||||
- вызовов снятия заморозки — **четыре**, пятого не появилось.
|
||||
|
||||
🪤 Гонять набор строго **по одному процессу**: один прогон я запустил, пока предыдущий
|
||||
ещё жил после обрыва по времени, — два набора били в одну базу, и три теста
|
||||
`AdminAdvertisingSpendTest` (они считают расход по ВСЕМ тенантам) покраснели на ровном
|
||||
месте. По одному процессу — стабильно зелено.
|
||||
|
||||
@@ -3,28 +3,28 @@
|
||||
Файл пишется в конце каждого захода. Читать его **первым делом** после компакта: всё,
|
||||
что нужно следующей сессии, лежит здесь, а не в переписке.
|
||||
|
||||
Обновлено: 28.07.2026, конец захода 2.
|
||||
Обновлено: 28.07.2026, конец захода 3.
|
||||
|
||||
---
|
||||
|
||||
## Где мы
|
||||
|
||||
- Worktree `.claude/worktrees/reklama-pokazy`, ветка `feat/reklama-yandex-pokazy`.
|
||||
- Последний коммит — **`fb63994a`**.
|
||||
- **Заходы 1 и 2 закрыты целиком** (задачи 1–8). **Кусок 1 замысла «переписка» готов.**
|
||||
Заходы 3 и 4 не начинались.
|
||||
- Последний коммит кода — **`6d34d663`** (+ коммит документации следом).
|
||||
- **Заходы 1, 2 и 3 закрыты целиком** (задачи 1–12). **Куски 1 «переписка» и 2
|
||||
«оживление» замысла готовы.** Заход 4 (робот) не начинался.
|
||||
- Никуда не пушили, на боевой не выкатывали, рубильник Директа выключен, в живой кабинет
|
||||
Яндекса никто не заходил.
|
||||
|
||||
Коммиты захода 2:
|
||||
Коммиты захода 3:
|
||||
|
||||
```text
|
||||
fb63994a test реклама за показы: в ленте не может быть наценки и пути файла на сервере
|
||||
958204d2 feat реклама за показы: под ярлыком Отклонено видна первая строка причины
|
||||
31709d01 feat реклама за показы: экран переписки в карточке кампании вместо мёртвого списка объявлений
|
||||
27367245 feat реклама за показы: ответ клиента с документом и отдача файла только своему тенанту
|
||||
5e5a9c7f feat реклама за показы: ручка списка сообщений кампании — только своя лента
|
||||
ffeffe35 docs реклама за показы: заход 1 закрыт — ход работ и снимок состояния
|
||||
6d34d663 fix реклама за показы: пометка отдана на починку держит правку открытой после возврата в черновик
|
||||
89e6a459 feat реклама за показы: кнопка Исправить оживляет кампанию перед мастером
|
||||
d29f45da feat реклама за показы: ручка Исправить и узкое исключение в замке правки
|
||||
729a2636 feat реклама за показы: сервис оживления отклонённой кампании
|
||||
abb3941e feat реклама за показы: удаление отклонённых объявлений в кабинете Яндекса
|
||||
6bc00ba6 docs реклама за показы: заход 2 закрыт — кусок переписки готов
|
||||
```
|
||||
|
||||
Не закоммичено — только три устаревших промта (`chast4-v3`, `chast4-v4`,
|
||||
@@ -32,69 +32,70 @@ ffeffe35 docs реклама за показы: заход 1 закрыт — х
|
||||
|
||||
## Зелёные числа на этом коммите
|
||||
|
||||
- портал: **322/322, 1090 проверок, ~54 с** — `cd app && DB_DATABASE=liderra_testing_reklama php artisan test --filter=Advertising`
|
||||
- фронт: **227 файлов, 1668 тестов** — `cd app && npx vitest run`
|
||||
- портал: **342/342, 1133 проверки, ~57 с** — `cd app && DB_DATABASE=liderra_testing_reklama php artisan test --filter=Advertising`
|
||||
- фронт: **227 файлов, 1671 тест** — `cd app && npx vitest run`
|
||||
🪤 единственная посторонняя ошибка в выводе — `autopodbor.ts::fetchProposalGroups`,
|
||||
чужая и давняя, к этой работе отношения не имеет.
|
||||
- `npm run type-check` — **6 чужих** ошибок, ни одной новой. Чужие не чинить.
|
||||
- робот: **60/60** — `cd bots/yandex-creatives && node --test`
|
||||
- мест снятия заморозки денег — **четыре**: `AdvertisingCampaignController:392`,
|
||||
`SyncCampaignModerationJob:165`, `PauseCampaignsOnAdStop:48`, `CampaignImpressionCharger:96`.
|
||||
- мест снятия заморозки денег — **четыре**: `AdvertisingCampaignController`,
|
||||
`SyncCampaignModerationJob`, `PauseCampaignsOnAdStop`, `CampaignImpressionCharger`.
|
||||
Остальные находки `->release(` — замки `Cache::lock`, не деньги.
|
||||
|
||||
🪤 Прогон — строго **по одному процессу**. Два набора против одной базы роняют три теста
|
||||
`AdminAdvertisingSpendTest` (они считают расход по ВСЕМ тенантам) на ровном месте.
|
||||
|
||||
## Что теперь работает
|
||||
|
||||
Круг «Яндекс → клиент → Яндекс» замкнут в одну сторону целиком:
|
||||
Круг «Яндекс → клиент → Яндекс» замкнут в обе стороны, кроме доставки документов:
|
||||
|
||||
1. Яндекс отклоняет объявление;
|
||||
2. джоб опроса модерации кладёт пояснение модератора **целиком** в `ad_campaign_messages`;
|
||||
3. клиенту уходит письмо и загорается колокольчик;
|
||||
4. клиент открывает карточку кампании и **видит переписку**, а в списке кампаний под
|
||||
красным ярлыком «Отклонено» — первую строку причины;
|
||||
5. клиент отвечает текстом и может приложить документ (pdf/jpg/png до 10 МБ);
|
||||
6. документ лежит на закрытом диске и отдаётся только своему тенанту.
|
||||
1. Яндекс отклоняет объявление, джоб кладёт пояснение **целиком** в переписку;
|
||||
2. клиенту письмо и колокольчик, в списке под ярлыком «Отклонено» — первая строка причины;
|
||||
3. клиент читает переписку в карточке кампании, отвечает и может приложить документ;
|
||||
4. **клиент жмёт «Исправить»** — отклонённые объявления удаляются из кабинета, кампания
|
||||
возвращается в черновик с отметкой «отдана на починку», номера кампании, группы
|
||||
и сегмента Яндекса целы;
|
||||
5. клиент меняет картинку и настройки привычными экранами;
|
||||
6. обычная кнопка «Запустить» доводит кампанию до модерации, ничего не заводя в Яндексе
|
||||
заново; отметка о починке гаснет, замок закрывается сам.
|
||||
|
||||
**Чего пока нет:** документ никуда не едет — робот его не носит (кусок 3), а кнопка
|
||||
«Исправить» по-прежнему ведёт в тупик (кусок 2, заход 3).
|
||||
**Чего пока нет:** документ клиента никуда не едет — робот его не носит, и причину
|
||||
из кабинета робот не читает (кусок 3, заход 4).
|
||||
|
||||
## Что дальше — заход 3, задачи 9–12
|
||||
## Что дальше — заход 4, задачи 13–16
|
||||
|
||||
По плану `docs/superpowers/plans/2026-07-28-yandex-otkazy-okno-peredachi.md`:
|
||||
🔴 **Задача 13 — снять живую разметку кабинета вместе с владельцем. Без неё заход
|
||||
не начинается.** Экран с причиной отказа и экран с документами мы не видели ни разу;
|
||||
код по воображаемым экранам даст зелёные тесты и мёртвую программу. Отказ можно вызвать
|
||||
нарочно: залить заведомо непроходное объявление.
|
||||
|
||||
- **Задача 9** — `YandexDirectClient::deleteAds()`, удаление отклонённых объявлений.
|
||||
- **Задача 10** — `CampaignReviveService`: возврат кампании в черновик, обнуление номеров
|
||||
креатива и объявления у отклонённых баннеров; **номера кампании, группы и сегмента
|
||||
уцелевают** — на них держится возобновляемый запуск.
|
||||
- **Задача 11** — ручка «Исправить» и **узкое** исключение в замке правки: по статусу
|
||||
`rejected`, а не по «есть ли номер кампании», иначе исключение откроет правку
|
||||
и работающей рекламе.
|
||||
- **Задача 12** — кнопка «Исправить» на экране.
|
||||
Дальше по плану: колонка `kind` у заданий робота (`upload` / `inspect` / `deliver`),
|
||||
разведка (робот читает кабинет и ничего в нём не меняет), доставка документа.
|
||||
|
||||
🔴 **Заход 4 не начинать, пока не снята живая разметка кабинета** (задача 13, вместе
|
||||
с владельцем). Код по воображаемым экранам даст зелёные тесты и мёртвую программу.
|
||||
## Свежие грабли захода 3
|
||||
|
||||
## Свежие грабли захода 2
|
||||
|
||||
- 🪤 **План забыл `ensureCsrfCookie()`** в отправке ответа клиента. Все прочие POST'ы
|
||||
модуля её берут; без неё кнопка «Отправить» молча ломалась бы в браузере при зелёных
|
||||
тестах. Проверять это на каждой новой мутации фронта.
|
||||
- 🪤 **Фильтр по тенанту на самом сообщении ничего не сторожит:** его вырезание оставило
|
||||
всё зелёным, потому что настоящий замок — на поиске кампании. Урок общий: вырезание
|
||||
показывает не только «защита есть», но и «эта защита ничего не держит».
|
||||
- 🪤 **Мутация фронта ломает чужие тесты не там, где ждёшь.** Встроенная в диалог отчёта
|
||||
лента уронила два чужих spec'а: их `vi.mock` не знал новых функций api-модуля.
|
||||
Диалог теперь переживает упавшую ленту, а специи получили заглушки.
|
||||
- 🪤 **Наивная отдача модели целиком утекает `file_path`** — путь файла на боевом
|
||||
сервере. Ручка обязана перечислять поля вручную; тест это ловит.
|
||||
- 🪤 **`\n` внутри heredoc-питона превращается в настоящий перенос строки** и ломает
|
||||
`.vue` разбором «Unterminated string constant». Такие строки править инструментом Edit.
|
||||
- 🔴🪤 **Тест проверял состояние, в котором продукт не бывает.** Исключение из замка
|
||||
правки было написано по статусу `rejected`, а кнопка «Исправить» этот статус
|
||||
немедленно покидает. 337 зелёных тестов, а живьём — тот же тупик. Поймала **только**
|
||||
живая проверка в браузере. Правило на будущее: проверять состояние **после** действия
|
||||
кнопки, а не до.
|
||||
- 🪤 **Синтетические клики Playwright по кнопкам Vuetify не срабатывают** — запрос
|
||||
не уходит вовсе, ошибки при этом нет. `element.click()` через `browser_evaluate`
|
||||
срабатывает. Иначе легко принять живой продукт за сломанный.
|
||||
- 🪤 **Тестовая база чистится прогоном набора** (в наборе есть `RefreshDatabase`):
|
||||
засеянные для живой проверки тенант, пользователь и кампания исчезают после каждого
|
||||
прогона. Сеять заново перед проверкой глазами.
|
||||
- 🪤 **Последовательность `ad_campaigns.id` в тестовой базе отстаёт** — `create()`
|
||||
падает на дубле ключа. Для живой проверки проще завести новый тенант, чем чинить.
|
||||
- 🪤 `->after('колонка')` в миграции на PostgreSQL — **пустое место**: физически колонка
|
||||
встаёт в конец таблицы. Ничего не ломает, но в журнале схемы это оговорено.
|
||||
- 🪤 В worktree нет `lefthook` — каждый коммит печатает `Can't find lefthook in PATH`.
|
||||
Это нормально; gitleaks гоняется руками:
|
||||
`"…/Документация/bin/gitleaks.exe" protect --staged --no-banner`.
|
||||
- 🪤 `crm_admin_user` гранта на `ad_campaign_messages` **не получил** — когда появится
|
||||
админский список «ждёт разбора», нужна догоняющая миграция `GRANT SELECT` по образцу
|
||||
`2026_07_27_100100_grant_admin_ad_campaign_banners.php`, иначе экран увидит ноль
|
||||
строк молча.
|
||||
- 🪤 В worktree нет `lefthook` — каждый коммит печатает `Can't find lefthook in PATH`.
|
||||
Это нормально; gitleaks гоняется руками:
|
||||
`"…/Документация/bin/gitleaks.exe" protect --staged --no-banner`.
|
||||
|
||||
## Красные линии, которые действуют всегда
|
||||
|
||||
@@ -106,5 +107,6 @@ ffeffe35 docs реклама за показы: заход 1 закрыт — х
|
||||
- Коммит по эскейпу владельца, сообщение без круглых скобок, только явные пути,
|
||||
`LEFTHOOK_EXCLUDE=larastan`, новые файлы требуют `git add`.
|
||||
- 🔴 После выката на бой перезапустить `db/03_service_bypass_policies.sql` — иначе
|
||||
служебные роли увидят в новой таблице ноль, а журнал будет зелёный.
|
||||
служебные роли увидят в новой таблице `ad_campaign_messages` ноль, а журнал будет
|
||||
зелёный. (Колонка `revived_at` перезапуска не требует — новых таблиц в заходе 3 нет.)
|
||||
- Открытые вопросы владельца не закрывать самому: Д4 и срок хранения чужих документов.
|
||||
|
||||
Reference in New Issue
Block a user