pnd8_rasp/AGENTS.md

141 lines
16 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.

# AGENTS.md — рабочие инструкции pnd8_app
Версия: 2026-08-10
Кодировка: UTF-8
## Назначение
- Этот файл — входная карта проекта для AI-ассистентов и разработчиков.
- Перед нетривиальной правкой сначала изучить затрагиваемый модуль, соседний модуль того же типа и связанные XML/шаблоны/миграции.
- Новые устойчивые правила проекта добавлять сюда. Не превращать файл в журнал реализации отдельных задач.
- Не удалять и не откатывать чужие изменения в dirty worktree без явного запроса.
- Не хранить в этом файле пароли, токены, API-ключи и другие секреты.
## Контекст проекта
`pnd8_app` — веб-приложение для поиска участка обслуживания ПНД по адресу и показа врачей с расписанием приёма.
Основной пользовательский сценарий:
1. Пользователь вводит адрес на публичной странице.
2. Яндекс Карты определяют координаты.
3. Приложение находит содержащий точку полигон `pnd_zone_geometry`.
4. Через `zone_id` загружаются участок `pnd_zones` и врачи `pnd_doctors`.
5. Расписание врача читается из JSON-поля `schedule` и отображается/печатается.
Данные врачей, участков и расписаний синхронизируются из внешней старой МИС cron-скриптом. FAQ, документы и статические страницы управляются через собственный движок и админку.
## Стек
- PHP 7.4 FPM и Composer 2.
- Собственный legacy PHP-фреймворк: `module`, `cat`, `cobject`, XML-компоновка, legacy `.htm` и BladeOne.
- MariaDB 10.6.21 в текущем `docker-compose.yml`; слой доступа к БД — собственный `db`/`cobject` поверх `mysqli`.
- Nginx 1.24, Docker Compose, phpMyAdmin.
- Публичный frontend: Bootstrap 4, jQuery 3.4.1, Font Awesome 5, Яндекс Карты и Suggest API.
- PHP CS Fixer подключён как Composer-зависимость; автоматизированного тестового набора в репозитории сейчас нет.
Не применять синтаксис и API PHP 8.x. Не обновлять версии runtime, Composer-зависимостей или frontend-библиотек попутно с прикладной задачей.
## Карта проекта
- `app/` — код приложения; в контейнерах монтируется в `/var/www/html`.
- `app/public_html/` — фактический web root и публичная точка входа `index.php`.
- `app/public_html/admin/` — точка входа админки.
- `app/public_html/assets/` — публичные CSS, JS, SCSS, шрифты и генератор статических include-файлов.
- `app/engine/bootstrap.php` — общая загрузка конфигурации, БД, ядра и BladeOne.
- `app/engine/core/` — ядро, `cobject`, БД, формы, фильтры, роутинг и типы атрибутов.
- `app/engine/www/modules/` — контроллеры публичной части.
- `app/engine/www/bladetpl/` — Blade-шаблоны публичной части.
- `app/engine/www/tpls/` — legacy-шаблоны и XML include-файлы публичной части.
- `app/engine/www/xml/` — XML-компоновка публичных категорий.
- `app/engine/admin/modules/`, `bladetpl/`, `tpls/`, `xml/` — соответствующие части админки.
- `app/engine/migrations/` — плоский каталог SQL-миграций и исполнитель `_migrate.php`.
- `app/engine/cron/data_sync/` — импорт врачей, участков и расписания из внешней МИС.
- `app/config/` — конфигурация и подключения приложения; считать содержимое чувствительным.
- `config/`, `docker/`, `docker-compose.yml` — инфраструктура контейнеров.
- `db/`, `logs/`, `sessions/` — runtime-данные; не редактировать и не добавлять в Git.
- `Договор/`, архивы и дампы в корне — не код приложения; не открывать и не изменять без прямой необходимости задачи.
README унаследован от Bambolo и местами устарел: в этом репозитории web root называется `public_html`, а текущий Compose содержит только `php`, `nginx`, `mariadb` и `phpmyadmin`. Проверять фактическую конфигурацию, а не слепо следовать README или `deploy.cmd`.
## Архитектурные правила
- Сначала искать аналогичный существующий модуль и сохранять принятый проектом паттерн.
- У модуля параметры запроса явно перечислять в `$_get_vars`, `$_post_vars` и `$_loc_vars`; внутри action использовать `$this->имяПараметра`.
- Action этого движка реализуются методами `_on_*`/`_ajax_*`; не смешивать несвязанные action и представления в одном шаблоне.
- Для Blade использовать общий `$blade` через `global $blade` и `$blade->run($this->getBladeTempl(...), $data)`.
- Для текущей категории использовать `global $cat` и `$cat->cat`, для редиректа — `_redirect()`.
- Не использовать `$GLOBALS[...]` и не добавлять новый прямой доступ к `$_REQUEST`.
- Бизнес-вычисления и SQL готовить в PHP-модуле; в Blade оставлять преимущественно отображение. При доработке существующего шаблона постепенно выносить сложную подготовку данных, если это входит в задачу.
- Не вводить новый фреймворк, ORM или сборщик ради локальной правки.
- Сохранять обратную совместимость публичных URL, XML-категорий и связки `module -> XML/category -> template`.
## База данных и миграции
- Перед изменением сущности проверить таблицу, `_sys_datatypes`, использующие её модули и предыдущие миграции.
- Любое изменение схемы или системных метаданных оформлять новым `.sql` в `app/engine/migrations/`; уже применённые миграции не переписывать.
- Имена новых миграций продолжать в существующем формате `YYYYMMDD-HHMM-description.sql` и обеспечивать уникальность имени.
- Исполнитель миграций примитивно делит SQL по `;` перед переводом строки. Не добавлять процедуры, триггеры или конструкции с внутренними `;` без предварительной доработки/проверки runner.
- SQL строить с приведением числовых значений через `(int)`/`intval()` и экранированием строк через `db_escape_string()`. Предпочитать методы `cobject`, когда они покрывают операцию.
- Не использовать `REPLACE INTO`; для upsert применять `INSERT ... ON DUPLICATE KEY UPDATE` либо явные `UPDATE`/`INSERT`.
- Геометрия зон хранится как MySQL spatial `POLYGON`. Сохранять действующий порядок координат и замыкать контур; проверять поиск точки через `ST_WITHIN`.
- Не запускать миграции на production и не импортировать дампы без явного запроса.
## Синхронизация с МИС
- `sync_doctors_and_zones.php` — потенциально разрушительная операция: она создаёт временные таблицы, очищает основные `pnd_zones`/`pnd_doctors`, переносит данные и удаляет временные таблицы.
- Не запускать этот скрипт автоматически для проверки. Сначала использовать режим dry-run или отдельную тестовую БД и явно проверить подключения.
- После миграции МИС рабочие слоты врачей находятся в `SimpleSchedule`; старую цепочку `Event`/`Action`/`ActionProperty_Time` для расписания не использовать.
- Рабочее время дня вычислять по всем действующим слотам присутствия врача в учреждении (`amb`, `external`, `internal`) независимо от `ticket`; заполненные номерки тоже расширяют диапазон активности. Исключать удалённые, отключённые и нулевые слоты, а также строки с `absence_reason`.
- Интервалы `SimpleSchedule.schedule_type = 'home'` относятся к работе на дому и не должны входить в отображаемый диапазон присутствия врача.
- `SimpleSchedule.ticket` ссылается на `TicketInfo.id`; `NULL` означает свободный слот. Для синхронизации только рабочих часов `TicketInfo` не читать и пациентские данные не переносить.
- ID врачей и участков сейчас совпадают с внешними ID старой МИС. Не менять эту семантику без миграционного плана.
- Поле `pnd_doctors.schedule` содержит JSON вида `YYYY-MM-DD => {start, end}` либо `null`; при изменениях сохранять обратную совместимость формата.
- Расписание формируется на 10 дней, включая текущий. Проверять границы дат, отсутствие приёма и часовой пояс `Europe/Moscow`.
- Не добавлять новые реквизиты подключения в код. Обнаруженные hardcoded-пароли и API-ключи не копировать в логи, ответы, документацию или новые файлы; при отдельной задаче переносить их в переменные окружения.
## UI и шаблоны
- Админка и публичная часть используют Bootstrap 4; не применять классы и `data-bs-*` из Bootstrap 5.
- Использовать существующие jQuery/Bootstrap/Font Awesome 5 и визуальные паттерны соседних шаблонов.
- Сохранять адаптивность крупного адресного поля, списка подсказок, модального результата и печати.
- Для изменений карты проверять оба сценария: выбор адреса по координатам и клик по полигону.
- Пользовательские и внешние строки не конкатенировать в HTML без экранирования. В Blade по умолчанию использовать `{{ ... }}`, а `{!! ... !!}` — только для заранее подготовленного доверенного содержимого.
- Не коммитить скомпилированные файлы из `app/engine/*/bladetpl/cache/`, если задача прямо не требует обновления уже отслеживаемых артефактов.
- После изменения перечня CSS/JS или исходной статики пересобрать include-файлы соответствующим `static_optimization.php` и проверить diff сгенерированных файлов.
## Кодировка и стиль
- Все новые и изменённые текстовые файлы сохранять в UTF-8 без порчи русских строк.
- В старых файлах уже встречается повреждённая кириллица. Не распространять её копированием и не делать массовое исправление кодировки вне отдельной задачи.
- Следовать стилю ближайшего файла; не проводить широкий форматирующий рефакторинг вместе с функциональной правкой.
- PHP-файлы проверять на синтаксис под PHP 7.4. Форматтер запускать только для файлов в области задачи и внимательно просматривать diff.
## Рабочие команды
Из корня проекта:
```powershell
docker compose up -d
docker compose ps
docker compose logs --tail=100 php
docker compose exec php composer install
docker compose exec php php -l engine/www/modules/site_index.php
docker compose exec php sh -lc "cd engine/migrations && php _migrate.php"
```
Последнюю команду запускать только когда задача действительно требует применения миграций к выбранной локальной БД.
Проверка синтаксиса всех изменённых PHP-файлов должна выполняться адресно. `app/php-cs-fixer.cmd` с `fix` изменяет много файлов, поэтому не запускать его по всему проекту без отдельного согласования.
## Минимальная проверка перед завершением
- Просмотреть `git status --short` и `git diff`; убедиться, что изменены только файлы задачи.
- Для каждого изменённого PHP-файла выполнить `php -l` в PHP 7.4 контейнере.
- Для SQL проверить совместимость с MariaDB 10.6.21 и ограничения `_migrate.php`.
- Для изменений публичного сценария вручную проверить: загрузку карты, подсказки адресов, поиск зоны, карточки врачей, пустое расписание, модальное окно и печать.
- Для изменений полигонов проверить создание/редактирование/удаление в админке и попадание точки внутрь зоны на публичной странице.
- Для cron сначала проверить dry-run/тестовую БД; убедиться, что временные таблицы и основные данные остаются согласованными при ошибке.
- После массовых замен отдельно проверить русские строки на «кракозябры».
- Не считать отсутствие автоматических тестов основанием пропустить адресную проверку.