chore(): 1.0.0

This commit is contained in:
Michał Chudy
2026-01-30 20:06:43 +01:00
parent 5fb5a624b8
commit f48680a65f
51 changed files with 506 additions and 285 deletions

4
package-lock.json generated
View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@akmf/ksef-fe-invoice-converter",
"version": "0.0.42",
"version": "1.0.0",
"scripts": {
"dev": "vite --mode public --config vite.config.ts",
"build": "vite build --mode production",

View File

@@ -15,7 +15,7 @@ inputInvoice.addEventListener('change', async (): Promise<void> => {
const additionalData: AdditionalDataTypes = {
nrKSeF: '5555555555-20250808-9231003CA67B-BE',
qrCode:
'https://qr-test.ksef.mf.gov.pl/invoice/5265877635/26-10-2025/HS5E1zrA8WVjDNq_xMVIN5SD6nyRymmQ-BcYHReUAa0',
'https://ksef-test.mf.gov.pl/invoice/5265877635/26-10-2025/HS5E1zrA8WVjDNq_xMVIN5SD6nyRymmQ-BcYHReUAa0',
};
generateInvoice(file, additionalData, 'blob').then((data: Blob): void => {

View File

@@ -1,7 +1,7 @@
import pdfMake, { TCreatedPdf } from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
import { Content, TDocumentDefinitions } from 'pdfmake/interfaces';
import { generateStyle, hasValue } from '../shared/PDF-functions';
import { generateStyle, getValue, hasValue } from '../shared/PDF-functions';
import { TRodzajFaktury } from '../shared/consts/const';
import { generateAdnotacje } from './generators/FA1/Adnotacje';
import { generateDodatkoweInformacje } from './generators/FA1/DodatkoweInformacje';
@@ -39,7 +39,8 @@ export function generateFA1(invoice: Faktura, additionalData: AdditionalDataType
ZamowienieKorekta.Order,
invoice.Fa?.P_15?._text ?? '',
invoice.Fa?.RodzajFaktury?._text ?? '',
invoice.Fa?.KodWaluty?._text ?? ''
invoice.Fa?.KodWaluty?._text ?? '',
getValue(invoice.Fa?.Adnotacje?.P_PMarzy) as string | undefined
),
generatePodsumowanieStawekPodatkuVat(invoice),
generateAdnotacje(invoice.Fa?.Adnotacje),

View File

@@ -1,7 +1,7 @@
import pdfMake, { TCreatedPdf } from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
import { Content, TDocumentDefinitions } from 'pdfmake/interfaces';
import { generateStyle, hasValue } from '../shared/PDF-functions';
import { generateStyle, getValue, hasValue } from '../shared/PDF-functions';
import { TRodzajFaktury } from '../shared/consts/const';
import { generateAdnotacje } from './generators/FA2/Adnotacje';
import { generateDodatkoweInformacje } from './generators/FA2/DodatkoweInformacje';
@@ -39,7 +39,8 @@ export function generateFA2(invoice: Faktura, additionalData: AdditionalDataType
ZamowienieKorekta.Order,
invoice.Fa?.P_15?._text ?? '',
invoice.Fa?.RodzajFaktury?._text ?? '',
invoice.Fa?.KodWaluty?._text ?? ''
invoice.Fa?.KodWaluty?._text ?? '',
getValue(invoice.Fa?.Adnotacje?.PMarzy?.P_PMarzy) as string | undefined
),
generatePodsumowanieStawekPodatkuVat(invoice),
generateAdnotacje(invoice.Fa?.Adnotacje),

View File

@@ -1,7 +1,7 @@
import pdfMake, { TCreatedPdf } from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
import { Content, TDocumentDefinitions } from 'pdfmake/interfaces';
import { generateStyle, hasValue } from '../shared/PDF-functions';
import { generateStyle, getValue, hasValue } from '../shared/PDF-functions';
import { TRodzajFaktury } from '../shared/consts/const';
import { generateAdnotacje } from './generators/FA3/Adnotacje';
import { generateDodatkoweInformacje } from './generators/FA3/DodatkoweInformacje';
@@ -39,7 +39,8 @@ export function generateFA3(invoice: Faktura, additionalData: AdditionalDataType
ZamowienieKorekta.Order,
invoice.Fa?.P_15?._text ?? '',
invoice.Fa?.RodzajFaktury?._text ?? '',
invoice.Fa?.KodWaluty?._text ?? ''
invoice.Fa?.KodWaluty?._text ?? '',
getValue(invoice.Fa?.Adnotacje?.PMarzy?.P_PMarzy) as string | undefined
),
generatePodsumowanieStawekPodatkuVat(invoice),
generateAdnotacje(invoice.Fa?.Adnotacje),

View File

@@ -112,12 +112,21 @@ export function generatePlatnosc(platnosc: Platnosc | undefined): Content {
table.push(tableZaplataCzesciowa.content);
}
table.push(
generateTwoColumns(
generujRachunekBankowy(getTable(platnosc.RachunekBankowy), 'Numer rachunku bankowego'),
generujRachunekBankowy(getTable(platnosc.RachunekBankowyFaktora), 'Numer rachunku bankowego faktora')
)
const rachunekBankowy: Content[][] = getTable(platnosc.RachunekBankowy).map((rachunek) =>
generujRachunekBankowy([rachunek], 'Numer rachunku bankowego')
);
const rachunekBankowyFaktora: Content[][] = getTable(platnosc.RachunekBankowyFaktora).map((rachunek) =>
generujRachunekBankowy([rachunek], 'Numer rachunku bankowego faktora')
);
const rachunkiBankowe: Content[][] = [...rachunekBankowy, ...rachunekBankowyFaktora];
if (rachunkiBankowe.length > 0) {
rachunkiBankowe.forEach((rachunek, index) => {
if (index % 2 === 0) {
table.push(generateTwoColumns(rachunek, rachunkiBankowe[index + 1] ?? []));
}
});
}
if (platnosc.Skonto) {
table.push(createHeader('Skonto', [0, 0]));

View File

@@ -12,6 +12,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
verticalSpacing: vi.fn((v: number) => ({ text: `SPACING:${v}` })),
getTable: vi.fn((data) => data || []),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
getValue: vi.fn(() => '1'),
}));
vi.mock('./PodmiotAdres', () => ({
generatePodmiotAdres: vi.fn((adres: any, label: string) => ({ adr: label })),
@@ -30,20 +31,18 @@ describe('generatePodmiot1Podmiot1K', () => {
const podmiot1: Podmiot1 = {
NrEORI: { _text: 'EORI' },
DaneIdentyfikacyjne: { NIP: { _text: '777' } },
StatusInfoPodatnika: { _text: 'AKTYWNY' },
StatusInfoPodatnika: { _text: '1' },
};
const podmiot1K: Podmiot1K = {};
const result: any = generatePodmiot1Podmiot1K(podmiot1, podmiot1K);
const firstCol: Content = result.find((r: any) => r.columns)?.columns[0];
const firstRow: Content = result[1];
expect(firstCol).toEqual(
expect.arrayContaining([
expect(firstRow).toEqual([
{ text: 'SUBHEADER:Dane identyfikacyjne' },
{ text: 'LABEL:Numer EORI: EORI' },
{ id: 'ID' },
{ text: 'LABEL:Status podatnika: AKTYWNY' },
])
);
{ text: `LABEL:Status podatnika: Stan likwidacji` },
]);
});
it('adds contact if Email present', () => {
@@ -53,9 +52,9 @@ describe('generatePodmiot1Podmiot1K', () => {
};
const podmiot1K: Podmiot1K = {};
const result: any = generatePodmiot1Podmiot1K(podmiot1, podmiot1K);
const firstCol: Content = result.find((r: any) => r.columns)?.columns[0];
const firstRow: Content = result[1];
expect(firstCol).toEqual(expect.arrayContaining([{ contact: 'KONTAKT' }]));
expect(firstRow).toEqual(expect.arrayContaining([{ contact: 'KONTAKT' }]));
});
it('adds verticalSpacing at the end', () => {

View File

@@ -5,12 +5,14 @@ import {
createSubHeader,
generateColumns,
getTable,
getValue,
verticalSpacing,
} from '../../../shared/PDF-functions';
import { Podmiot1, Podmiot1K } from '../../types/fa1.types';
import { generatePodmiotAdres } from './PodmiotAdres';
import { generateDaneIdentyfikacyjne } from './PodmiotDaneIdentyfikacyjne';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { TAXPAYER_STATUS } from '../../../shared/consts/const';
export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot1K): Content[] {
const result: Content[] = createHeader('Sprzedawca');
@@ -26,13 +28,12 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
firstColumn.push(generateDaneKontaktowe(podmiot1.Email, getTable(podmiot1.Telefon)));
}
if (podmiot1.StatusInfoPodatnika) {
firstColumn.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika));
const statusInfo: string = TAXPAYER_STATUS[getValue(podmiot1.StatusInfoPodatnika)!];
firstColumn.push(createLabelText('Status podatnika: ', statusInfo));
}
if (firstColumn.length) {
result.push({
columns: [firstColumn, []],
columnGap: 20,
});
result.push(firstColumn);
}
firstColumn = generateCorrectedContent(podmiot1K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot1, 'Treść korygująca');

View File

@@ -14,6 +14,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
getValue: vi.fn((val) => (val && val._text ? val._text : '')),
hasValue: vi.fn((val) => Boolean(val && val._text)),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
generateLine: vi.fn((): Content[] => [{ line: true } as any]),
}));
vi.mock('./PodmiotAdres', () => ({
generatePodmiotAdres: vi.fn((adres, label) => ({ adr: label })),
@@ -37,12 +38,14 @@ describe('generatePodmiot2Podmiot2K', () => {
);
}
it('renders HEADER and at least one columns object', () => {
it('renders new line and at least one columns object', () => {
const podmiot2: Podmiot2 = { NrEORI: { _text: 'A' } };
const podmiot2K: Podmiot2K = {};
const result: Content[] = generatePodmiot2Podmiot2K(podmiot2, podmiot2K);
expect(result[0]).toEqual({ text: 'HEADER:Nabywca' });
expect(result[0]).toEqual([{
"line": true,
}]);
expect(
result.some((r: Content) => {
if (hasColumns(r)) {

View File

@@ -4,6 +4,7 @@ import {
createLabelText,
createSubHeader,
generateColumns,
generateLine,
getTable,
getValue,
hasValue,
@@ -15,7 +16,10 @@ import { generateDaneIdentyfikacyjne } from './PodmiotDaneIdentyfikacyjne';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot2K): Content[] {
const result: Content[] = createHeader('Nabywca');
const result: Content[] = [];
result.push(generateLine());
result.push(createHeader('Nabywca'));
let firstColumn: Content[] = [];
let secondColumn: Content[] = [];
@@ -36,7 +40,7 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
columnGap: 20,
});
}
if(podmiot2K.Adres?.AdresPol || podmiot2K.Adres?.AdresZagr) {
if (podmiot2K.DaneIdentyfikacyjne) {
firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca');
}

View File

@@ -38,7 +38,7 @@ export function generateDaneIdentyfikacyjneTPodmiot3Dto(
createLabelText('Numer EORI: ', podmiot1.NrEORI),
createLabelText('Rola: ', getRolaString(podmiot1.Rola, 1)),
createLabelText('Rola inna: ', podmiot1.OpisRoli),
createLabelText('Udział: ', podmiot1.Udzial, FormatTyp.Currency6)
createLabelText('Udział: ', podmiot1.Udzial, FormatTyp.Percentage)
);
}

View File

@@ -9,7 +9,7 @@ export function generateDaneIdentyfikacyjne(daneIdentyfikacyjne: DaneIdentyfikac
if (hasValue(daneIdentyfikacyjne.ImiePierwsze) || hasValue(daneIdentyfikacyjne.Nazwisko)) {
result.push(
createLabelText(
'',
'Imię i nazwisko: ',
`${getValue(daneIdentyfikacyjne.ImiePierwsze)} ${getValue(daneIdentyfikacyjne.Nazwisko)}`
)
);

View File

@@ -1,4 +1,4 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { FP } from '../../types/fa1.types';
@@ -26,7 +26,7 @@ describe('generateDaneKontaktowe', () => {
const tel = [{ _text: '123456789' }];
const result = generateDaneKontaktowe(undefined, tel);
expect(result).toEqual([{ text: 'LABEL:Tel.: [object Object]\n' }]);
expect(result).toEqual([{ text: 'LABEL:Tel.: 123456789\n' }]);
});
it('returns email and all telephones in order', () => {
@@ -36,8 +36,8 @@ describe('generateDaneKontaktowe', () => {
expect(result[0]).toEqual({ text: 'LABEL:Email: z@x.io' });
expect(result.length).toBe(3);
expect(result[1]).toEqual({ text: 'LABEL:Tel.: [object Object]\n' });
expect(result[2]).toEqual({ text: 'LABEL:Tel.: [object Object]\n' });
expect(result[1]).toEqual({ text: 'LABEL:Tel.: 101\n' });
expect(result[2]).toEqual({ text: 'LABEL:Tel.: 202\n' });
});
it('handles multiple telephones', () => {

View File

@@ -10,7 +10,7 @@ export function generateDaneKontaktowe(email?: FP, telefon?: FP[]): Content[] {
}
if (telefon) {
telefon.forEach((item) => {
result.push(createLabelText('Tel.: ', `${item}\n`));
result.push(createLabelText('Tel.: ', `${item._text}\n`));
});
}
return result;

View File

@@ -46,18 +46,32 @@ export function generatePodsumowanieStawekPodatkuVat(faktura: Faktura): Content[
const definedHeader: Content[] = [
...[{ text: 'Lp.', style: FormatTyp.GrayBoldTitle }],
...(AnyP13P14_5Diff0 ? [{ text: 'Stawka podatku', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5)
? [
{
text: 'Stawka podatku',
style: FormatTyp.GrayBoldTitle,
},
]
: []),
...(AnyP13 ? [{ text: 'Kwota netto', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 ? [{ text: 'Kwota podatku', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5)
? [
{
text: 'Kwota podatku',
style: FormatTyp.GrayBoldTitle,
},
]
: []),
...(AnyP13 ? [{ text: 'Kwota brutto', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP_14xW ? [{ text: 'Kwota podatku PLN', style: FormatTyp.GrayBoldTitle }] : []),
];
const widths: Content[] = [
...['auto'],
...(AnyP13P14_5Diff0 ? ['*'] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5) ? ['*'] : []),
...(AnyP13 ? ['*'] : []),
...(AnyP13P14_5Diff0 ? ['*'] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5) ? ['*'] : []),
...(AnyP13 ? ['*'] : []),
...(AnyP_14xW ? ['*'] : []),
];
@@ -70,13 +84,23 @@ export function generatePodsumowanieStawekPodatkuVat(faktura: Faktura): Content[
data.push(item.no);
if (AnyP13P14_5Diff0) {
if (item.taxRateString) {
data.push(item.taxRateString);
} else if (getValue(faktura.Fa?.P_13_5)) {
data.push('OSS');
} else {
data.push('');
}
} else if (hasValue(faktura.Fa?.P_14_5)) {
data.push('OSS');
}
if (AnyP13) {
data.push(formatText(item.net, FormatTyp.Currency));
}
if (AnyP13P14_5Diff0) {
data.push(formatText(item.tax, FormatTyp.Currency));
} else if (hasValue(faktura.Fa?.P_14_5)) {
data.push(getValue(faktura.Fa?.P_14_5) as string);
}
if (AnyP13) {
data.push(formatText(item.gross, FormatTyp.Currency));
@@ -162,10 +186,10 @@ export function getSummaryTaxRate(fa: Fa): TaxSummaryTypes[] {
summary.push({
no,
net: getNumberRounded(fa.P_13_5).toFixed(2),
gross: getNumberRounded(fa.P_13_5).toFixed(2),
gross: (getNumberRounded(fa.P_13_5) + getNumberRounded(fa.P_14_5)).toFixed(2),
tax: getNumberRounded(fa.P_14_5).toFixed(2),
taxPLN: '',
taxRateString: getValue(fa.P_14_5) != 0 ? 'niepodlegające opodatkowaniu' : '',
taxRateString: getValue(fa.P_14_5) != 0 ? 'OSS' : '',
});
no++;
}

View File

@@ -1,7 +1,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import * as PDFFunctions from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum';
import {TRodzajFaktury} from '../../../shared/consts/const';
import { TRodzajFaktury } from '../../../shared/consts/const';
import { Fa } from '../../types/fa1.types';
import { generateWiersze } from './Wiersze';
@@ -13,7 +13,8 @@ vi.mock('../../../shared/PDF-functions', () => ({
getContentTable: vi.fn(),
getTable: vi.fn(),
getValue: vi.fn(),
getTStawkaPodatku: vi.fn()
getTStawkaPodatku: vi.fn(),
getDifferentColumnsValue: vi.fn(),
}));
describe(generateWiersze.name, () => {
@@ -61,6 +62,7 @@ describe(generateWiersze.name, () => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['Header'] as any);
vi.mocked(PDFFunctions.createSection).mockReturnValue({ section: 'content' } as any);
vi.mocked(PDFFunctions.createLabelTextArray).mockReturnValue(['Label', 'Value'] as any);
vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([]);
};
describe('when no invoice lines exist', () => {
@@ -71,6 +73,7 @@ describe(generateWiersze.name, () => {
fieldsWithValue: [],
});
vi.mocked(PDFFunctions.getValue).mockReturnValue('0');
vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([]);
const result = generateWiersze(mockFaVat);
@@ -108,7 +111,9 @@ describe(generateWiersze.name, () => {
});
it('should display "brutto" when P_11 is not in fieldsWithValue', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable).mockReturnValue({
content: { table: {} } as any,
@@ -151,7 +156,9 @@ describe(generateWiersze.name, () => {
});
it('should generate two tables when fieldsWithValue.length > 8', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable)
.mockReturnValueOnce({
@@ -178,7 +185,9 @@ describe(generateWiersze.name, () => {
});
it('should not add second table if it has only 1 field with value', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable)
.mockReturnValueOnce({

View File

@@ -5,6 +5,7 @@ import {
createSection,
formatText,
getContentTable,
getDifferentColumnsValue,
getTable,
getTStawkaPodatku,
getValue,
@@ -42,11 +43,19 @@ export function generateWiersze(faVat: Fa): Content {
{ name: 'P_8A', title: 'Miara', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_10', title: 'Rabat', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_12', title: 'Stawka podatku', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12_XII', title: 'Stawka podatku OSS', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12_XII', title: 'Stawka podatku OSS', format: FormatTyp.Percentage, width: 'auto' },
{ name: 'P_11', title: 'Wartość sprzedaży netto', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_11A', title: 'Wartość sprzedaży brutto', format: FormatTyp.Currency, width: 'auto' },
{ name: 'KursWaluty', title: 'Kurs waluty', format: FormatTyp.Currency6, width: 'auto' },
];
if (getDifferentColumnsValue('KursWaluty', faWiersze).length !== 1) {
definedHeader1.push({
name: 'KursWaluty',
title: 'Kurs waluty',
format: FormatTyp.Currency6,
width: 'auto',
});
}
const definedHeader2: HeaderDefine[] = [
{ name: 'GTIN', title: 'GTIN', format: FormatTyp.Default, width: 'auto' },
{ name: 'PKWiU', title: 'PKWiU', format: FormatTyp.Default, width: 'auto' },

View File

@@ -20,7 +20,8 @@ export function generateZamowienie(
zamowienieKorekta: ZamowienieKorekta,
p_15: string,
rodzajFaktury: string,
KodWaluty: string
KodWaluty: string,
P_PMarzy?: string
): Content[] {
if (!orderData) {
return [];
@@ -31,9 +32,7 @@ export function generateZamowienie(
if (!el.NrWierszaZam._text) {
el.NrWierszaZam._text = (index + 1).toString();
}
if (getValue(el.P_12)) {
el.P_12._text = getTStawkaPodatku(getValue(el.P_12) as string, 1);
}
el.P_12Z = { _text: getTStawkaPodatku(getValue(el.P_12Z) as string, 1, P_PMarzy) };
return el;
});
const definedHeaderLp: HeaderDefine[] = [
@@ -50,7 +49,7 @@ export function generateZamowienie(
{ name: 'P_8BZ', title: 'Ilość', format: FormatTyp.Right, width: 'auto' },
{ name: 'P_8AZ', title: 'Miara', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z', title: 'Stawka podatku', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z_XII', title: 'Stawka podatku OSS', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z_XII', title: 'Stawka podatku OSS', format: FormatTyp.Percentage, width: 'auto' },
{ name: 'P_11NettoZ', title: 'Wartość sprzedaży netto', format: formatAbs, width: 'auto' },
{ name: 'P_11VatZ', title: 'Kwota podatku', format: formatAbs, width: 'auto' },
{ name: 'KursWalutyZ', title: 'Kwota podatku', format: formatAbs, width: 'auto' },

View File

@@ -109,18 +109,21 @@ export function generatePlatnosc(platnosc: Platnosc | undefined): Content {
table.push(tableZaplataCzesciowa.content);
}
table.push(
generateTwoColumns(
generujRachunekBankowy(
getTable(platnosc.RachunekBankowy as Record<string, FP>[]),
'Numer rachunku bankowego'
),
generujRachunekBankowy(
getTable(platnosc.RachunekBankowyFaktora as Record<string, FP>[]),
'Numer rachunku bankowego faktora'
)
)
const rachunekBankowy: Content[][] = getTable(platnosc.RachunekBankowy as Record<string, FP>[]).map(
(rachunek) => generujRachunekBankowy([rachunek], 'Numer rachunku bankowego')
);
const rachunekBankowyFaktora: Content[][] = getTable(
platnosc.RachunekBankowyFaktora as Record<string, FP>[]
).map((rachunek) => generujRachunekBankowy([rachunek], 'Numer rachunku bankowego faktora'));
const rachunkiBankowe: Content[][] = [...rachunekBankowy, ...rachunekBankowyFaktora];
if (rachunkiBankowe.length > 0) {
rachunkiBankowe.forEach((rachunek, index) => {
if (index % 2 === 0) {
table.push(generateTwoColumns(rachunek, rachunkiBankowe[index + 1] ?? []));
}
});
}
if (platnosc.Skonto) {
table.push(createHeader('Skonto', [0, 0]));

View File

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

View File

@@ -5,6 +5,7 @@ import {
formatText,
generateColumns,
getTable,
getValue,
verticalSpacing,
} from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum';
@@ -12,6 +13,7 @@ import { Podmiot1, Podmiot1K } from '../../types/fa2.types';
import { generateAdres } from './Adres';
import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { TAXPAYER_STATUS } from '../../../shared/consts/const';
export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot1K): Content[] {
const result: Content[] = createHeader('Sprzedawca');
@@ -27,13 +29,12 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
firstColumn.push(generateDaneKontaktowe(getTable(podmiot1.DaneKontaktowe)));
}
if (podmiot1.StatusInfoPodatnika) {
firstColumn.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika));
const statusInfo: string = TAXPAYER_STATUS[getValue(podmiot1.StatusInfoPodatnika)!];
firstColumn.push(createLabelText('Status podatnika: ', statusInfo));
}
if (firstColumn.length) {
result.push({
columns: [firstColumn, []],
columnGap: 20,
});
result.push(firstColumn);
}
firstColumn = generateCorrectedContent(podmiot1K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot1, 'Treść korygująca');

View File

@@ -12,6 +12,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
hasValue: vi.fn((value: any) => value !== undefined && value !== null),
verticalSpacing: vi.fn((margin: number) => ({ margin })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
generateLine: vi.fn((): Content[] => [{ line: true } as any]),
}));
vi.mock('./Adres', () => ({
@@ -41,18 +42,25 @@ describe(generatePodmiot2Podmiot2K.name, () => {
} as any;
const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any;
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
expect(result[0]).toEqual([{
"line": true,
}]);
expect(result[1]).toHaveProperty('columns');
expect(Array.isArray(result[1].columns[0])).toBe(true);
expect(Array.isArray(result[1].columns[1])).toBe(true);
expect(result[1].columns[0].length).toBeGreaterThan(0);
expect(result[1].columns[1].length).toBe(0);
expect(result[1][0]).toHaveProperty('text');
expect(result[1][0]).toHaveProperty('style');
expect(result[1][0]).toEqual({ text: 'Nabywca', style: 'header' });
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[1].length).toBe(0);
expect(result[2]).toHaveProperty('columns');
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[3]).toEqual({ margin: 1 });
expect(result[4]).toEqual({ margin: 1 });
});
it('calls generateAdres if AdresKoresp exists', () => {
@@ -67,7 +75,7 @@ describe(generatePodmiot2Podmiot2K.name, () => {
const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any;
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(Array.isArray(result[2].columns[1])).toBe(true);
expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0);
});
@@ -90,12 +98,14 @@ describe(generatePodmiot2Podmiot2K.name, () => {
const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any;
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(result.length).toBeGreaterThan(3);
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
expect(result[0]).toEqual([{
"line": true,
}]);
expect(result[2]).toHaveProperty('columns');
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[result.length - 1]).toHaveProperty('margin');
});
});

View File

@@ -4,6 +4,7 @@ import {
createLabelText,
formatText,
generateColumns,
generateLine,
getTable,
hasValue,
verticalSpacing,
@@ -11,17 +12,20 @@ import {
import FormatTyp from '../../../shared/enums/common.enum';
import { Podmiot2, Podmiot2K } from '../../types/fa3.types';
import { generateAdres } from './Adres';
import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { generateDaneIdentyfikacyjneTPodmiot2Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot2Dto';
export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot2K): Content[] {
const result: Content[] = createHeader('Nabywca');
const result: Content[] = [];
result.push(generateLine());
result.push(createHeader('Nabywca'));
let firstColumn: Content[] = [];
let secondColumn: Content[] = [];
firstColumn.push(createHeader('Dane identyfikacyjne'), createLabelText('Numer EORI: ', podmiot2.NrEORI));
if (podmiot2.DaneIdentyfikacyjne) {
firstColumn.push(...generateDaneIdentyfikacyjneTPodmiot1Dto(podmiot2.DaneIdentyfikacyjne));
firstColumn.push(...generateDaneIdentyfikacyjneTPodmiot2Dto(podmiot2.DaneIdentyfikacyjne));
}
if (podmiot2.DaneKontaktowe) {
@@ -37,7 +41,7 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
});
}
if(podmiot2K.Adres?.AdresL1?._text) {
if (podmiot2K.DaneIdentyfikacyjne) {
firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca');
}
@@ -67,7 +71,7 @@ export function generateCorrectedContent(podmiot: Podmiot2 | Podmiot2K, header:
result.push(createLabelText('Identyfikator nabywcy: ', podmiot.IDNabywcy));
}
if (podmiot.DaneIdentyfikacyjne) {
result.push(...generateDaneIdentyfikacyjneTPodmiot1Dto(podmiot.DaneIdentyfikacyjne));
result.push(...generateDaneIdentyfikacyjneTPodmiot2Dto(podmiot.DaneIdentyfikacyjne));
}
if (podmiot.Adres) {
result.push(formatText('Adres', [FormatTyp.Label, FormatTyp.LabelMargin]), generateAdres(podmiot.Adres));

View File

@@ -38,12 +38,14 @@ export function generatePodmiot3(podmiot: Podmiot3, index: number): Content[] {
...generateAdres(podmiot.AdresKoresp)
);
}
if (podmiot.DaneKontaktowe || podmiot.NrKlienta) {
column2.push(formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]));
if (podmiot.DaneKontaktowe) {
column2.push(
formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]),
...generateDaneKontaktowe(podmiot.DaneKontaktowe),
createLabelText('Numer klienta: ', podmiot.NrKlienta)
);
column2.push(...generateDaneKontaktowe(podmiot.DaneKontaktowe));
}
if (podmiot.NrKlienta) {
column2.push(createLabelText('Numer klienta: ', podmiot.NrKlienta));
}
}
result.push(generateTwoColumns(column1, column2));
return result;

View File

@@ -1,5 +1,6 @@
import { describe, expect, it, vi } from 'vitest';
import { generateDaneIdentyfikacyjneTPodmiot3Dto } from './Podmiot3Podmiot2k';
import {Content} from "pdfmake/interfaces";
vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((text: string) => [`header:${text}`]),
@@ -7,6 +8,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
generateTwoColumns: vi.fn((col1: any, col2: any) => ({ columns: [col1, col2] })),
getTable: vi.fn((data: any) => (data ? ['table:data'] : [])),
hasValue: vi.fn((val: any) => val !== undefined && val !== null && val !== ''),
generateLine: vi.fn((): Content[] => [{ line: true } as any]),
}));
vi.mock('../../../shared/generators/common/functions', () => ({
@@ -54,9 +56,9 @@ describe(generateDaneIdentyfikacyjneTPodmiot3Dto.name, () => {
const result = generateDaneIdentyfikacyjneTPodmiot3Dto(podmiotDto as any, 0);
expect(result[0]).toEqual('header:Podmiot inny 1');
expect(result.some((r: any) => Array.isArray(r) && r[0].startsWith('label:'))).toBe(true);
expect(result[0]).toEqual([{
"line": true,
}]);
expect(result.some((r: any) => r.columns)).toBe(true);
});
@@ -69,6 +71,8 @@ describe(generateDaneIdentyfikacyjneTPodmiot3Dto.name, () => {
const result = generateDaneIdentyfikacyjneTPodmiot3Dto(podmiotDto as any, 1);
expect(result[0]).toEqual('header:Podmiot inny 2');
expect(result[0]).toEqual([{
"line": true,
}]);
});
});

View File

@@ -2,6 +2,7 @@ import { Content } from 'pdfmake/interfaces';
import {
createHeader,
createLabelText,
generateLine,
generateTwoColumns,
getTable,
hasValue,
@@ -25,7 +26,10 @@ export function generateDaneIdentyfikacyjneTPodmiot3Dto(
const podmiot1: Podmiot3 = podmiot2KDto.fakturaPodmiotNDto;
const podmiot1DaneKontaktowe: Podmiot1DaneKontaktowe[] = getTable(podmiot1.DaneKontaktowe);
const podmiot1K: (Podmiot2K & { Adres?: Adres }) | undefined = podmiot2KDto.podmiot2KDto;
const result: Content[] = createHeader(`Podmiot inny ${index + 1}`);
const result: Content[] = [];
result.push(generateLine());
result.push(createHeader(`Podmiot inny ${index + 1}`));
if (
hasValue(podmiot1.NrEORI) ||
@@ -38,7 +42,7 @@ export function generateDaneIdentyfikacyjneTPodmiot3Dto(
createLabelText('Numer EORI: ', podmiot1.NrEORI),
createLabelText('Rola: ', getRolaString(podmiot1.Rola, 2)),
createLabelText('Rola inna: ', podmiot1.OpisRoli),
createLabelText('Udział: ', podmiot1.Udzial, FormatTyp.Currency6)
createLabelText('Udział: ', podmiot1.Udzial, FormatTyp.Percentage)
);
}

View File

@@ -69,15 +69,14 @@ describe(generatePodmioty.name, () => {
expect(generatePodmiot1Podmiot1K).toHaveBeenCalledWith(baseInvoice.Podmiot1, baseInvoice.Fa.Podmiot1K);
expect(generatePodmiot2Podmiot2K).toHaveBeenCalledWith(baseInvoice.Podmiot2, baseInvoice.Fa.Podmiot2K[0]);
expect(generatePodmiot3).toHaveBeenCalled();
expect(generateDaneIdentyfikacyjneTPodmiot3Dto).not.toHaveBeenCalled();
expect(generateDaneIdentyfikacyjneTPodmiot3Dto).toHaveBeenCalled();
expect(generatePodmiotUpowazniony).toHaveBeenCalledWith(baseInvoice.PodmiotUpowazniony);
expect(createSection).toHaveBeenCalled();
expect(result.flag).toBe(true);
expect(content).toHaveLength(4);
expect(content[0]).toEqual({ text: 'Podmiot1K content' });
expect(content[1]).toEqual({ text: 'Podmiot2K content' });
expect(content[2]).toEqual({ text: 'Podmiot3 content 0' });
expect(content[2]).toEqual({ text: 'DaneIdentyfikacyjne Podmiot3 0' });
expect(content[3]).toEqual({ text: 'PodmiotUpowazniony content' });
});
@@ -104,13 +103,12 @@ describe(generatePodmioty.name, () => {
expect(generateDaneIdentyfikacyjneTPodmiot3Dto).toHaveBeenCalled();
expect(generatePodmiot3).toHaveBeenCalled();
expect(result.flag).toBe(true);
expect(content).toHaveLength(6);
expect(content).toHaveLength(5);
expect(content[0]).toEqual({ text: 'Podmiot2K content' });
expect(content[1]).toEqual({ text: 'Podmiot2K content' });
expect(content[2]).toEqual({ text: 'DaneIdentyfikacyjne Podmiot3 0' });
expect(content[3]).toEqual({ text: '', margin: [0, 8, 0, 0] });
expect(content[4]).toEqual({ text: 'Podmiot3 content 1' });
expect(content[5]).toEqual({ text: 'PodmiotUpowazniony content' });
expect(content[1]).toEqual({ text: 'DaneIdentyfikacyjne Podmiot3 0' });
expect(content[2]).toEqual({ text: '', margin: [0, 8, 0, 0] });
expect(content[3]).toEqual({ text: 'Podmiot3 content 1' });
expect(content[4]).toEqual({ text: 'PodmiotUpowazniony content' });
});
it('handles empty Podmiot3 gracefully', () => {

View File

@@ -1,7 +1,7 @@
import { Content } from 'pdfmake/interfaces';
import { createSection, generateColumns, getTable, getValue } from '../../../shared/PDF-functions';
import { Faktura, Podmiot2K as Podmiot2Kfa2, Podmiot3 } from '../../types/fa2.types';
import { Podmiot2K as Podmiot2Kfa1 } from '../../types/fa1.types';
import { Adres } from '../../types/fa1.types';
import { Podmiot3Podmiot2KDto } from '../../types/fa2-additional-types';
import { generatePodmiot1 } from './Podmiot1';
import { generatePodmiot1Podmiot1K } from './Podmiot1Podmiot1K';
@@ -10,23 +10,30 @@ import { generatePodmiot2Podmiot2K } from './Podmiot2Podmiot2k';
import { generatePodmiot3 } from './Podmiot3';
import { generateDaneIdentyfikacyjneTPodmiot3Dto } from './Podmiot3Podmiot2k';
import { generatePodmiotUpowazniony } from './PodmiotUpowazniony';
import { Podmiot2K } from '../../types/fa3.types';
export function generatePodmioty(invoice: Faktura): Content[] {
const result: Content[] = [];
const podmiot2K: Podmiot2Kfa2[] = getTable(invoice.Fa?.Podmiot2K);
const podmiot2KTable: Podmiot2Kfa2[] = getTable(invoice.Fa?.Podmiot2K);
const podmiot3: Podmiot3[] = getTable(invoice.Podmiot3);
if (invoice.Fa?.Podmiot1K || podmiot2K.length > 0) {
if (invoice.Fa?.Podmiot1K || podmiot2KTable.length > 0) {
if (invoice.Fa?.Podmiot1K) {
result.push(generatePodmiot1Podmiot1K(invoice.Podmiot1 ?? {}, invoice.Fa?.Podmiot1K));
} else if (invoice.Podmiot1 != null) {
result.push(generatePodmiot1(invoice.Podmiot1));
}
if (podmiot2K.length > 0) {
podmiot2K.forEach((podmiot2K: Podmiot2Kfa2): void => {
if (invoice.Fa?.Podmiot2K) {
const podmiot2K = podmiot2KTable.find(
(podmiot) => getValue(podmiot.IDNabywcy) === getValue(invoice.Podmiot2?.IDNabywcy)
);
if (podmiot2K) {
result.push(generatePodmiot2Podmiot2K(invoice.Podmiot2 ?? {}, podmiot2K));
});
} else {
result.push(createSection(generatePodmiot2(invoice.Podmiot2!), true));
}
} else if (invoice.Podmiot2) {
result.push(createSection(generatePodmiot2(invoice.Podmiot2!), true));
}
@@ -40,7 +47,11 @@ export function generatePodmioty(invoice: Faktura): Content[] {
}
if (podmiot3.length > 0) {
const podmiot3Podmiot2KDto: Podmiot3Podmiot2KDto[] = getPodmiot3Podmiot2KDto(podmiot2K, podmiot3);
const podmiot3Podmiot2KDto: Podmiot3Podmiot2KDto[] = getPodmiot3Podmiot2KDto(podmiot2KTable, podmiot3);
podmiot3Podmiot2KDto.filter(
(podmiot3Podmiot2) => podmiot3Podmiot2.fakturaPodmiotNDto.IDNabywcy === invoice.Podmiot2?.IDNabywcy
);
if (podmiot3Podmiot2KDto.length > 0) {
podmiot3Podmiot2KDto.forEach((pdm2KDto: Podmiot3Podmiot2KDto, i: number): void => {
@@ -67,24 +78,20 @@ export function generatePodmioty(invoice: Faktura): Content[] {
return createSection(result, true);
}
function getPodmiot3Podmiot2KDto(podmioty2K: Podmiot2Kfa2[], podmioty3: Podmiot3[]): Podmiot3Podmiot2KDto[] {
function getPodmiot3Podmiot2KDto(podmioty2K: Podmiot2K[], podmioty3: Podmiot3[]): Podmiot3Podmiot2KDto[] {
const result: Podmiot3Podmiot2KDto[] = [];
if (
podmioty2K.length > 1 &&
podmioty3.filter((p: Podmiot3): boolean => getValue(p.Rola) === '4').length > 0
) {
let idx: number = 1;
if (podmioty3.filter((p: Podmiot3): boolean => getValue(p.Rola) === '4').length > 0) {
podmioty3.forEach((podmiot3: Podmiot3): void => {
if (getValue(podmiot3.Rola) === '4') {
if (podmioty2K.length > idx) {
result.push({
fakturaPodmiotNDto: podmiot3,
podmiot2KDto: podmioty2K[idx] as Podmiot2Kfa1,
podmiot2KDto: podmioty2K.find(
(podmiot) => getValue(podmiot.IDNabywcy) === getValue(podmiot3.IDNabywcy)
) as Podmiot2K[] & {
Adres: Adres;
},
});
}
idx++;
} else {
result.push({
fakturaPodmiotNDto: podmiot3,

View File

@@ -1,4 +1,4 @@
import { Content, ContentTable, ContentText, TableCell } from 'pdfmake/interfaces';
import { Content, ContentTable, TableCell } from 'pdfmake/interfaces';
import {
createHeader,
createSection,
@@ -59,18 +59,32 @@ export function generatePodsumowanieStawekPodatkuVat(faktura: Faktura): Content[
const definedHeader: Content[] = [
...[{ text: 'Lp.', style: FormatTyp.GrayBoldTitle }],
...(AnyP13P14_5Diff0 ? [{ text: 'Stawka podatku', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5)
? [
{
text: 'Stawka podatku',
style: FormatTyp.GrayBoldTitle,
},
]
: []),
...(AnyP13 ? [{ text: 'Kwota netto', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 ? [{ text: 'Kwota podatku', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5)
? [
{
text: 'Kwota podatku',
style: FormatTyp.GrayBoldTitle,
},
]
: []),
...(AnyP13 ? [{ text: 'Kwota brutto', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP_14xW ? [{ text: 'Kwota podatku PLN', style: FormatTyp.GrayBoldTitle }] : []),
];
const widths: Content[] = [
...['auto'],
...(AnyP13P14_5Diff0 ? ['*'] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5) ? ['*'] : []),
...(AnyP13 ? ['*'] : []),
...(AnyP13P14_5Diff0 ? ['*'] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5) ? ['*'] : []),
...(AnyP13 ? ['*'] : []),
...(AnyP_14xW ? ['*'] : []),
];
@@ -78,18 +92,28 @@ export function generatePodsumowanieStawekPodatkuVat(faktura: Faktura): Content[
if (faktura?.Fa) {
const summary: TaxSummaryTypes[] = getSummaryTaxRate(faktura.Fa);
tableBody = summary.map((item: TaxSummaryTypes): (string | number | ContentText)[] => {
tableBody = summary.map((item: TaxSummaryTypes) => {
const data = [];
data.push(item.no);
if (AnyP13P14_5Diff0) {
if (item.taxRateString) {
data.push(item.taxRateString);
} else if (getValue(faktura.Fa?.P_13_5)) {
data.push('OSS');
} else {
data.push('');
}
} else if (hasValue(faktura.Fa?.P_14_5)) {
data.push('OSS');
}
if (AnyP13) {
data.push(formatText(item.net, FormatTyp.Currency));
}
if (AnyP13P14_5Diff0) {
data.push(formatText(item.tax, FormatTyp.Currency));
} else if (hasValue(faktura.Fa?.P_14_5)) {
data.push(getValue(faktura.Fa?.P_14_5));
}
if (AnyP13) {
data.push(formatText(item.gross, FormatTyp.Currency));
@@ -128,7 +152,7 @@ export function getSummaryTaxRate(fa: Fa): TaxSummaryTypes[] {
const AnyP13_9Diff0: boolean = hasValueAndDiff0(fa?.P_13_9);
const AnyP13_10Diff0: boolean = hasValueAndDiff0(fa?.P_13_10);
const AnyP13_11Diff0: boolean = hasValueAndDiff0(fa?.P_13_11);
let no: number = 1;
let no = 1;
if (AnyP13_1P14_1P14_1WDiff0) {
summary.push({
@@ -182,10 +206,10 @@ export function getSummaryTaxRate(fa: Fa): TaxSummaryTypes[] {
summary.push({
no,
net: getNumberRounded(fa.P_13_5).toFixed(2),
gross: getNumberRounded(fa.P_13_5).toFixed(2),
gross: (getNumberRounded(fa.P_13_5) + getNumberRounded(fa.P_14_5)).toFixed(2),
tax: getNumberRounded(fa.P_14_5).toFixed(2),
taxPLN: '',
taxRateString: getValue(fa.P_14_5) != 0 ? 'niepodlegające opodatkowaniu' : '',
taxRateString: getValue(fa.P_14_5) != 0 ? 'OSS' : '',
});
no++;
}

View File

@@ -13,7 +13,8 @@ vi.mock('../../../shared/PDF-functions', () => ({
getContentTable: vi.fn(),
getTable: vi.fn(),
getValue: vi.fn(),
getTStawkaPodatku: vi.fn()
getTStawkaPodatku: vi.fn(),
getDifferentColumnsValue: vi.fn(),
}));
describe(generateWiersze.name, () => {
@@ -61,6 +62,7 @@ describe(generateWiersze.name, () => {
vi.mocked(PDFFunctions.createHeader).mockReturnValue(['Header'] as any);
vi.mocked(PDFFunctions.createSection).mockReturnValue({ section: 'content' } as any);
vi.mocked(PDFFunctions.createLabelTextArray).mockReturnValue(['Label', 'Value'] as any);
vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([]);
};
describe('when no invoice lines exist', () => {
@@ -71,6 +73,7 @@ describe(generateWiersze.name, () => {
fieldsWithValue: [],
});
vi.mocked(PDFFunctions.getValue).mockReturnValue('0');
vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([]);
const result = generateWiersze(mockFaVat);
@@ -108,7 +111,9 @@ describe(generateWiersze.name, () => {
});
it('should display "brutto" when P_11 is not in fieldsWithValue', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable).mockReturnValue({
content: { table: {} } as any,
@@ -150,7 +155,9 @@ describe(generateWiersze.name, () => {
});
it('should generate two tables when fieldsWithValue.length > 8', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable)
.mockReturnValueOnce({
@@ -177,7 +184,9 @@ describe(generateWiersze.name, () => {
});
it('should not add second table if it has only 1 field with value', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable)
.mockReturnValueOnce({

View File

@@ -5,6 +5,7 @@ import {
createSection,
formatText,
getContentTable,
getDifferentColumnsValue,
getTable,
getTStawkaPodatku,
getValue,
@@ -41,7 +42,7 @@ export function generateWiersze(faVat: Fa): Content {
{ name: 'P_8A', title: 'Miara', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_10', title: 'Rabat', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_12', title: 'Stawka podatku', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12_XII', title: 'Stawka podatku OSS', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12_XII', title: 'Stawka podatku OSS', format: FormatTyp.Percentage, width: 'auto' },
{
name: 'P_12_Zal_15',
title: 'Znacznik dla towaru lub usługi z zał. nr 15 do ustawy',
@@ -51,9 +52,17 @@ export function generateWiersze(faVat: Fa): Content {
{ name: 'P_11', title: 'Wartość sprzedaży netto', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_11A', title: 'Wartość sprzedaży brutto', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_11Vat', title: 'Wartość sprzedaży vat', format: FormatTyp.Currency, width: 'auto' },
{ name: 'KursWaluty', title: 'Kurs waluty', format: FormatTyp.Currency6, width: 'auto' },
{ name: 'StanPrzed', title: 'Stan przed', format: FormatTyp.Boolean, width: 'auto' },
];
if (getDifferentColumnsValue('KursWaluty', faWiersze).length !== 1) {
definedHeader1.push({
name: 'KursWaluty',
title: 'Kurs waluty',
format: FormatTyp.Currency6,
width: 'auto',
});
}
definedHeader1.push({ name: 'StanPrzed', title: 'Stan przed', format: FormatTyp.Boolean, width: 'auto' });
const definedHeader2: HeaderDefine[] = [
{ name: 'GTIN', title: 'GTIN', format: FormatTyp.Default, width: 'auto' },
{ name: 'PKWiU', title: 'PKWiU', format: FormatTyp.Default, width: 'auto' },

View File

@@ -20,7 +20,8 @@ export function generateZamowienie(
zamowienieKorekta: ZamowienieKorekta,
p_15: string,
rodzajFaktury: string,
KodWaluty: string
KodWaluty: string,
P_PMarzy?: string
): Content[] {
if (!orderData) {
return [];
@@ -31,9 +32,7 @@ export function generateZamowienie(
if (!el.NrWierszaZam._text) {
el.NrWierszaZam._text = (index + 1).toString();
}
if (getValue(el.P_12)) {
el.P_12._text = getTStawkaPodatku(getValue(el.P_12) as string, 2);
}
el.P_12Z = { _text: getTStawkaPodatku(getValue(el.P_12Z) as string, 2, P_PMarzy) };
return el;
});
const definedHeaderLp: HeaderDefine[] = [
@@ -51,7 +50,7 @@ export function generateZamowienie(
{ name: 'P_8BZ', title: 'Ilość', format: FormatTyp.Right, width: 'auto' },
{ name: 'P_8AZ', title: 'Miara', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z', title: 'Stawka podatku', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z_XII', title: 'Stawka podatku OSS', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z_XII', title: 'Stawka podatku OSS', format: FormatTyp.Percentage, width: 'auto' },
{
name: 'P_12Z_Zal_15',
title: 'Znacznik dla towaru lub usługi z zał. nr 15 do ustawy',

View File

@@ -132,12 +132,21 @@ export function generatePlatnosc(platnosc: Platnosc | undefined): Content {
table.push(createLabelText('Identyfikator płatności Krajowego Systemu e-Faktur: ', platnosc.IPKSeF));
}
table.push(
generateTwoColumns(
generujRachunekBankowy(getTable(platnosc.RachunekBankowy), 'Numer rachunku bankowego'),
generujRachunekBankowy(getTable(platnosc.RachunekBankowyFaktora), 'Numer rachunku bankowego faktora')
)
const rachunekBankowy: Content[][] = getTable(platnosc.RachunekBankowy).map((rachunek) =>
generujRachunekBankowy([rachunek], 'Numer rachunku bankowego')
);
const rachunekBankowyFaktora: Content[][] = getTable(platnosc.RachunekBankowyFaktora).map((rachunek) =>
generujRachunekBankowy([rachunek], 'Numer rachunku bankowego faktora')
);
const rachunkiBankowe: Content[][] = [...rachunekBankowy, ...rachunekBankowyFaktora];
if (rachunkiBankowe.length > 0) {
rachunkiBankowe.forEach((rachunek, index) => {
if (index % 2 === 0) {
table.push(generateTwoColumns(rachunek, rachunkiBankowe[index + 1] ?? []));
}
});
}
if (platnosc.Skonto) {
table.push(createHeader('Skonto', [0, 0]));

View File

@@ -11,6 +11,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
formatText: vi.fn((text: string, style?: any): Content => ({ text, style })),
verticalSpacing: vi.fn((margin: number) => ({ margin })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
getValue: vi.fn(() => '1'),
}));
vi.mock('./Adres', () => ({
@@ -52,17 +53,14 @@ describe(generatePodmiot1Podmiot1K.name, () => {
const result: any = generatePodmiot1Podmiot1K(podmiot1, podmiot1K);
expect(result[0]).toEqual({ text: 'Sprzedawca', style: 'header' });
expect(result[1]).toHaveProperty('columns');
expect(Array.isArray(result[1].columns[0])).toBe(true);
expect(Array.isArray(result[1].columns[1])).toBe(true);
expect(result[1].columns[0].length).toBeGreaterThan(0);
expect(result[1].columns[1].length).toBe(0);
expect(Array.isArray(result[1][0])).toBe(true);
expect(Array.isArray(result[1][1])).toBe(true);
expect(result[1].length).toBeGreaterThan(0);
expect(result[1].length).toBe(2);
expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(result[2].columns[0].length).toBeGreaterThan(0);
expect(result[3]).toEqual({ margin: 1 });
});
@@ -86,8 +84,8 @@ describe(generatePodmiot1Podmiot1K.name, () => {
expect(result.length).toBe(4);
expect(result[0]).toEqual({ text: 'Sprzedawca', style: 'header' });
expect(result[1].columns[0]).toBeInstanceOf(Array);
expect(result[1].columns[1]).toBeInstanceOf(Array);
expect(result[1][0]).toBeInstanceOf(Array);
expect(result[1][1]).toBeInstanceOf(Array);
expect(result[2].columns[0]).toBeInstanceOf(Array);
expect(result[3]).toEqual({ margin: 1 });
});

View File

@@ -5,6 +5,7 @@ import {
formatText,
generateColumns,
getTable,
getValue,
verticalSpacing,
} from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum';
@@ -12,6 +13,7 @@ import { Podmiot1, Podmiot1K } from '../../types/fa2.types';
import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { generateAdres } from './Adres';
import { TAXPAYER_STATUS } from '../../../shared/consts/const';
export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot1K): Content[] {
const result: Content[] = createHeader('Sprzedawca');
@@ -32,13 +34,12 @@ export function generatePodmiot1Podmiot1K(podmiot1: Podmiot1, podmiot1K: Podmiot
}
}
if (podmiot1.StatusInfoPodatnika) {
firstColumn.push(createLabelText('Status podatnika: ', podmiot1.StatusInfoPodatnika));
const statusInfo: string = TAXPAYER_STATUS[getValue(podmiot1.StatusInfoPodatnika)!];
firstColumn.push(createLabelText('Status podatnika: ', statusInfo));
}
if (firstColumn.length) {
result.push({
columns: [firstColumn, []],
columnGap: 20,
});
result.push(firstColumn);
}
firstColumn = generateCorrectedContent(podmiot1K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot1, 'Treść korygująca');

View File

@@ -41,13 +41,17 @@ export function generatePodmiot2(podmiot2: Podmiot2): Content[] {
const daneKontaktowe = getTable(podmiot2.DaneKontaktowe);
if (daneKontaktowe.length) {
result.push(
createLabelText(
'Faktura dotyczy jednostki podrzędnej JST: ',
daneKontaktowe[0].JST?._text === '1' ? 'TAK' : 'NIE'
)
);
result.push(
createLabelText(
'Faktura dotyczy członka grupy GV: ',
daneKontaktowe[0].GV?._text === '1' ? 'TAK' : 'NIE'
)
);
}
}

View File

@@ -13,6 +13,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
hasValue: vi.fn((value: any) => value !== undefined && value !== null),
verticalSpacing: vi.fn((margin: number) => ({ margin })),
generateColumns: vi.fn((left, right) => ({ columns: [left, right] })),
generateLine: vi.fn((): Content[] => [{ line: true } as any]),
}));
vi.mock('./Adres', () => ({
@@ -42,20 +43,25 @@ describe(generatePodmiot2Podmiot2K.name, () => {
} as any;
const podmiot2K: Podmiot2K = { IDNabywcy: 'ID123' } as any;
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
expect(result[0]).toEqual([{
"line": true,
}]);
expect(result[1]).toHaveProperty('columns');
expect(Array.isArray(result[1].columns[0])).toBe(true);
expect(Array.isArray(result[1].columns[1])).toBe(true);
expect(result[1].columns[0].length).toBeGreaterThan(0);
expect(result[1].columns[1].length).toBe(0);
expect(result[1][0]).toHaveProperty('text');
expect(result[1][0]).toHaveProperty('style');
expect(result[1][0]).toEqual({ text: 'Nabywca', style: 'header' });
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[1].length).toBe(0);
expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(Array.isArray(result[2].columns[1])).toBe(true);
expect(result[2].columns[0].length).toBeGreaterThan(0);
expect(result[3]).toEqual({ margin: 1 });
expect(result[4]).toEqual({ margin: 1 });
});
it('calls generateAdres if AdresKoresp exists', () => {
@@ -96,11 +102,13 @@ describe(generatePodmiot2Podmiot2K.name, () => {
const result = generatePodmiot2Podmiot2K(podmiot2, podmiot2K) as any;
expect(result.length).toBeGreaterThan(3);
expect(result[0]).toEqual({ text: 'Nabywca', style: 'header' });
expect(result[0]).toEqual([{
"line": true,
}]);
expect(result[2]).toHaveProperty('columns');
expect(Array.isArray(result[2].columns[0])).toBe(true);
expect(Array.isArray(result[2].columns[1])).toBe(false);
expect(Array.isArray(result[2].columns[1])).toBe(true);
expect(result[2].columns[0].length).toBeGreaterThanOrEqual(0);
expect(result[result.length - 1]).toHaveProperty('margin');
});

View File

@@ -4,24 +4,28 @@ import {
createLabelText,
formatText,
generateColumns,
generateLine,
getTable,
verticalSpacing,
} from '../../../shared/PDF-functions';
import FormatTyp from '../../../shared/enums/common.enum';
import { Podmiot2, Podmiot2K } from '../../types/fa3.types';
import { generateDaneIdentyfikacyjneTPodmiot1Dto } from './PodmiotDaneIdentyfikacyjneTPodmiot1Dto';
import { generateDaneKontaktowe } from './PodmiotDaneKontaktowe';
import { generateCorrectedContent } from '../FA2/Podmiot2Podmiot2k';
import { generateAdres } from '../FA2/Adres';
import { generateDaneIdentyfikacyjneTPodmiot2Dto } from '../FA2/PodmiotDaneIdentyfikacyjneTPodmiot2Dto';
export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot2K): Content[] {
const result: Content[] = createHeader('Nabywca');
const result: Content[] = [];
result.push(generateLine());
result.push(createHeader('Nabywca'));
let firstColumn: Content[] = [];
let secondColumn: Content[] = [];
firstColumn.push(createHeader('Dane identyfikacyjne'), createLabelText('Numer EORI: ', podmiot2.NrEORI));
if (podmiot2.DaneIdentyfikacyjne) {
firstColumn.push(...generateDaneIdentyfikacyjneTPodmiot1Dto(podmiot2.DaneIdentyfikacyjne));
firstColumn.push(...generateDaneIdentyfikacyjneTPodmiot2Dto(podmiot2.DaneIdentyfikacyjne));
}
if (podmiot2.DaneKontaktowe) {
@@ -39,7 +43,7 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot
});
}
if(podmiot2K.Adres?.AdresL1?._text){
if (podmiot2K.DaneIdentyfikacyjne) {
firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana');
secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca');
}

View File

@@ -38,12 +38,14 @@ export function generatePodmiot3(podmiot: Podmiot3, index: number): Content[] {
...generateAdres(podmiot.AdresKoresp)
);
}
if (podmiot.DaneKontaktowe || podmiot.NrKlienta) {
column2.push(formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]));
if (podmiot.DaneKontaktowe) {
column2.push(
formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]),
...generateDaneKontaktowe(podmiot.DaneKontaktowe),
createLabelText('Numer klienta: ', podmiot.NrKlienta)
);
column2.push(...generateDaneKontaktowe(podmiot.DaneKontaktowe));
}
if (podmiot.NrKlienta) {
column2.push(createLabelText('Numer klienta: ', podmiot.NrKlienta));
}
}
result.push(generateTwoColumns(column1, column2));
return result;

View File

@@ -1,5 +1,6 @@
import { describe, expect, it, vi } from 'vitest';
import { generateDaneIdentyfikacyjneTPodmiot3Dto } from './Podmiot3Podmiot2k';
import type {Content} from "pdfmake/interfaces";
vi.mock('../../../shared/PDF-functions', () => ({
createHeader: vi.fn((text: string) => [`header:${text}`]),
@@ -7,6 +8,7 @@ vi.mock('../../../shared/PDF-functions', () => ({
generateTwoColumns: vi.fn((col1: any, col2: any) => ({ columns: [col1, col2] })),
getTable: vi.fn((data: any) => (data ? ['table:data'] : [])),
hasValue: vi.fn((val: any) => val !== undefined && val !== null && val !== ''),
generateLine: vi.fn((): Content[] => [{ line: true } as any]),
}));
vi.mock('../../../shared/generators/common/functions', () => ({
@@ -54,9 +56,9 @@ describe(generateDaneIdentyfikacyjneTPodmiot3Dto.name, () => {
const result = generateDaneIdentyfikacyjneTPodmiot3Dto(podmiotDto as any, 0);
expect(result[0]).toEqual('header:Podmiot inny 1');
expect(result.some((r: any) => Array.isArray(r) && r[0].startsWith('label:'))).toBe(true);
expect(result[0]).toEqual([{
"line": true,
}]);
expect(result.some((r: any) => r.columns)).toBe(true);
});
@@ -69,6 +71,8 @@ describe(generateDaneIdentyfikacyjneTPodmiot3Dto.name, () => {
const result = generateDaneIdentyfikacyjneTPodmiot3Dto(podmiotDto as any, 1);
expect(result[0]).toEqual('header:Podmiot inny 2');
expect(result[0]).toEqual([{
"line": true,
}]);
});
});

View File

@@ -2,6 +2,7 @@ import { Content } from 'pdfmake/interfaces';
import {
createHeader,
createLabelText,
generateLine,
generateTwoColumns,
getTable,
hasValue,
@@ -26,7 +27,10 @@ export function generateDaneIdentyfikacyjneTPodmiot3Dto(
const podmiot1: Podmiot3 = podmiot2KDto.fakturaPodmiotNDto;
const podmiot1DaneKontaktowe: Podmiot1DaneKontaktowe[] = getTable(podmiot1.DaneKontaktowe);
const podmiot1K: (Podmiot2K & { Adres?: Adres }) | undefined = podmiot2KDto.podmiot2KDto;
const result: Content[] = createHeader(`Podmiot inny ${index + 1}`);
const result: Content[] = [];
result.push(generateLine());
result.push(createHeader(`Podmiot inny ${index + 1}`));
if (
hasValue(podmiot1.NrEORI) ||
@@ -39,7 +43,7 @@ export function generateDaneIdentyfikacyjneTPodmiot3Dto(
createLabelText('Numer EORI: ', podmiot1.NrEORI),
createLabelText('Rola: ', getRolaString(podmiot1.Rola, 3)),
createLabelText('Rola inna: ', podmiot1.OpisRoli),
createLabelText('Udział: ', podmiot1.Udzial, FormatTyp.Currency6)
createLabelText('Udział: ', podmiot1.Udzial, FormatTyp.Percentage)
);
}

View File

@@ -69,15 +69,14 @@ describe(generatePodmioty.name, () => {
expect(generatePodmiot1Podmiot1K).toHaveBeenCalledWith(baseInvoice.Podmiot1, baseInvoice.Fa.Podmiot1K);
expect(generatePodmiot2Podmiot2K).toHaveBeenCalledWith(baseInvoice.Podmiot2, baseInvoice.Fa.Podmiot2K[0]);
expect(generatePodmiot3).toHaveBeenCalled();
expect(generateDaneIdentyfikacyjneTPodmiot3Dto).not.toHaveBeenCalled();
expect(generateDaneIdentyfikacyjneTPodmiot3Dto).toHaveBeenCalled();
expect(generatePodmiotUpowazniony).toHaveBeenCalledWith(baseInvoice.PodmiotUpowazniony);
expect(createSection).toHaveBeenCalled();
expect(result.flag).toBe(true);
expect(content).toHaveLength(4);
expect(content[0]).toEqual({ text: 'Podmiot1K content' });
expect(content[1]).toEqual({ text: 'Podmiot2K content' });
expect(content[2]).toEqual({ text: 'Podmiot3 content 0' });
expect(content[2]).toEqual({ text: 'DaneIdentyfikacyjne Podmiot3 0' });
expect(content[3]).toEqual({ text: 'PodmiotUpowazniony content' });
});
@@ -104,13 +103,12 @@ describe(generatePodmioty.name, () => {
expect(generateDaneIdentyfikacyjneTPodmiot3Dto).toHaveBeenCalled();
expect(generatePodmiot3).toHaveBeenCalled();
expect(result.flag).toBe(true);
expect(content).toHaveLength(6);
expect(content).toHaveLength(5);
expect(content[0]).toEqual({ text: 'Podmiot2K content' });
expect(content[1]).toEqual({ text: 'Podmiot2K content' });
expect(content[2]).toEqual({ text: 'DaneIdentyfikacyjne Podmiot3 0' });
expect(content[3]).toEqual({ text: '', margin: [0, 8, 0, 0] });
expect(content[4]).toEqual({ text: 'Podmiot3 content 1' });
expect(content[5]).toEqual({ text: 'PodmiotUpowazniony content' });
expect(content[1]).toEqual({ text: 'DaneIdentyfikacyjne Podmiot3 0' });
expect(content[2]).toEqual({ text: '', margin: [0, 8, 0, 0] });
expect(content[3]).toEqual({ text: 'Podmiot3 content 1' });
expect(content[4]).toEqual({ text: 'PodmiotUpowazniony content' });
});
it('handles empty Podmiot3 gracefully', () => {

View File

@@ -5,28 +5,34 @@ import { Podmiot3Podmiot2KDto } from '../../types/fa2-additional-types';
import { generatePodmiot1 } from './Podmiot1';
import { generatePodmiot1Podmiot1K } from './Podmiot1Podmiot1K';
import { generatePodmiot2 } from './Podmiot2';
import { generatePodmiot2Podmiot2K } from './Podmiot2Podmiot2k';
import { generatePodmiot3 } from './Podmiot3';
import { generateDaneIdentyfikacyjneTPodmiot3Dto } from './Podmiot3Podmiot2k';
import { generatePodmiotUpowazniony } from './PodmiotUpowazniony';
import { Adres } from '../../types/fa1.types';
import { generatePodmiot2Podmiot2K } from './Podmiot2Podmiot2k';
export function generatePodmioty(invoice: Faktura): Content[] {
const result: Content[] = [];
const podmiot2K: Podmiot2K[] = getTable(invoice.Fa?.Podmiot2K);
const podmiot2KTable: Podmiot2K[] = getTable(invoice.Fa?.Podmiot2K);
const podmiot3: Podmiot3[] = getTable(invoice.Podmiot3);
if (invoice.Fa?.Podmiot1K || podmiot2K.length > 0) {
if (invoice.Fa?.Podmiot1K || podmiot2KTable.length > 0) {
if (invoice.Fa?.Podmiot1K) {
result.push(generatePodmiot1Podmiot1K(invoice.Podmiot1 ?? {}, invoice.Fa?.Podmiot1K));
} else if (invoice.Podmiot1 != null) {
result.push(generatePodmiot1(invoice.Podmiot1));
}
if (podmiot2K.length > 0) {
podmiot2K.forEach((podmiot2K: Podmiot2K): void => {
if (invoice.Fa?.Podmiot2K) {
const podmiot2K = podmiot2KTable.find(
(podmiot) => getValue(podmiot.IDNabywcy) === getValue(invoice.Podmiot2?.IDNabywcy)
);
if (podmiot2K) {
result.push(generatePodmiot2Podmiot2K(invoice.Podmiot2 ?? {}, podmiot2K));
});
} else {
result.push(createSection(generatePodmiot2(invoice.Podmiot2!), true));
}
} else if (invoice.Podmiot2) {
result.push(createSection(generatePodmiot2(invoice.Podmiot2!), true));
}
@@ -40,7 +46,11 @@ export function generatePodmioty(invoice: Faktura): Content[] {
}
if (podmiot3.length > 0) {
const podmiot3Podmiot2KDto = getPodmiot3Podmiot2KDto(podmiot2K, podmiot3);
const podmiot3Podmiot2KDto = getPodmiot3Podmiot2KDto(podmiot2KTable, podmiot3);
podmiot3Podmiot2KDto.filter(
(podmiot3Podmiot2) => podmiot3Podmiot2.fakturaPodmiotNDto.IDNabywcy === invoice.Podmiot2?.IDNabywcy
);
if (podmiot3Podmiot2KDto.length > 0) {
podmiot3Podmiot2KDto.forEach((pdm2KDto, i) => {
@@ -70,21 +80,17 @@ export function generatePodmioty(invoice: Faktura): Content[] {
function getPodmiot3Podmiot2KDto(podmioty2K: Podmiot2K[], podmioty3: Podmiot3[]): Podmiot3Podmiot2KDto[] {
const result: Podmiot3Podmiot2KDto[] = [];
if (
podmioty2K.length > 1 &&
podmioty3.filter((p: Podmiot3): boolean => getValue(p.Rola) === '4').length > 0
) {
let idx: number = 1;
if (podmioty3.filter((p: Podmiot3): boolean => getValue(p.Rola) === '4').length > 0) {
podmioty3.forEach((podmiot3: Podmiot3): void => {
if (getValue(podmiot3.Rola) === '4') {
if (podmioty2K.length > idx) {
result.push({
fakturaPodmiotNDto: podmiot3,
podmiot2KDto: podmioty2K[idx] as Podmiot2K[] & { Adres: Adres },
podmiot2KDto: podmioty2K.find(
(podmiot) => getValue(podmiot.IDNabywcy) === getValue(podmiot3.IDNabywcy)
) as Podmiot2K[] & {
Adres: Adres;
},
});
}
idx++;
} else {
result.push({
fakturaPodmiotNDto: podmiot3,

View File

@@ -63,18 +63,32 @@ export function generatePodsumowanieStawekPodatkuVat(faktura: Faktura): Content[
const definedHeader: Content[] = [
...[{ text: 'Lp.', style: FormatTyp.GrayBoldTitle }],
...(AnyP13P14_5Diff0 ? [{ text: 'Stawka podatku', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5)
? [
{
text: 'Stawka podatku',
style: FormatTyp.GrayBoldTitle,
},
]
: []),
...(AnyP13 ? [{ text: 'Kwota netto', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 ? [{ text: 'Kwota podatku', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5)
? [
{
text: 'Kwota podatku',
style: FormatTyp.GrayBoldTitle,
},
]
: []),
...(AnyP13 ? [{ text: 'Kwota brutto', style: FormatTyp.GrayBoldTitle }] : []),
...(AnyP_14xW ? [{ text: 'Kwota podatku PLN', style: FormatTyp.GrayBoldTitle }] : []),
];
const widths: Content[] = [
...['auto'],
...(AnyP13P14_5Diff0 ? ['*'] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5) ? ['*'] : []),
...(AnyP13 ? ['*'] : []),
...(AnyP13P14_5Diff0 ? ['*'] : []),
...(AnyP13P14_5Diff0 || hasValue(faktura.Fa?.P_14_5) ? ['*'] : []),
...(AnyP13 ? ['*'] : []),
...(AnyP_14xW ? ['*'] : []),
];
@@ -87,13 +101,23 @@ export function generatePodsumowanieStawekPodatkuVat(faktura: Faktura): Content[
data.push(item.no);
if (AnyP13P14_5Diff0) {
if (item.taxRateString) {
data.push(item.taxRateString);
} else if (getValue(faktura.Fa?.P_13_5)) {
data.push('OSS');
} else {
data.push('');
}
} else if (hasValue(faktura.Fa?.P_14_5)) {
data.push('OSS');
}
if (AnyP13) {
data.push(formatText(item.net, FormatTyp.Currency));
}
if (AnyP13P14_5Diff0) {
data.push(formatText(item.tax, FormatTyp.Currency));
} else if (hasValue(faktura.Fa?.P_14_5)) {
data.push(getValue(faktura.Fa?.P_14_5));
}
if (AnyP13) {
data.push(formatText(item.gross, FormatTyp.Currency));
@@ -186,10 +210,10 @@ export function getSummaryTaxRate(fa: Fa): TaxSummaryTypes[] {
summary.push({
no,
net: getNumberRounded(fa.P_13_5).toFixed(2),
gross: getNumberRounded(fa.P_13_5).toFixed(2),
gross: (getNumberRounded(fa.P_13_5) + getNumberRounded(fa.P_14_5)).toFixed(2),
tax: getNumberRounded(fa.P_14_5).toFixed(2),
taxPLN: '',
taxRateString: getValue(fa.P_14_5) != 0 ? 'niepodlegające opodatkowaniu' : '',
taxRateString: getValue(fa.P_14_5) != 0 ? 'OSS' : '',
});
no++;
}
@@ -201,7 +225,8 @@ export function getSummaryTaxRate(fa: Fa): TaxSummaryTypes[] {
gross: getNumberRounded(fa.P_13_6_1).toFixed(2),
tax: '0.00',
taxPLN: '',
taxRateString: '0% w przypadku sprzedaży towarów i świadczenia usług na terytorium kraju (z wyłączeniem WDT i eksportu)',
taxRateString:
'0% w przypadku sprzedaży towarów i świadczenia usług na terytorium kraju (z wyłączeniem WDT i eksportu)',
});
no++;
}

View File

@@ -13,7 +13,8 @@ vi.mock('../../../shared/PDF-functions', () => ({
getContentTable: vi.fn(),
getTable: vi.fn(),
getValue: vi.fn((v) => v?._text || v),
getTStawkaPodatku: vi.fn()
getTStawkaPodatku: vi.fn(),
getDifferentColumnsValue: vi.fn(),
}));
describe(generateWiersze.name, () => {
@@ -62,7 +63,7 @@ describe(generateWiersze.name, () => {
vi.mocked(PDFFunctions.createSection).mockReturnValue({ section: 'content' } as any);
vi.mocked(PDFFunctions.createLabelTextArray).mockReturnValue(['Label', 'Value'] as any);
vi.mocked(PDFFunctions.getTStawkaPodatku).mockReturnValue('0' as any);
vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([]);
};
describe('when no invoice lines exist', () => {
@@ -73,6 +74,7 @@ describe(generateWiersze.name, () => {
fieldsWithValue: [],
});
vi.mocked(PDFFunctions.getValue).mockReturnValue('0');
vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([]);
const result = generateWiersze(mockFaVat);
@@ -110,7 +112,9 @@ describe(generateWiersze.name, () => {
});
it('should display "brutto" when P_11 is not in fieldsWithValue', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable).mockReturnValue({
content: { table: {} } as any,
@@ -152,7 +156,9 @@ describe(generateWiersze.name, () => {
});
it('should generate two tables when fieldsWithValue.length > 8', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable)
.mockReturnValueOnce({
@@ -179,7 +185,9 @@ describe(generateWiersze.name, () => {
});
it('should not add second table if it has only 1 field with value', () => {
vi.mocked(PDFFunctions.getTable).mockReturnValue([{ NrWierszaFa: { _text: '1' }, P_12: {_text: '23'} }] as any);
vi.mocked(PDFFunctions.getTable).mockReturnValue([
{ NrWierszaFa: { _text: '1' }, P_12: { _text: '23' } },
] as any);
vi.mocked(PDFFunctions.getContentTable)
.mockReturnValueOnce({

View File

@@ -5,6 +5,7 @@ import {
createSection,
formatText,
getContentTable,
getDifferentColumnsValue,
getTable,
getTStawkaPodatku,
getValue,
@@ -41,7 +42,7 @@ export function generateWiersze(faVat: Fa): Content {
{ name: 'P_8A', title: 'Miara', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_10', title: 'Rabat', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_12', title: 'Stawka podatku', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12_XII', title: 'Stawka podatku OSS', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12_XII', title: 'Stawka podatku OSS', format: FormatTyp.Percentage, width: 'auto' },
{
name: 'P_12_Zal_15',
title: 'Znacznik dla towaru lub usługi z zał. nr 15 do ustawy',
@@ -51,9 +52,17 @@ export function generateWiersze(faVat: Fa): Content {
{ name: 'P_11', title: 'Wartość sprzedaży netto', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_11A', title: 'Wartość sprzedaży brutto', format: FormatTyp.Currency, width: 'auto' },
{ name: 'P_11Vat', title: 'Wartość sprzedaży vat', format: FormatTyp.Currency, width: 'auto' },
{ name: 'KursWaluty', title: 'Kurs waluty', format: FormatTyp.Currency6, width: 'auto' },
{ name: 'StanPrzed', title: 'Stan przed', format: FormatTyp.Boolean, width: 'auto' },
];
if (getDifferentColumnsValue('KursWaluty', faWiersze).length !== 1) {
definedHeader1.push({
name: 'KursWaluty',
title: 'Kurs waluty',
format: FormatTyp.Currency6,
width: 'auto',
});
}
definedHeader1.push({ name: 'StanPrzed', title: 'Stan przed', format: FormatTyp.Boolean, width: 'auto' });
const definedHeader2: HeaderDefine[] = [
{ name: 'GTIN', title: 'GTIN', format: FormatTyp.Default, width: 'auto' },
{ name: 'PKWiU', title: 'PKWiU', format: FormatTyp.Default, width: 'auto' },

View File

@@ -19,7 +19,8 @@ export function generateZamowienie(
zamowienieKorekta: ZamowienieKorekta,
p_15: string,
rodzajFaktury: string,
KodWaluty: string
KodWaluty: string,
P_PMarzy?: string
): Content[] {
if (!orderData) {
return [];
@@ -30,9 +31,7 @@ export function generateZamowienie(
if (!el.NrWierszaZam._text) {
el.NrWierszaZam._text = (index + 1).toString();
}
if (getValue(el.P_12Z)) {
el.P_12Z._text = getTStawkaPodatku(getValue(el.P_12Z) as string, 3);
}
el.P_12Z = { _text: getTStawkaPodatku(getValue(el.P_12Z) as string, 3, P_PMarzy) };
return el;
});
const definedHeaderLp: HeaderDefine[] = [
@@ -50,7 +49,7 @@ export function generateZamowienie(
{ name: 'P_8BZ', title: 'Ilość', format: FormatTyp.Right, width: 'auto' },
{ name: 'P_8AZ', title: 'Miara', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z', title: 'Stawka podatku', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z_XII', title: 'Stawka podatku OSS', format: FormatTyp.Default, width: 'auto' },
{ name: 'P_12Z_XII', title: 'Stawka podatku OSS', format: FormatTyp.Percentage, width: 'auto' },
{
name: 'P_12Z_Zal_15',
title: 'Znacznik dla towaru lub usługi z zał. nr 15 do ustawy',

View File

@@ -21,7 +21,7 @@ describe('chunkArray', () => {
expect(result.length).toBe(2);
expect(result[0].length).toBe(4);
expect(result[1].length).toBe(4);
expect(result[1].length).toBe(5);
});
it('should split into two parts with first bigger by 1 when odd columns between 8 and 14', () => {
@@ -30,7 +30,7 @@ describe('chunkArray', () => {
expect(result.length).toBe(2);
expect(result[0].length).toBe(5);
expect(result[1].length).toBe(4);
expect(result[1].length).toBe(5);
});
it('should split into three parts with roughly equal parts for columns > 14', () => {
@@ -39,8 +39,8 @@ describe('chunkArray', () => {
expect(result.length).toBe(3);
expect(result[0].length).toBe(6);
expect(result[1].length).toBe(6);
expect(result[2].length).toBe(6);
expect(result[1].length).toBe(7);
expect(result[2].length).toBe(7);
});
it('should split 20 columns into 7,7,and 6', () => {
@@ -49,8 +49,8 @@ describe('chunkArray', () => {
expect(result.length).toBe(3);
expect(result[0].length).toBe(7);
expect(result[1].length).toBe(7);
expect(result[2].length).toBe(6);
expect(result[1].length).toBe(8);
expect(result[2].length).toBe(7);
});
it('should split 15 columns into 5,5,5', () => {
@@ -59,7 +59,7 @@ describe('chunkArray', () => {
expect(result.length).toBe(3);
expect(result[0].length).toBe(5);
expect(result[1].length).toBe(5);
expect(result[2].length).toBe(5);
expect(result[1].length).toBe(6);
expect(result[2].length).toBe(6);
});
});

View File

@@ -128,7 +128,12 @@ function generateTable(tabela: Tabela): Content[] {
return result;
}
function createTable(cols: Kol[], rows: Wiersz | Wiersz[], subTableIndex: number, totalLength: number): ContentTable {
function createTable(
cols: Kol[],
rows: Wiersz | Wiersz[],
subTableIndex: number,
totalLength: number
): ContentTable {
const definedHeader: Content[] = cols.map((item: Kol): string | ContentText =>
formatText(item.NKom?._text, FormatTyp.GrayBoldTitle)
);
@@ -205,9 +210,9 @@ export function chunkArray<T>(columns: T[]): T[][] {
const half: number = Math.floor(n / 2);
if (n % 2 === 0) {
return [columns.slice(0, half), columns.slice(half)];
return [columns.slice(0, half), [columns[0], ...columns.slice(half)]];
} else {
return [columns.slice(0, half + 1), columns.slice(half + 1)];
return [columns.slice(0, half + 1), [columns[0], ...columns.slice(half + 1)]];
}
} else {
const base: number = Math.floor(n / 3);
@@ -226,6 +231,8 @@ export function chunkArray<T>(columns: T[]): T[][] {
result.push(columns.slice(idx, idx + size));
idx += size;
}
result[1].unshift(columns[0]);
result[2].unshift(columns[0]);
return result;
}
}

View File

@@ -17,7 +17,7 @@ import {
TStawkaPodatku_FA2,
TStawkaPodatku_FA3,
} from './consts/const';
import {formatDateTime, formatTime, getFormaPlatnosciString} from './generators/common/functions';
import { formatDateTime, formatTime, getFormaPlatnosciString } from './generators/common/functions';
import { HeaderDefine, PdfFP, PdfOptionField } from './types/pdf-types';
import { FP } from '../lib-public/types/fa3.types';
import { DifferentValues, FilteredKeysOfValues, TypesOfValues } from './types/universal.types';
@@ -516,7 +516,7 @@ export function getKraj(code: string): string {
return code;
}
export function getTStawkaPodatku(code: string, version: 1 | 2 | 3): string {
export function getTStawkaPodatku(code: string, version: 1 | 2 | 3, P_PMarzy?: string): string {
let TStawkaPodatkuVersioned: Record<string, string> = {};
switch (version) {
@@ -530,6 +530,9 @@ export function getTStawkaPodatku(code: string, version: 1 | 2 | 3): string {
TStawkaPodatkuVersioned = TStawkaPodatku_FA3;
break;
}
if (!code && P_PMarzy === '1') {
return 'marża';
}
if (TStawkaPodatkuVersioned[code]) {
return TStawkaPodatkuVersioned[code];