fix build config & fixes for invoice FA1/FA2/FA3

This commit is contained in:
Michał Chudy
2025-12-03 13:42:56 +01:00
parent b9972746aa
commit 1912b5b48d
68 changed files with 1144 additions and 227 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@akmf/ksef-fe-invoice-converter", "name": "@akmf/ksef-fe-invoice-converter",
"version": "0.0.30", "version": "0.0.32",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@akmf/ksef-fe-invoice-converter", "name": "@akmf/ksef-fe-invoice-converter",
"version": "0.0.30", "version": "0.0.32",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"pdfmake": "^0.2.20", "pdfmake": "^0.2.20",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@akmf/ksef-fe-invoice-converter", "name": "@akmf/ksef-fe-invoice-converter",
"version": "0.0.30", "version": "0.0.32",
"scripts": { "scripts": {
"dev": "vite --mode public --config vite.config.ts", "dev": "vite --mode public --config vite.config.ts",
"build": "vite build --mode production", "build": "vite build --mode production",
@@ -9,15 +9,15 @@
"test:ui": "vitest --ui", "test:ui": "vitest --ui",
"test:ci": "vitest run --coverage" "test:ci": "vitest run --coverage"
}, },
"main": "./ksef-fe-invoice-converter.umd.js", "main": "./ksef-fe-invoice-converter.umd.cjs",
"module": "./ksef-fe-invoice-converter.es.js", "module": "./ksef-fe-invoice-converter.js",
"types": "./src/lib/index.d.ts", "types": "./index.d.ts",
"type": "module", "type": "module",
"exports": { "exports": {
".": { ".": {
"types": "./src/lib/index.d.ts", "types": "./index.d.ts",
"import": "./ksef-fe-invoice-converter.es.js", "import": "./ksef-fe-invoice-converter.js",
"require": "./ksef-fe-invoice-converter.umd.js" "require": "./ksef-fe-invoice-converter.umd.cjs"
} }
}, },
"keywords": [], "keywords": [],

View File

@@ -8,6 +8,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
formatText: vi.fn().mockImplementation((text) => ({ text })), formatText: vi.fn().mockImplementation((text) => ({ text })),
hasValue: vi.fn((val) => Boolean(val && val._text)), hasValue: vi.fn((val) => Boolean(val && val._text)),
verticalSpacing: vi.fn().mockImplementation((size) => ({ text: `SPACING:${size}` })), verticalSpacing: vi.fn().mockImplementation((size) => ({ text: `SPACING:${size}` })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
describe(generateAdnotacje.name, () => { describe(generateAdnotacje.name, () => {

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
formatText, formatText,
generateColumns,
hasValue, hasValue,
verticalSpacing, verticalSpacing,
} from '../../../shared/PDF-functions'; } from '../../../shared/PDF-functions';
@@ -120,7 +121,7 @@ export function generateAdnotacje(adnotacje?: Adnotacje): Content[] {
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ columns: [firstColumn, secondColumn], columnGap: 20 }); result.push(generateColumns([firstColumn, secondColumn]));
} }
if (result.length) { if (result.length) {

View File

@@ -14,15 +14,20 @@ import FormatTyp from '../../../shared/enums/common.enum';
import { FakturaZaliczkowa, TableWithFields } from '../../types/fa1-additional-types'; import { FakturaZaliczkowa, TableWithFields } from '../../types/fa1-additional-types';
export function generateDodatkoweInformacje(faVat: Fa): Content[] { export function generateDodatkoweInformacje(faVat: Fa): Content[] {
const tpLabel1: Content[] = []; const tpLabel: Content[] = [];
const tpLabel2: Content[] = [];
if (getValue(faVat.TP) === '1') { if (getValue(faVat.TP) === '1') {
tpLabel1.push( tpLabel.push(
formatText('- Istniejące powiązania między nabywcą a dokonującym dostawy towarów lub usługodawcą') formatText('- Istniejące powiązania między nabywcą a dokonującym dostawy towarów lub usługodawcą')
); );
tpLabel2.push(formatText('- Faktura, o której mowa w art. 109 ust. 3d ustawy'));
} }
const fpLabel: Content[] = [];
if (getValue(faVat.FP) === '1') {
fpLabel.push(formatText('- Faktura, o której mowa w art. 109 ust. 3d ustawy'));
}
const zwrotAkcyzyLabel: Content[] = []; const zwrotAkcyzyLabel: Content[] = [];
if (getValue(faVat.ZwrotAkcyzy) === '1') { if (getValue(faVat.ZwrotAkcyzy) === '1') {
@@ -33,7 +38,7 @@ export function generateDodatkoweInformacje(faVat: Fa): Content[] {
); );
} }
const labels: Content[][] = [tpLabel1, tpLabel2, zwrotAkcyzyLabel].filter((el) => el.length > 0); const labels: Content[][] = [tpLabel, fpLabel, zwrotAkcyzyLabel].filter((el) => el.length > 0);
const table: Content[] = [ const table: Content[] = [
...createHeader('Dodatkowe informacje'), ...createHeader('Dodatkowe informacje'),
...labels, ...labels,

View File

@@ -9,6 +9,8 @@ vi.mock('../../../shared/PDF-functions', () => ({
})), })),
formatText: vi.fn((text: string, _args?: any) => ({ text: `FMT:${text}` })), formatText: vi.fn((text: string, _args?: any) => ({ text: `FMT:${text}` })),
getTable: vi.fn((data) => data || []), getTable: vi.fn((data) => data || []),
getValue: vi.fn((val) => val?._text || ''),
hasValue: vi.fn((val) => Boolean(val && val._text)),
})); }));
vi.mock('./PodmiotAdres', () => ({ vi.mock('./PodmiotAdres', () => ({
generatePodmiotAdres: vi.fn((adres: any, label: string) => ({ adr: `${label}` })), generatePodmiotAdres: vi.fn((adres: any, label: string) => ({ adr: `${label}` })),
@@ -33,7 +35,7 @@ describe('generatePodmiot1', () => {
expect(result).toEqual( expect(result).toEqual(
expect.arrayContaining([ expect.arrayContaining([
{ text: 'HEADER:Sprzedawca' }, { text: 'HEADER:Sprzedawca' },
{ text: 'LABEL:NrEORI: EORI123' }, { text: 'LABEL:Numer EORI: EORI123' },
{ text: 'LABEL:Prefiks VAT: PL' }, { text: 'LABEL:Prefiks VAT: PL' },
]) ])
); );
@@ -66,7 +68,7 @@ describe('generatePodmiot1', () => {
NrEORI: { _text: 'xxx' }, NrEORI: { _text: 'xxx' },
PrefiksPodatnika: { _text: 'PL' }, PrefiksPodatnika: { _text: 'PL' },
Email: { _text: 'a@b.pl' }, Email: { _text: 'a@b.pl' },
StatusInfoPodatnika: { _text: 'zarejestrowany' }, StatusInfoPodatnika: { _text: '2' },
}; };
const result = generatePodmiot1(podmiot1); const result = generatePodmiot1(podmiot1);
@@ -74,7 +76,7 @@ describe('generatePodmiot1', () => {
expect.arrayContaining([ expect.arrayContaining([
{ text: 'FMT:Dane kontaktowe' }, { text: 'FMT:Dane kontaktowe' },
{ contact: 'KONTAKT' }, { contact: 'KONTAKT' },
{ text: 'LABEL:Status podatnika: zarejestrowany' }, { text: 'LABEL:Status podatnika: Postępowanie restrukturyzacyjne' },
]) ])
); );
}); });
@@ -83,10 +85,10 @@ describe('generatePodmiot1', () => {
const podmiot1: Podmiot1 = { const podmiot1: Podmiot1 = {
NrEORI: { _text: 'xxx' }, NrEORI: { _text: 'xxx' },
PrefiksPodatnika: { _text: 'PL' }, PrefiksPodatnika: { _text: 'PL' },
StatusInfoPodatnika: { _text: 'SAMO' }, StatusInfoPodatnika: { _text: '1' },
}; };
const result = generatePodmiot1(podmiot1); const result = generatePodmiot1(podmiot1);
expect(result).toEqual(expect.arrayContaining([{ text: 'LABEL:Status podatnika: SAMO' }])); expect(result).toEqual(expect.arrayContaining([{ text: 'LABEL:Status podatnika: Stan likwidacji' }]));
}); });
}); });

View File

@@ -1,16 +1,24 @@
import { Content } from 'pdfmake/interfaces'; import { Content } from 'pdfmake/interfaces';
import { createHeader, createLabelText, formatText, getTable } from '../../../shared/PDF-functions'; import {
createHeader,
createLabelText,
formatText,
getTable,
getValue,
hasValue,
} from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum'; import FormatTyp from '../../../shared/enums/common.enum';
import { Podmiot1 } from '../../types/fa1.types'; import { Podmiot1 } from '../../types/fa1.types';
import { generatePodmiotAdres } from './PodmiotAdres'; import { generatePodmiotAdres } from './PodmiotAdres';
import { generateDaneIdentyfikacyjne } from './PodmiotDaneIdentyfikacyjne'; import { generateDaneIdentyfikacyjne } from './PodmiotDaneIdentyfikacyjne';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe'; import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { TAXPAYER_STATUS } from '../../../shared/consts/const';
export function generatePodmiot1(podmiot1: Podmiot1): Content[] { export function generatePodmiot1(podmiot1: Podmiot1): Content[] {
const result: Content[] = createHeader('Sprzedawca'); const result: Content[] = createHeader('Sprzedawca');
result.push( result.push(
createLabelText('NrEORI: ', podmiot1.NrEORI), createLabelText('Numer EORI: ', podmiot1.NrEORI),
createLabelText('Prefiks VAT: ', podmiot1.PrefiksPodatnika) createLabelText('Prefiks VAT: ', podmiot1.PrefiksPodatnika)
); );
if (podmiot1.DaneIdentyfikacyjne) { if (podmiot1.DaneIdentyfikacyjne) {
@@ -30,10 +38,11 @@ export function generatePodmiot1(podmiot1: Podmiot1): Content[] {
formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]), formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]),
...generateDaneKontaktowe(podmiot1.Email, getTable(podmiot1.Telefon)) ...generateDaneKontaktowe(podmiot1.Email, getTable(podmiot1.Telefon))
); );
}
if (hasValue(podmiot1.StatusInfoPodatnika)) {
const statusInfo: string = TAXPAYER_STATUS[getValue(podmiot1.StatusInfoPodatnika)!];
result.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika)); result.push(createLabelText('Status podatnika: ', statusInfo));
} else if (podmiot1.StatusInfoPodatnika) {
result.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika));
} }
return result; return result;
} }

View File

@@ -11,6 +11,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
createSubHeader: vi.fn((label: string) => ({ text: `SUBHEADER:${label}` })), createSubHeader: vi.fn((label: string) => ({ text: `SUBHEADER:${label}` })),
verticalSpacing: vi.fn((v: number) => ({ text: `SPACING:${v}` })), verticalSpacing: vi.fn((v: number) => ({ text: `SPACING:${v}` })),
getTable: vi.fn((data) => data || []), getTable: vi.fn((data) => data || []),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./PodmiotAdres', () => ({ vi.mock('./PodmiotAdres', () => ({
generatePodmiotAdres: vi.fn((adres: any, label: string) => ({ adr: label })), generatePodmiotAdres: vi.fn((adres: any, label: string) => ({ adr: label })),

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
createSubHeader, createSubHeader,
generateColumns,
getTable, getTable,
verticalSpacing, verticalSpacing,
} from '../../../shared/PDF-functions'; } from '../../../shared/PDF-functions';
@@ -42,10 +43,7 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
); );
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ result.push(generateColumns([firstColumn, secondColumn]));
columns: [firstColumn, secondColumn],
columnGap: 20,
});
} }
if (result.length) { if (result.length) {
result.push(verticalSpacing(1)); result.push(verticalSpacing(1));

View File

@@ -32,7 +32,7 @@ describe('generatePodmiot2', () => {
const result = generatePodmiot2(podmiot2); const result = generatePodmiot2(podmiot2);
expect(result).toEqual( expect(result).toEqual(
expect.arrayContaining([{ text: 'HEADER:Nabywca' }, { text: 'LABEL:NrEORI: EORI777' }]) expect.arrayContaining([{ text: 'HEADER:Nabywca' }, { text: 'LABEL:Numer EORI: EORI777' }])
); );
}); });

View File

