--- 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": "Магнит " } } }, ] ``` Будут отображены в таком виде: ![](https://i.imgur.com/NycAx6T.png) Сложность создаёт наличие разных типов данных внутри ячеек: 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 раз, при регистрации в системе, и почти не меняются. ## Страница Контрагент Содержит всю связанную с контрагентом информацию * юрлица * точки * договоры ## Страница Должности по договору Содержит все позиции (должности) со ставками. Открывается как вспомогательное окно из страницы Контрагента при нажатии на Договор. ## Табель Страница где по горизонтали выставляются работники, а по вертикали дни заданного периода. В заголовке выставляется контрагент или точка. Каждая ячейка, если заполнена, создаёт "Выход на работу" с заданным числом часов (или другой меры работы). По удержаниям можно сделать подобный табель, либо в одном совмещать обе Модели.