---
image: https://i.imgur.com/NycAx6T.png
---
# Универсальная таблица
## Чтение
В файле \`columns.tsx\` создается универсальное отображение всех моделей бэкенда в виде таблицы.
Например, данные по ссылке `/contracts`:
```json
[
{
"id": 1,
"name": "Договор №1",
"date": "20.08.2021",
"jurperson": {
"id": 1,
"name": "ЗАО ОМЕГА, Татарстан",
"address": "адрес: город, улица, дом, офис",
"bankDetails": "Банковские реквизиты"
},
"counterpartyJurperson": {
"id": 1,
"name": "ООО Один",
"address": "адрес: город, улица, дом, офис",
"bankDetails": "Банковские реквизиты",
"counterpartyCompany": {
"id": 1,
"name": "Магнит "
}
}
},
]
```
Будут отображены в таком виде:

Сложность создаёт наличие разных типов данных внутри ячеек:
1. примитивные данные \- текст, число, дата ==`0й уровень вложенности`==
1. объект \- `{id, name}` ==`1й уровень вложенности`==
1. вложенные данные, когда объект ячейки получаем из объекта другого столбца (может быть несколько уровней вложенности) ==`2й и 3й уровни вложенности`==
1. комбинированные данные (`name` = `shortName` + `fullName`)
1. частично вложенные данные, когда хотим вывести в ячейку название вложенного столбца, но сохранить ссылку на исходную модель и её экземпляр
1. массив объектов (множество моделей)
Чтобы избежать этой сложности мы могли бы предварительно перед выводом модели сделать данные примитивным (строкой с названием). Но вместо этого мы помещаем в ячейку объект `{id, name}` и используем компонент отрисовки `renderCell`, чтобы представить там модель должным образом со всеми её параметрами. Это позволит нам открывать любую модель прямо из таблицы (например, для исправления). То есть любая ячейка таблицы связана с первоисточником.
Пример вложенных данных (3): `Выплата/Должность/Точка/Контрагент`. (3й уровень вложенности, пока самый глубокий)
Пример комбинированных данных (4), это Мера работы, она составляется из данных первого уровня (без использования вложенностей) `name = shortName + fullName`
Пример частичной вложенности (5) `Выход/Должность/Профессия`. Если вывести просто `Должность`, то будет услуга, типа "Разгрузочные работы", а нам надо указать "Грузчик", но чтобы при это сохранить ссылку на `Должность` по договору. Поэтому `{id}` попадает из `Должности`, а название из `Профессии`.
Пример многих моделей -- опциональные параметры работника или должности, каждый из которых является отдельной моделью.
Почему выбран подход писать универсальный компонент? Потому что очень много моделей и рутинного кода, чтобы отображать каждый из них. Если бы мы писали для каждой модели своё описание столбцов со всеми событиями, это было бы неподъемный объем рутины. В универсальном компоненте хоть и есть много отклонений от "одинаковости" в моделях, большинство кода получилось использовать однотипным.
## Запись
Если читать данные удобно в "расширенных" страницах, типа "покажи всех юрлиц" и мы видим общий список и столбец "Контрагент", чтобы фильтровать их и сортировать... То писать данные логично из "суженного" формата. Например, добавлять работников находясь на странице "Филиала". Потому что в универсальной странице, если мы вбиваем 10 работников, пришлось бы 10 раз указывать Филиал (каждому одинаковый), а на странице "Филиала" он и так понятен. То же самое касается Выходов -- им не надо выбирать каждому дату из календаря. Наоборот, мы смотрим на календарь с заранее проставленным периодом, и вписываем туда числа отработанных часов. То есть большинство информации уже подставлена (точка, должность, работник, число) и нам остаётся её немного уточнить/дополнить.
На базовом уровне запись можно разделить на 3 пункта.
1) Вбивание текста
2) Выбор одного (работника, точки и т.д.)
3) Выбор многих (опциональные параметры должности)
Для записи данных мы будем использовать те же таблицы, что для чтения но с доработками:
1. отсечение столбцов
1. предварительная загрузка данных для выбора
1. фильтрация данных
(1) Суть отсечения столбцов в том, что когда мы находимся на странице Контрагента и добавляем туда новые Юрлица, нам не нужен столбец Контрагент:
* для чтения он всегда один и тот же, и это будет ненужный шум
* для записи его нельзя менять, иначе юрлицо прикрепится к другому контрагенту
(2) Когда мы заполняем документы, например табель и нам нужно подставлять работников -- необходимо предварительно загрузить их. Пока данных не сильно много, это можно сделать за раз при первом открытии программы. Далее будем регулировать загружаемые данные по мере необходимости.
(3) Когда данные загружены, в конкретных документах надо фильтровать их, например, чтоб не приходилось выбирать из 100 человек, а из 10-20, по разным критериям. То же самое касается любой модели (которую приходится выбирать).
### Модели
Заглянем в файл`src/localization/ru.js`, там компактно описаны все наши модели:
```js
{
// Организация и её настройки
companies: 'Компания',
jurpersons: 'Юрлица',
units: 'Филиалы',
professions: 'Профессии',
'work-params': 'Доп.параметры (должности)',
'work-measures': 'Меры работы',
'redemption-types': 'Типы выплат/удержаний',
// Контрагенты и договоры
'counterparty-companies': 'Контрагенты',
'counterparty-jurpersons': 'Юрлица контрагентов',
'counterparty-units': 'Точки контрагентов',
contracts: 'Договоры',
positions: 'Должности (по договору)',
// Работники и события
workers: 'Работники',
redemptions: 'Выплаты/Удержания',
attendances: 'Выходы (на работу)',
}
```
Видно, что почти все модели малочисленные (ограниченное, медленно растущее число записей). Их можно загружать при первом открытии программы и точечно обновлять при правках. Только последний блок (Работники и события) является "текучим, бесконечным", для него есть смысл создать динамическую загрузку - загружать порциями по разным сценариям (смотря какой документ открыт, какой период выставлен и т.д.).
# Рабочие пространства
Запись данных происходит не в общей таблице модели, а в рабочем пространстве, где можно создавать, редактировать и выбирать много связанных моделей (с заранее проставленными данными).
## Организация и настройки
Эти данные создаются, грубо говоря, 1 раз, при регистрации в системе, и почти не меняются.
## Страница Контрагент
Содержит всю связанную с контрагентом информацию
* юрлица
* точки
* договоры
## Страница Должности по договору
Содержит все позиции (должности) со ставками. Открывается как вспомогательное окно из страницы Контрагента при нажатии на Договор.
## Табель
Страница где по горизонтали выставляются работники, а по вертикали дни заданного периода. В заголовке выставляется контрагент или точка. Каждая ячейка, если заполнена, создаёт "Выход на работу" с заданным числом часов (или другой меры работы).
По удержаниям можно сделать подобный табель, либо в одном совмещать обе Модели.