fix(table): закрыть пропуски исходного перечня AURORA-1892 по сверке 02.11.2026
validation.js: добавлены колонки, пропущенные в первой реализации (разделы 5/6.1 сверки) — approved.*, collegial.approved, ckk.*, contract_detail.* (включая amount_foreign), corrected_plan, pay_ho/pay_rf, booking, rem_actual/ residual_after_actual, qN.total, new_plan, data.qN.economy. Отдельно добавлен transfer_econ формы 2 — явное исключение из общего префикса transfer_*, так как перечень Салмина прямо требует контроль минуса для этих колонок (раздел 6.3, противоречие с Word). Тест validationUtils.test.js обновлён под это исключение и дополнен проверкой полноты перечня и отсутствия дублей с remaining-booking. FORM_1/OPER.js, AHR.js, CAP.js: перестановка колонок Q4 — «Комментарий» теперь перед «Скорректированный план 4 кв.» во всех пяти таблицах (раздел 8 сверки). Не включено (требует отдельного решения заказчика, раздел 12.2 сверки): контроль месячного факта/СПОД, контроль факта расшифровочных листов сверх плановых колонок, область действия правила для формы 4. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
d518961365
commit
4675b461d8
@ -3568,14 +3568,14 @@ export const config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Скорректированный план 4 кв. {year:short}',
|
||||
accessorKey: '4_kvartal_2026_skorr_plan_4_kv_26',
|
||||
header: 'Комментарий',
|
||||
accessorKey: '4_kvartal_2024_kommentariy',
|
||||
columns: [
|
||||
{
|
||||
header: 'Сумма, тыс. руб. (без НДС)',
|
||||
accessorKey: 'data.q4.corrected_plan',
|
||||
columnLetter: 'GH',
|
||||
size: 250,
|
||||
header: 'Сумма, тыс. руб. (с учётом НДС)',
|
||||
accessorKey: 'data.q4.adj_comment',
|
||||
columnLetter: 'GG',
|
||||
size: 300,
|
||||
filterFn: 'contains',
|
||||
},
|
||||
],
|
||||
@ -3587,14 +3587,14 @@ export const config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Комментарий',
|
||||
accessorKey: '4_kvartal_2024_kommentariy',
|
||||
header: 'Скорректированный план 4 кв. {year:short}',
|
||||
accessorKey: '4_kvartal_2026_skorr_plan_4_kv_26',
|
||||
columns: [
|
||||
{
|
||||
header: 'Сумма, тыс. руб. (с учётом НДС)',
|
||||
accessorKey: 'data.q4.adj_comment',
|
||||
columnLetter: 'GG',
|
||||
size: 300,
|
||||
header: 'Сумма, тыс. руб. (без НДС)',
|
||||
accessorKey: 'data.q4.corrected_plan',
|
||||
columnLetter: 'GH',
|
||||
size: 250,
|
||||
filterFn: 'contains',
|
||||
},
|
||||
],
|
||||
|
||||
@ -3582,13 +3582,13 @@ export const config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Скорректированный план 4 кв. {year:short}',
|
||||
accessorKey: '4_kvartal_2024_skorr_plan_4_kv_24',
|
||||
header: 'Комментарий',
|
||||
accessorKey: '4_kvartal_2024_kommentariy',
|
||||
columns: [
|
||||
{
|
||||
header: 'Сумма, тыс. руб. (с учётом НДС)',
|
||||
accessorKey: 'data.q4.corrected_plan',
|
||||
columnLetter: 'GH',
|
||||
accessorKey: 'data.q4.adj_comment',
|
||||
columnLetter: 'GG',
|
||||
size: 300,
|
||||
filterFn: 'contains',
|
||||
},
|
||||
@ -3601,13 +3601,13 @@ export const config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Комментарий',
|
||||
accessorKey: '4_kvartal_2024_kommentariy',
|
||||
header: 'Скорректированный план 4 кв. {year:short}',
|
||||
accessorKey: '4_kvartal_2024_skorr_plan_4_kv_24',
|
||||
columns: [
|
||||
{
|
||||
header: 'Сумма, тыс. руб. (с учётом НДС)',
|
||||
accessorKey: 'data.q4.adj_comment',
|
||||
columnLetter: 'GG',
|
||||
accessorKey: 'data.q4.corrected_plan',
|
||||
columnLetter: 'GH',
|
||||
size: 300,
|
||||
filterFn: 'contains',
|
||||
},
|
||||
|
||||
@ -3566,13 +3566,13 @@ export const config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Скорректированный план 4 кв. {year:short}',
|
||||
accessorKey: '4_kvartal_2024_skorr_plan_4_kv_24',
|
||||
header: 'Комментарий',
|
||||
accessorKey: '4_kvartal_2024_kommentariy',
|
||||
columns: [
|
||||
{
|
||||
header: 'Сумма, тыс. руб. (с учётом НДС)',
|
||||
accessorKey: 'data.q4.corrected_plan',
|
||||
columnLetter: 'GH',
|
||||
accessorKey: 'data.q4.adj_comment',
|
||||
columnLetter: 'GG',
|
||||
size: 300,
|
||||
filterFn: 'contains',
|
||||
},
|
||||
@ -3585,13 +3585,13 @@ export const config = {
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Комментарий',
|
||||
accessorKey: '4_kvartal_2024_kommentariy',
|
||||
header: 'Скорректированный план 4 кв. {year:short}',
|
||||
accessorKey: '4_kvartal_2024_skorr_plan_4_kv_24',
|
||||
columns: [
|
||||
{
|
||||
header: 'Сумма, тыс. руб. (с учётом НДС)',
|
||||
accessorKey: 'data.q4.adj_comment',
|
||||
columnLetter: 'GG',
|
||||
accessorKey: 'data.q4.corrected_plan',
|
||||
columnLetter: 'GH',
|
||||
size: 300,
|
||||
filterFn: 'contains',
|
||||
},
|
||||
|
||||
@ -88,7 +88,10 @@ const bookingLessBalanceRuleScope = {
|
||||
// Перечень — из вложения Салмина М.П. к AURORA-1892 (AURORA-1892_Перечень_колонок.md),
|
||||
// уточнённого кодовыми именами колонок (см. рулинги в PR). Корректировки и переносы
|
||||
// (adj_*, base_correction, revision_*, seq_*, target_change, transfer_*) сюда не входят —
|
||||
// там минус — нормальная операция.
|
||||
// там минус — нормальная операция. Исключение — transfer_econ (перенос в фонд экономии,
|
||||
// формы 2): перечень Салмина прямо требует контроль для этих колонок (см. сверку
|
||||
// AURORA-1892 от 02.11.2026, раздел 6.3); общий префикс transfer_* на этот ключ не
|
||||
// распространяется.
|
||||
export const nonNegativeColumnKeys = [
|
||||
// Основные листы форм 1, 2, 4 (Операц/АХР/КВ): план по кварталам и за год.
|
||||
"data.plan.q1",
|
||||
@ -165,6 +168,95 @@ export const nonNegativeColumnKeys = [
|
||||
"data.amount_q4",
|
||||
"data.limit_with_vat",
|
||||
"data.limit_without_vat",
|
||||
|
||||
// Доработка по сверке AURORA-1892 от 02.11.2026 (разделы 5, 6.1): колонки из
|
||||
// исходного перечня Салмина, пропущенные при первой реализации.
|
||||
// Платежи следующих лет и сумма других ССП.
|
||||
"data.contract_summary.future_y1",
|
||||
"data.contract_summary.future_y2",
|
||||
"data.contract_summary.other_ssp",
|
||||
|
||||
// Утверждённый план по кварталам и за год.
|
||||
"data.approved.q1",
|
||||
"data.approved.q2",
|
||||
"data.approved.q3",
|
||||
"data.approved.q4",
|
||||
"data.approved.year",
|
||||
|
||||
// Сумма коллегиального органа.
|
||||
"data.collegial.approved",
|
||||
|
||||
// Расходы ЦКК по кварталам и по сметам РФ.
|
||||
"data.ckk.q1",
|
||||
"data.ckk.q2",
|
||||
"data.ckk.q3",
|
||||
"data.ckk.q4",
|
||||
"data.ckk.rf_schedule",
|
||||
|
||||
// Расходы договора по кварталам, по сметам РФ и сумма в валюте.
|
||||
"data.contract_detail.q1",
|
||||
"data.contract_detail.q2",
|
||||
"data.contract_detail.q3",
|
||||
"data.contract_detail.q4",
|
||||
"data.contract_detail.rf_schedule",
|
||||
"data.contract_detail.amount_foreign",
|
||||
|
||||
// Скорректированный план по кварталам.
|
||||
"data.q1.corrected_plan",
|
||||
"data.q2.corrected_plan",
|
||||
"data.q3.corrected_plan",
|
||||
"data.q4.corrected_plan",
|
||||
|
||||
// Части платежа ГО и РФ.
|
||||
"data.q1.pay_ho",
|
||||
"data.q1.pay_rf",
|
||||
"data.q2.pay_ho",
|
||||
"data.q2.pay_rf",
|
||||
"data.q3.pay_ho",
|
||||
"data.q3.pay_rf",
|
||||
"data.q4.pay_ho",
|
||||
"data.q4.pay_rf",
|
||||
|
||||
// Бронь квартала (отдельно от ввода брони на 2026/2027 годы выше).
|
||||
"data.q1.booking",
|
||||
"data.q2.booking",
|
||||
"data.q3.booking",
|
||||
"data.q4.booking",
|
||||
|
||||
// Остаток после факта (формы 1 и 2 используют разные кодовые имена).
|
||||
"data.q1.rem_actual",
|
||||
"data.q2.rem_actual",
|
||||
"data.q3.rem_actual",
|
||||
"data.q4.rem_actual",
|
||||
"data.q1.residual_after_actual",
|
||||
"data.q2.residual_after_actual",
|
||||
"data.q3.residual_after_actual",
|
||||
"data.q4.residual_after_actual",
|
||||
|
||||
// Перенос в фонд экономии формы 1 (data.economy — другой ключ, чем transfer_econ
|
||||
// формы 2 ниже, и не входит в исключённый префикс transfer_*).
|
||||
"data.q1.economy",
|
||||
"data.q2.economy",
|
||||
"data.q3.economy",
|
||||
"data.q4.economy",
|
||||
|
||||
// Перенос в фонд экономии формы 2 — исключение из transfer_*, см. комментарий
|
||||
// к nonNegativeColumnKeys выше.
|
||||
"data.q1.transfer_econ",
|
||||
"data.q2.transfer_econ",
|
||||
"data.q3.transfer_econ",
|
||||
"data.q4.transfer_econ",
|
||||
|
||||
// Всего при закрытии квартала.
|
||||
"data.q1.total",
|
||||
"data.q2.total",
|
||||
"data.q3.total",
|
||||
"data.q4.total",
|
||||
|
||||
// Новый план на подпись (кварталов II–IV; для I квартала поле отсутствует).
|
||||
"data.q2.new_plan",
|
||||
"data.q3.new_plan",
|
||||
"data.q4.new_plan",
|
||||
];
|
||||
|
||||
const isNegativeNumber = (value) =>
|
||||
|
||||
@ -51,11 +51,15 @@ test('a scoped rule is disabled outside its form/sheet scope', () => {
|
||||
assert.equal(isValidationRuleEnabled(rule, { formType: 'FORM_2', sheetName: 'AHR' }), false);
|
||||
});
|
||||
|
||||
test('the shared nonNegativeColumnKeys list excludes correction and transfer columns', () => {
|
||||
test('the shared nonNegativeColumnKeys list excludes correction and transfer columns, except the explicit transfer_econ carve-out', () => {
|
||||
const excludedPrefixes = ['adj_', 'base_correction', 'revision_', 'seq_', 'target_change', 'transfer_'];
|
||||
// AURORA-1892, сверка 02.11.2026 (раздел 6.3): перечень Салмина прямо требует контроль
|
||||
// минуса для transfer_econ, в отличие от остальных transfer_* — это намеренное исключение.
|
||||
const allowedException = 'transfer_econ';
|
||||
|
||||
for (const key of nonNegativeColumnKeys) {
|
||||
const segment = key.split('.').pop();
|
||||
if (segment === allowedException) continue;
|
||||
for (const prefix of excludedPrefixes) {
|
||||
assert.equal(
|
||||
segment.startsWith(prefix),
|
||||
@ -65,3 +69,51 @@ test('the shared nonNegativeColumnKeys list excludes correction and transfer col
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('nonNegativeColumnKeys has no duplicate entries', () => {
|
||||
assert.equal(nonNegativeColumnKeys.length, new Set(nonNegativeColumnKeys).size);
|
||||
});
|
||||
|
||||
test('nonNegativeColumnKeys covers the gaps confirmed by the AURORA-1892 audit (02.11.2026)', () => {
|
||||
const mustInclude = [
|
||||
// Разделы 5/6.1 сверки: обязательные показатели, пропущенные в первой реализации.
|
||||
'data.contract_summary.future_y1',
|
||||
'data.contract_summary.other_ssp',
|
||||
'data.approved.q1',
|
||||
'data.approved.year',
|
||||
'data.collegial.approved',
|
||||
'data.ckk.q1',
|
||||
'data.ckk.rf_schedule',
|
||||
'data.contract_detail.q1',
|
||||
'data.contract_detail.amount_foreign',
|
||||
'data.q4.corrected_plan',
|
||||
'data.q1.pay_ho',
|
||||
'data.q1.pay_rf',
|
||||
'data.q1.booking',
|
||||
'data.q1.rem_actual',
|
||||
'data.q1.residual_after_actual',
|
||||
'data.q4.total',
|
||||
'data.q2.new_plan',
|
||||
// Раздел 6.3: исключение из transfer_* по прямому требованию перечня Салмина.
|
||||
'data.q1.transfer_econ',
|
||||
'data.q4.transfer_econ',
|
||||
// Раздел 5: экономия формы 1 — другой ключ, чем transfer_econ, не затронут исключением.
|
||||
'data.q1.economy',
|
||||
];
|
||||
|
||||
for (const key of mustInclude) {
|
||||
assert.ok(nonNegativeColumnKeys.includes(key), `${key} must be in nonNegativeColumnKeys`);
|
||||
}
|
||||
|
||||
// Д-статус из раздела 5/6.1: эти остатки уже покрыты правилом remaining-booking
|
||||
// и не должны дублироваться здесь (иначе пользователь увидит две причины ошибки).
|
||||
const mustExclude = [
|
||||
'data.q1.rem_booking',
|
||||
'data.q4.rem_booking',
|
||||
'data.q1.residual_after_booking',
|
||||
'data.q4.residual_after_booking',
|
||||
];
|
||||
for (const key of mustExclude) {
|
||||
assert.ok(!nonNegativeColumnKeys.includes(key), `${key} is already covered by remaining-booking and must not duplicate here`);
|
||||
}
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user