@@ -17,7 +17,7 @@ import { DaneIdentyfikacyjneTPodmiot2Dto } from '../../types/fa2-additional-type
export function generatePodmiot2(podmiot2: Podmiot2): Content[] { export function generatePodmiot2(podmiot2: Podmiot2): Content[] {
const result: Content[] = createHeader('Nabywca'); const result: Content[] = createHeader('Nabywca');
result.push(createLabelText('NrEORI: ', podmiot2.NrEORI)); result.push(createLabelText('Numer EORI: ', podmiot2.NrEORI));
if (hasValue(podmiot2.PrefiksNabywcy)) { if (hasValue(podmiot2.PrefiksNabywcy)) {
result.push(createLabelText('Prefiks VAT: ', podmiot2.PrefiksNabywcy)); result.push(createLabelText('Prefiks VAT: ', podmiot2.PrefiksNabywcy));
} }

View File

@@ -13,6 +13,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn((arr) => arr || []), getTable: vi.fn((arr) => arr || []),
getValue: vi.fn((val) => (val && val._text ? val._text : '')), getValue: vi.fn((val) => (val && val._text ? val._text : '')),
hasValue: vi.fn((val) => Boolean(val && val._text)), hasValue: vi.fn((val) => Boolean(val && val._text)),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./PodmiotAdres', () => ({ vi.mock('./PodmiotAdres', () => ({
generatePodmiotAdres: vi.fn((adres, label) => ({ adr: label })), generatePodmiotAdres: vi.fn((adres, label) => ({ adr: label })),

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
createSubHeader, createSubHeader,
generateColumns,
getTable, getTable,
getValue, getValue,
hasValue, hasValue,
@@ -44,10 +45,7 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ result.push(generateColumns([firstColumn, secondColumn]));
columns: [firstColumn, secondColumn],
columnGap: 20,
});
} }
if (result.length) { if (result.length) {
result.push(verticalSpacing(1)); result.push(verticalSpacing(1));

View File

@@ -40,7 +40,7 @@ describe('generatePodmiot3', () => {
expect(last.left).toEqual( expect(last.left).toEqual(
expect.arrayContaining([ expect.arrayContaining([
{ text: 'HEADER:Podmiot inny 1' }, { text: 'HEADER:Podmiot inny 1' },
{ text: 'LABEL:NrEORI: 999' }, { text: 'LABEL:Numer EORI: 999' },
[{ text: 'LABEL:Rola: SPRZEDAWCA' }, { text: 'LABEL:Rola inna: ' }, { text: 'LABEL:Udział: ' }], [{ text: 'LABEL:Rola: SPRZEDAWCA' }, { text: 'LABEL:Rola inna: ' }, { text: 'LABEL:Udział: ' }],
]) ])
); );
@@ -60,7 +60,7 @@ describe('generatePodmiot3', () => {
expect(col1).toEqual( expect(col1).toEqual(
expect.arrayContaining([ expect.arrayContaining([
{ text: 'HEADER:Podmiot inny 2' }, { text: 'HEADER:Podmiot inny 2' },
{ text: 'LABEL:NrEORI: 1000' }, { text: 'LABEL:Numer EORI: 1000' },
{ text: 'LABEL:Identyfikator podatkowy inny: TAXX' }, { text: 'LABEL:Identyfikator podatkowy inny: TAXX' },
{ text: 'LABEL:Brak identyfikatora ' }, { text: 'LABEL:Brak identyfikatora ' },
{ id: 'ID' }, { id: 'ID' },

View File

@@ -21,7 +21,7 @@ export function generatePodmiot3(podmiot: Podmiot3, index: number): Content[] {
const column1: Content[] = [ const column1: Content[] = [
...createHeader(`Podmiot inny ${index + 1}`), ...createHeader(`Podmiot inny ${index + 1}`),
createLabelText('NrEORI: ', podmiot.NrEORI), createLabelText('Numer EORI: ', podmiot.NrEORI),
]; ];
if (hasValue(podmiot.DaneIdentyfikacyjne?.NrID)) { if (hasValue(podmiot.DaneIdentyfikacyjne?.NrID)) {

View File

@@ -27,7 +27,7 @@ export function generatePodmiotUpowazniony(podmiot: PodmiotUpowazniony | undefin
columnLeft.push(createLabelText('Rola: ', getRolaUpowaznionegoString(podmiot.RolaPU, 1))); columnLeft.push(createLabelText('Rola: ', getRolaUpowaznionegoString(podmiot.RolaPU, 1)));
} }
if (hasValue(podmiot.NrEORI)) { if (hasValue(podmiot.NrEORI)) {
columnLeft.push(createLabelText('NrEORI: ', podmiot.NrEORI)); columnLeft.push(createLabelText('Numer EORI: ', podmiot.NrEORI));
} }
if (podmiot.DaneIdentyfikacyjne) { if (podmiot.DaneIdentyfikacyjne) {
if (hasValue(podmiot.DaneIdentyfikacyjne.NrID)) { if (hasValue(podmiot.DaneIdentyfikacyjne.NrID)) {

View File

@@ -7,6 +7,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn((obj) => (obj ? (Array.isArray(obj) ? obj : [obj]) : [])), getTable: vi.fn((obj) => (obj ? (Array.isArray(obj) ? obj : [obj]) : [])),
getValue: vi.fn((val) => (val && val._text ? val._text : '')), getValue: vi.fn((val) => (val && val._text ? val._text : '')),
hasValue: vi.fn((val) => Boolean(val && val._text)), hasValue: vi.fn((val) => Boolean(val && val._text)),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Podmiot1', () => ({ vi.mock('./Podmiot1', () => ({
generatePodmiot1: vi.fn(() => [{ podmiot1: true }]), generatePodmiot1: vi.fn(() => [{ podmiot1: true }]),

View File

@@ -1,5 +1,5 @@
import { Content } from 'pdfmake/interfaces'; import { Content } from 'pdfmake/interfaces';
import { createSection, getTable, getValue } from '../../../shared/PDF-functions'; import { createSection, generateColumns, getTable, getValue } from '../../../shared/PDF-functions';
import { Faktura, Podmiot2K, Podmiot3 } from '../../types/fa1.types'; import { Faktura, Podmiot2K, Podmiot3 } from '../../types/fa1.types';
import { Podmiot3Podmiot2KDto } from '../../types/fa1-additional-types'; import { Podmiot3Podmiot2KDto } from '../../types/fa1-additional-types';
import { generatePodmiot1 } from './Podmiot1'; import { generatePodmiot1 } from './Podmiot1';
@@ -31,10 +31,10 @@ export function generatePodmioty(invoice: Faktura): Content[] {
} }
} else { } else {
result.push([ result.push([
{ generateColumns([generatePodmiot1(invoice.Podmiot1!), generatePodmiot2(invoice.Podmiot2!)], {
columns: [generatePodmiot1(invoice.Podmiot1!), generatePodmiot2(invoice.Podmiot2!)],
margin: [0, 0, 0, 8], margin: [0, 0, 0, 8],
}, columnGap: 20,
}),
]); ]);
} }

View File

@@ -0,0 +1,242 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { generujRachunekBankowy } from './RachunekBankowy';
import * as PDFFunctions from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum';
import * as CommonFunctions from '../../../shared/generators/common/functions';
import { makeBreakable } from '../../../shared/PDF-functions';
vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn(),
createSection: vi.fn(),
formatText: vi.fn(),
makeBreakable: vi.fn(),
getValue: vi.fn((val) => (val && val._text ? val._text : '')),
hasValue: vi.fn((val) => Boolean(val && val._text)),
}));
vi.mock('../../../shared/generators/common/functions', () => ({
getTypRachunkowWlasnych: vi.fn(),
}));
describe(generujRachunekBankowy.name, () => {
beforeEach(() => {
vi.clearAllMocks();
});
const mockAccount: any = {
NrRB: { _text: '12345678901234567890123456' },
SWIFT: { _text: 'BPKOPLPW' },
RachunekWlasnyBanku: { _text: '1' },
NazwaBanku: { _text: 'PKO Bank Polski' },
OpisRachunku: { _text: 'Rachunek główny' },
} as any;
beforeEach(() => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['header'] as any);
vi.mocked(PDFFunctions.createSection).mockReturnValue('section' as any);
vi.mocked(PDFFunctions.formatText).mockReturnValue('formatted' as any);
vi.mocked(CommonFunctions.getTypRachunkowWlasnych).mockReturnValue('Tak');
});
describe('when accounts is undefined or empty', () => {
it('should return empty array when accounts is undefined', () => {
const result = generujRachunekBankowy(undefined, 'Rachunek bankowy');
expect(result).toEqual([]);
});
it('should return empty array when accounts is empty array', () => {
const result = generujRachunekBankowy([], 'Rachunek bankowy');
expect(result).toEqual([]);
});
});
describe('when accounts exist', () => {
it('should call createHeader with provided title', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.createHeader).toHaveBeenCalledWith('Rachunek bankowy ', [0, 12, 0, 8]);
});
it('should call createHeader with empty string when title is not provided', () => {
generujRachunekBankowy([mockAccount]);
expect(PDFFunctions.createHeader).toHaveBeenCalledWith('', [0, 12, 0, 8]);
});
it('should call createSection and return result', () => {
const mockSection = 'section';
vi.mocked(PDFFunctions.createSection).mockReturnValue(mockSection as any);
const result = generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.createSection).toHaveBeenCalledWith(expect.any(Array), false);
expect(result).toEqual(mockSection);
});
it('should format "Kod SWIFT" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Kod SWIFT', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(mockAccount.SWIFT?._text, FormatTyp.Default);
});
it('should format "Rachunek własny banku" field', () => {
vi.mocked(CommonFunctions.getTypRachunkowWlasnych).mockReturnValue('Tak');
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Rachunek własny banku', FormatTyp.GrayBoldTitle);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(mockAccount.RachunekWlasnyBanku);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(makeBreakable('Tak'), FormatTyp.Default);
});
it('should format "Nazwa banku" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Nazwa banku', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(
makeBreakable(mockAccount.NazwaBanku?._text),
FormatTyp.Default
);
});
it('should create table structure with correct widths', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('table');
expect(tableContent.table).toHaveProperty('widths', ['*', 'auto']);
});
it('should create table structure with unbreakable property', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('unbreakable', true);
});
it('should create table with correct layout', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('layout');
expect(tableContent.layout).toHaveProperty('hLineWidth');
expect(tableContent.layout).toHaveProperty('hLineColor');
expect(tableContent.layout).toHaveProperty('vLineWidth');
expect(tableContent.layout).toHaveProperty('vLineColor');
});
it('should create table with correct line colors', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.layout.hLineColor()).toBe('#BABABA');
expect(tableContent.layout.vLineColor()).toBe('#BABABA');
});
it('should create table with correct line widths', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.layout.hLineWidth()).toBe(1);
expect(tableContent.layout.vLineWidth()).toBe(1);
});
it('should handle account with undefined fields', () => {
const accountWithUndefined: any = {
NrRB: { _text: undefined },
SWIFT: { _text: undefined },
RachunekWlasnyBanku: { _text: undefined },
NazwaBanku: { _text: undefined },
OpisRachunku: { _text: undefined },
} as any;
generujRachunekBankowy([accountWithUndefined], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith(undefined, FormatTyp.Default);
});
});
describe('when multiple accounts exist', () => {
it('should create multiple tables for multiple accounts', () => {
const account2: any = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
} as any;
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
expect(sectionCall.length).toBe(2);
});
it('should call getTypRachunkowWlasnych for each account', () => {
const account2: any = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
} as any;
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledTimes(2);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(mockAccount.RachunekWlasnyBanku);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(account2.RachunekWlasnyBanku);
});
it('should format all fields for all accounts', () => {
const account2: any = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
} as any;
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Kod SWIFT', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Kod SWIFT', FormatTyp.GrayBoldTitle);
});
});
describe('table structure', () => {
it('should create table with 5 rows', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.table.body.length).toBe(3);
});
it('should include header in result array', () => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['header-content'] as any);
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
expect(sectionCall[0][0]).toBe('header-content');
});
});
});

View File

