feat: migrate to VitePress from monorepo docs, add test-contour section
This commit is contained in:
+474
@@ -0,0 +1,474 @@
|
||||
# Модели данных
|
||||
|
||||
Эта страница описывает основные сущности, найденные в `apps/backend/src/Entity` и `apps/cabinet/src/Entity`. В проектах есть много справочных полей; ниже выделены доменные ядра и связи, которые важны для понимания системы.
|
||||
|
||||
## Backend ER-схема
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
SPECIALIST ||--o{ LOCATION : "id -> specialist_id"
|
||||
SPECIALIST ||--o{ REVIEW : "id -> specialist_id"
|
||||
SPECIALIST ||--o{ SPECIALIST_DOCS : "id -> specialist_id"
|
||||
SPECIALIST ||--o{ SPECIALIST_DCODE_DESCRIPTION : "id -> specialist_id"
|
||||
SPECIALIST }o--o{ STOCK : "join table"
|
||||
RECORD ||--o| ALERT_SMS : "id -> record_id"
|
||||
WIDGET_FORM ||--o{ WIDGET_FORM_INPUT : "id -> widget_form_id"
|
||||
|
||||
SPECIALIST {
|
||||
int id PK
|
||||
string name
|
||||
string alias
|
||||
int region_id
|
||||
string post
|
||||
string experience
|
||||
bool active
|
||||
bool display_schedule
|
||||
jsonb dcodes
|
||||
}
|
||||
|
||||
LOCATION {
|
||||
bigint id PK
|
||||
int specialist_id FK
|
||||
bigint dcode
|
||||
bigint department
|
||||
int filial
|
||||
bool online_mode
|
||||
date nearest_date
|
||||
}
|
||||
|
||||
REVIEW {
|
||||
int id PK
|
||||
int specialist_id FK
|
||||
bool active
|
||||
date date_create
|
||||
string author
|
||||
float rating
|
||||
string source
|
||||
int external_id
|
||||
}
|
||||
|
||||
SPECIALIST_DOCS {
|
||||
int id PK
|
||||
int specialist_id FK
|
||||
string name
|
||||
string picture
|
||||
bool active
|
||||
string type
|
||||
}
|
||||
|
||||
SPECIALIST_DCODE_DESCRIPTION {
|
||||
int id PK
|
||||
int specialist_id FK
|
||||
bigint dcode
|
||||
bigint department
|
||||
text content
|
||||
}
|
||||
|
||||
STOCK {
|
||||
int id PK
|
||||
string name
|
||||
text content
|
||||
date start_date
|
||||
date end_date
|
||||
}
|
||||
|
||||
RECORD {
|
||||
int id PK
|
||||
int specialist_id
|
||||
string phone
|
||||
datetime create_at
|
||||
string hash
|
||||
json reserve
|
||||
}
|
||||
|
||||
ALERT_SMS {
|
||||
int id PK
|
||||
int record_id FK
|
||||
datetime date_create
|
||||
text response
|
||||
}
|
||||
|
||||
WIDGET_FORM {
|
||||
int id PK
|
||||
string name
|
||||
}
|
||||
|
||||
WIDGET_FORM_INPUT {
|
||||
int id PK
|
||||
int widget_form_id FK
|
||||
string text
|
||||
string type
|
||||
string bitrix24_id
|
||||
int sort
|
||||
}
|
||||
```
|
||||
|
||||
### Backend: перевод сущностей
|
||||
|
||||
| Сущность на диаграмме | Русское название | Смысл |
|
||||
| --- | --- | --- |
|
||||
| `SPECIALIST` | Врач | Карточка врача в новом API |
|
||||
| `LOCATION` | Локация приема | Привязка врача к отделению, филиалу и режиму приема |
|
||||
| `REVIEW` | Отзыв | Отзыв о враче |
|
||||
| `SPECIALIST_DOCS` | Документ врача | Сертификат/документ/изображение врача |
|
||||
| `SPECIALIST_DCODE_DESCRIPTION` | Описание врача по `dcode` | Текстовое описание для конкретного кода врача/отделения |
|
||||
| `STOCK` | Акция | Акция, связанная с врачами через `ManyToMany` |
|
||||
| `RECORD` | Запись пациента | Локальная запись факта бронирования |
|
||||
| `ALERT_SMS` | SMS-уведомление | Ответ SMS-провайдера по записи |
|
||||
| `WIDGET_FORM` | Форма виджета | Конструктор формы |
|
||||
| `WIDGET_FORM_INPUT` | Поле формы | Поле формы виджета |
|
||||
|
||||
### Backend: ключи связей
|
||||
|
||||
| Связь | Тип | Ключи |
|
||||
| --- | --- | --- |
|
||||
| Врач -> Локация приема | `OneToMany` / `ManyToOne` | `specialist.id = location.specialist_id` |
|
||||
| Врач -> Отзыв | `OneToMany` / `ManyToOne` | `specialist.id = review.specialist_id` |
|
||||
| Врач -> Документ врача | `OneToMany` / `ManyToOne` | Doctrine создает `specialist_docs.specialist_id -> specialist.id` |
|
||||
| Врач -> Описание по dcode | `ManyToOne` на стороне описания | `specialist_dcode_description.specialist_id -> specialist.id` |
|
||||
| Врач <-> Акция | `ManyToMany` | join-таблица генерируется Doctrine; владелец связи `Stock::$specialist` |
|
||||
| Запись -> SMS-уведомление | `OneToOne` | Doctrine создает `alert_sms.record_id -> record.id` |
|
||||
| Форма виджета -> Поле формы | `OneToMany` / `ManyToOne` | Doctrine создает `widget_form_input.widget_form_id -> widget_form.id` |
|
||||
|
||||
`Record.specialistId` в backend не является Doctrine-связью с `Specialist`: это логический внешний идентификатор врача, сохраненный как число.
|
||||
|
||||
## Backend справочники и контент
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Department {
|
||||
id
|
||||
did
|
||||
name
|
||||
groupName
|
||||
onlineMode
|
||||
alias
|
||||
active
|
||||
}
|
||||
|
||||
class Filial {
|
||||
id
|
||||
fid
|
||||
name
|
||||
address
|
||||
regionId
|
||||
siteId
|
||||
company
|
||||
phone
|
||||
email
|
||||
}
|
||||
|
||||
class PriceDepartment {
|
||||
id
|
||||
name
|
||||
groupId
|
||||
doctCount
|
||||
viewInWeb
|
||||
}
|
||||
|
||||
class PriceList {
|
||||
id
|
||||
kodoper
|
||||
schname
|
||||
specname
|
||||
speccode
|
||||
priceInfo
|
||||
discprice
|
||||
filial
|
||||
groupId
|
||||
}
|
||||
|
||||
class SiteService {
|
||||
id
|
||||
name
|
||||
alias
|
||||
regionId
|
||||
anons
|
||||
content
|
||||
faq
|
||||
tags
|
||||
clinics
|
||||
}
|
||||
|
||||
class Disease {
|
||||
id
|
||||
name
|
||||
alias
|
||||
regionId
|
||||
symptom
|
||||
content
|
||||
tags
|
||||
staffList
|
||||
}
|
||||
|
||||
class MedicalCenter {
|
||||
id
|
||||
name
|
||||
alias
|
||||
regionId
|
||||
doctors
|
||||
services
|
||||
content
|
||||
}
|
||||
|
||||
class Article {
|
||||
id
|
||||
name
|
||||
alias
|
||||
doctors
|
||||
services
|
||||
content
|
||||
}
|
||||
|
||||
class News {
|
||||
id
|
||||
name
|
||||
alias
|
||||
regionId
|
||||
content
|
||||
photos
|
||||
}
|
||||
|
||||
class Promo {
|
||||
id
|
||||
name
|
||||
alias
|
||||
regionId
|
||||
clinics
|
||||
period
|
||||
}
|
||||
```
|
||||
|
||||
## Cabinet ER-схема
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
CITY ||--o{ FILIAL : "id -> city_id"
|
||||
CITY ||--o{ REVIEW_SOURCE : "id -> city_id"
|
||||
CITY ||--o| BANNER : "id -> city_id"
|
||||
FILIAL ||--o{ REVIEW_SOURCE : "id -> filial_id"
|
||||
CATEGORY_PAGE ||--o{ PAGE : "id -> category_id"
|
||||
RECORD ||--o| ALERT_SMS : "id -> record_id"
|
||||
WIDGET_FORM ||--o{ WIDGET_FORM_INPUT : "id -> widget_form_id"
|
||||
|
||||
CITY {
|
||||
int id PK
|
||||
string name
|
||||
int region_id
|
||||
int time_zone
|
||||
}
|
||||
|
||||
FILIAL {
|
||||
int id PK
|
||||
int city_id FK
|
||||
int fid
|
||||
string name
|
||||
string address
|
||||
int site_id
|
||||
bool active
|
||||
string company
|
||||
}
|
||||
|
||||
REVIEW_SOURCE {
|
||||
int id PK
|
||||
int city_id FK
|
||||
int filial_id FK
|
||||
string name
|
||||
int count_row
|
||||
bool active
|
||||
float rating
|
||||
date date_create
|
||||
}
|
||||
|
||||
BANNER {
|
||||
int id PK
|
||||
int city_id FK
|
||||
string href
|
||||
string src
|
||||
bool active
|
||||
}
|
||||
|
||||
CATEGORY_PAGE {
|
||||
int id PK
|
||||
string name
|
||||
bool active
|
||||
}
|
||||
|
||||
PAGE {
|
||||
int id PK
|
||||
int category_id FK
|
||||
string name
|
||||
string alias
|
||||
text description
|
||||
bool active
|
||||
}
|
||||
|
||||
RECORD {
|
||||
int id PK
|
||||
int specialist_id
|
||||
string phone
|
||||
datetime create_at
|
||||
string hash
|
||||
json reserve
|
||||
}
|
||||
|
||||
ALERT_SMS {
|
||||
int id PK
|
||||
int record_id FK
|
||||
datetime date_create
|
||||
text response
|
||||
}
|
||||
|
||||
WIDGET_FORM {
|
||||
int id PK
|
||||
string name
|
||||
}
|
||||
|
||||
WIDGET_FORM_INPUT {
|
||||
int id PK
|
||||
int widget_form_id FK
|
||||
string text
|
||||
string type
|
||||
string bitrix24_id
|
||||
int sort
|
||||
}
|
||||
```
|
||||
|
||||
### Cabinet: перевод сущностей
|
||||
|
||||
| Сущность на диаграмме | Русское название | Смысл |
|
||||
| --- | --- | --- |
|
||||
| `CITY` | Город | Региональная привязка кабинета |
|
||||
| `FILIAL` | Филиал | Клиника/филиал, привязанный к городу |
|
||||
| `REVIEW_SOURCE` | Источник отзывов | Внешний источник рейтинга/отзывов по городу или филиалу |
|
||||
| `BANNER` | Баннер | Региональный баннер |
|
||||
| `CATEGORY_PAGE` | Категория страниц | Группа CMS-страниц |
|
||||
| `PAGE` | Страница | CMS-страница |
|
||||
| `RECORD` | Запись пациента | Локальная запись факта бронирования |
|
||||
| `ALERT_SMS` | SMS-уведомление | Ответ SMS-провайдера по записи |
|
||||
| `WIDGET_FORM` | Форма виджета | Конструктор формы |
|
||||
| `WIDGET_FORM_INPUT` | Поле формы | Поле формы виджета |
|
||||
|
||||
### Cabinet: ключи связей
|
||||
|
||||
| Связь | Тип | Ключи |
|
||||
| --- | --- | --- |
|
||||
| Город -> Филиал | `OneToMany` / `ManyToOne` | Doctrine создает `filial.city_id -> city.id` |
|
||||
| Город -> Источник отзывов | `OneToMany` / `ManyToOne` | Doctrine создает `review_source.city_id -> city.id`, `nullable=false` |
|
||||
| Город -> Баннер | `OneToOne` | Doctrine создает `banner.city_id -> city.id` |
|
||||
| Филиал -> Источник отзывов | `OneToMany` / `ManyToOne` | Doctrine создает `review_source.filial_id -> filial.id` |
|
||||
| Категория страниц -> Страница | `OneToMany` / `ManyToOne` | Doctrine создает `page.category_id -> category_page.id`, `nullable=false` |
|
||||
| Запись -> SMS-уведомление | `OneToOne` | Doctrine создает `alert_sms.record_id -> record.id` |
|
||||
| Форма виджета -> Поле формы | `OneToMany` / `ManyToOne` | Doctrine создает `widget_form_input.widget_form_id -> widget_form.id` |
|
||||
|
||||
`Record.specialistId`, `SpecialistView.dcode`, `LocationView.specialistId`, `PriceList.filial`, `PriceList.groupId`, `PriceList.kodoper` в cabinet используются как логические внешние ключи и фильтры, но не оформлены как Doctrine relations.
|
||||
|
||||
## Cabinet представления и справочники
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class SpecialistView {
|
||||
id
|
||||
name
|
||||
speciality
|
||||
category
|
||||
experience
|
||||
description
|
||||
alias
|
||||
dcode
|
||||
regionId
|
||||
kodoper
|
||||
acceptsDms
|
||||
}
|
||||
|
||||
class LocationView {
|
||||
id
|
||||
dcode
|
||||
department
|
||||
filial
|
||||
specialistId
|
||||
onlineMode
|
||||
active
|
||||
nearestDate
|
||||
}
|
||||
|
||||
class PriceDepartment {
|
||||
id
|
||||
name
|
||||
groupId
|
||||
groupName
|
||||
doctCount
|
||||
viewInWeb
|
||||
}
|
||||
|
||||
class PriceList {
|
||||
id
|
||||
kodoper
|
||||
schname
|
||||
specname
|
||||
speccode
|
||||
priceInfo
|
||||
discprice
|
||||
filial
|
||||
groupId
|
||||
}
|
||||
|
||||
class User {
|
||||
id
|
||||
email
|
||||
roles
|
||||
uid
|
||||
token
|
||||
fullName
|
||||
phone
|
||||
confirm
|
||||
createdAt
|
||||
lastActivityAt
|
||||
}
|
||||
|
||||
class Usrlog {
|
||||
id
|
||||
pcode
|
||||
agent
|
||||
clientIp
|
||||
method
|
||||
createdAt
|
||||
}
|
||||
|
||||
class DirectCompany {
|
||||
id
|
||||
name
|
||||
companyId
|
||||
city
|
||||
}
|
||||
|
||||
class DirectReport {
|
||||
id
|
||||
date
|
||||
adGroupId
|
||||
campaignId
|
||||
adId
|
||||
impressions
|
||||
clicks
|
||||
cost
|
||||
conversions
|
||||
}
|
||||
```
|
||||
|
||||
## Общие доменные понятия
|
||||
|
||||
- `Specialist` / `SpecialistView` - врач. В `backend` это полноценная сущность с явными связями; в `cabinet` это view-модель для чтения.
|
||||
- `Location` / `LocationView` - где и как врач принимает.
|
||||
- `PriceList` и `PriceDepartment` - прайс и группы услуг.
|
||||
- `Record` - запись пациента, хранит payload бронирования в `reserve`.
|
||||
- `AlertSms` - SMS-уведомление по записи.
|
||||
- `Filial` и `Department` - филиалы и отделения.
|
||||
- `Review` и `ReviewSource` - отзывы и источники отзывов.
|
||||
- `WidgetForm` и `WidgetFormInput` - динамические формы для виджетов.
|
||||
|
||||
## Особенности модели
|
||||
|
||||
- В `backend` используются PHP attributes Doctrine, в `cabinet` - annotations.
|
||||
- Часть связей хранится не как Doctrine relation, а как внешние идентификаторы (`dcode`, `fid`, `did`, `regionId`, `groupId`, `kodoper`). Это важно: не все связи можно увидеть по `ManyToOne`.
|
||||
- `backend` подключается к нескольким источникам данных: основной PostgreSQL, Bitrix MySQL и базе cabinet.
|
||||
- `cabinet` содержит view-сущности (`SpecialistView`, `LocationView`), поэтому часть данных, вероятно, приходит из SQL views или синхронизированных таблиц.
|
||||
Reference in New Issue
Block a user