Compare commits

...

5 Commits

Author SHA1 Message Date
coopops 995f65f524 [989-10][@ant] fix: убрать лишний поясняющий хинт у поля «Рег. номер ПФР» — по замечанию пользователя ни у одного другого поля в реквизитах/форме ЕФС-1 такого хинта нет, заполняющий и так знает, что это за номер 2026-07-21 19:12:09 +00:00
coopops 5298e55a7b [989-10][@ant] fix: ЕФС-1 (4-ФСС) — использовать рег. номер ПФР, а не СФР, в имени файла и <ЕФС8:РегНомер>
Сторонние бухгалтерские системы (СБИС и др.) при приёме ЕФС-1 отклоняли выгруженный XML: "Рег. номер отправителя из наименования файла не соответствует ни рег. номеру ПФР организации, ни рег. номеру СФР". Причина в двух местах:
1) generateGenericFileName для FSS4 хардкодил сегмент отправителя как "0000000000" — реальный номер туда не попадал вообще (тот же класс бага, что чинили в idFile для нулёвок ранее).
2) fss4.generator.ts писал в <ЕФС8:РегНомер> sfrRegNumber (10-значный унифицированный номер СФР) — но внешние системы сверяют этот тег с рег. номером ПФР организации (формат XXX-XXX-XXXXXX), который у них уже настроен через канал ФСС ЭДО, а не с номером СФР.

