🧩 Логика «Итога»

Текущий проект: —

Общая идея

Страница «Итог» — это визуализация уже посчитанных данных. Сами расчёты делаются на вкладке «Расчёт зарплаты» (журнал смен) и в справочниках. «Итог» только собирает их в таблицу по шаблону Excel.

Документ каждый раз нового размера: фиксирована только шапка A1:L5, ниже — данные (4 строки на сотрудника) и смены справа.

Блок-схема

1. Загрузка данныхпроект · журнал смен · типы работ · сотрудники · ставки · надбавки
2. Фильтр типов работостаются смена / дежурство / пушка → колонки D, E, F
3. Фильтр сментолько смены, у которых есть записи в журнале
4. Для каждого сотрудника (mark = V)4 строки: ФИО / должность / базовая ставка
5. Колонки типов работстроки 6–8: coef (или ₽) по видам работ · строка 9: сумма sum
Складывать «просчёт» в первую колонку? (флаг)
да
Сложить в «Монтаж / Демонтаж»строки 6–8: + коэф · строка 9: + оплата
нет
Пропустить«просчёт» не учитывается
6. Рендер таблицы + экспорт Excel

Откуда берутся данные

Проект (Расчёт зарплаты → Проект)

  • name, venue — название и площадка (строка 1).
  • date_start, date_end — даты (день недели смен, строка 1).
  • employees — список {employee_id, mark}; берём только mark = "V" (галочка), в порядке списка.
  • shifts — список смен {name, type, start, end} (правые колонки).

Справочник «Персонал» (employees)

  • name — «Фамилия Имя» → разбиваем: первое слово = Фамилия, остальное = Имя.
  • position — должность (колонка B).
  • employment — занятость: «Не устроен» / «ИП» / «Самозанятый» (колонка B и базовая ставка).

Журнал смен (Расчёт зарплаты → Журнал смен)

  • Каждая строка — смена: employee_id, shift_type (тип смены), work_kind (вид работ), coef (коэффициент), sum (оплата).
  • Группируем по employee_id и work_kind.

Справочники (config)

  • base_rates — базовая ставка: {должность: {занятость: ставка}}.
  • allowances — надбавки: {должность: {вид работ: сумма}}.

Строки (4 на сотрудника)

Каждый сотрудник занимает 4 строки, начиная с 6-й:

СтрокаA (Сотрудник)B (Должность)C (Базовая ставка)
1-яФамилияДолжность + ЗанятостьБазовая ставка
2-яИмяДолжность + Занятость + Пром. альпинистБазовая ставка + надбавка (Пром. альпинист)
3-япустоДолжность + Занятость + РиггерБазовая ставка + надбавка (Риггер)
4-япустопустопусто

Вид «обычная» в колонке B подразумевается, но не пишется. Занятость «Не устроен» держим для расчёта, но в тексте не выводим.

Колонки A–C

A — Сотрудник

Из name сотрудника: первое слово → Фамилия (строка 1), остальное → Имя (строка 2), строки 3–4 пустые. Текст жирный, фон — выделенный блок темы (--bg-selected), внутренние границы блока невидимы.

B — Должность

Должность + Занятость + Вид работы. Занятость «Не устроен» в тексте не выводится.

C — Базовая ставка

  • строка 1 = base_rates[должность][занятость];
  • строка 2 = базовая ставка + allowances[должность]["Пром. альпинист"];
  • строка 3 = базовая ставка + allowances[должность]["Риггер"];
  • строка 4 = пусто.

Колонки типов работ (D, E, F…)

Колонки D, E, F… — это типы работ из справочника work_types. У каждого типа есть kind: coefficient (коэффициент) или hourly (почасовая оплата). Первая колонка подписывается «Монтаж / Демонтаж».

Строки 6–8 (по видам работ)

Для каждого вида работ (обычная, Пром. альпинист, Риггер) суммируются все смены сотрудника с shift_type = тип:

  • тип coefficient — сумма coef (коэффициентов);
  • тип hourly — сумма sum (оплаты, ₽).

Строка 9 (итог по типу)

Сумма sum (оплаты, ₽) всех смен сотрудника с shift_type = тип — по всем видам работ. Это фактические суммы из журнала смен, а не пересчёт «(база + надбавка) × коэф».

Для первой колонки дополнительно прибавляется сумма по сменам shift_type = «просчёт»: в строки 6–8 — коэффициент, в строку 9 — оплата.

Шапка раздела — цвет типа (TYPE_COLORS), белый текст. Строка 9: для coefficient — цвет типа + белый текст; для hourly — прозрачный фон + цвет темы. Денежный формат (₽).

Смены справа (колонки M и далее)

На каждую смену из project.shifts — блок из 2 колонок:

  • верхняя строка (2) — день недели, вычисляется от date_start проекта: смены идут парами День/Ночь, каждая пара = один день (смещение = floor(индекс / 2)); фон #4E7927, белый текст;
  • нижние строки (3–4) — название смены (project.shifts[i].name); фон — шапка таблицы темы (--bg-table-head);
  • вокруг блока — жирная рамка.

Ключевой код (условия)

Какие типы работ попадают в колонки D, E, F

workTypesData = (res[2] || []).filter(function (t) {
    return ['простой', 'погрузка', 'просчёт', 'пульт'].indexOf(t.name) === -1;
});

Остаются типы, не входящие в список: смена, дежурство, пушка.

Строки 6–8 (по видам работ)

if ((v.shift_type || '') === wt.name) {
    var val = (kind === 'hourly') ? num(v.sum) : num(v.coef);
    sums[workKind] = (sums[workKind] || 0) + val;
}

Почасовая оплата — сумма денег; коэффициент — сумма коэффициентов.

Строка 9 (итог по типу)

if ((v.shift_type || '') === td.name) {
    total += num(v.sum);
}

D9:F9 — фактические суммы оплаты из журнала, а не пересчёт «(база + надбавка) × коэф».

Спорное правило «просчёт»

if (ADD_PROSCHET_COEF_TO_MONTAZH) {
    montazh.sums[wk] += num(v.coef);  // строки 6–8: коэффициент
    typeTotals[0]    += num(v.sum);   // строка 9: оплата (₽)
}

Смены «просчёт» складываются в первую колонку («Монтаж / Демонтаж»).

Какие смены выводятся справа

var usedShiftNames = {};
journal.forEach(function (s) {
    var name = String((s.values && s.values.shift) || '').trim();
    if (name) usedShiftNames[name] = true;
});
// выводятся только смены с записями в журнале

Оформление

  • Шрифт всего документа — Calibri.
  • Высоты строк: 1 → 46.3, 2 → 36.9, 3 → 18.5, 4 → 18.9, 5 → 15, данные → 15.9 (пункты).
  • Ширины колонок A–K заданы из шаблона; смены — 14.15.
  • Строка 5 («$») — объединена, фон темы (--bg-hover), верх/низ — жирные границы.
  • Денежный формат: целые рубли, пробел через 3 знака, значок ₽, без копеек.
  • Текст, выходящий за границы ячейки, обрезается.