---
# System prepended metadata

title: Универсальная таблица

---

---
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 раз, при регистрации в системе, и почти не меняются. 

## Страница Контрагент 

Содержит всю связанную с контрагентом информацию 
* юрлица
* точки 
* договоры

## Страница Должности по договору 

Содержит все позиции (должности) со ставками. Открывается как вспомогательное окно из страницы Контрагента при нажатии на Договор.

## Табель 

Страница где по горизонтали выставляются работники, а по вертикали дни заданного периода. В заголовке выставляется контрагент или точка. Каждая ячейка, если заполнена, создаёт "Выход на работу" с заданным числом часов (или другой меры работы). 

По удержаниям можно сделать подобный табель, либо в одном совмещать обе Модели. 