import { ICompany } from '../dictionary/models/ICompany'; import { IEmployeeOrganization } from '../dictionary/models/IEmployeeOrganization'; import { describeEdoError } from './edoErrors'; import { splitFio } from './fio'; import { resolveSigningTargets } from './signingTarget'; const TANSU_ID = '9de064a4-44c8-88ef-11ec-8284930fad96'; function record(overrides: Partial = {}): IEmployeeOrganization { return { id: 'e1', fio: 'Иванов Иван Иванович', email: 'ivanov@tnsu.kz', iin: '950515123452', company: 'ТОО TANSU Construction', companyId: TANSU_ID, section: '', departmentId: '', position: 'Инженер', mobile: '', ...overrides }; } const COMPANIES: ICompany[] = [ { Id: TANSU_ID, Name: 'ТОО TANSU Construction', Bin: '021040005165' }, { Id: '0a1b2c3d-0000-4000-8000-000000000002', Name: 'ТОО Без БИН', Bin: '' } ]; describe('Ф.И.О. по частям для ЭДО', () => { it('три слова', () => { expect(splitFio('Иванов Иван Иванович')).toEqual({ lastName: 'Иванов', firstName: 'Иван', middleName: 'Иванович' }); }); it('без отчества', () => { expect(splitFio('Иванов Иван')).toEqual({ lastName: 'Иванов', firstName: 'Иван', middleName: '' }); }); it('лишние пробелы и «оглы» не теряются', () => { expect(splitFio(' Алиев Тимур Расул оглы ')).toEqual({ lastName: 'Алиев', firstName: 'Тимур', middleName: 'Расул оглы' }); }); it('одно слово или пусто — не разобрать', () => { expect(splitFio('Иванов')).toBeUndefined(); expect(splitFio('')).toBeUndefined(); }); }); const STROY_ID = '0a1b2c3d-0000-4000-8000-000000000003'; const NO_BIN_ID = '0a1b2c3d-0000-4000-8000-000000000002'; describe('кому и по каким компаниям отправлять на подпись', () => { const companies: ICompany[] = [...COMPANIES, { Id: STROY_ID, Name: 'ТОО TANSU Строй', Bin: '021040005166' }]; it('ИИН из справочника сотрудников, БИН из справочника компаний', () => { const targets = resolveSigningTargets([record()], companies); expect(targets.iin).toBe('950515123452'); expect(targets.name.lastName).toBe('Иванов'); expect(targets.companies).toEqual([{ bin: '021040005165', name: 'ТОО TANSU Construction', position: 'Инженер' }]); expect(targets.skipped).toEqual([]); }); // Заявку заполняют одну, а подписывают по каждой компании, где человек работает. it('по документу на каждую компанию, со своей должностью', () => { const targets = resolveSigningTargets( [record(), record({ company: 'ТОО TANSU Строй', companyId: STROY_ID, position: 'Главный инженер' })], companies ); expect(targets.companies).toEqual([ { bin: '021040005165', name: 'ТОО TANSU Construction', position: 'Инженер' }, { bin: '021040005166', name: 'ТОО TANSU Строй', position: 'Главный инженер' } ]); }); it('одна и та же компания дважды не попадает', () => { const targets = resolveSigningTargets([record(), record({ position: 'Совместитель' })], companies); expect(targets.companies).toHaveLength(1); }); it('идентификаторы компаний сравниваются без учёта регистра', () => { expect(resolveSigningTargets([record({ companyId: TANSU_ID.toUpperCase() })], companies).companies[0].bin).toBe( '021040005165' ); }); it('компания без БИН не мешает остальным — уходит в пропущенные с причиной', () => { const targets = resolveSigningTargets( [record({ company: 'ТОО Без БИН', companyId: NO_BIN_ID }), record()], companies ); expect(targets.companies.map((c) => c.bin)).toEqual(['021040005165']); expect(targets.skipped).toEqual([{ name: 'ТОО Без БИН', reason: 'в справочнике компаний нет БИН' }]); }); it('компании нет в справочнике — тоже пропущена', () => { const targets = resolveSigningTargets( [record({ company: 'ТОО Неизвестная', companyId: 'ffffffff-0000-4000-8000-000000000000' })], companies ); expect(targets.companies).toEqual([]); expect(targets.skipped[0].name).toBe('ТОО Неизвестная'); }); it('нет записи о сотруднике — понятная причина', () => { expect(() => resolveSigningTargets([], companies)).toThrow('нет в кадровом справочнике'); }); it('нет ИИН в карточке', () => { expect(() => resolveSigningTargets([record({ iin: ' ' })], companies)).toThrow('не указан ИИН'); }); it('ФИО из одного слова не годится', () => { expect(() => resolveSigningTargets([record({ fio: 'Иванов' })], companies)).toThrow('Ф.И.О.'); }); it('ни в одной записи нет компании', () => { expect(() => resolveSigningTargets([record({ companyId: '' })], companies)).toThrow('не указана компания'); }); }); describe('текст ошибки ЭДО', () => { it('берёт русский detail из ProblemDetails', () => { const body = JSON.stringify({ title: 'Bad Request', detail: 'Для компании «X» не загружен сертификат Sigex.' }); expect(describeEdoError(400, body)).toBe('Для компании «X» не загружен сертификат Sigex.'); }); it('title, если detail нет', () => { expect(describeEdoError(400, JSON.stringify({ title: 'Подписант не найден' }))).toBe('Подписант не найден'); }); it('ошибки проверки собираются в одну строку', () => { const body = JSON.stringify({ errors: { Iin: ['ИИН неверный'], Email: ['Email неверный', 'Слишком длинный'] } }); expect(describeEdoError(400, body)).toBe('ИИН неверный; Email неверный; Слишком длинный'); }); it('не JSON — по статусу', () => { expect(describeEdoError(502, 'Bad gateway')).toBe('ЭДО ответил 502'); expect(describeEdoError(401, '')).toContain('401'); expect(describeEdoError(403, '')).toContain('403'); }); });