@@ -1,5 +1,12 @@
import { Content, ContentTable } from 'pdfmake/interfaces'; import { Content, ContentTable } from 'pdfmake/interfaces';
import { createHeader, createSection, formatText } from '../../../shared/PDF-functions'; import {
createHeader,
createSection,
formatText,
getValue,
hasValue,
makeBreakable,
} from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum'; import FormatTyp from '../../../shared/enums/common.enum';
import { FP } from '../../types/fa1.types'; import { FP } from '../../types/fa1.types';
import { getTypRachunkowWlasnych } from '../../../shared/generators/common/functions'; import { getTypRachunkowWlasnych } from '../../../shared/generators/common/functions';
@@ -22,40 +29,40 @@ export const generujRachunekBankowy: (accounts?: Record<string, FP>[], title?: s
[0, 12, 0, 8] [0, 12, 0, 8]
); );
if (account.NrRBZagr?._text) { if (hasValue(account.NrRBZagr)) {
table.push([ table.push([
formatText('Format rachunku', FormatTyp.GrayBoldTitle), formatText('Format rachunku', FormatTyp.GrayBoldTitle),
formatText('Zagraniczny', FormatTyp.Default), formatText('Zagraniczny', FormatTyp.Default),
]); ]);
} else if (account.NrRBPL?._text) { } else if (hasValue(account.NrRBPL)) {
table.push([ table.push([
formatText('Format rachunku', FormatTyp.GrayBoldTitle), formatText('Format rachunku', FormatTyp.GrayBoldTitle),
formatText('Polski', FormatTyp.Default), formatText('Polski', FormatTyp.Default),
]); ]);
} }
if (account.NrRBPL?._text) { if (hasValue(account.NrRBPL)) {
table.push([ table.push([
formatText('Pełny numer rachunku w standardzie NRB', FormatTyp.GrayBoldTitle), formatText('Pełny numer rachunku w standardzie NRB', FormatTyp.GrayBoldTitle),
formatText(account.NrRBPL?._text, FormatTyp.Default), formatText(getValue(account.NrRBPL), FormatTyp.Default),
]); ]);
} }
if (account.NrRBZagr?._text) { if (hasValue(account.NrRBZagr)) {
table.push([ table.push([
formatText('Pełny numer rachunku zagranicznego', FormatTyp.GrayBoldTitle), formatText('Pełny numer rachunku zagranicznego', FormatTyp.GrayBoldTitle),
formatText(account.NrRBZagr?._text, FormatTyp.Default), formatText(getValue(account.NrRBZagr), FormatTyp.Default),
]); ]);
} }
table.push([ table.push([
formatText('Kod SWIFT', FormatTyp.GrayBoldTitle), formatText('Kod SWIFT', FormatTyp.GrayBoldTitle),
formatText(account.SWIFT?._text, FormatTyp.Default), formatText(getValue(account.SWIFT), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Rachunek własny banku', FormatTyp.GrayBoldTitle), formatText('Rachunek własny banku', FormatTyp.GrayBoldTitle),
formatText(getTypRachunkowWlasnych(account.RachunekWlasnyBanku), FormatTyp.Default), formatText(makeBreakable(getTypRachunkowWlasnych(account.RachunekWlasnyBanku), 20), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Nazwa banku', FormatTyp.GrayBoldTitle), formatText('Nazwa banku', FormatTyp.GrayBoldTitle),
formatText(account.NazwaBanku?._text, FormatTyp.Default), formatText(makeBreakable(getValue(account.NazwaBanku), 20), FormatTyp.Default),
]); ]);
result.push([ result.push([
...base, ...base,

View File

@@ -9,6 +9,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn(() => []), getTable: vi.fn(() => []),
hasValue: vi.fn((v) => !!v?._text), hasValue: vi.fn((v) => !!v?._text),
verticalSpacing: vi.fn((n: number) => ({ text: `space-${n}` })), verticalSpacing: vi.fn((n: number) => ({ text: `space-${n}` })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
describe(generateAdnotacje.name, () => { describe(generateAdnotacje.name, () => {
@@ -114,9 +115,15 @@ describe(generateDostawy.name, () => {
const result = generateAdnotacje(annotations); const result = generateAdnotacje(annotations);
const flat = result.flatMap((r: any) => (Array.isArray(r.columns) ? r.columns.flat() : [r]))?.flat(); const flat = result.flatMap((r: any) => (Array.isArray(r.columns) ? r.columns.flat() : [r]))?.flat();
expect(flat.some((c: any) => c.text?.includes('Directive'))).toBe(true); expect(
flat.flatMap((c) => (Array.isArray(c) ? c : [c])).some((item) => item?.text?.includes('Directive'))
).toBe(true);
expect(flat.some((c: any) => c.text?.includes('Dostawa towarów lub świadczenie'))).toBe(true); expect(flat.some((c: any) => c.text?.includes('Dostawa towarów lub świadczenie'))).toBe(true);
expect(flat.some((c: any) => c.text?.includes('Podstawa zwolnienia od podatku'))).toBe(true); expect(
flat
.flatMap((c) => (Array.isArray(c) ? c : [c]))
.some((item) => item?.text?.includes('Podstawa zwolnienia od podatku'))
).toBe(true);
}); });
it('adds VAT-22 and calls generateDostawy', () => { it('adds VAT-22 and calls generateDostawy', () => {

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
formatText, formatText,
generateColumns,
getTable, getTable,
hasValue, hasValue,
verticalSpacing, verticalSpacing,
@@ -105,7 +106,7 @@ export function generateAdnotacje(adnotacje?: Adnotacje): Content[] {
secondColumn.push({ text: 'Samofakturowanie' }); secondColumn.push({ text: 'Samofakturowanie' });
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ columns: [firstColumn, secondColumn], columnGap: 20 }); result.push(generateColumns([firstColumn, secondColumn]));
} }
if (result.length) { if (result.length) {

View File

@@ -1,6 +1,5 @@
import { describe, it, expect, vi, beforeEach, test } from 'vitest'; import { describe, it, expect, vi, beforeEach, test } from 'vitest';
import { generateDodatkoweInformacje } from './DodatkoweInformacje'; import { generateDodatkoweInformacje } from './DodatkoweInformacje';
import FormatTyp from '../../../shared/enums/common.enum';
vi.mock('../../../shared/PDF-functions', () => ({ vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((text: string) => [{ text, style: 'header' }]), createHeader: vi.fn((text: string) => [{ text, style: 'header' }]),
@@ -13,11 +12,9 @@ vi.mock('../../../shared/PDF-functions', () => ({
})); }));
import { import {
createHeader,
createSection, createSection,
createSubHeader, createSubHeader,
formatText, formatText,
getValue,
getTable, getTable,
getContentTable, getContentTable,
} from '../../../shared/PDF-functions'; } from '../../../shared/PDF-functions';
@@ -79,4 +76,15 @@ describe(generateDodatkoweInformacje.name, () => {
expect(createSection).toHaveBeenCalled(); expect(createSection).toHaveBeenCalled();
expect(result.length).toBeGreaterThan(0); expect(result.length).toBeGreaterThan(0);
}); });
it('poprawnie dodaje sekcję FP', () => {
const faVat = {
FP: { _text: '1' },
};
const result = generateDodatkoweInformacje(faVat as any);
expect(formatText).toHaveBeenCalledWith('- Faktura, o której mowa w art. 109 ust. 3d ustawy');
expect(createSection).toHaveBeenCalled();
expect(result.length).toBeGreaterThan(0);
});
}); });

View File

@@ -14,15 +14,20 @@ import FormatTyp from '../../../shared/enums/common.enum';
import { FormContentState } from '../../../shared/types/additional-data.types'; import { FormContentState } from '../../../shared/types/additional-data.types';
export function generateDodatkoweInformacje(faVat: Fa): Content[] { export function generateDodatkoweInformacje(faVat: Fa): Content[] {
const tpLabel1: Content[] = []; const tpLabel: Content[] = [];
const tpLabel2: Content[] = [];
if (getValue(faVat.TP) === '1') { if (getValue(faVat.TP) === '1') {
tpLabel1.push( tpLabel.push(
formatText('- Istniejące powiązania między nabywcą a dokonującym dostawy towarów lub usługodawcą') formatText('- Istniejące powiązania między nabywcą a dokonującym dostawy towarów lub usługodawcą')
); );
tpLabel2.push(formatText('- Faktura, o której mowa w art. 109 ust. 3d ustawy'));
} }
const fpLabel: Content[] = [];
if (getValue(faVat.FP) === '1') {
fpLabel.push(formatText('- Faktura, o której mowa w art. 109 ust. 3d ustawy'));
}
const zwrotAkcyzyLabel: Content[] = []; const zwrotAkcyzyLabel: Content[] = [];
if (getValue(faVat.ZwrotAkcyzy) === '1') { if (getValue(faVat.ZwrotAkcyzy) === '1') {
@@ -33,7 +38,7 @@ export function generateDodatkoweInformacje(faVat: Fa): Content[] {
); );
} }
const labels: Content[][] = [tpLabel1, tpLabel2, zwrotAkcyzyLabel].filter( const labels: Content[][] = [tpLabel, fpLabel, zwrotAkcyzyLabel].filter(
(el: Content[]): boolean => el.length > 0 (el: Content[]): boolean => el.length > 0
); );
const table: Content[] = [ const table: Content[] = [

View File

@@ -11,6 +11,8 @@ vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((text: string): Content[] => [{ text, style: 'header' }]), createHeader: vi.fn((text: string): Content[] => [{ text, style: 'header' }]),
createLabelText: vi.fn((label: string, value: any): Content[] => [{ text: `${label}${value ?? ''}` }]), createLabelText: vi.fn((label: string, value: any): Content[] => [{ text: `${label}${value ?? ''}` }]),
formatText: vi.fn((text: string, style?: any): Content => ({ text, style })), formatText: vi.fn((text: string, style?: any): Content => ({ text, style })),
getValue: vi.fn((val) => val?._text || ''),
hasValue: vi.fn((val) => Boolean(val && val._text)),
})); }));
vi.mock('./Adres', () => ({ vi.mock('./Adres', () => ({
@@ -40,7 +42,7 @@ describe(generatePodmiot1.name, (): void => {
const result: Content[] = generatePodmiot1(podmiot as Podmiot1); const result: Content[] = generatePodmiot1(podmiot as Podmiot1);
expect(createHeader).toHaveBeenCalledWith('Sprzedawca'); expect(createHeader).toHaveBeenCalledWith('Sprzedawca');
expect(createLabelText).toHaveBeenCalledWith('NrEORI: ', 'EORI123'); expect(createLabelText).toHaveBeenCalledWith('Numer EORI: ', 'EORI123');
expect(createLabelText).toHaveBeenCalledWith('Prefiks VAT: ', 'PL'); expect(createLabelText).toHaveBeenCalledWith('Prefiks VAT: ', 'PL');
expect((result as any[]).some((c) => c?.[0]?.text.includes('EORI123'))).toBe(true); expect((result as any[]).some((c) => c?.[0]?.text.includes('EORI123'))).toBe(true);
}); });
@@ -72,29 +74,27 @@ describe(generatePodmiot1.name, (): void => {
expect(formatText).toHaveBeenCalledWith('Adres do korespondencji', ['Label', 'LabelMargin']); expect(formatText).toHaveBeenCalledWith('Adres do korespondencji', ['Label', 'LabelMargin']);
}); });
it('generates contact data and taxpayer status', (): void => { it('generates contact data', (): void => {
const podmiot: Partial<Podmiot1> = { const podmiot: Partial<Podmiot1> = {
DaneKontaktowe: [{ Telefon: { _text: '123' } }], DaneKontaktowe: [{ Telefon: { _text: '123' } }],
StatusInfoPodatnika: { _text: 'active' },
}; };
const result = generatePodmiot1(podmiot as Podmiot1); const result = generatePodmiot1(podmiot as Podmiot1);
expect(generateDaneKontaktowe).toHaveBeenCalledWith([{ Telefon: { _text: '123' } }]); expect(generateDaneKontaktowe).toHaveBeenCalledWith([{ Telefon: { _text: '123' } }]);
expect(createLabelText).toHaveBeenCalledWith('Status podatnika: ', { _text: 'active' });
expect(result.some((c: Content): boolean => (c as any).text === 'mockDaneKontaktowe')).toBe(true); expect(result.some((c: Content): boolean => (c as any).text === 'mockDaneKontaktowe')).toBe(true);
}); });
it('generates only taxpayer status if no contact data', () => { it('generates taxpayer status ', () => {
const podmiot: Partial<Podmiot1> = { const podmiot: Partial<Podmiot1> = {
StatusInfoPodatnika: { _text: 'inactive' }, StatusInfoPodatnika: { _text: '1' },
}; };
const result: Content[] = generatePodmiot1(podmiot as Podmiot1); const result: Content[] = generatePodmiot1(podmiot as Podmiot1);
expect(generateDaneKontaktowe).not.toHaveBeenCalled();
expect(createLabelText).toHaveBeenCalledWith( expect(createLabelText).toHaveBeenCalledWith(
expect.stringContaining('Status podatnika'), expect.stringContaining('Status podatnika'),
expect.objectContaining({ _text: 'inactive' }) expect.stringContaining('Stan likwidacji')
); );
expect(result.some((c: Content): boolean => (c as any).text === 'mockDaneKontaktowe')).toBe(false);
}); });
}); });

View File

@@ -1,16 +1,17 @@
import { Content } from 'pdfmake/interfaces'; import { Content } from 'pdfmake/interfaces';
import { createHeader, createLabelText, formatText } from '../../../shared/PDF-functions'; import { createHeader, createLabelText, formatText, getValue, hasValue } from '../../../shared/PDF-functions';
import { Podmiot1 } from '../../types/fa2.types'; import { Podmiot1 } from '../../types/fa2.types';
import { generateAdres } from './Adres'; import { generateAdres } from './Adres';
import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto'; import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe'; import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import FormatTyp from '../../../shared/enums/common.enum'; import FormatTyp from '../../../shared/enums/common.enum';
import { TAXPAYER_STATUS } from '../../../shared/consts/const';
export function generatePodmiot1(podmiot1: Podmiot1): Content[] { export function generatePodmiot1(podmiot1: Podmiot1): Content[] {
const result: Content[] = createHeader('Sprzedawca'); const result: Content[] = createHeader('Sprzedawca');
result.push( result.push(
createLabelText('NrEORI: ', podmiot1.NrEORI), createLabelText('Numer EORI: ', podmiot1.NrEORI),
createLabelText('Prefiks VAT: ', podmiot1.PrefiksPodatnika) createLabelText('Prefiks VAT: ', podmiot1.PrefiksPodatnika)
); );
if (podmiot1.DaneIdentyfikacyjne) { if (podmiot1.DaneIdentyfikacyjne) {
@@ -31,10 +32,11 @@ export function generatePodmiot1(podmiot1: Podmiot1): Content[] {
formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]), formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]),
...generateDaneKontaktowe(podmiot1.DaneKontaktowe) ...generateDaneKontaktowe(podmiot1.DaneKontaktowe)
); );
}
if (hasValue(podmiot1.StatusInfoPodatnika)) {
const statusInfo: string = TAXPAYER_STATUS[getValue(podmiot1.StatusInfoPodatnika)!];
result.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika)); result.push(createLabelText('Status podatnika: ', statusInfo));
} else if (podmiot1.StatusInfoPodatnika) {
result.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika));
} }
return result; return result;
} }

View File