Добавлено отдельное обязательное поле pfrRegNumber (report_requisites.pfr_reg_number, XXX-XXX-XXXXXX) — не заменяет sfrRegNumber (оставлен, вдруг понадобится), а используется отдельно для генерации ЕФС-1: и в сегменте имени файла, и в теге <ЕФС8:РегНомер>. Заодно сузили маску sfrRegNumber до строго 10 цифр (раньше маска дублировала формат ПФР и два поля выглядели взаимозаменяемыми — по замечанию в ревью). Цепочка regen пройдена (generate-schema → generate-client → sdk build), controller tsc и desktop vue-tsc чистые, добавлены/обновлены unit-тесты Fss4Generator.
2026-07-21 18:45:12 +00:00
coopops db28ba1137 [989-10][@ant] fix: чинить генерацию имени файла нулёвых отчётов (idFile/ИдФайл) — терялся код формы ФНС/СФР
generateGenericFileName брал префикс как первый underscore-сегмент имени XSD (xsd.split('_')[0]), а для всех форм с xsdFile вида 'NO_<Форма>_...' первый сегмент всегда равен 'NO' — код формы (NDFL6.2, RASCHSV, PERSSVFL, USN, UVISCHSUMNAL) терялся из имени файла. Внешние системы (в частности приёмка Сбера) отклоняли выгруженный XML как нераспознанный по имени, а после ручного добавления '_NDFL6.2_' в имя падала уже сверка тега <ИдФайл> с фактическим именем файла — оба генерировались одной и той же испорченной функцией. Исправлено: префикс строится из первых двух сегментов XSD-имени (slice(0, 2)), что совпадает с реальным форматом имени файла ФНС/СФР и с эталонными фикстурами tests/fixtures/reports-references/*.
2026-07-21 16:23:21 +00:00
coopops 6a05e88ba1 [989-10][@ant] fix: убрать stack-раскладку (иконка над текстом) у кнопок панели действий в ReportEditorDialog расширения reports — canon-паддинг q-btn (0 14px, без вертикального зазора) при вертикальной раскладке icon+label прижимал иконку к верхней границе кнопки, из-за чего панель «Действия»/«Скачать»/«Отметить сданным» выглядела недоделанной; иконка возвращена в строку рядом с текстом 2026-07-21 15:56:09 +00:00
coopops 09eaa6192c [reports][@ant] fix: показывать серверные ошибки валидации формы отчёта для полей шапки и строк баланса — счётчик «Ошибок: N» был непрозрачным без единой подсказки
BuhotchEditor/ZeroReportEditor подключали fieldErrors только для части полей
(организация, часть подписанта). Поля шапки (reportYear/period/docDate/
correctionNumber) и все строки баланса (BalanceRowEditor — otch/prev/prePrev)
не имели inline-подсветки вообще, хотя backend (validateReportEdits) исправно
возвращал path+message. В проде это привело к невидимой ошибке
organization.ogrn — 12 vs 13 цифр (опечатка в реквизитах, отдельно исправлена
data-фиксом в organizations, не кодом).

- BalanceRowEditor: добавлены basePath/fieldErrors пропсы, подсветка otch/prev/prePrev.
- BuhotchEditor: прокинул field-errors во все 6 BalanceRowEditor, подключил
  header.reportYear/docDate/correctionNumber.
- ZeroReportEditor: подключил header.reportYear/period.
- ReportEditorDialog: добавлен явный список ошибок (path → человекочитаемое
  сообщение) в панели действий — страховка на случай ещё не подключённых полей.
2026-07-21 15:45:20 +00:00
26 changed files with 317 additions and 52 deletions
@@ -1,7 +1,7 @@
import { ObjectType, Field, InputType, registerEnumType } from '@nestjs/graphql';
import { IsOptional, IsString, IsIn, Matches, MaxLength } from 'class-validator';
import { ReportType } from '../../domain/enums/report-type.enum';
import { SFR_REG_NUMBER_PATTERN } from '../../domain/patterns';
import { SFR_REG_NUMBER_PATTERN, PFR_REG_NUMBER_PATTERN } from '../../domain/patterns';
export enum RequisiteSource {
DATABASE = 'database',
@@ -44,6 +44,7 @@ export class ReportRequisitesViewDTO {
@Field(() => RequisiteFieldViewDTO) oktmo!: RequisiteFieldViewDTO;
@Field(() => RequisiteFieldViewDTO) okpo!: RequisiteFieldViewDTO;
@Field(() => RequisiteFieldViewDTO) sfrRegNumber!: RequisiteFieldViewDTO;
@Field(() => RequisiteFieldViewDTO) pfrRegNumber!: RequisiteFieldViewDTO;
@Field(() => RequisiteFieldViewDTO) chairmanPosition!: RequisiteFieldViewDTO;
@Field(() => RequisiteFieldViewDTO) signerSnils!: RequisiteFieldViewDTO;
@Field(() => RequisiteFieldViewDTO) signerRepDoc!: RequisiteFieldViewDTO;
@@ -66,7 +67,10 @@ export class ReportRequisitesViewDTO {
* ОКТМО — `\d{8}` или `\d{11}`
* ОКПО — `\d{8}` или `\d{10}`
* СНИЛС — `\d{3}-\d{3}-\d{3} \d{2}` (14 симв.) или 11 цифр подряд
* РегНом СФР — `\d{3}-\d{3}-\d{6}` (14 симв. с тире) или 10 цифр подряд
* РегНом СФР — `\d{10}` (10 цифр подряд, без тире)
* РегНом ПФР — `\d{3}-\d{3}-\d{6}` (14 симв. с тире), только этот формат —
* отдельное поле от РегНом СФР, требуется для ЕФС-1 (внешние
* бухгалтерские системы сверяют его при приёме отчёта)
*/
@InputType('UpdateReportRequisitesInput')
export class UpdateReportRequisitesInputDTO {
@@ -100,12 +104,18 @@ export class UpdateReportRequisitesInputDTO {
@Matches(/^\d{8}(\d{2})?$/, { message: 'ОКПО — 8 или 10 цифр' })
okpo?: string | null;
@Field(() => String, { nullable: true, description: 'Рег. номер СФР — XXX-XXX-XXXXXX или 10 цифр' })
@Field(() => String, { nullable: true, description: 'Рег. номер СФР — 10 цифр' })
@IsOptional()
@IsString()
@Matches(SFR_REG_NUMBER_PATTERN, { message: 'Рег. номер СФР — XXX-XXX-XXXXXX или 10 цифр' })
@Matches(SFR_REG_NUMBER_PATTERN, { message: 'Рег. номер СФР — 10 цифр' })
sfrRegNumber?: string | null;
@Field(() => String, { nullable: true, description: 'Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР)' })
@IsOptional()
@IsString()
@Matches(PFR_REG_NUMBER_PATTERN, { message: 'Рег. номер ПФР — XXX-XXX-XXXXXX' })
pfrRegNumber?: string | null;
@Field(() => String, { nullable: true })
@IsOptional()
@IsString()
@@ -21,6 +21,7 @@ import {
OKTMO_PATTERN,
OKVED_PATTERN,
SFR_REG_NUMBER_PATTERN,
PFR_REG_NUMBER_PATTERN,
SNILS_PATTERN,
DATE_DDMMYYYY_PATTERN,
} from '../../domain/patterns';
@@ -200,9 +201,14 @@ export class ZeroReportSignerEditsInputDTO {
@Field(() => String, { nullable: true })
@IsOptional()
@Matches(SFR_REG_NUMBER_PATTERN, { message: 'Рег.номер СФР — XXX-XXX-XXXXXX или 10 цифр' })
@Matches(SFR_REG_NUMBER_PATTERN, { message: 'Рег.номер СФР — 10 цифр' })
sfrRegNumber!: string | null;
@Field(() => String, { nullable: true })
@IsOptional()
@Matches(PFR_REG_NUMBER_PATTERN, { message: 'Рег.номер ПФР — XXX-XXX-XXXXXX' })
pfrRegNumber!: string | null;
@Field(() => String, { nullable: true })
@IsOptional()
@IsString()
@@ -219,6 +225,7 @@ export class ZeroReportSignerEditsDTO {
@Field(() => String, { nullable: true }) repDoc!: string | null;
@Field(() => String, { nullable: true }) snils!: string | null;
@Field(() => String, { nullable: true }) sfrRegNumber!: string | null;
@Field(() => String, { nullable: true }) pfrRegNumber!: string | null;
@Field(() => String, { nullable: true }) chairmanPosition!: string | null;
}
@@ -53,6 +53,7 @@ export class ReportRequisitesResolver {
oktmo: input.oktmo ?? undefined,
okpo: input.okpo ?? undefined,
sfr_reg_number: input.sfrRegNumber ?? undefined,
pfr_reg_number: input.pfrRegNumber ?? undefined,
chairman_position: input.chairmanPosition ?? undefined,
signer_snils: input.signerSnils ?? undefined,
signer_rep_doc: input.signerRepDoc ?? undefined,
@@ -109,6 +110,7 @@ function toView(m: MergedRequisites): ReportRequisitesViewDTO {
oktmo: f(m.oktmo),
okpo: f(m.okpo),
sfrRegNumber: f(m.sfrRegNumber),
pfrRegNumber: f(m.pfrRegNumber),
chairmanPosition: f(m.chairmanPosition),
signerSnils: f(m.signerSnils),
signerRepDoc: f(m.signerRepDoc),
@@ -51,6 +51,14 @@ export interface ZeroReportSignerShape {
snils: string | null;
/** Регистрационный номер в СФР — обязателен для ЕФС-1. */
sfrRegNumber: string | null;
/**
* Регистрационный номер в ПФР (XXX-XXX-XXXXXX) — обязателен для ЕФС-1,
* попадает и в <ЕФС8:РегНомер>, и в имя файла. Отдельное поле от
* sfrRegNumber: сторонние бухгалтерские системы (СБИС и др.) при приёме
* ЕФС-1 сверяют номер отправителя именно с рег. номером ПФР организации,
* не с 10-значным номером СФР.
*/
pfrRegNumber: string | null;
/** Должность председателя — для ЕФС-1 (<УТ8:Должность>). */
chairmanPosition: string | null;
}
@@ -47,7 +47,7 @@ export interface ReportInput {
correctionNumber?: number;
/** СНИЛС председателя (для ПСВ) */
signerSnils?: string;
/** Регистрационный номер страхователя в СФР/ПФР (для ЕФС-1). */
/** Регистрационный номер страхователя в СФР (для ЕФС-1). Legacy-путь — актуальные генераторы берут ZeroReportSignerShape.pfrRegNumber отдельно. */
sfrRegNumber?: string;
/** Должность руководителя для подачи в СФР (по умолчанию «Председатель Совета»). */
chairmanPosition?: string;
@@ -43,9 +43,19 @@ export const OKPO_PATTERN = /^\d{8}(\d{2})?$/;
// СНИЛС: XXX-XXX-XXX YY (с пробелом/тире) или 11 цифр подряд.
export const SNILS_PATTERN = /^(\d{3}-\d{3}-\d{3} \d{2}|\d{11})$/;
// Регистрационный номер СФР: действующий XXX-XXX-XXXXXX (3-3-6, 12 цифр)
// или прежний — 10 цифр без разделителей (ТипРегНомерОбщ в XSD ЕФС-1).
export const SFR_REG_NUMBER_PATTERN = /^(\d{3}-\d{3}-\d{6}|\d{10})$/;
// Регистрационный номер страхователя в СФР: только 10 цифр без разделителей
// (унифицированный номер СФР, ТипРегНомерОбщ в XSD ЕФС-1). Формат
// XXX-XXX-XXXXXX сюда больше не входит — он теперь отдельное поле
// PFR_REG_NUMBER_PATTERN, чтобы два похожих номера не путались в одной маске.
export const SFR_REG_NUMBER_PATTERN = /^\d{10}$/;
// Регистрационный номер страхователя в ПФР: только формат XXX-XXX-XXXXXX
// (3-3-6, 12 цифр с тире) — старый/«действующий» формат, который сверяют
// сторонние бухгалтерские системы (СБИС и др.) при приёме ЕФС-1. Это
// отдельное поле от sfrRegNumber (10-значный унифицированный номер СФР):
// внешние системы могут не знать организацию по 10-значному номеру, но
// знать по этому.
export const PFR_REG_NUMBER_PATTERN = /^\d{3}-\d{3}-\d{6}$/;
/** Дата в формате `DD.MM.YYYY` (XSD `xs:date`-совместимый ФНС-формат). */
export const DATE_DDMMYYYY_PATTERN = /^\d{2}\.\d{2}\.\d{4}$/;
@@ -10,6 +10,7 @@ export interface ReportRequisitesRecord {
oktmo: string | null;
okpo: string | null;
sfr_reg_number: string | null;
pfr_reg_number: string | null;
chairman_position: string | null;
signer_snils: string | null;
signer_rep_doc: string | null;
@@ -28,6 +29,7 @@ export interface UpsertReportRequisitesInput {
oktmo?: string | null;
okpo?: string | null;
sfr_reg_number?: string | null;
pfr_reg_number?: string | null;
chairman_position?: string | null;
signer_snils?: string | null;
signer_rep_doc?: string | null;
@@ -203,7 +203,12 @@ export class ReportEditsBuilderService {
return {
header: {
idFile: this.generateGenericFileName(reportType, merged.inn.value ?? '', merged.kpp.value ?? ''),
idFile: this.generateGenericFileName(
reportType,
merged.inn.value ?? '',
merged.kpp.value ?? '',
merged.pfrRegNumber.value,
),
versProgram: 'Платформа отчётности кооператива 1.0',
docDate: formatDate(new Date()),
reportYear: year,
@@ -230,6 +235,7 @@ export class ReportEditsBuilderService {
repDoc: merged.signerRepDoc.value,
snils: merged.signerSnils.value,
sfrRegNumber: merged.sfrRegNumber.value,
pfrRegNumber: merged.pfrRegNumber.value,
chairmanPosition:
merged.chairmanPosition.value || merged.chairmanPositionFromOrg.value,
},
@@ -243,19 +249,33 @@ export class ReportEditsBuilderService {
return 1;
}
private generateGenericFileName(reportType: ReportType, inn: string, kpp: string): string {
// Упрощённый префикс по типу отчёта — точный формат имени зависит от
// формы (NO_NDFL6.2_..., СФР_..._ЕФС-1_...), но для предварительного
// idFile достаточно. Генератор сам перезапишет его при необходимости.
private generateGenericFileName(
reportType: ReportType,
inn: string,
kpp: string,
pfrRegNumber?: string | null,
): string {
// Префикс = первые два underscore-сегмента имени XSD (например,
// 'NO_NDFL6.2_1_231_...xsd' → 'NO_NDFL6.2', 'UT_UVISCHSUMNAL_...xsd' →
// 'UT_UVISCHSUMNAL') — это и есть код формата в имени файла по формату
// ФНС/СФР. Брать только первый сегмент нельзя: для всех форм с 'NO_'
// в начале он всегда равен 'NO' и код формы (NDFL6.2/RASCHSV/PERSSVFL/
// USN) терялся — импорт стороннего ПО (Сбер и др.) отклонял файл как
// нераспознанный по имени.
const xsd = REPORT_CONFIG[reportType]?.xsdFile ?? 'REPORT';
const prefix = xsd.split('_')[0] ?? 'REPORT';
const prefix = xsd.split('_').slice(0, 2).join('_') || 'REPORT';
const now = new Date();
const dateStr = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`;
const unit = `${inn}${kpp}`;
const tax = kpp.substring(0, 4);
const uuid = randomUUID();
if (reportType === ReportType.FSS4) {
return `СФР_0000000000_ЕФС-1_${dateStr}_${uuid}`;
// Сегмент отправителя в имени файла — рег. номер ПФР организации, не
// заглушка из нулей: сторонние бухгалтерские системы (СБИС и др.)
// сверяют этот сегмент со своим профилем организации и отклоняют файл,
// если он не совпадает ни с известным им номером ПФР, ни с номером
// СФР. См. также <ЕФС8:РегНомер> в fss4.generator.ts — то же значение.
return `СФР_${pfrRegNumber || '0000000000'}_ЕФС-1_${dateStr}_${uuid}`;
}
return `${prefix}_${tax}_${tax}_${unit}_${dateStr}_${uuid}`;
}
@@ -39,6 +39,8 @@ export interface MergedRequisites {
oktmo: RequisiteField;
okpo: RequisiteField;
sfrRegNumber: RequisiteField;
/** Рег. номер страхователя в ПФР (XXX-XXX-XXXXXX) — отдельный от sfrRegNumber, требуется для ЕФС-1. */
pfrRegNumber: RequisiteField;
chairmanPosition: RequisiteField;
signerSnils: RequisiteField;
signerRepDoc: RequisiteField;
@@ -94,6 +96,7 @@ const REQUIRED_BY_TYPE: Record<ReportType, RequiredFieldSpec[]> = {
[ReportType.FSS4]: [
{ key: 'oktmo', label: 'ОКТМО', source: 'manual' },
{ key: 'sfrRegNumber', label: 'Регистрационный номер в СФР', source: 'manual' },
{ key: 'pfrRegNumber', label: 'Регистрационный номер в ПФР', source: 'manual' },
{ key: 'chairmanPosition', label: 'Должность руководителя', source: 'manual' },
],
[ReportType.PSV]: [{ key: 'signerSnils', label: 'СНИЛС подписанта', source: 'manual' }],
@@ -152,6 +155,7 @@ export class ReportRequisitesService {
oktmo: mn(manual?.oktmo),
okpo: mn(manual?.okpo),
sfrRegNumber: mn(manual?.sfr_reg_number),
pfrRegNumber: mn(manual?.pfr_reg_number),
chairmanPosition: mn(manual?.chairman_position),
signerSnils: mn(manual?.signer_snils),
signerRepDoc: mn(manual?.signer_rep_doc),
@@ -218,6 +222,7 @@ export class ReportRequisitesService {
oktmo: input.oktmo ?? undefined,
okpo: input.okpo ?? undefined,
sfr_reg_number: input.sfr_reg_number ?? undefined,
pfr_reg_number: input.pfr_reg_number ?? undefined,
chairman_position: input.chairman_position ?? undefined,
signer_snils: input.signer_snils ?? undefined,
signer_rep_doc: input.signer_rep_doc ?? undefined,
@@ -5,6 +5,7 @@ import { Entity, Column, PrimaryColumn, UpdateDateColumn } from 'typeorm';
*
* Хранятся поля, которых нет в профиле организации (`IOrganizationData` в
* основной БД кооператива): ОКВЭД, ОКФС, ОКОПФ, ОКТМО, ОКПО, регномер СФР,
* регномер ПФР (для ЕФС-1 — отдельный от regномера СФР, см. patterns.ts),
* должность руководителя, СНИЛС подписанта, описание доверенности. Плюс
* возможные override'ы телефона и адреса (если в отчётности нужен не тот,
* что в профиле организации).
@@ -34,6 +35,9 @@ export class ReportRequisitesEntity {
@Column({ type: 'varchar', length: 32, nullable: true })
sfr_reg_number?: string | null;
@Column({ type: 'varchar', length: 32, nullable: true })
pfr_reg_number?: string | null;
@Column({ type: 'varchar', length: 255, nullable: true })
chairman_position?: string | null;
@@ -68,6 +68,13 @@ export class Fss4Generator implements IReportGenerator {
const errors: string[] = [];
if (!edits.signer.sfrRegNumber) {
errors.push('Для ЕФС-1 обязателен рег. номер страхователя в СФР (поле signer.sfrRegNumber)');
}
if (!edits.signer.pfrRegNumber) {
// pfrRegNumber, а не sfrRegNumber, идёт в <ЕФС8:РегНомер> и в имя
// файла — см. комментарий у strah.ele('ЕФС8:РегНомер') ниже.
errors.push('Для ЕФС-1 обязателен рег. номер страхователя в ПФР (поле signer.pfrRegNumber)');
}
if (errors.length) {
return { reportType: this.reportType, xml: '', fileName, errors, isValid: false };
}
try {
@@ -100,8 +107,13 @@ export class Fss4Generator implements IReportGenerator {
const efs1 = edsfr.ele('ЕФС-1');
const strah = efs1.ele('Страхователь');
// sfrRegNumber гарантированно определён — guard в generate() выше.
strah.ele('ЕФС8:РегНомер').txt(signer.sfrRegNumber ?? '').up();
// Тег «Действующий регистрационный номер страхователя» (см. XSD
// efs-types.xsd/ТипСтрахователь) — сюда идёт номер ПФР, а не СФР:
// сторонние бухгалтерские системы (СБИС и др.) при приёме ЕФС-1 сверяют
// рег. номер отправителя в имени файла и в этом теге со своим профилем
// организации, где обычно заведён именно старый номер ПФР (XXX-XXX-XXXXXX).
// pfrRegNumber гарантированно определён — guard в generate() выше.
strah.ele('ЕФС8:РегНомер').txt(signer.pfrRegNumber ?? '').up();
strah.ele('ЕФС8:Наименование').txt(organization.orgName).up();
strah.ele('УТ8:ИНН').txt(organization.inn).up();
strah.ele('УТ8:КПП').txt(organization.kpp).up();
@@ -39,6 +39,7 @@ export class ReportRequisitesTypeormRepository implements ReportRequisitesReposi
if (input.oktmo !== undefined) row.oktmo = input.oktmo;
if (input.okpo !== undefined) row.okpo = input.okpo;
if (input.sfr_reg_number !== undefined) row.sfr_reg_number = input.sfr_reg_number;
if (input.pfr_reg_number !== undefined) row.pfr_reg_number = input.pfr_reg_number;
if (input.chairman_position !== undefined) row.chairman_position = input.chairman_position;
if (input.signer_snils !== undefined) row.signer_snils = input.signer_snils;
if (input.signer_rep_doc !== undefined) row.signer_rep_doc = input.signer_rep_doc;
@@ -66,6 +67,7 @@ export class ReportRequisitesTypeormRepository implements ReportRequisitesReposi
oktmo: entity.oktmo ?? null,
okpo: entity.okpo ?? null,
sfr_reg_number: entity.sfr_reg_number ?? null,
pfr_reg_number: entity.pfr_reg_number ?? null,
chairman_position: entity.chairman_position ?? null,
signer_snils: entity.signer_snils ?? null,
signer_rep_doc: entity.signer_rep_doc ?? null,
@@ -202,6 +202,7 @@ const zeroBaseEdits: ZeroReportEditsShape = {
repDoc: 'Доверенность №1 от 01.01.2024',
snils: '123-456-789 00',
sfrRegNumber: '7701234567',
pfrRegNumber: '087-701-579643',
chairmanPosition: 'Председатель Совета',
},
};
@@ -581,6 +582,21 @@ describe('ЕФС-1 (Fss4Generator, СФР)', () => {
expect(result.errors.join('|')).toContain('sfrRegNumber');
});
it('возвращает ошибку без pfrRegNumber', () => {
const result = gen.generate({
...withPeriod(1),
signer: { ...zeroBaseEdits.signer, pfrRegNumber: null },
});
expect(result.isValid).toBe(false);
expect(result.errors.join('|')).toContain('pfrRegNumber');
});
it('использует pfrRegNumber (не sfrRegNumber) в <ЕФС8:РегНомер> — сторонние бухгалтерские системы сверяют именно рег. номер ПФР', () => {
const result = gen.generate(withPeriod(1));
expect(result.xml).toContain('<ЕФС8:РегНомер>087-701-579643</ЕФС8:РегНомер>');
expect(result.xml).not.toContain('<ЕФС8:РегНомер>7701234567</ЕФС8:РегНомер>');
});
it('эхом возвращает header.idFile в result.fileName', () => {
const result = gen.generate({
...withPeriod(1),
+2
View File
@@ -4821,6 +4821,7 @@ export const ReturnTypes: Record<string,any> = {
oktmo:"RequisiteFieldView",
okved:"RequisiteFieldView",
orgName:"RequisiteFieldView",
pfrRegNumber:"RequisiteFieldView",
phone:"RequisiteFieldView",
sfrRegNumber:"RequisiteFieldView",
signerFirstName:"RequisiteFieldView",
@@ -5063,6 +5064,7 @@ export const ReturnTypes: Record<string,any> = {
firstName:"String",
lastName:"String",
middleName:"String",
pfrRegNumber:"String",
repDoc:"String",
sfrRegNumber:"String",
snils:"String",
+20 -4
View File
@@ -9043,6 +9043,7 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
oktmo?:ValueTypes["RequisiteFieldView"],
okved?:ValueTypes["RequisiteFieldView"],
orgName?:ValueTypes["RequisiteFieldView"],
pfrRegNumber?:ValueTypes["RequisiteFieldView"],
phone?:ValueTypes["RequisiteFieldView"],
sfrRegNumber?:ValueTypes["RequisiteFieldView"],
signerFirstName?:ValueTypes["RequisiteFieldView"],
@@ -10179,8 +10180,10 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
oktmo?: string | undefined | null | Variable<any, string>,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null | Variable<any, string>,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null | Variable<any, string>,
phoneOverride?: string | undefined | null | Variable<any, string>,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null | Variable<any, string>,
signerRepDoc?: string | undefined | null | Variable<any, string>,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -10482,6 +10485,7 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
firstName?:boolean | `@${string}`,
lastName?:boolean | `@${string}`,
middleName?:boolean | `@${string}`,
pfrRegNumber?:boolean | `@${string}`,
repDoc?:boolean | `@${string}`,
sfrRegNumber?:boolean | `@${string}`,
snils?:boolean | `@${string}`,
@@ -18204,6 +18208,7 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
oktmo?:ResolverInputTypes["RequisiteFieldView"],
okved?:ResolverInputTypes["RequisiteFieldView"],
orgName?:ResolverInputTypes["RequisiteFieldView"],
pfrRegNumber?:ResolverInputTypes["RequisiteFieldView"],
phone?:ResolverInputTypes["RequisiteFieldView"],
sfrRegNumber?:ResolverInputTypes["RequisiteFieldView"],
signerFirstName?:ResolverInputTypes["RequisiteFieldView"],
@@ -19317,8 +19322,10 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
oktmo?: string | undefined | null,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null,
phoneOverride?: string | undefined | null,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null,
signerRepDoc?: string | undefined | null,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -19614,6 +19621,7 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
firstName?:boolean | `@${string}`,
lastName?:boolean | `@${string}`,
middleName?:boolean | `@${string}`,
pfrRegNumber?:boolean | `@${string}`,
repDoc?:boolean | `@${string}`,
sfrRegNumber?:boolean | `@${string}`,
snils?:boolean | `@${string}`,
@@ -27847,6 +27855,7 @@ export type ModelTypes = {
oktmo: ModelTypes["RequisiteFieldView"],
okved: ModelTypes["RequisiteFieldView"],
orgName: ModelTypes["RequisiteFieldView"],
pfrRegNumber: ModelTypes["RequisiteFieldView"],
phone: ModelTypes["RequisiteFieldView"],
sfrRegNumber: ModelTypes["RequisiteFieldView"],
signerFirstName: ModelTypes["RequisiteFieldView"],
@@ -28930,8 +28939,10 @@ export type ModelTypes = {
oktmo?: string | undefined | null,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null,
phoneOverride?: string | undefined | null,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null,
signerRepDoc?: string | undefined | null,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -29214,6 +29225,7 @@ export type ModelTypes = {
firstName: string,
lastName: string,
middleName?: string | undefined | null,
pfrRegNumber?: string | undefined | null,
repDoc?: string | undefined | null,
sfrRegNumber?: string | undefined | null,
snils?: string | undefined | null,
@@ -37955,6 +37967,7 @@ export type GraphQLTypes = {
oktmo: GraphQLTypes["RequisiteFieldView"],
okved: GraphQLTypes["RequisiteFieldView"],
orgName: GraphQLTypes["RequisiteFieldView"],
pfrRegNumber: GraphQLTypes["RequisiteFieldView"],
phone: GraphQLTypes["RequisiteFieldView"],
sfrRegNumber: GraphQLTypes["RequisiteFieldView"],
signerFirstName: GraphQLTypes["RequisiteFieldView"],
@@ -39090,8 +39103,10 @@ export type GraphQLTypes = {
oktmo?: string | undefined | null,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null,
phoneOverride?: string | undefined | null,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null,
signerRepDoc?: string | undefined | null,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -39395,6 +39410,7 @@ export type GraphQLTypes = {
firstName: string,
lastName: string,
middleName?: string | undefined | null,
pfrRegNumber?: string | undefined | null,
repDoc?: string | undefined | null,
sfrRegNumber?: string | undefined | null,
snils?: string | undefined | null,
@@ -116,6 +116,21 @@ q-dialog(
span(v-if='isValid') Форма валидна
span(v-else) Ошибок: {{ errorsCount }}
//- Явный список ошибок полей — страховка на случай, если конкретное
//- поле формы не подсвечивается инлайн (не все секции формы ещё
//- подключены к fieldErrors). Без этого списка счётчик показывал
//- «Ошибок: N» без единой подсказки, где именно искать.
q-list.error-list.q-mb-sm(
v-if='!isValid && fieldErrorEntries.length'
dense bordered separator
)
q-item(v-for='err in fieldErrorEntries' :key='err.key' dense)
q-item-section(avatar top)
q-icon(name='fa-solid fa-circle-exclamation' color='negative' size='14px')
q-item-section
q-item-label.text-caption.text-weight-medium {{ err.label }}
q-item-label(caption) {{ err.message }}
.text-subtitle2.q-mb-sm Действия
q-btn.q-mb-sm(
@@ -126,7 +141,6 @@ q-dialog(
:loading='isGenerating'
@click='downloadXml'
no-caps
stack
)
q-tooltip Сохраняет черновик, генерирует XML, валидирует XSD и скачивает файл
q-btn.q-mb-sm(
@@ -137,7 +151,6 @@ q-dialog(
:loading='pdfLoading'
@click='downloadPdf'
no-caps
stack
)
q-tooltip(v-if='!hasPdfPaperView') PDF-экспорт для {{ reportTitle }} пока не поддерживается
q-tooltip(v-else) Заполненный отчёт в PDF (из бумажного вида)
@@ -152,7 +165,6 @@ q-dialog(
:disable='isLoading'
@click='regenerate'
no-caps
stack
)
q-tooltip Подтянуть актуальные данные из реестра; ваши правки сохраняются
@@ -164,7 +176,6 @@ q-dialog(
label='Удалить черновик'
@click='clearDraft'
no-caps
stack
)
q-tooltip Вернуть форму к дефолтам
@@ -192,7 +203,6 @@ q-dialog(
:loading='markLoading'
@click='clearMark'
no-caps
stack
)
q-tooltip Вернуть обычный статус периода
@@ -207,7 +217,6 @@ q-dialog(
:loading='markLoading'
@click='clearMark'
no-caps
stack
)
q-tooltip Вернуть обычный статус периода
@@ -220,7 +229,6 @@ q-dialog(
:loading='markLoading'
@click='markSubmittedExternally'
no-caps
stack
)
q-tooltip Если отчёт уже сдан в бумаге / через стороннюю систему. В архив XML не попадает, но ячейка станет зелёной.
q-btn(
@@ -231,7 +239,6 @@ q-dialog(
:loading='markLoading'
@click='markNotRequired'
no-caps
stack
)
q-tooltip Отметить, что этот период сдавать не нужно ячейка станет серой
@@ -484,6 +491,7 @@ interface ZeroReportEdits {
repDoc: string | null
snils: string | null
sfrRegNumber: string | null
pfrRegNumber: string | null
chairmanPosition: string | null
}
}
@@ -513,6 +521,34 @@ const errorsCount = computed(() => {
return count
})
// Человекочитаемые названия секций формы — для расшифровки JSONPath из
// серверной ошибки валидации (см. error-list ниже).
const FIELD_SECTION_LABELS: Record<string, string> = {
header: 'Шапка',
organization: 'Организация',
signer: 'Подписант',
balance: 'Баланс',
notes: 'Пояснения',
}
function humanizeFieldPath(path: string): string {
const [section, ...rest] = path.split('.')
const sectionLabel = FIELD_SECTION_LABELS[section] ?? section
return rest.length ? `${sectionLabel}${rest.join(' → ')}` : sectionLabel
}
interface FieldErrorEntry { key: string; label: string; message: string }
const fieldErrorEntries = computed<FieldErrorEntry[]>(() => {
const out: FieldErrorEntry[] = []
for (const [path, messages] of Object.entries(fieldErrors.value)) {
messages.forEach((message, i) => {
out.push({ key: `${path}#${i}`, label: humanizeFieldPath(path), message })
})
}
return out
})
const saveStatusColor = computed(() => {
if (isSaving.value) return 'orange'
if (hasDraft.value) return 'positive'
@@ -839,6 +875,22 @@ function goToRequisites(): void {
}
}
.error-list {
background: var(--p-surface-1, #fff);
border-color: var(--p-neg-soft);
max-height: 220px;
overflow-y: auto;
:deep(.q-item) {
min-height: unset;
padding: 6px 8px;
}
:deep(.q-item__label--caption) {
color: var(--p-ink-2);
}
}
.mark-hint {
font-size: var(--p-fs-meta, 12px);
color: var(--p-ink-2);
@@ -46,11 +46,11 @@ q-form.settings-page(@submit.prevent='save' @validation-error='onValidationError
@update:value='v => (manualInput[f.key] = v)'
)
//- СФР (ЕФС-1)
//- СФР/ПФР (ЕФС-1)
q-card.q-mt-md(flat)
q-card-section.q-py-sm
.text-h6 СФР (для ЕФС-1)
.text-caption.t-muted Регистрационный номер СФР и должность председателя
.text-h6 СФР/ПФР (для ЕФС-1)
.text-caption.t-muted Регистрационные номера страхователя и должность председателя
q-separator
@@ -60,14 +60,27 @@ q-form.settings-page(@submit.prevent='save' @validation-error='onValidationError
id='field-sfrRegNumber'
label='Рег. номер СФР'
:value='manualInput.sfrRegNumber'
placeholder='XXX-XXX-XXXXXX или 10 цифр'
digits-extra-chars='-'
:max-length='14'
placeholder='10 цифр'
mask='##########'
:max-length='10'
:exact-lengths='[10]'
:pattern='SFR_REG_PATTERN'
pattern-message='Формат: XXX-XXX-XXXXXX (12 цифр) или 10 цифр без разделителей'
pattern-message='Формат: 10 цифр без разделителей'
required
@update:value='v => (manualInput.sfrRegNumber = v)'
)
RequisiteField.col-md-6.col-12(
id='field-pfrRegNumber'
label='Рег. номер ПФР'
:value='manualInput.pfrRegNumber'
placeholder='XXX-XXX-XXXXXX'
mask='###-###-######'
:max-length='14'
:pattern='PFR_REG_PATTERN'
pattern-message='Формат: XXX-XXX-XXXXXX (12 цифр с тире)'
required
@update:value='v => (manualInput.pfrRegNumber = v)'
)
RequisiteField.col-md-6.col-12(
id='field-chairmanPosition'
label='Должность председателя'
@@ -164,6 +177,7 @@ type ManualKey =
| 'oktmo'
| 'okpo'
| 'sfrRegNumber'
| 'pfrRegNumber'
| 'chairmanPosition'
| 'signerSnils'
| 'signerRepDoc'
@@ -177,6 +191,7 @@ const manualInput = reactive<Record<ManualKey, string>>({
oktmo: '',
okpo: '',
sfrRegNumber: '',
pfrRegNumber: '',
chairmanPosition: '',
signerSnils: '',
signerRepDoc: '',
@@ -266,7 +281,8 @@ const signerTypeOptions = [
// пользователь прожал пару цифр и нажал «Сохранить»: mask не мешает
// сохранить частичный ввод, паттерн-правило блокирует.
const SNILS_PATTERN = /^\d{3}-\d{3}-\d{3} \d{2}$/
const SFR_REG_PATTERN = /^(\d{3}-\d{3}-\d{6}|\d{10})$/
const SFR_REG_PATTERN = /^\d{10}$/
const PFR_REG_PATTERN = /^\d{3}-\d{3}-\d{6}$/
function getValue(key: keyof IReportRequisitesView): string {
const v = requisites.value?.[key] as any
@@ -9,6 +9,8 @@
@update:model-value='v => emitField("otch", v)'
dense outlined
input-class='text-right'
:error='errFor("otch")'
:error-message='msgFor("otch")'
)
.br-input
q-input(
@@ -17,6 +19,8 @@
@update:model-value='v => emitField("prev", v)'
dense outlined
input-class='text-right'
:error='errFor("prev")'
:error-message='msgFor("prev")'
)
.br-input
q-input(
@@ -25,6 +29,8 @@
@update:model-value='v => emitField("prePrev", v)'
dense outlined
input-class='text-right'
:error='errFor("prePrev")'
:error-message='msgFor("prePrev")'
)
</template>
@@ -39,6 +45,10 @@ const props = defineProps<{
label: string
code: string
row: BalanceRow | null
/** JSONPath строки без учёта суффикса (например "balance.assetsTotal") — для сопоставления с fieldErrors. */
basePath?: string
/** Серверные ошибки валидации всей формы: ключ = JSONPath поля. */
fieldErrors?: Record<string, string[]>
}>()
const emit = defineEmits<{
@@ -58,6 +68,18 @@ function emitField(key: keyof BalanceRow, raw: unknown): void {
const next: BalanceRow = { ...base, [key]: clamp(raw) }
emit('update', next)
}
function pathFor(key: keyof BalanceRow): string {
return props.basePath ? `${props.basePath}.${key}` : key
}
function errFor(key: keyof BalanceRow): boolean {
return (props.fieldErrors?.[pathFor(key)]?.length ?? 0) > 0
}
function msgFor(key: keyof BalanceRow): string {
return props.fieldErrors?.[pathFor(key)]?.[0] ?? ''
}
</script>
<style scoped lang="scss">
@@ -11,6 +11,8 @@
:model-value='editsValue.header.correctionNumber'
@update:model-value='v => updateField("header.correctionNumber", clampInt(v, 0, 999))'
:rules='[v => (v >= 0 && v <= 999) || "0..999"]'
:error='errFor("header.correctionNumber")'
:error-message='msgFor("header.correctionNumber")'
dense filled
)
q-input(
@@ -18,6 +20,8 @@
type='number'
:model-value='editsValue.header.reportYear'
@update:model-value='v => updateField("header.reportYear", clampInt(v, 2000, 2100))'
:error='errFor("header.reportYear")'
:error-message='msgFor("header.reportYear")'
dense filled
)
q-input(
@@ -26,6 +30,8 @@
@update:model-value='v => updateField("header.docDate", v)'
mask='##.##.####'
:rules='[reportRules.dateDdMmYyyy()]'
:error='errFor("header.docDate")'
:error-message='msgFor("header.docDate")'
dense filled
)
@@ -191,24 +197,32 @@
label='Нематериальные, финансовые и др. внеоборотные активы'
code='1170'
:row='editsValue.balance.nonMaterialAndLongFin'
base-path='balance.nonMaterialAndLongFin'
:field-errors='props.fieldErrors'
@update='row => updateRow("balance.nonMaterialAndLongFin", row)'
)
BalanceRowEditor(
label='Денежные средства и денежные эквиваленты'
code='1250'
:row='editsValue.balance.cash'
base-path='balance.cash'
:field-errors='props.fieldErrors'
@update='row => updateRow("balance.cash", row)'
)
BalanceRowEditor(
label='Финансовые и другие оборотные активы'
code='1260'
:row='editsValue.balance.shortTermFin'
base-path='balance.shortTermFin'
:field-errors='props.fieldErrors'
@update='row => updateRow("balance.shortTermFin", row)'
)
BalanceRowEditor.total(
label='БАЛАНС (актив)'
code='1600'
:row='editsValue.balance.assetsTotal'
base-path='balance.assetsTotal'
:field-errors='props.fieldErrors'
@update='row => updateRow("balance.assetsTotal", row)'
)
@@ -218,12 +232,16 @@
label='Целевые средства (паевой фонд + целевые поступления)'
code='1350'
:row='editsValue.balance.targetFunds'
base-path='balance.targetFunds'
:field-errors='props.fieldErrors'
@update='row => updateRow("balance.targetFunds", row)'
)
BalanceRowEditor.total(
label='БАЛАНС (пассив)'
code='1700'
:row='editsValue.balance.passivesTotal'
base-path='balance.passivesTotal'
:field-errors='props.fieldErrors'
@update='row => updateRow("balance.passivesTotal", row)'
)
@@ -26,8 +26,8 @@
.kv-row
.kv-cell
.kv-label Регистрационный номер в СФР
.kv-value.code {{ header.sfrRegNumber || '—' }}
.kv-label Регистрационный номер страхователя
.kv-value.code {{ header.pfrRegNumber || '—' }}
.kv-cell
.kv-label ОГРН
.kv-value.code {{ ogrn || '—' }}
@@ -9,6 +9,8 @@
type='number'
:model-value='editsValue.header.reportYear'
@update:model-value='v => updateField("header.reportYear", clampInt(v, 2000, 2100))'
:error='errFor("header.reportYear")'
:error-message='msgFor("header.reportYear")'
dense filled
)
q-input(
@@ -17,6 +19,8 @@
type='number'
:model-value='editsValue.header.period'
@update:model-value='v => updateField("header.period", clampInt(v, 1, periodKind === "quarter" ? 4 : 12))'
:error='errFor("header.period")'
:error-message='msgFor("header.period")'
dense filled
)
q-input(
@@ -162,8 +166,20 @@
:rules='[reportRules.sfrRegNumber()]'
:error='errFor("signer.sfrRegNumber")'
:error-message='msgFor("signer.sfrRegNumber")'
maxlength='10'
hint='10 цифр — обязателен для ЕФС-1'
dense filled
)
q-input(
v-if='needs.sfrExtras'
label='Регистрационный номер ПФР'
:model-value='editsValue.signer.pfrRegNumber || ""'
@update:model-value='v => updateField("signer.pfrRegNumber", v || null)'
:rules='[reportRules.pfrRegNumber()]'
:error='errFor("signer.pfrRegNumber")'
:error-message='msgFor("signer.pfrRegNumber")'
maxlength='14'
hint='XXX-XXX-XXXXXX или 10 цифр — обязателен для ЕФС-1'
dense filled
)
@@ -215,6 +231,7 @@ interface ZeroReportEdits {
repDoc: string | null
snils: string | null
sfrRegNumber: string | null
pfrRegNumber: string | null
chairmanPosition: string | null
}
}
@@ -33,7 +33,8 @@ export interface BaseHeader {
signerMiddleName: string
signerRepDoc: string
signerSnils: string
sfrRegNumber: string
/** Рег. номер ПФР — читается из тега `<РегНомер>` ЕФС-1 (fss4.generator.ts кладёт туда именно ПФР, не СФР). */
pfrRegNumber: string
}
export interface UseReportXmlReturn {
@@ -117,7 +118,7 @@ export function useReportXml(
signerLastName: '', signerFirstName: '', signerMiddleName: '',
signerRepDoc: '',
signerSnils: '',
sfrRegNumber: '',
pfrRegNumber: '',
}
if (!doc.value) return withRequisites(empty)
@@ -147,7 +148,7 @@ export function useReportXml(
signerMiddleName: getAttr('Подписант ФИО', 'Отчество') || getText('Отчество'),
signerRepDoc: getAttr('Подписант СвПред', 'НаимДок'),
signerSnils: getAttr('ПерсСвФЛ', 'СНИЛС'),
sfrRegNumber: getText('РегНомер'),
pfrRegNumber: getText('РегНомер'),
}
return withRequisites(h)
})
@@ -174,7 +175,7 @@ export function useReportXml(
signerFirstName: h.signerFirstName || get('signerFirstName'),
signerMiddleName: h.signerMiddleName || get('signerMiddleName'),
signerSnils: h.signerSnils || get('signerSnils'),
sfrRegNumber: h.sfrRegNumber || get('sfrRegNumber'),
pfrRegNumber: h.pfrRegNumber || get('pfrRegNumber'),
}
}
@@ -41,8 +41,11 @@ export const OKPO_PATTERN = /^\d{8}(\d{2})?$/;
/** СНИЛС: XXX-XXX-XXX YY или 11 цифр подряд. */
export const SNILS_PATTERN = /^(\d{3}-\d{3}-\d{3} \d{2}|\d{11})$/;
/** Регистрационный номер СФР: действующий XXX-XXX-XXXXXX (3-3-6, 12 цифр) или прежний — 10 цифр без разделителей. */
export const SFR_REG_NUMBER_PATTERN = /^(\d{3}-\d{3}-\d{6}|\d{10})$/;
/** Регистрационный номер страхователя в СФР: 10 цифр без разделителей (унифицированный номер). */
export const SFR_REG_NUMBER_PATTERN = /^\d{10}$/;
/** Регистрационный номер страхователя в ПФР: XXX-XXX-XXXXXX (3-3-6, 12 цифр с тире) — отдельное поле от SFR_REG_NUMBER_PATTERN, требуется для ЕФС-1. */
export const PFR_REG_NUMBER_PATTERN = /^\d{3}-\d{3}-\d{6}$/;
/** Дата в формате DD.MM.YYYY (ФНС). */
export const DATE_DDMMYYYY_PATTERN = /^\d{2}\.\d{2}\.\d{4}$/;
@@ -70,7 +73,8 @@ export const reportRules = {
okopf: (message = 'ОКОПФ — 5 цифр') => (v: unknown) => OKOPF_PATTERN.test(String(v ?? '')) || message,
okpo: (message = 'ОКПО — 8 или 10 цифр') => (v: unknown) => OKPO_PATTERN.test(String(v ?? '')) || message,
snils: (message = 'СНИЛС — XXX-XXX-XXX YY или 11 цифр') => (v: unknown) => SNILS_PATTERN.test(String(v ?? '')) || message,
sfrRegNumber: (message = 'Рег. номер СФР — XXX-XXX-XXXXXX или 10 цифр') => (v: unknown) => SFR_REG_NUMBER_PATTERN.test(String(v ?? '')) || message,
sfrRegNumber: (message = 'Рег. номер СФР — 10 цифр') => (v: unknown) => SFR_REG_NUMBER_PATTERN.test(String(v ?? '')) || message,
pfrRegNumber: (message = 'Рег. номер ПФР — XXX-XXX-XXXXXX') => (v: unknown) => PFR_REG_NUMBER_PATTERN.test(String(v ?? '')) || message,
dateDdMmYyyy: (message = 'Дата — DD.MM.YYYY') => (v: unknown) => DATE_DDMMYYYY_PATTERN.test(String(v ?? '')) || message,
kbk: (message = 'КБК — 20 цифр') => (v: unknown) => KBK_PATTERN.test(String(v ?? '')) || message,
/** Непустая строка длиной от `min` до `max` символов. */
@@ -24,6 +24,7 @@ export const rawReportRequisitesViewSelector = {
oktmo: rawRequisiteFieldViewSelector,
okpo: rawRequisiteFieldViewSelector,
sfrRegNumber: rawRequisiteFieldViewSelector,
pfrRegNumber: rawRequisiteFieldViewSelector,
chairmanPosition: rawRequisiteFieldViewSelector,
signerSnils: rawRequisiteFieldViewSelector,
signerRepDoc: rawRequisiteFieldViewSelector,
+2
View File
@@ -4821,6 +4821,7 @@ export const ReturnTypes: Record<string,any> = {
oktmo:"RequisiteFieldView",
okved:"RequisiteFieldView",
orgName:"RequisiteFieldView",
pfrRegNumber:"RequisiteFieldView",
phone:"RequisiteFieldView",
sfrRegNumber:"RequisiteFieldView",
signerFirstName:"RequisiteFieldView",
@@ -5063,6 +5064,7 @@ export const ReturnTypes: Record<string,any> = {
firstName:"String",
lastName:"String",
middleName:"String",
pfrRegNumber:"String",
repDoc:"String",
sfrRegNumber:"String",
snils:"String",
+20 -4
View File
@@ -9043,6 +9043,7 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
oktmo?:ValueTypes["RequisiteFieldView"],
okved?:ValueTypes["RequisiteFieldView"],
orgName?:ValueTypes["RequisiteFieldView"],
pfrRegNumber?:ValueTypes["RequisiteFieldView"],
phone?:ValueTypes["RequisiteFieldView"],
sfrRegNumber?:ValueTypes["RequisiteFieldView"],
signerFirstName?:ValueTypes["RequisiteFieldView"],
@@ -10179,8 +10180,10 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
oktmo?: string | undefined | null | Variable<any, string>,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null | Variable<any, string>,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null | Variable<any, string>,
phoneOverride?: string | undefined | null | Variable<any, string>,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null | Variable<any, string>,
signerRepDoc?: string | undefined | null | Variable<any, string>,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -10482,6 +10485,7 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
firstName?:boolean | `@${string}`,
lastName?:boolean | `@${string}`,
middleName?:boolean | `@${string}`,
pfrRegNumber?:boolean | `@${string}`,
repDoc?:boolean | `@${string}`,
sfrRegNumber?:boolean | `@${string}`,
snils?:boolean | `@${string}`,
@@ -18204,6 +18208,7 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
oktmo?:ResolverInputTypes["RequisiteFieldView"],
okved?:ResolverInputTypes["RequisiteFieldView"],
orgName?:ResolverInputTypes["RequisiteFieldView"],
pfrRegNumber?:ResolverInputTypes["RequisiteFieldView"],
phone?:ResolverInputTypes["RequisiteFieldView"],
sfrRegNumber?:ResolverInputTypes["RequisiteFieldView"],
signerFirstName?:ResolverInputTypes["RequisiteFieldView"],
@@ -19317,8 +19322,10 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
oktmo?: string | undefined | null,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null,
phoneOverride?: string | undefined | null,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null,
signerRepDoc?: string | undefined | null,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -19614,6 +19621,7 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
firstName?:boolean | `@${string}`,
lastName?:boolean | `@${string}`,
middleName?:boolean | `@${string}`,
pfrRegNumber?:boolean | `@${string}`,
repDoc?:boolean | `@${string}`,
sfrRegNumber?:boolean | `@${string}`,
snils?:boolean | `@${string}`,
@@ -27847,6 +27855,7 @@ export type ModelTypes = {
oktmo: ModelTypes["RequisiteFieldView"],
okved: ModelTypes["RequisiteFieldView"],
orgName: ModelTypes["RequisiteFieldView"],
pfrRegNumber: ModelTypes["RequisiteFieldView"],
phone: ModelTypes["RequisiteFieldView"],
sfrRegNumber: ModelTypes["RequisiteFieldView"],
signerFirstName: ModelTypes["RequisiteFieldView"],
@@ -28930,8 +28939,10 @@ export type ModelTypes = {
oktmo?: string | undefined | null,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null,
phoneOverride?: string | undefined | null,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null,
signerRepDoc?: string | undefined | null,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -29214,6 +29225,7 @@ export type ModelTypes = {
firstName: string,
lastName: string,
middleName?: string | undefined | null,
pfrRegNumber?: string | undefined | null,
repDoc?: string | undefined | null,
sfrRegNumber?: string | undefined | null,
snils?: string | undefined | null,
@@ -37955,6 +37967,7 @@ export type GraphQLTypes = {
oktmo: GraphQLTypes["RequisiteFieldView"],
okved: GraphQLTypes["RequisiteFieldView"],
orgName: GraphQLTypes["RequisiteFieldView"],
pfrRegNumber: GraphQLTypes["RequisiteFieldView"],
phone: GraphQLTypes["RequisiteFieldView"],
sfrRegNumber: GraphQLTypes["RequisiteFieldView"],
signerFirstName: GraphQLTypes["RequisiteFieldView"],
@@ -39090,8 +39103,10 @@ export type GraphQLTypes = {
oktmo?: string | undefined | null,
/** ОКВЭД — напр. 94.99, 46.73.7 */
okved?: string | undefined | null,
/** Рег. номер ПФР — XXX-XXX-XXXXXX (для ЕФС-1, отдельно от рег. номера СФР) */
pfrRegNumber?: string | undefined | null,
phoneOverride?: string | undefined | null,
/** Рег. номер СФР — XXX-XXX-XXXXXX */
/** Рег. номер СФР — 10 цифр */
sfrRegNumber?: string | undefined | null,
signerRepDoc?: string | undefined | null,
/** СНИЛС — XXX-XXX-XXX YY или 11 цифр */
@@ -39395,6 +39410,7 @@ export type GraphQLTypes = {
firstName: string,
lastName: string,
middleName?: string | undefined | null,
pfrRegNumber?: string | undefined | null,
repDoc?: string | undefined | null,
sfrRegNumber?: string | undefined | null,
snils?: string | undefined | null,