@@ -10,6 +10,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn((data: any) => data || []), getTable: vi.fn((data: any) => data || []),
formatText: vi.fn((text: string, style?: any): Content => ({ text, style })), formatText: vi.fn((text: string, style?: any): Content => ({ text, style })),
verticalSpacing: vi.fn((margin: number) => ({ margin })), verticalSpacing: vi.fn((margin: number) => ({ margin })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Adres', () => ({ vi.mock('./Adres', () => ({
@@ -51,19 +52,15 @@ describe(generatePodmiot1Podmiot1K.name, () => {
const result: any = generatePodmiot1Podmiot1K(podmiot1, podmiot1K); const result: any = generatePodmiot1Podmiot1K(podmiot1, podmiot1K);
expect(result[0]).toEqual({ text: 'Sprzedawca', style: 'header' }); expect(result[0]).toEqual({ text: 'Sprzedawca', style: 'header' });
expect(result[1]).toHaveProperty('columns'); expect(result[1]).toHaveProperty('columns');
expect(Array.isArray(result[1].columns[0])).toBe(true); expect(Array.isArray(result[1].columns[0])).toBe(true);
expect(Array.isArray(result[1].columns[1])).toBe(true); expect(Array.isArray(result[1].columns[1])).toBe(true);
expect(result[1].columns[0].length).toBeGreaterThan(0); expect(result[1].columns[0].length).toBeGreaterThan(0);
expect(result[1].columns[1].length).toBe(0); expect(result[1].columns[1].length).toBe(0);
expect(result[2]).toHaveProperty('columns'); expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true); expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(result[2].columns[0].length).toBeGreaterThan(0); expect(result[2].columns[0].length).toBeGreaterThan(0);
expect(result[2].columns[1].length).toBeGreaterThan(0);
expect(result[3]).toEqual({ margin: 1 }); expect(result[3]).toEqual({ margin: 1 });
}); });
@@ -90,9 +87,7 @@ describe(generatePodmiot1Podmiot1K.name, () => {
expect(result[1].columns[0]).toBeInstanceOf(Array); expect(result[1].columns[0]).toBeInstanceOf(Array);
expect(result[1].columns[1]).toBeInstanceOf(Array); expect(result[1].columns[1]).toBeInstanceOf(Array);
expect(result[2].columns[0]).toBeInstanceOf(Array); expect(result[2].columns[0]).toBeInstanceOf(Array);
expect(result[2].columns[1]).toBeInstanceOf(Array);
expect(result[3]).toEqual({ margin: 1 }); expect(result[3]).toEqual({ margin: 1 });
}); });

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
formatText, formatText,
generateColumns,
getTable, getTable,
verticalSpacing, verticalSpacing,
} from '../../../shared/PDF-functions'; } from '../../../shared/PDF-functions';
@@ -34,8 +35,8 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
columnGap: 20, columnGap: 20,
}); });
} }
firstColumn = generateCorrectedContent(podmiot1K); firstColumn = generateCorrectedContent(podmiot1K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot1); secondColumn = generateCorrectedContent(podmiot1, 'Treść korygująca');
if (podmiot1.AdresKoresp) { if (podmiot1.AdresKoresp) {
secondColumn.push( secondColumn.push(
@@ -44,10 +45,7 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
); );
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ result.push(generateColumns([firstColumn, secondColumn]));
columns: [firstColumn, secondColumn],
columnGap: 20,
});
} }
if (result.length) { if (result.length) {
result.push(verticalSpacing(1)); result.push(verticalSpacing(1));
@@ -55,10 +53,10 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
return result; return result;
} }
export function generateCorrectedContent(podmiot: Podmiot1 | Podmiot1K): Content[] { export function generateCorrectedContent(podmiot: Podmiot1 | Podmiot1K, header: string): Content[] {
const result: Content[] = []; const result: Content[] = [];
result.push(createHeader('Treść korygowana')); result.push(createHeader(header));
if (podmiot.PrefiksPodatnika?._text) { if (podmiot.PrefiksPodatnika?._text) {
result.push(createLabelText('Prefiks VAT: ', podmiot.PrefiksPodatnika)); result.push(createLabelText('Prefiks VAT: ', podmiot.PrefiksPodatnika));

View File

@@ -8,6 +8,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
createLabelText: vi.fn((label: string, value: any): Content[] => [{ text: `${label}${value ?? ''}` }]), createLabelText: vi.fn((label: string, value: any): Content[] => [{ text: `${label}${value ?? ''}` }]),
formatText: vi.fn((text: string, style?: any): Content => ({ text, style })), formatText: vi.fn((text: string, style?: any): Content => ({ text, style })),
verticalSpacing: vi.fn().mockImplementation((size) => ({ margin: size })), verticalSpacing: vi.fn().mockImplementation((size) => ({ margin: size })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Adres', () => ({ vi.mock('./Adres', () => ({
@@ -25,38 +26,43 @@ vi.mock('./PodmiotDaneKontaktowe', () => ({
})); }));
describe(generateCorrectedContent.name, () => { describe(generateCorrectedContent.name, () => {
const header = 'Treść korygowana';
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();
}); });
it('should generate corrected content base values ', () => { it('should generate corrected content base values ', () => {
const podmiot: Podmiot1K = {}; const podmiot: Podmiot1K = {};
const result: Content[] = generateCorrectedContent(podmiot); const result: Content[] = generateCorrectedContent(podmiot, header);
expect((result[0] as any).some((c: any) => c.text === 'Treść korygowana')).toBe(true);
expect((result[0] as any).some((c: any) => c.text === header)).toBe(true);
}); });
it('should generate corrected content with prefixPodatnika ', () => { it('should generate corrected content with prefixPodatnika ', () => {
const podmiot: Podmiot1K = { PrefiksPodatnika: { _text: 'tekst' } }; const podmiot: Podmiot1K = { PrefiksPodatnika: { _text: 'tekst' } };
const result: Content[] = generateCorrectedContent(podmiot); const result: Content[] = generateCorrectedContent(podmiot, header);
expect(result.length).equal(2);
expect((result[0] as any).some((c: any) => c.text === 'Treść korygowana')).toBe(true); expect(result.length).equal(2);
expect((result[0] as any).some((c: any) => c.text === header)).toBe(true);
expect((result[1] as any).some((c: any) => c.text.includes('Prefiks VAT: '))).toBe(true); expect((result[1] as any).some((c: any) => c.text.includes('Prefiks VAT: '))).toBe(true);
expect((result[1] as any).some((c: any) => c.text.includes('[object Object]'))).toBe(true); expect((result[1] as any).some((c: any) => c.text.includes('[object Object]'))).toBe(true);
}); });
it('should generate corrected content with id data ', () => { it('should generate corrected content with id data ', () => {
const podmiot: Podmiot1K = { DaneIdentyfikacyjne: { NIP: 'NIP' as FP, Nazwa: 'nazwa' as FP } }; const podmiot: Podmiot1K = { DaneIdentyfikacyjne: { NIP: 'NIP' as FP, Nazwa: 'nazwa' as FP } };
const result: Content[] = generateCorrectedContent(podmiot); const result: Content[] = generateCorrectedContent(podmiot, header);
expect(result.length).equal(2); expect(result.length).equal(2);
expect((result[0] as any).some((c: any) => c.text === 'Treść korygowana')).toBe(true); expect((result[0] as any).some((c: any) => c.text === header)).toBe(true);
expect((result[1] as any).text.includes('mockDaneIdentyfikacyjne')).toBe(true); expect((result[1] as any).text.includes('mockDaneIdentyfikacyjne')).toBe(true);
}); });
it('should generate corrected content with address ', () => { it('should generate corrected content with address ', () => {
const podmiot: Podmiot1K = { Adres: { KodKraju: 'PL' as FP } }; const podmiot: Podmiot1K = { Adres: { KodKraju: 'PL' as FP } };
const result: any = generateCorrectedContent(podmiot); const result: any = generateCorrectedContent(podmiot, header);
expect(result.length).equal(3); expect(result.length).equal(3);
expect((result[0] as any).some((c: any) => c.text === 'Treść korygowana')).toBe(true); expect((result[0] as any).some((c: any) => c.text === header)).toBe(true);
expect((result[1] as any).text.includes('Adres')).toBe(true); expect((result[1] as any).text.includes('Adres')).toBe(true);
expect((result[2] as any).some((c: { text: string }) => c.text === 'mockAdres')).toBe(true); expect((result[2] as any).some((c: { text: string }) => c.text === 'mockAdres')).toBe(true);
}); });
@@ -67,8 +73,9 @@ describe(generateCorrectedContent.name, () => {
DaneIdentyfikacyjne: { NIP: '123' as FP, Nazwa: 'Firma' as FP }, DaneIdentyfikacyjne: { NIP: '123' as FP, Nazwa: 'Firma' as FP },
Adres: { KodKraju: 'PL' as FP }, Adres: { KodKraju: 'PL' as FP },
}; };
const result: any = generateCorrectedContent(podmiot); const result: any = generateCorrectedContent(podmiot, header);
expect((result[0] as any).some((c: any) => c.text === 'Treść korygowana')).toBe(true);
expect((result[0] as any).some((c: any) => c.text === header)).toBe(true);
expect((result[1] as any).some((c: any) => c.text.includes('Prefiks VAT: '))).toBe(true); expect((result[1] as any).some((c: any) => c.text.includes('Prefiks VAT: '))).toBe(true);
expect((result[1] as any).some((c: any) => c.text.includes('[object Object]'))).toBe(true); expect((result[1] as any).some((c: any) => c.text.includes('[object Object]'))).toBe(true);
expect((result[2] as any).text.includes('mockDaneIdentyfikacyjne')).toBe(true); expect((result[2] as any).text.includes('mockDaneIdentyfikacyjne')).toBe(true);

View File

@@ -15,6 +15,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
vi.mock('./Adres', async () => { vi.mock('./Adres', async () => {
const actual = await vi.importActual('./Adres'); const actual = await vi.importActual('./Adres');
return { return {
...actual, ...actual,
generateAdres: vi.fn((adres: any): Content[] => [{ text: 'mockAddress' }]), generateAdres: vi.fn((adres: any): Content[] => [{ text: 'mockAddress' }]),
@@ -23,6 +24,7 @@ vi.mock('./Adres', async () => {
vi.mock('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto', async () => { vi.mock('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto', async () => {
const actual = await vi.importActual('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto'); const actual = await vi.importActual('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto');
return { return {
...actual, ...actual,
generateDaneIdentyfikacyjneTPodmiot2Dto: vi.fn((data: any): Content[] => [ generateDaneIdentyfikacyjneTPodmiot2Dto: vi.fn((data: any): Content[] => [
@@ -33,6 +35,7 @@ vi.mock('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto', async () => {
vi.mock('./PodmiotDaneKontaktowe', async () => { vi.mock('./PodmiotDaneKontaktowe', async () => {
const actual = await vi.importActual('./PodmiotDaneKontaktowe'); const actual = await vi.importActual('./PodmiotDaneKontaktowe');
return { return {
...actual, ...actual,
generateDaneKontaktowe: vi.fn((data: any): Content[] => [{ text: 'mockDaneKontaktowe' }]), generateDaneKontaktowe: vi.fn((data: any): Content[] => [{ text: 'mockDaneKontaktowe' }]),
@@ -50,7 +53,7 @@ describe(generatePodmiot2.name, () => {
expect(createHeader).toHaveBeenCalledWith('Nabywca'); expect(createHeader).toHaveBeenCalledWith('Nabywca');
expect(createLabelText).toHaveBeenCalledWith('Identyfikator nabywcy: ', 'ID123'); expect(createLabelText).toHaveBeenCalledWith('Identyfikator nabywcy: ', 'ID123');
expect(createLabelText).toHaveBeenCalledWith('NrEORI: ', 'EORI123'); expect(createLabelText).toHaveBeenCalledWith('Numer EORI: ', 'EORI123');
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' }); expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
}); });
@@ -98,6 +101,7 @@ describe(generatePodmiot2.name, () => {
DaneKontaktowe: [{ Telefon: '123' }] as any, DaneKontaktowe: [{ Telefon: '123' }] as any,
}; };
const result: Content = generatePodmiot2(podmiot as Podmiot2); const result: Content = generatePodmiot2(podmiot as Podmiot2);
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' }); expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
expect(result.some((c: any): boolean => c.text === 'mockDaneIdentyfikacyjne')).toBe(true); expect(result.some((c: any): boolean => c.text === 'mockDaneIdentyfikacyjne')).toBe(true);
expect( expect(

View File

@@ -12,7 +12,7 @@ export function generatePodmiot2(podmiot2: Podmiot2): Content[] {
result.push( result.push(
createLabelText('Identyfikator nabywcy: ', podmiot2.IDNabywcy), createLabelText('Identyfikator nabywcy: ', podmiot2.IDNabywcy),
createLabelText('NrEORI: ', podmiot2.NrEORI) createLabelText('Numer EORI: ', podmiot2.NrEORI)
); );
if (podmiot2.DaneIdentyfikacyjne) { if (podmiot2.DaneIdentyfikacyjne) {
result.push( result.push(

View File

@@ -1,6 +1,8 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'; import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { Content } from 'pdfmake/interfaces'; import type { Content } from 'pdfmake/interfaces';
import type { Podmiot2, Podmiot2K } from '../../types/fa2.types'; import type { Podmiot2, Podmiot2K } from '../../types/fa2.types';
import { generateAdres } from './Adres';
import { generatePodmiot2Podmiot2K } from './Podmiot2Podmiot2k';
vi.mock('../../../shared/PDF-functions', () => ({ vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((text: string): Content[] => [{ text, style: 'header' }]), createHeader: vi.fn((text: string): Content[] => [{ text, style: 'header' }]),
@@ -9,6 +11,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn((data: any) => data || []), getTable: vi.fn((data: any) => data || []),
hasValue: vi.fn((value: any) => value !== undefined && value !== null), hasValue: vi.fn((value: any) => value !== undefined && value !== null),
verticalSpacing: vi.fn((margin: number) => ({ margin })), verticalSpacing: vi.fn((margin: number) => ({ margin })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Adres', () => ({ vi.mock('./Adres', () => ({
@@ -25,10 +28,6 @@ vi.mock('./PodmiotDaneKontaktowe', () => ({
generateDaneKontaktowe: vi.fn((data: any): Content[] => [{ text: 'mockDaneKontaktowe' }]), generateDaneKontaktowe: vi.fn((data: any): Content[] => [{ text: 'mockDaneKontaktowe' }]),
})); }));
import { createHeader, createLabelText, formatText } from '../../../shared/PDF-functions';
import { generateAdres } from './Adres';
import { generatePodmiot2Podmiot2K } from './Podmiot2Podmiot2k';
describe(generatePodmiot2Podmiot2K.name, () => { describe(generatePodmiot2Podmiot2K.name, () => {
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();
@@ -52,10 +51,7 @@ describe(generatePodmiot2Podmiot2K.name, () => {
expect(result[2]).toHaveProperty('columns'); expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true);
expect(result[2].columns[0].length).toBeGreaterThan(0); expect(result[2].columns[0].length).toBeGreaterThan(0);
expect(result[2].columns[1].length).toBeGreaterThan(0);
expect(result[3]).toEqual({ margin: 1 }); expect(result[3]).toEqual({ margin: 1 });
}); });
@@ -71,9 +67,8 @@ describe(generatePodmiot2Podmiot2K.name, () => {
const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any; const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any;
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any; const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true); expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0); expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0);
expect(result[2].columns[1].length).toBeGreaterThanOrEqual(0);
}); });
it('adds vertical spacing at the end', () => { it('adds vertical spacing at the end', () => {
@@ -94,15 +89,12 @@ describe(generatePodmiot2Podmiot2K.name, () => {
} as any; } as any;
const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any; const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any;
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any; const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(result.length).toBeGreaterThan(3); expect(result.length).toBeGreaterThan(3);
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' }); expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
expect(result[2]).toHaveProperty('columns'); expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true);
expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0); expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0);
expect(result[2].columns[1].length).toBeGreaterThanOrEqual(0);
expect(result[result.length - 1]).toHaveProperty('margin'); expect(result[result.length - 1]).toHaveProperty('margin');
}); });

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
formatText, formatText,
generateColumns,
getTable, getTable,
hasValue, hasValue,
verticalSpacing, verticalSpacing,
@@ -35,8 +36,8 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
columnGap: 20, columnGap: 20,
}); });
} }
firstColumn = generateCorrectedContent(podmiot2K); firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot2); secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca');
if (podmiot2.AdresKoresp) { if (podmiot2.AdresKoresp) {
secondColumn.push( secondColumn.push(
formatText('Adres do korespondencji', [FormatTyp.Label, FormatTyp.LabelMargin]), formatText('Adres do korespondencji', [FormatTyp.Label, FormatTyp.LabelMargin]),
@@ -45,10 +46,7 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ result.push(generateColumns([firstColumn, secondColumn]));
columns: [firstColumn, secondColumn],
columnGap: 20,
});
} }
if (result.length) { if (result.length) {
result.push(verticalSpacing(1)); result.push(verticalSpacing(1));
@@ -56,10 +54,10 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
return result; return result;
} }
export function generateCorrectedContent(podmiot: Podmiot2 | Podmiot2K): Content[] { export function generateCorrectedContent(podmiot: Podmiot2 | Podmiot2K, header: string): Content[] {
const result: Content[] = []; const result: Content[] = [];
result.push(createHeader('Treść korygowana')); result.push(createHeader(header));
if (hasValue(podmiot.IDNabywcy)) { if (hasValue(podmiot.IDNabywcy)) {
result.push(createLabelText('Identyfikator nabywcy: ', podmiot.IDNabywcy)); result.push(createLabelText('Identyfikator nabywcy: ', podmiot.IDNabywcy));

View File

@@ -20,7 +20,7 @@ export function generatePodmiot3(podmiot: Podmiot3, index: number): Content[] {
const column1: Content[] = [ const column1: Content[] = [
...createHeader(`Podmiot inny ${index + 1}`), ...createHeader(`Podmiot inny ${index + 1}`),
createLabelText('Identyfikator nabywcy: ', podmiot.IDNabywcy), createLabelText('Identyfikator nabywcy: ', podmiot.IDNabywcy),
createLabelText('NrEORI: ', podmiot.NrEORI), createLabelText('Numer EORI: ', podmiot.NrEORI),
...generateDaneIdentyfikacyjneTPodmiot3Dto(podmiot.DaneIdentyfikacyjne), ...generateDaneIdentyfikacyjneTPodmiot3Dto(podmiot.DaneIdentyfikacyjne),
createLabelText('Rola: ', getRolaString(podmiot.Rola, 2)), createLabelText('Rola: ', getRolaString(podmiot.Rola, 2)),
createLabelText('Rola inna: ', podmiot.OpisRoli), createLabelText('Rola inna: ', podmiot.OpisRoli),

View File

@@ -21,11 +21,11 @@ describe(generateDaneKontaktowe.name, () => {
it('returns mapped Content array when daneKontaktowe is provided', () => { it('returns mapped Content array when daneKontaktowe is provided', () => {
const result = generateDaneKontaktowe(mockData); const result = generateDaneKontaktowe(mockData);
expect(getTable).toHaveBeenCalledWith(mockData); expect(getTable).toHaveBeenCalledWith(mockData);
expect(createLabelText).toHaveBeenCalledWith('Email: ', mockData[0].Email); expect(createLabelText).toHaveBeenCalledWith('E-mail: ', mockData[0].Email);
expect(createLabelText).toHaveBeenCalledWith('Tel.: ', mockData[0].Telefon); expect(createLabelText).toHaveBeenCalledWith('Tel.: ', mockData[0].Telefon);
expect(Array.isArray(result)).toBe(true); expect(Array.isArray(result)).toBe(true);
expect(result?.length).toBe(2); expect(result?.length).toBe(2);
expect(result?.[0]).toEqual([{ text: 'Email: test@example.com' }, { text: 'Tel.: 123456789' }]); expect(result?.[0]).toEqual([{ text: 'E-mail: test@example.com' }, { text: 'Tel.: 123456789' }]);
}); });
it('returns undefined when getTable returns undefined', () => { it('returns undefined when getTable returns undefined', () => {

View File

@@ -5,7 +5,7 @@ import { Podmiot1DaneKontaktowe } from '../../types/fa2.types';
export function generateDaneKontaktowe(daneKontaktowe: Podmiot1DaneKontaktowe[]): Content[] { export function generateDaneKontaktowe(daneKontaktowe: Podmiot1DaneKontaktowe[]): Content[] {
return getTable(daneKontaktowe)?.map((daneKontaktowe) => { return getTable(daneKontaktowe)?.map((daneKontaktowe) => {
return [ return [
createLabelText('Email: ', daneKontaktowe.Email), createLabelText('E-mail: ', daneKontaktowe.Email),
createLabelText('Tel.: ', daneKontaktowe.Telefon), createLabelText('Tel.: ', daneKontaktowe.Telefon),
]; ];
}); });

View File

@@ -14,6 +14,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
createSection: vi.fn((content: any, flag: boolean) => ({ content, flag })), createSection: vi.fn((content: any, flag: boolean) => ({ content, flag })),
getTable: vi.fn((data: any) => data || []), getTable: vi.fn((data: any) => data || []),
getValue: vi.fn((val: any) => val?._text ?? val), getValue: vi.fn((val: any) => val?._text ?? val),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Podmiot1', () => ({ vi.mock('./Podmiot1', () => ({

View File

@@ -1,5 +1,5 @@
import { Content } from 'pdfmake/interfaces'; import { Content } from 'pdfmake/interfaces';
import { createSection, getTable, getValue } from '../../../shared/PDF-functions'; import { createSection, generateColumns, getTable, getValue } from '../../../shared/PDF-functions';
import { Faktura, Podmiot2K as Podmiot2Kfa2, Podmiot3 } from '../../types/fa2.types'; import { Faktura, Podmiot2K as Podmiot2Kfa2, Podmiot3 } from '../../types/fa2.types';
import { Podmiot2K as Podmiot2Kfa1 } from '../../types/fa1.types'; import { Podmiot2K as Podmiot2Kfa1 } from '../../types/fa1.types';
import { Podmiot3Podmiot2KDto } from '../../types/fa2-additional-types'; import { Podmiot3Podmiot2KDto } from '../../types/fa2-additional-types';
@@ -32,10 +32,10 @@ export function generatePodmioty(invoice: Faktura): Content[] {
} }
} else { } else {
result.push([ result.push([
{ generateColumns([generatePodmiot1(invoice.Podmiot1!), generatePodmiot2(invoice.Podmiot2!)], {
columns: [generatePodmiot1(invoice.Podmiot1!), generatePodmiot2(invoice.Podmiot2!)],
margin: [0, 0, 0, 8], margin: [0, 0, 0, 8],
}, columnGap: 20,
}),
]); ]);
} }

View File

@@ -0,0 +1,259 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { generujRachunekBankowy } from './RachunekBankowy';
import * as PDFFunctions from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum';
import { FP } from '../../types/fa2.types';
import * as CommonFunctions from '../../../shared/generators/common/functions';
import { makeBreakable } from '../../../shared/PDF-functions';
vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn(),
createSection: vi.fn(),
formatText: vi.fn(),
makeBreakable: vi.fn(),
getValue: vi.fn((val) => (val && val._text ? val._text : '')),
hasValue: vi.fn((val) => Boolean(val && val._text)),
}));
vi.mock('../../../shared/generators/common/functions', () => ({
getTypRachunkowWlasnych: vi.fn(),
}));
describe(generujRachunekBankowy.name, () => {
beforeEach(() => {
vi.clearAllMocks();
});
const mockAccount: Record<string, FP> = {
NrRB: { _text: '12345678901234567890123456' },
SWIFT: { _text: 'BPKOPLPW' },
RachunekWlasnyBanku: { _text: '1' },
NazwaBanku: { _text: 'PKO Bank Polski' },
OpisRachunku: { _text: 'Rachunek główny' },
};
beforeEach(() => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['header'] as any);
vi.mocked(PDFFunctions.createSection).mockReturnValue('section' as any);
vi.mocked(PDFFunctions.formatText).mockReturnValue('formatted' as any);
vi.mocked(CommonFunctions.getTypRachunkowWlasnych).mockReturnValue('Tak');
});
describe('when accounts is undefined or empty', () => {
it('should return empty array when accounts is undefined', () => {
const result = generujRachunekBankowy(undefined, 'Rachunek bankowy');
expect(result).toEqual([]);
});
it('should return empty array when accounts is empty array', () => {
const result = generujRachunekBankowy([], 'Rachunek bankowy');
expect(result).toEqual([]);
});
});
describe('when accounts exist', () => {
it('should call createHeader with provided title', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.createHeader).toHaveBeenCalledWith('Rachunek bankowy ', [0, 12, 0, 8]);
});
it('should call createHeader with empty string when title is not provided', () => {
generujRachunekBankowy([mockAccount]);
expect(PDFFunctions.createHeader).toHaveBeenCalledWith('', [0, 12, 0, 8]);
});
it('should call createSection and return result', () => {
const mockSection = 'section';
vi.mocked(PDFFunctions.createSection).mockReturnValue(mockSection as any);
const result = generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.createSection).toHaveBeenCalledWith(expect.any(Array), false);
expect(result).toEqual(mockSection);
});
it('should format "Pełny numer rachunku" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Pełny numer rachunku', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(mockAccount.NrRB?._text, FormatTyp.Default);
});
it('should format "Kod SWIFT" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Kod SWIFT', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(mockAccount.SWIFT?._text, FormatTyp.Default);
});
it('should format "Rachunek własny banku" field', () => {
vi.mocked(CommonFunctions.getTypRachunkowWlasnych).mockReturnValue('Tak');
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Rachunek własny banku', FormatTyp.GrayBoldTitle);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(mockAccount.RachunekWlasnyBanku);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(makeBreakable('Tak', 20), FormatTyp.Default);
});
it('should format "Nazwa banku" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith(
makeBreakable(mockAccount.NazwaBanku?._text),
FormatTyp.Default
);
});
it('should format "Opis rachunku" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Opis rachunku', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(
makeBreakable(mockAccount.OpisRachunku?._text),
FormatTyp.Default
);
});
it('should create table structure with correct widths', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('table');
expect(tableContent.table).toHaveProperty('widths', ['*', 'auto']);
});
it('should create table structure with unbreakable property', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('unbreakable', true);
});
it('should create table with correct layout', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('layout');
expect(tableContent.layout).toHaveProperty('hLineWidth');
expect(tableContent.layout).toHaveProperty('hLineColor');
expect(tableContent.layout).toHaveProperty('vLineWidth');
expect(tableContent.layout).toHaveProperty('vLineColor');
});
it('should create table with correct line colors', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.layout.hLineColor()).toBe('#BABABA');
expect(tableContent.layout.vLineColor()).toBe('#BABABA');
});
it('should create table with correct line widths', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.layout.hLineWidth()).toBe(1);
expect(tableContent.layout.vLineWidth()).toBe(1);
});
it('should handle account with undefined fields', () => {
const accountWithUndefined: Record<string, FP> = {
NrRB: { _text: undefined },
SWIFT: { _text: undefined },
RachunekWlasnyBanku: { _text: undefined },
NazwaBanku: { _text: undefined },
OpisRachunku: { _text: undefined },
};
generujRachunekBankowy([accountWithUndefined], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith(undefined, FormatTyp.Default);
});
});
describe('when multiple accounts exist', () => {
it('should create multiple tables for multiple accounts', () => {
const account2: Record<string, FP> = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
};
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
expect(sectionCall.length).toBe(2);
});
it('should call getTypRachunkowWlasnych for each account', () => {
const account2: Record<string, FP> = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
};
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledTimes(2);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(mockAccount.RachunekWlasnyBanku);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(account2.RachunekWlasnyBanku);
});
it('should format all fields for all accounts', () => {
const account2: Record<string, FP> = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
};
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith(mockAccount.NrRB?._text, FormatTyp.Default);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(account2.NrRB?._text, FormatTyp.Default);
});
});
describe('table structure', () => {
it('should create table with 5 rows', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.table.body.length).toBe(5);
});
it('should include header in result array', () => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['header-content'] as any);
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
expect(sectionCall[0][0]).toBe('header-content');
});
});
});

View File

@@ -1,5 +1,12 @@
import { Content, ContentTable } from 'pdfmake/interfaces'; import { Content, ContentTable } from 'pdfmake/interfaces';
import { createHeader, createSection, formatText } from '../../../shared/PDF-functions'; import {
createHeader,
createSection,
formatText,
getValue,
hasValue,
makeBreakable,
} from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum'; import FormatTyp from '../../../shared/enums/common.enum';
import { RachunekBankowy } from '../../types/fa2.types'; import { RachunekBankowy } from '../../types/fa2.types';
import { getTypRachunkowWlasnych } from '../../../shared/generators/common/functions'; import { getTypRachunkowWlasnych } from '../../../shared/generators/common/functions';
@@ -25,23 +32,33 @@ export const generujRachunekBankowy: (accounts?: Record<string, FP>[], title?: s
table.push([ table.push([
formatText('Pełny numer rachunku', FormatTyp.GrayBoldTitle), formatText('Pełny numer rachunku', FormatTyp.GrayBoldTitle),
formatText(account.NrRB?._text, FormatTyp.Default), formatText(getValue(account.NrRB), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Kod SWIFT', FormatTyp.GrayBoldTitle), formatText('Kod SWIFT', FormatTyp.GrayBoldTitle),
formatText(account.SWIFT?._text, FormatTyp.Default), formatText(getValue(account.SWIFT), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Rachunek własny banku', FormatTyp.GrayBoldTitle), formatText('Rachunek własny banku', FormatTyp.GrayBoldTitle),
formatText(getTypRachunkowWlasnych(account.RachunekWlasnyBanku), FormatTyp.Default), formatText(makeBreakable(getTypRachunkowWlasnych(account.RachunekWlasnyBanku), 20), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Nazwa banku', FormatTyp.GrayBoldTitle), formatText('Nazwa banku', FormatTyp.GrayBoldTitle),
formatText(account.NazwaBanku?._text, FormatTyp.Default), formatText(
hasValue(account.NazwaBanku)
? makeBreakable(getValue(account.NazwaBanku), 20)
: getValue(account.NazwaBanku),
FormatTyp.Default
),
]); ]);
table.push([ table.push([
formatText('Opis rachunku', FormatTyp.GrayBoldTitle), formatText('Opis rachunku', FormatTyp.GrayBoldTitle),
formatText(account.OpisRachunku?._text, FormatTyp.Default), formatText(
hasValue(account.OpisRachunku)
? makeBreakable(getValue(account.OpisRachunku), 20)
: getValue(account.OpisRachunku),
FormatTyp.Default
),
]); ]);
result.push([ result.push([
...base, ...base,

View File

@@ -1,4 +1,6 @@
import { describe, it, expect, vi, beforeEach, test } from 'vitest'; import { beforeEach, describe, expect, it, test, vi } from 'vitest';
import { createHeader, createLabelText, formatText, getTable } from '../../../shared/PDF-functions';
import { generateAdnotacje, generateDostawy } from './Adnotacje';
vi.mock('../../../shared/PDF-functions', () => ({ vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((text: string) => ({ text, style: 'header' })), createHeader: vi.fn((text: string) => ({ text, style: 'header' })),
@@ -7,11 +9,9 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn(() => []), getTable: vi.fn(() => []),
hasValue: vi.fn((v) => !!v?._text), hasValue: vi.fn((v) => !!v?._text),
verticalSpacing: vi.fn((n: number) => ({ text: `space-${n}` })), verticalSpacing: vi.fn((n: number) => ({ text: `space-${n}` })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
import { createHeader, createLabelText, getTable, formatText } from '../../../shared/PDF-functions';
import { generateAdnotacje, generateDostawy } from './Adnotacje';
describe(generateAdnotacje.name, () => { describe(generateAdnotacje.name, () => {
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
formatText, formatText,
generateColumns,
getTable, getTable,
hasValue, hasValue,
verticalSpacing, verticalSpacing,
@@ -130,7 +131,7 @@ export function generateAdnotacje(adnotacje?: Adnotacje): Content[] {
addToColumn(firstColumn, secondColumn, { text: 'Samofakturowanie' }); addToColumn(firstColumn, secondColumn, { text: 'Samofakturowanie' });
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ columns: [firstColumn, secondColumn], columnGap: 20 }); result.push(generateColumns([firstColumn, secondColumn]));
} }
if (result.length) { if (result.length) {

View File

@@ -76,4 +76,17 @@ describe(generateDodatkoweInformacje.name, () => {
expect(createSection).toHaveBeenCalled(); expect(createSection).toHaveBeenCalled();
expect(result.length).toBeGreaterThan(0); expect(result.length).toBeGreaterThan(0);
}); });
it('poprawnie dodaje sekcję FP', () => {
const faVat = {
FP: { _text: '1' },
};
const result = generateDodatkoweInformacje(faVat as any);
expect(formatText).toHaveBeenCalledWith(
'- Faktura, o której mowa w art. 109 ust. 3d ustawy'
);
expect(createSection).toHaveBeenCalled();
expect(result.length).toBeGreaterThan(0);
});
}); });

View File

@@ -13,15 +13,20 @@ import { DodatkowyOpi, Fa } from '../../types/fa3.types';
import FormatTyp from '../../../shared/enums/common.enum'; import FormatTyp from '../../../shared/enums/common.enum';
export function generateDodatkoweInformacje(faVat: Fa): Content[] { export function generateDodatkoweInformacje(faVat: Fa): Content[] {
const tpLabel1: Content[] = []; const tpLabel: Content[] = [];
const tpLabel2: Content[] = [];
if (getValue(faVat.TP) === '1') { if (getValue(faVat.TP) === '1') {
tpLabel1.push( tpLabel.push(
formatText('- Istniejące powiązania między nabywcą a dokonującym dostawy towarów lub usługodawcą') formatText('- Istniejące powiązania między nabywcą a dokonującym dostawy towarów lub usługodawcą')
); );
tpLabel2.push(formatText('- Faktura, o której mowa w art. 109 ust. 3d ustawy'));
} }
const fpLabel: Content[] = [];
if (getValue(faVat.FP) === '1') {
fpLabel.push(formatText('- Faktura, o której mowa w art. 109 ust. 3d ustawy'));
}
const zwrotAkcyzyLabel: Content[] = []; const zwrotAkcyzyLabel: Content[] = [];
if (getValue(faVat.ZwrotAkcyzy) === '1') { if (getValue(faVat.ZwrotAkcyzy) === '1') {
@@ -32,7 +37,7 @@ export function generateDodatkoweInformacje(faVat: Fa): Content[] {
); );
} }
const labels = [tpLabel1, tpLabel2, zwrotAkcyzyLabel].filter((el) => el.length > 0); const labels = [tpLabel, fpLabel, zwrotAkcyzyLabel].filter((el) => el.length > 0);
const table: Content[] = [ const table: Content[] = [
...createHeader('Dodatkowe informacje'), ...createHeader('Dodatkowe informacje'),
...labels, ...labels,

View File

@@ -80,7 +80,9 @@ export function generatePlatnosc(platnosc: Platnosc | undefined): Content {
const tableZaplataCzesciowa = getContentTable<(typeof zaplataCzesciowa)[0]>( const tableZaplataCzesciowa = getContentTable<(typeof zaplataCzesciowa)[0]>(
zaplataCzesciowaNaglowek, zaplataCzesciowaNaglowek,
zaplataCzesciowa, zaplataCzesciowa,
'*' '*',
undefined,
20
); );
const terminPatnosciContent = terminPlatnosci.map((platnosc) => { const terminPatnosciContent = terminPlatnosci.map((platnosc) => {
if (!terminPlatnosci.some((termin) => termin.TerminOpis)) { if (!terminPlatnosci.some((termin) => termin.TerminOpis)) {
@@ -98,7 +100,9 @@ export function generatePlatnosc(platnosc: Platnosc | undefined): Content {
const tableTerminPlatnosci = getContentTable<(typeof terminPlatnosci)[0]>( const tableTerminPlatnosci = getContentTable<(typeof terminPlatnosci)[0]>(
zaplataCzesciowaHeader, zaplataCzesciowaHeader,
terminPatnosciContent, terminPatnosciContent,
'*' '*',
undefined,
20
); );
if (zaplataCzesciowa.length > 0 && terminPlatnosci.length > 0) { if (zaplataCzesciowa.length > 0 && terminPlatnosci.length > 0) {
@@ -125,7 +129,7 @@ export function generatePlatnosc(platnosc: Platnosc | undefined): Content {
} as ContentText); } as ContentText);
} }
if (platnosc.IPKSeF?._text) { if (platnosc.IPKSeF?._text) {
createLabelText('Identyfikator płatności Krajowego Systemu e-Faktur: ', platnosc.IPKSeF); table.push(createLabelText('Identyfikator płatności Krajowego Systemu e-Faktur: ', platnosc.IPKSeF));
} }
table.push( table.push(

View File

@@ -11,6 +11,8 @@ vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((text: string): Content[] => [{ text, style: 'header' }]), createHeader: vi.fn((text: string): Content[] => [{ text, style: 'header' }]),
createLabelText: vi.fn((label: string, value: any): Content[] => [{ text: `${label}${value ?? ''}` }]), createLabelText: vi.fn((label: string, value: any): Content[] => [{ text: `${label}${value ?? ''}` }]),
formatText: vi.fn((text: string, style?: any): Content => ({ text, style })), formatText: vi.fn((text: string, style?: any): Content => ({ text, style })),
getValue: vi.fn((val) => val?._text || ''),
hasValue: vi.fn((val) => Boolean(val && val._text)),
})); }));
vi.mock('./Adres', () => ({ vi.mock('./Adres', () => ({
@@ -40,7 +42,7 @@ describe(generatePodmiot1.name, () => {
const result = generatePodmiot1(podmiot as Podmiot1); const result = generatePodmiot1(podmiot as Podmiot1);
expect(createHeader).toHaveBeenCalledWith('Sprzedawca'); expect(createHeader).toHaveBeenCalledWith('Sprzedawca');
expect(createLabelText).toHaveBeenCalledWith('NrEORI: ', 'EORI123'); expect(createLabelText).toHaveBeenCalledWith('Numer EORI: ', 'EORI123');
expect(createLabelText).toHaveBeenCalledWith('Prefiks VAT: ', 'PL'); expect(createLabelText).toHaveBeenCalledWith('Prefiks VAT: ', 'PL');
expect((result as any[]).some((c) => c?.[0]?.text.includes('EORI123'))).toBe(true); expect((result as any[]).some((c) => c?.[0]?.text.includes('EORI123'))).toBe(true);
}); });
@@ -72,25 +74,23 @@ describe(generatePodmiot1.name, () => {
expect(formatText).toHaveBeenCalledWith('Adres do korespondencji', ['Label', 'LabelMargin']); expect(formatText).toHaveBeenCalledWith('Adres do korespondencji', ['Label', 'LabelMargin']);
}); });
it('generates contact data and taxpayer status', () => { it('generates contact data', () => {
const podmiot: Partial<Podmiot1> = { const podmiot: Partial<Podmiot1> = {
DaneKontaktowe: [{ Telefon: { _text: '123' } }], DaneKontaktowe: [{ Telefon: { _text: '123' } }],
StatusInfoPodatnika: { _text: 'active' },
}; };
const result = generatePodmiot1(podmiot as Podmiot1); const result = generatePodmiot1(podmiot as Podmiot1);
expect(generateDaneKontaktowe).toHaveBeenCalledWith([{ Telefon: { _text: '123' } }]); expect(generateDaneKontaktowe).toHaveBeenCalledWith([{ Telefon: { _text: '123' } }]);
expect(createLabelText).toHaveBeenCalledWith('Status podatnika: ', { _text: 'active' });
expect(result.some((c) => (c as any).text === 'mockDaneKontaktowe')).toBe(true); expect(result.some((c) => (c as any).text === 'mockDaneKontaktowe')).toBe(true);
}); });
it('generates only taxpayer status if no contact data', () => { it('generates taxpayer status', () => {
const podmiot: Partial<Podmiot1> = { const podmiot: Partial<Podmiot1> = {
StatusInfoPodatnika: { _text: 'inactive' }, StatusInfoPodatnika: { _text: '1' },
}; };
const result = generatePodmiot1(podmiot as Podmiot1); const result = generatePodmiot1(podmiot as Podmiot1);
expect(generateDaneKontaktowe).not.toHaveBeenCalled(); expect(createLabelText).toHaveBeenCalledWith('Status podatnika: ', 'Stan likwidacji');
expect(createLabelText).toHaveBeenCalledWith('Status podatnika: ', { _text: 'inactive' }); expect(result.some((c) => (c as any).text === 'mockDaneKontaktowe')).toBe(false);
}); });
}); });

View File

@@ -1,16 +1,17 @@
import { Content } from 'pdfmake/interfaces'; import { Content } from 'pdfmake/interfaces';
import { createHeader, createLabelText, formatText } from '../../../shared/PDF-functions'; import { createHeader, createLabelText, formatText, getValue, hasValue } from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum'; import FormatTyp from '../../../shared/enums/common.enum';
import { Podmiot1 } from '../../types/fa3.types'; import { Podmiot1 } from '../../types/fa3.types';
import { generateAdres } from './Adres'; import { generateAdres } from './Adres';
import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto'; import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe'; import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { TAXPAYER_STATUS } from '../../../shared/consts/const';
export function generatePodmiot1(podmiot1: Podmiot1): Content[] { export function generatePodmiot1(podmiot1: Podmiot1): Content[] {
const result: Content[] = createHeader('Sprzedawca'); const result: Content[] = createHeader('Sprzedawca');
result.push( result.push(
createLabelText('NrEORI: ', podmiot1.NrEORI), createLabelText('Numer EORI: ', podmiot1.NrEORI),
createLabelText('Prefiks VAT: ', podmiot1.PrefiksPodatnika) createLabelText('Prefiks VAT: ', podmiot1.PrefiksPodatnika)
); );
if (podmiot1.DaneIdentyfikacyjne) { if (podmiot1.DaneIdentyfikacyjne) {
@@ -31,10 +32,11 @@ export function generatePodmiot1(podmiot1: Podmiot1): Content[] {
formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]), formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]),
...generateDaneKontaktowe(podmiot1.DaneKontaktowe) ...generateDaneKontaktowe(podmiot1.DaneKontaktowe)
); );
}
if (hasValue(podmiot1.StatusInfoPodatnika)) {
const statusInfo: string = TAXPAYER_STATUS[getValue(podmiot1.StatusInfoPodatnika)!];
result.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika)); result.push(createLabelText('Status podatnika: ', statusInfo));
} else if (podmiot1.StatusInfoPodatnika) {
result.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika));
} }
return result; return result;
} }

View File

@@ -10,6 +10,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn((data: any) => data || []), getTable: vi.fn((data: any) => data || []),
formatText: vi.fn((text: string, style?: any): Content => ({ text, style })), formatText: vi.fn((text: string, style?: any): Content => ({ text, style })),
verticalSpacing: vi.fn((margin: number) => ({ margin })), verticalSpacing: vi.fn((margin: number) => ({ margin })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Adres', () => ({ vi.mock('./Adres', () => ({
@@ -60,9 +61,7 @@ describe(generatePodmiot1Podmiot1K.name, () => {
expect(result[2]).toHaveProperty('columns'); expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true);
expect(result[2].columns[0].length).toBeGreaterThan(0); expect(result[2].columns[0].length).toBeGreaterThan(0);
expect(result[2].columns[1].length).toBeGreaterThan(0);
expect(result[3]).toEqual({ margin: 1 }); expect(result[3]).toEqual({ margin: 1 });
}); });
@@ -87,13 +86,9 @@ describe(generatePodmiot1Podmiot1K.name, () => {
expect(result.length).toBe(4); expect(result.length).toBe(4);
expect(result[0]).toEqual({ text: 'Sprzedawca', style: 'header' }); expect(result[0]).toEqual({ text: 'Sprzedawca', style: 'header' });
expect(result[1].columns[0]).toBeInstanceOf(Array); expect(result[1].columns[0]).toBeInstanceOf(Array);
expect(result[1].columns[1]).toBeInstanceOf(Array); expect(result[1].columns[1]).toBeInstanceOf(Array);
expect(result[2].columns[0]).toBeInstanceOf(Array); expect(result[2].columns[0]).toBeInstanceOf(Array);
expect(result[2].columns[1]).toBeInstanceOf(Array);
expect(result[3]).toEqual({ margin: 1 }); expect(result[3]).toEqual({ margin: 1 });
}); });
}); });

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
formatText, formatText,
generateColumns,
getTable, getTable,
verticalSpacing, verticalSpacing,
} from '../../../shared/PDF-functions'; } from '../../../shared/PDF-functions';
@@ -39,8 +40,8 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
columnGap: 20, columnGap: 20,
}); });
} }
firstColumn = generateCorrectedContent(podmiot1K); firstColumn = generateCorrectedContent(podmiot1K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot1); secondColumn = generateCorrectedContent(podmiot1, 'Treść korygująca');
if (podmiot1.AdresKoresp) { if (podmiot1.AdresKoresp) {
secondColumn.push( secondColumn.push(
@@ -49,10 +50,7 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
); );
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ result.push(generateColumns([firstColumn, secondColumn]));
columns: [firstColumn, secondColumn],
columnGap: 20,
});
} }
if (result.length) { if (result.length) {
result.push(verticalSpacing(1)); result.push(verticalSpacing(1));
@@ -60,10 +58,10 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
return result; return result;
} }
export function generateCorrectedContent(podmiot: Podmiot1 | Podmiot1K): Content[] { export function generateCorrectedContent(podmiot: Podmiot1 | Podmiot1K, header: string): Content[] {
const result: Content[] = []; const result: Content[] = [];
result.push(createHeader('Treść korygowana')); result.push(createHeader(header));
if (podmiot.PrefiksPodatnika?._text) { if (podmiot.PrefiksPodatnika?._text) {
result.push(createLabelText('Prefiks VAT: ', podmiot.PrefiksPodatnika)); result.push(createLabelText('Prefiks VAT: ', podmiot.PrefiksPodatnika));

View File

@@ -18,6 +18,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
vi.mock('./Adres', async () => { vi.mock('./Adres', async () => {
const actual = await vi.importActual('./Adres'); const actual = await vi.importActual('./Adres');
return { return {
...actual, ...actual,
generateAdres: vi.fn((): Content[] => [{ text: 'mockAddress' } as Content]), generateAdres: vi.fn((): Content[] => [{ text: 'mockAddress' } as Content]),
@@ -26,6 +27,7 @@ vi.mock('./Adres', async () => {
vi.mock('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto', async () => { vi.mock('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto', async () => {
const actual = await vi.importActual('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto'); const actual = await vi.importActual('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto');
return { return {
...actual, ...actual,
generateDaneIdentyfikacyjneTPodmiot2Dto: vi.fn((): Content[] => [ generateDaneIdentyfikacyjneTPodmiot2Dto: vi.fn((): Content[] => [
@@ -36,6 +38,7 @@ vi.mock('./PodmiotDaneIdentyfikacyjneTPodmiot2Dto', async () => {
vi.mock('./PodmiotDaneKontaktowe', async () => { vi.mock('./PodmiotDaneKontaktowe', async () => {
const actual = await vi.importActual('./PodmiotDaneKontaktowe'); const actual = await vi.importActual('./PodmiotDaneKontaktowe');
return { return {
...actual, ...actual,
generateDaneKontaktowe: vi.fn((): Content[] => [{ text: 'mockDaneKontaktowe' } as Content]), generateDaneKontaktowe: vi.fn((): Content[] => [{ text: 'mockDaneKontaktowe' } as Content]),
@@ -53,7 +56,7 @@ describe(generatePodmiot2.name, () => {
expect(createHeader).toHaveBeenCalledWith('Nabywca'); expect(createHeader).toHaveBeenCalledWith('Nabywca');
expect(createLabelText).toHaveBeenCalledWith('Identyfikator nabywcy: ', 'ID123'); expect(createLabelText).toHaveBeenCalledWith('Identyfikator nabywcy: ', 'ID123');
expect(createLabelText).toHaveBeenCalledWith('NrEORI: ', 'EORI123'); expect(createLabelText).toHaveBeenCalledWith('Numer EORI: ', 'EORI123');
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' }); expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
}); });
@@ -110,8 +113,8 @@ describe(generatePodmiot2.name, () => {
const addressCount = result.filter((c: any) => c.text === 'mockAddress').length; const addressCount = result.filter((c: any) => c.text === 'mockAddress').length;
const fifthElementLength = Array.isArray(result[5]) ? result[5].length : 0; const fifthElementLength = Array.isArray(result[5]) ? result[5].length : 0;
expect(addressCount + fifthElementLength).toBe(2);
expect(addressCount + fifthElementLength).toBe(2);
expect(result.some((c: any) => c.text === 'mockDaneKontaktowe')).toBe(true); expect(result.some((c: any) => c.text === 'mockDaneKontaktowe')).toBe(true);
expect(createLabelText).toHaveBeenCalledWith('Numer klienta: ', 'CL123'); expect(createLabelText).toHaveBeenCalledWith('Numer klienta: ', 'CL123');
}); });

View File

@@ -12,7 +12,7 @@ export function generatePodmiot2(podmiot2: Podmiot2): Content[] {
result.push( result.push(
createLabelText('Identyfikator nabywcy: ', podmiot2.IDNabywcy), createLabelText('Identyfikator nabywcy: ', podmiot2.IDNabywcy),
createLabelText('NrEORI: ', podmiot2.NrEORI) createLabelText('Numer EORI: ', podmiot2.NrEORI)
); );
if (podmiot2.DaneIdentyfikacyjne) { if (podmiot2.DaneIdentyfikacyjne) {
result.push( result.push(

View File

@@ -12,6 +12,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getTable: vi.fn((data: any) => data || []), getTable: vi.fn((data: any) => data || []),
hasValue: vi.fn((value: any) => value !== undefined && value !== null), hasValue: vi.fn((value: any) => value !== undefined && value !== null),
verticalSpacing: vi.fn((margin: number) => ({ margin })), verticalSpacing: vi.fn((margin: number) => ({ margin })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Adres', () => ({ vi.mock('./Adres', () => ({
@@ -51,9 +52,8 @@ describe(generatePodmiot2Podmiot2K.name, () => {
expect(result[2]).toHaveProperty('columns'); expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true); expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(result[2].columns[0].length).toBeGreaterThan(0); expect(result[2].columns[0].length).toBeGreaterThan(0);
expect(result[2].columns[1].length).toBeGreaterThan(0);
expect(result[3]).toEqual({ margin: 1 }); expect(result[3]).toEqual({ margin: 1 });
}); });
@@ -71,10 +71,9 @@ describe(generatePodmiot2Podmiot2K.name, () => {
const podmiot2: Podmiot2 = { NrEORI: 'EORI123' } as any; const podmiot2: Podmiot2 = { NrEORI: 'EORI123' } as any;
const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any; const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any;
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any; const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true);
expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0); expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0);
expect(result[2].columns[1].length).toBeGreaterThanOrEqual(0);
}); });
it('adds vertical spacing at the end', () => { it('adds vertical spacing at the end', () => {
@@ -101,10 +100,8 @@ describe(generatePodmiot2Podmiot2K.name, () => {
expect(result[2]).toHaveProperty('columns'); expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true); expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(true); expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0); expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0);
expect(result[2].columns[1].length).toBeGreaterThanOrEqual(0);
expect(result[result.length - 1]).toHaveProperty('margin'); expect(result[result.length - 1]).toHaveProperty('margin');
}); });
}); });

View File

@@ -3,6 +3,7 @@ import {
createHeader, createHeader,
createLabelText, createLabelText,
formatText, formatText,
generateColumns,
getTable, getTable,
verticalSpacing, verticalSpacing,
} from '../../../shared/PDF-functions'; } from '../../../shared/PDF-functions';
@@ -37,8 +38,9 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
columnGap: 20, columnGap: 20,
}); });
} }
firstColumn = generateCorrectedContent(podmiot2K); firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot2); secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca');
if (podmiot2.AdresKoresp) { if (podmiot2.AdresKoresp) {
secondColumn.push( secondColumn.push(
formatText('Adres do korespondencji', [FormatTyp.Label, FormatTyp.LabelMargin]), formatText('Adres do korespondencji', [FormatTyp.Label, FormatTyp.LabelMargin]),
@@ -47,10 +49,7 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
} }
if (firstColumn.length || secondColumn.length) { if (firstColumn.length || secondColumn.length) {
result.push({ result.push(generateColumns([firstColumn, secondColumn]));
columns: [firstColumn, secondColumn],
columnGap: 20,
});
} }
if (result.length) { if (result.length) {
result.push(verticalSpacing(1)); result.push(verticalSpacing(1));

View File

@@ -20,7 +20,7 @@ export function generatePodmiot3(podmiot: Podmiot3, index: number): Content[] {
const column1: Content[] = [ const column1: Content[] = [
...createHeader(`Podmiot inny ${index + 1}`), ...createHeader(`Podmiot inny ${index + 1}`),
createLabelText('Identyfikator nabywcy: ', podmiot.IDNabywcy), createLabelText('Identyfikator nabywcy: ', podmiot.IDNabywcy),
createLabelText('NrEORI: ', podmiot.NrEORI), createLabelText('Numer EORI: ', podmiot.NrEORI),
...generateDaneIdentyfikacyjneTPodmiot3Dto(podmiot.DaneIdentyfikacyjne), ...generateDaneIdentyfikacyjneTPodmiot3Dto(podmiot.DaneIdentyfikacyjne),
createLabelText('Rola: ', getRolaString(podmiot.Rola, 3)), createLabelText('Rola: ', getRolaString(podmiot.Rola, 3)),
createLabelText('Rola inna: ', podmiot.OpisRoli), createLabelText('Rola inna: ', podmiot.OpisRoli),

View File

@@ -21,11 +21,11 @@ describe(generateDaneKontaktowe.name, () => {
it('returns mapped Content array when daneKontaktowe is provided', () => { it('returns mapped Content array when daneKontaktowe is provided', () => {
const result = generateDaneKontaktowe(mockData); const result = generateDaneKontaktowe(mockData);
expect(getTable).toHaveBeenCalledWith(mockData); expect(getTable).toHaveBeenCalledWith(mockData);
expect(createLabelText).toHaveBeenCalledWith('Email: ', mockData[0].Email); expect(createLabelText).toHaveBeenCalledWith('E-mail: ', mockData[0].Email);
expect(createLabelText).toHaveBeenCalledWith('Tel.: ', mockData[0].Telefon); expect(createLabelText).toHaveBeenCalledWith('Tel.: ', mockData[0].Telefon);
expect(Array.isArray(result)).toBe(true); expect(Array.isArray(result)).toBe(true);
expect(result?.length).toBe(2); expect(result?.length).toBe(2);
expect(result?.[0]).toEqual([{ text: 'Email: test@example.com' }, { text: 'Tel.: 123456789' }]); expect(result?.[0]).toEqual([{ text: 'E-mail: test@example.com' }, { text: 'Tel.: 123456789' }]);
}); });
it('returns undefined when getTable returns undefined', () => { it('returns undefined when getTable returns undefined', () => {

View File

@@ -5,7 +5,7 @@ import { Podmiot1DaneKontaktowe } from '../../types/fa3.types';
export function generateDaneKontaktowe(daneKontaktowe: Podmiot1DaneKontaktowe[]): Content[] { export function generateDaneKontaktowe(daneKontaktowe: Podmiot1DaneKontaktowe[]): Content[] {
return getTable(daneKontaktowe)?.map((daneKontaktowe) => { return getTable(daneKontaktowe)?.map((daneKontaktowe) => {
return [ return [
createLabelText('Email: ', daneKontaktowe.Email), createLabelText('E-mail: ', daneKontaktowe.Email),
createLabelText('Tel.: ', daneKontaktowe.Telefon), createLabelText('Tel.: ', daneKontaktowe.Telefon),
]; ];
}); });

View File

@@ -14,6 +14,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
createSection: vi.fn((content: any, flag: boolean) => ({ content, flag })), createSection: vi.fn((content: any, flag: boolean) => ({ content, flag })),
getTable: vi.fn((data: any) => data || []), getTable: vi.fn((data: any) => data || []),
getValue: vi.fn((val: any) => val?._text ?? val), getValue: vi.fn((val: any) => val?._text ?? val),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
})); }));
vi.mock('./Podmiot1', () => ({ vi.mock('./Podmiot1', () => ({

View File

@@ -1,5 +1,5 @@
import { Content } from 'pdfmake/interfaces'; import { Content } from 'pdfmake/interfaces';
import { createSection, getTable, getValue } from '../../../shared/PDF-functions'; import { createSection, generateColumns, getTable, getValue } from '../../../shared/PDF-functions';
import { Faktura, Podmiot2K, Podmiot3 } from '../../types/fa3.types'; import { Faktura, Podmiot2K, Podmiot3 } from '../../types/fa3.types';
import { Podmiot3Podmiot2KDto } from '../../types/fa2-additional-types'; import { Podmiot3Podmiot2KDto } from '../../types/fa2-additional-types';
import { generatePodmiot1 } from './Podmiot1'; import { generatePodmiot1 } from './Podmiot1';
@@ -32,10 +32,10 @@ export function generatePodmioty(invoice: Faktura): Content[] {
} }
} else { } else {
result.push([ result.push([
{ generateColumns([generatePodmiot1(invoice.Podmiot1!), generatePodmiot2(invoice.Podmiot2!)], {
columns: [generatePodmiot1(invoice.Podmiot1!), generatePodmiot2(invoice.Podmiot2!)],
margin: [0, 0, 0, 8], margin: [0, 0, 0, 8],
}, columnGap: 20,
}),
]); ]);
} }

View File

@@ -0,0 +1,263 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { generujRachunekBankowy } from './RachunekBankowy';
import * as PDFFunctions from '../../../shared/PDF-functions';
import { makeBreakable } from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum';
import { RachunekBankowy } from '../../types/fa3.types';
import * as CommonFunctions from '../../../shared/generators/common/functions';
vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn(),
createSection: vi.fn(),
formatText: vi.fn(),
makeBreakable: vi.fn(),
getValue: (val: any) => val?._text || '',
hasValue: (val: any) => val?._text || '',
}));
vi.mock('../../../shared/generators/common/functions', () => ({
getTypRachunkowWlasnych: vi.fn(),
}));
describe(generujRachunekBankowy.name, () => {
beforeEach(() => {
vi.clearAllMocks();
});
const mockAccount: RachunekBankowy = {
NrRB: { _text: '12345678901234567890123456' },
SWIFT: { _text: 'BPKOPLPW' },
RachunekWlasnyBanku: { _text: '1' },
NazwaBanku: { _text: 'PKO Bank Polski' },
OpisRachunku: { _text: 'Rachunek główny' },
} as any;
beforeEach(() => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['header'] as any);
vi.mocked(PDFFunctions.createSection).mockReturnValue('section' as any);
vi.mocked(PDFFunctions.formatText).mockReturnValue('formatted' as any);
vi.mocked(CommonFunctions.getTypRachunkowWlasnych).mockReturnValue('Tak');
});
describe('when accounts is undefined or empty', () => {
it('should return empty array when accounts is undefined', () => {
const result = generujRachunekBankowy(undefined, 'Rachunek bankowy');
expect(result).toEqual([]);
});
it('should return empty array when accounts is empty array', () => {
const result = generujRachunekBankowy([], 'Rachunek bankowy');
expect(result).toEqual([]);
});
});
describe('when accounts exist', () => {
it('should call createHeader with provided title', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.createHeader).toHaveBeenCalledWith('Rachunek bankowy ', [0, 12, 0, 8]);
});
it('should call createHeader with empty string when title is not provided', () => {
generujRachunekBankowy([mockAccount]);
expect(PDFFunctions.createHeader).toHaveBeenCalledWith('', [0, 12, 0, 8]);
});
it('should call createSection and return result', () => {
const mockSection = 'section';
vi.mocked(PDFFunctions.createSection).mockReturnValue(mockSection as any);
const result = generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.createSection).toHaveBeenCalledWith(expect.any(Array), false);
expect(result).toEqual(mockSection);
});
it('should format "Pełny numer rachunku" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Pełny numer rachunku', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(mockAccount.NrRB?._text, FormatTyp.Default);
});
it('should format "Kod SWIFT" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Kod SWIFT', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(mockAccount.SWIFT?._text, FormatTyp.Default);
});
it('should format "Rachunek własny banku" field', () => {
vi.mocked(CommonFunctions.getTypRachunkowWlasnych).mockReturnValue('Tak');
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Rachunek własny banku', FormatTyp.GrayBoldTitle);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(mockAccount.RachunekWlasnyBanku);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(
mockAccount.NazwaBanku?._text ? makeBreakable('Bank', 20) : 'Tak',
FormatTyp.Default
);
});
it('should format "Nazwa banku" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Nazwa banku', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(
mockAccount.NazwaBanku?._text ? makeBreakable('Bank', 20) : 'Nazwa banku',
FormatTyp.Default
);
});
it('should format "Opis rachunku" field', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith('Opis rachunku', FormatTyp.GrayBoldTitle);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(
mockAccount.NazwaBanku?._text ? makeBreakable('Bank', 20) : 'Nazwa banku',
FormatTyp.Default
);
});
it('should create table structure with correct widths', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('table');
expect(tableContent.table).toHaveProperty('widths', ['*', 'auto']);
});
it('should create table structure with unbreakable property', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('unbreakable', true);
});
it('should create table with correct layout', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent).toHaveProperty('layout');
expect(tableContent.layout).toHaveProperty('hLineWidth');
expect(tableContent.layout).toHaveProperty('hLineColor');
expect(tableContent.layout).toHaveProperty('vLineWidth');
expect(tableContent.layout).toHaveProperty('vLineColor');
});
it('should create table with correct line colors', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.layout.hLineColor()).toBe('#BABABA');
expect(tableContent.layout.vLineColor()).toBe('#BABABA');
});
it('should create table with correct line widths', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.layout.hLineWidth()).toBe(1);
expect(tableContent.layout.vLineWidth()).toBe(1);
});
it('should handle account with undefined fields', () => {
const accountWithUndefined: RachunekBankowy = {
NrRB: { _text: undefined },
SWIFT: { _text: undefined },
RachunekWlasnyBanku: { _text: undefined },
NazwaBanku: { _text: undefined },
OpisRachunku: { _text: undefined },
} as any;
generujRachunekBankowy([accountWithUndefined], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith(undefined, FormatTyp.Default);
});
});
describe('when multiple accounts exist', () => {
it('should create multiple tables for multiple accounts', () => {
const account2: RachunekBankowy = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
} as any;
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
expect(sectionCall.length).toBe(2);
});
it('should call getTypRachunkowWlasnych for each account', () => {
const account2: RachunekBankowy = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
} as any;
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledTimes(2);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(mockAccount.RachunekWlasnyBanku);
expect(CommonFunctions.getTypRachunkowWlasnych).toHaveBeenCalledWith(account2.RachunekWlasnyBanku);
});
it('should format all fields for all accounts', () => {
const account2: RachunekBankowy = {
NrRB: { _text: '98765432109876543210987654' },
SWIFT: { _text: 'PKOPPLPW' },
RachunekWlasnyBanku: { _text: '0' },
NazwaBanku: { _text: 'mBank' },
OpisRachunku: { _text: 'Rachunek pomocniczy' },
} as any;
generujRachunekBankowy([mockAccount, account2], 'Rachunek bankowy');
expect(PDFFunctions.formatText).toHaveBeenCalledWith(mockAccount.NrRB?._text, FormatTyp.Default);
expect(PDFFunctions.formatText).toHaveBeenCalledWith(account2.NrRB?._text, FormatTyp.Default);
});
});
describe('table structure', () => {
it('should create table with 5 rows', () => {
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
const tableContent = sectionCall[0][1];
expect(tableContent.table.body.length).toBe(5);
});
it('should include header in result array', () => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['header-content'] as any);
generujRachunekBankowy([mockAccount], 'Rachunek bankowy');
const sectionCall = vi.mocked(PDFFunctions.createSection).mock.calls[0][0] as any[];
expect(sectionCall[0][0]).toBe('header-content');
});
});
});

View File

@@ -1,5 +1,12 @@
import { Content, ContentTable } from 'pdfmake/interfaces'; import { Content, ContentTable } from 'pdfmake/interfaces';
import { createHeader, createSection, formatText } from '../../../shared/PDF-functions'; import {
createHeader,
createSection,
formatText,
getValue,
hasValue,
makeBreakable,
} from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum'; import FormatTyp from '../../../shared/enums/common.enum';
import { RachunekBankowy } from '../../types/fa3.types'; import { RachunekBankowy } from '../../types/fa3.types';
import { getTypRachunkowWlasnych } from '../../../shared/generators/common/functions'; import { getTypRachunkowWlasnych } from '../../../shared/generators/common/functions';
@@ -20,23 +27,33 @@ export const generujRachunekBankowy = (accounts?: RachunekBankowy[], title?: str
table.push([ table.push([
formatText('Pełny numer rachunku', FormatTyp.GrayBoldTitle), formatText('Pełny numer rachunku', FormatTyp.GrayBoldTitle),
formatText(account.NrRB?._text, FormatTyp.Default), formatText(getValue(account.NrRB), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Kod SWIFT', FormatTyp.GrayBoldTitle), formatText('Kod SWIFT', FormatTyp.GrayBoldTitle),
formatText(account.SWIFT?._text, FormatTyp.Default), formatText(getValue(account.SWIFT), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Rachunek własny banku', FormatTyp.GrayBoldTitle), formatText('Rachunek własny banku', FormatTyp.GrayBoldTitle),
formatText(getTypRachunkowWlasnych(account.RachunekWlasnyBanku), FormatTyp.Default), formatText(makeBreakable(getTypRachunkowWlasnych(account.RachunekWlasnyBanku), 20), FormatTyp.Default),
]); ]);
table.push([ table.push([
formatText('Nazwa banku', FormatTyp.GrayBoldTitle), formatText('Nazwa banku', FormatTyp.GrayBoldTitle),
formatText(account.NazwaBanku?._text, FormatTyp.Default), formatText(
hasValue(account.NazwaBanku)
? makeBreakable(getValue(account.NazwaBanku), 20)
: getValue(account.NazwaBanku),
FormatTyp.Default
),
]); ]);
table.push([ table.push([
formatText('Opis rachunku', FormatTyp.GrayBoldTitle), formatText('Opis rachunku', FormatTyp.GrayBoldTitle),
formatText(account.OpisRachunku?._text, FormatTyp.Default), formatText(
hasValue(account.OpisRachunku)
? makeBreakable(getValue(account.OpisRachunku), 20)
: getValue(account.OpisRachunku),
FormatTyp.Default
),
]); ]);
result.push([ result.push([
...base, ...base,

View File

@@ -125,7 +125,9 @@ describe(generateWarunkiTransakcji.name, () => {
expect.objectContaining({ name: 'NrUmowy', title: 'Numer umowy' }), expect.objectContaining({ name: 'NrUmowy', title: 'Numer umowy' }),
]), ]),
expect.any(Array), expect.any(Array),
'*' '*',
undefined,
20
); );
}); });
@@ -173,7 +175,9 @@ describe(generateWarunkiTransakcji.name, () => {
expect.objectContaining({ name: 'NrZamowienia', title: 'Numer zamówienia' }), expect.objectContaining({ name: 'NrZamowienia', title: 'Numer zamówienia' }),
]), ]),
expect.any(Array), expect.any(Array),
'*' '*',
undefined,
20
); );
}); });

View File

@@ -38,14 +38,20 @@ export function generateWarunkiTransakcji(warunkiTransakcji: WarunkiTransakcji |
table.push(createHeader('Warunki transakcji', [0, 8, 0, 4])); table.push(createHeader('Warunki transakcji', [0, 8, 0, 4]));
if (umowy.length > 0) { if (umowy.length > 0) {
const tabUmowy = getContentTable<(typeof umowy)[0]>(definedHeaderUmowy, umowy, '*'); const tabUmowy = getContentTable<(typeof umowy)[0]>(definedHeaderUmowy, umowy, '*', undefined, 20);
if (tabUmowy.content) { if (tabUmowy.content) {
Kolumny.umowy = [createSubHeader('Umowa'), tabUmowy.content]; Kolumny.umowy = [createSubHeader('Umowa'), tabUmowy.content];
} }
} }
if (zamowienia.length > 0) { if (zamowienia.length > 0) {
const tabZamowienia = getContentTable<(typeof zamowienia)[0]>(definedHeaderZamowienia, zamowienia, '*'); const tabZamowienia = getContentTable<(typeof zamowienia)[0]>(
definedHeaderZamowienia,
zamowienia,
'*',
undefined,
20
);
if (tabZamowienia.content && tabZamowienia.fieldsWithValue.length > 0) { if (tabZamowienia.content && tabZamowienia.fieldsWithValue.length > 0) {
Kolumny.zamowienia = [createSubHeader('Zamówienie'), tabZamowienia.content]; Kolumny.zamowienia = [createSubHeader('Zamówienie'), tabZamowienia.content];

View File

@@ -6,6 +6,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((...args) => ({ header: args[0], margin: args[1] })), createHeader: vi.fn((...args) => ({ header: args[0], margin: args[1] })),
createSubHeader: vi.fn((label) => ({ subHeader: label })), createSubHeader: vi.fn((label) => ({ subHeader: label })),
generateTwoColumns: vi.fn((left, right) => ({ columns: [left, right] })), generateTwoColumns: vi.fn((left, right) => ({ columns: [left, right] })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
getTable: vi.fn((rows) => rows ?? []), getTable: vi.fn((rows) => rows ?? []),
getContentTable: vi.fn((header, rows) => ({ content: rows })), getContentTable: vi.fn((header, rows) => ({ content: rows })),
createLabelText: vi.fn((label, value) => ({ label, value })), createLabelText: vi.fn((label, value) => ({ label, value })),

View File

@@ -5,6 +5,7 @@ import {
createLabelTextArray, createLabelTextArray,
createSection, createSection,
createSubHeader, createSubHeader,
generateColumns,
generateTwoColumns, generateTwoColumns,
getContentTable, getContentTable,
getTable, getTable,
@@ -52,12 +53,16 @@ export function generateRozliczenie(
const tableObciazenia: FormContentState = getContentTable<(typeof obciazenia)[0]>( const tableObciazenia: FormContentState = getContentTable<(typeof obciazenia)[0]>(
headerObciazenia, headerObciazenia,
obciazenia, obciazenia,
'*' '*',
undefined,
20
); );
const tableOdliczenia: FormContentState = getContentTable<(typeof odliczenia)[0]>( const tableOdliczenia: FormContentState = getContentTable<(typeof odliczenia)[0]>(
headerOdliczenia, headerOdliczenia,
odliczenia, odliczenia,
'*' '*',
undefined,
20
); );
const SumaObciazen: Content[] = createLabelText( const SumaObciazen: Content[] = createLabelText(
'Suma kwot obciążenia: ', 'Suma kwot obciążenia: ',
@@ -88,7 +93,7 @@ export function generateRozliczenie(
result.push(createHeader('Rozliczenie', [0, 8, 0, 4])); result.push(createHeader('Rozliczenie', [0, 8, 0, 4]));
if (obciazenia.length > 0 && odliczenia.length > 0) { if (obciazenia.length > 0 && odliczenia.length > 0) {
result.push(generateTwoColumns([resultObciazenia], [resultOdliczenia])); result.push(generateColumns([resultObciazenia, resultOdliczenia]));
} else if (obciazenia.length > 0) { } else if (obciazenia.length > 0) {
result.push(generateTwoColumns([resultObciazenia], [])); result.push(generateTwoColumns([resultObciazenia], []));
} else if (odliczenia.length > 0) { } else if (odliczenia.length > 0) {

View File

@@ -26,7 +26,7 @@ describe('formatText', () => {
expect(content).toEqual( expect(content).toEqual(
expect.objectContaining({ expect.objectContaining({
alignment: Position.RIGHT, alignment: Position.RIGHT,
text: '100.00 PLN', text: '100,00 PLN',
style: FormatTyp.Currency, style: FormatTyp.Currency,
bold: true, bold: true,
}) })

View File

@@ -75,21 +75,27 @@ function formatValue(
): void { ): void {
switch (item) { switch (item) {
case FormatTyp.Currency: case FormatTyp.Currency:
result.text = isNaN(Number(value)) ? (value as string) : `${Number(value).toFixed(2)} ${currency}`; result.text = isNaN(Number(value))
? (value as string)
: `${dotToComma(Number(value).toFixed(2))} ${currency}`;
result.alignment = Position.RIGHT; result.alignment = Position.RIGHT;
break; break;
case FormatTyp.CurrencyAbs: case FormatTyp.CurrencyAbs:
result.text = isNaN(Number(value)) result.text = isNaN(Number(value))
? (value as string) ? (value as string)
: `${Math.abs(Number(value)).toFixed(2)} ${currency}`; : `${dotToComma(Math.abs(Number(value)).toFixed(2))} ${currency}`;
result.alignment = Position.RIGHT; result.alignment = Position.RIGHT;
break; break;
case FormatTyp.CurrencyGreater: case FormatTyp.CurrencyGreater:
result.text = isNaN(Number(value)) ? (value as string) : `${Number(value).toFixed(2)} ${currency}`; result.text = isNaN(Number(value))
? (value as string)
: `${dotToComma(Number(value).toFixed(2))} ${currency}`;
result.fontSize = 10; result.fontSize = 10;
break; break;
case FormatTyp.Currency6: case FormatTyp.Currency6:
result.text = isNaN(Number(value)) ? (value as string) : `${Number(value).toFixed(6)} ${currency}`; result.text = isNaN(Number(value))
? (value as string)
: `${dotToComma(Number(value).toFixed(6))} ${currency}`;
result.alignment = Position.RIGHT; result.alignment = Position.RIGHT;
break; break;
case FormatTyp.DateTime: case FormatTyp.DateTime:
@@ -110,6 +116,10 @@ function formatValue(
} }
} }
function dotToComma(value: string): string {
return value.replace('.', ',');
}
export function hasValue(value: FP | string | number | undefined): boolean { export function hasValue(value: FP | string | number | undefined): boolean {
return ( return (
!!((typeof value !== 'object' && value) || (typeof value === 'object' && value._text)) || value === 0 !!((typeof value !== 'object' && value) || (typeof value === 'object' && value._text)) || value === 0
@@ -356,7 +366,8 @@ export function getContentTable<T>(
headers: HeaderDefine[], headers: HeaderDefine[],
data: T[], data: T[],
defaultWidths: string, defaultWidths: string,
margin?: Margins margin?: Margins,
wordBreak?: number
): { content: ContentTable | null; fieldsWithValue: string[] } { ): { content: ContentTable | null; fieldsWithValue: string[] } {
const fieldsWithValue: HeaderDefine[] = headers.filter((header: HeaderDefine): boolean => { const fieldsWithValue: HeaderDefine[] = headers.filter((header: HeaderDefine): boolean => {
return data.some((d: T): boolean => { return data.some((d: T): boolean => {
@@ -392,7 +403,10 @@ export function getContentTable<T>(
const value: string | undefined = typeof fp === 'object' ? fp?._text : fp; const value: string | undefined = typeof fp === 'object' ? fp?._text : fp;
return formatText( return formatText(
header.mappingData && value ? header.mappingData[value] : (value ?? ''), makeBreakable(
header.mappingData && value ? header.mappingData[value] : (value ?? ''),
wordBreak ?? 40
),
header.format ?? FormatTyp.Default, header.format ?? FormatTyp.Default,
{ rowSpan: fp?._rowSpan ?? 1 } { rowSpan: fp?._rowSpan ?? 1 }
); );
@@ -417,10 +431,22 @@ export function getContentTable<T>(
export function generateTwoColumns(kol1: Column, kol2: Column, margin?: Margins): Content { export function generateTwoColumns(kol1: Column, kol2: Column, margin?: Margins): Content {
return { return {
columns: [ columns: [
{ stack: [kol1], margin: [0, 0, 5, 0] }, { stack: [kol1], width: '50%' },
{ stack: [kol2], margin: [5, 0, 0, 0] }, { stack: [kol2], width: '50%' },
], ],
margin: margin ?? [0, 0, 0, 0], margin: margin ?? [0, 0, 0, 0],
columnGap: 20,
};
}
export function generateColumns(contents: Content[][], style: Style | undefined = undefined): Content {
const width: string = (100 / contents.length).toFixed(0) + '%';
const columns: Column = contents.map((content: Content[]) => ({ stack: content, width }));
const columnStyle: Style = style ? { ...style } : { columnGap: 20 };
return {
columns,
...columnStyle,
}; };
} }
@@ -464,3 +490,13 @@ export function generateLine(): Content {
} as CustomTableLayout, } as CustomTableLayout,
}; };
} }
export function makeBreakable(
value: string | number | undefined,
wordBreak = 40
): string | number | undefined {
if (typeof value === 'string') {
return value.replace(new RegExp(`(.{${wordBreak}})`, 'g'), '$1\u200B');
}
return value;
}

View File

@@ -404,3 +404,10 @@ export const DEFAULT_TABLE_LAYOUT: {
vLineWidth: (): number => 1, vLineWidth: (): number => 1,
vLineColor: (): string => '#BABABA', vLineColor: (): string => '#BABABA',
}; };
export const TAXPAYER_STATUS: Record<string, string> = {
'1': 'Stan likwidacji',
'2': 'Postępowanie restrukturyzacyjne',
'3': 'Stan upadłości',
'4': 'Przedsiębiorstwo w spadku',
};