From f48680a65f5601b7e00ccb28b21a28fc7b3c3364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chudy?= Date: Fri, 30 Jan 2026 20:06:43 +0100 Subject: [PATCH] chore(): 1.0.0 --- package-lock.json | 4 +- package.json | 2 +- src/app-public/main.ts | 2 +- src/lib-public/FA1-generator.ts | 5 +- src/lib-public/FA2-generator.ts | 5 +- src/lib-public/FA3-generator.ts | 5 +- src/lib-public/generators/FA1/Platnosc.ts | 19 +++++-- .../generators/FA1/Podmiot1Podmiot1K.spec.ts | 23 +++++---- .../generators/FA1/Podmiot1Podmiot1K.ts | 11 +++-- .../generators/FA1/Podmiot2Podmiot2k.spec.ts | 7 ++- .../generators/FA1/Podmiot2Podmiot2k.ts | 12 +++-- .../generators/FA1/Podmiot3Podmiot2k.ts | 2 +- .../FA1/PodmiotDaneIdentyfikacyjne.ts | 2 +- .../FA1/PodmiotDaneKontaktowe.spec.ts | 8 +-- .../generators/FA1/PodmiotDaneKontaktowe.ts | 2 +- .../FA1/PodsumowanieStawekPodatkuVat.ts | 38 +++++++++++--- src/lib-public/generators/FA1/Wiersze.spec.ts | 19 +++++-- src/lib-public/generators/FA1/Wiersze.ts | 13 ++++- src/lib-public/generators/FA1/Zamowienie.ts | 9 ++-- src/lib-public/generators/FA2/Platnosc.ts | 25 +++++----- .../generators/FA2/Podmiot1Podmiot1K.spec.ts | 16 +++--- .../generators/FA2/Podmiot1Podmiot1K.ts | 11 +++-- .../generators/FA2/Podmiot2Podmiot2k.spec.ts | 30 ++++++++---- .../generators/FA2/Podmiot2Podmiot2k.ts | 14 ++++-- src/lib-public/generators/FA2/Podmiot3.ts | 14 +++--- .../generators/FA2/Podmiot3Podmiot2k.spec.ts | 12 +++-- .../generators/FA2/Podmiot3Podmiot2k.ts | 8 ++- .../generators/FA2/Podmioty.spec.ts | 16 +++--- src/lib-public/generators/FA2/Podmioty.ts | 49 +++++++++++-------- .../FA2/PodsumowanieStawekPodatkuVat.ts | 44 +++++++++++++---- src/lib-public/generators/FA2/Wiersze.spec.ts | 17 +++++-- src/lib-public/generators/FA2/Wiersze.ts | 15 ++++-- src/lib-public/generators/FA2/Zamowienie.ts | 9 ++-- src/lib-public/generators/FA3/Platnosc.ts | 19 +++++-- .../generators/FA3/Podmiot1Podmiot1K.spec.ts | 18 +++---- .../generators/FA3/Podmiot1Podmiot1K.ts | 11 +++-- src/lib-public/generators/FA3/Podmiot2.ts | 16 +++--- .../generators/FA3/Podmiot2Podmiot2k.spec.ts | 28 +++++++---- .../generators/FA3/Podmiot2Podmiot2k.ts | 16 +++--- src/lib-public/generators/FA3/Podmiot3.ts | 14 +++--- .../generators/FA3/Podmiot3Podmiot2k.spec.ts | 12 +++-- .../generators/FA3/Podmiot3Podmiot2k.ts | 8 ++- .../generators/FA3/Podmioty.spec.ts | 16 +++--- src/lib-public/generators/FA3/Podmioty.ts | 46 +++++++++-------- .../FA3/PodsumowanieStawekPodatkuVat.ts | 41 +++++++++++++--- src/lib-public/generators/FA3/Wiersze.spec.ts | 18 +++++-- src/lib-public/generators/FA3/Wiersze.ts | 15 ++++-- src/lib-public/generators/FA3/Zamowienie.ts | 9 ++-- .../generators/common/Zalaczniki.spec.ts | 16 +++--- .../generators/common/Zalaczniki.ts | 13 +++-- src/shared/PDF-functions.ts | 7 ++- 51 files changed, 506 insertions(+), 285 deletions(-) diff --git a/package-lock.json b/package-lock.json index ad05791..69eb438 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 02ffb7f..feb772c 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/app-public/main.ts b/src/app-public/main.ts index 53f3123..6aba246 100644 --- a/src/app-public/main.ts +++ b/src/app-public/main.ts @@ -15,7 +15,7 @@ inputInvoice.addEventListener('change', async (): Promise => { 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 => { diff --git a/src/lib-public/FA1-generator.ts b/src/lib-public/FA1-generator.ts index a33b03d..6adf12c 100644 --- a/src/lib-public/FA1-generator.ts +++ b/src/lib-public/FA1-generator.ts @@ -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), diff --git a/src/lib-public/FA2-generator.ts b/src/lib-public/FA2-generator.ts index 0f326b5..02a04fd 100644 --- a/src/lib-public/FA2-generator.ts +++ b/src/lib-public/FA2-generator.ts @@ -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), diff --git a/src/lib-public/FA3-generator.ts b/src/lib-public/FA3-generator.ts index 5da41fa..b826965 100644 --- a/src/lib-public/FA3-generator.ts +++ b/src/lib-public/FA3-generator.ts @@ -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), diff --git a/src/lib-public/generators/FA1/Platnosc.ts b/src/lib-public/generators/FA1/Platnosc.ts index 6f5c033..857f049 100644 --- a/src/lib-public/generators/FA1/Platnosc.ts +++ b/src/lib-public/generators/FA1/Platnosc.ts @@ -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])); diff --git a/src/lib-public/generators/FA1/Podmiot1Podmiot1K.spec.ts b/src/lib-public/generators/FA1/Podmiot1Podmiot1K.spec.ts index 7b68086..be13f79 100644 --- a/src/lib-public/generators/FA1/Podmiot1Podmiot1K.spec.ts +++ b/src/lib-public/generators/FA1/Podmiot1Podmiot1K.spec.ts @@ -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([ - { text: 'SUBHEADER:Dane identyfikacyjne' }, - { text: 'LABEL:Numer EORI: EORI' }, - { id: 'ID' }, - { text: 'LABEL:Status podatnika: AKTYWNY' }, - ]) - ); + expect(firstRow).toEqual([ + { text: 'SUBHEADER:Dane identyfikacyjne' }, + { text: 'LABEL:Numer EORI: EORI' }, + { id: 'ID' }, + { 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', () => { diff --git a/src/lib-public/generators/FA1/Podmiot1Podmiot1K.ts b/src/lib-public/generators/FA1/Podmiot1Podmiot1K.ts index 90c9d04..435d560 100644 --- a/src/lib-public/generators/FA1/Podmiot1Podmiot1K.ts +++ b/src/lib-public/generators/FA1/Podmiot1Podmiot1K.ts @@ -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'); diff --git a/src/lib-public/generators/FA1/Podmiot2Podmiot2k.spec.ts b/src/lib-public/generators/FA1/Podmiot2Podmiot2k.spec.ts index ff6ec3b..5a56862 100644 --- a/src/lib-public/generators/FA1/Podmiot2Podmiot2k.spec.ts +++ b/src/lib-public/generators/FA1/Podmiot2Podmiot2k.spec.ts @@ -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)) { diff --git a/src/lib-public/generators/FA1/Podmiot2Podmiot2k.ts b/src/lib-public/generators/FA1/Podmiot2Podmiot2k.ts index 096b9e0..b6d0873 100644 --- a/src/lib-public/generators/FA1/Podmiot2Podmiot2k.ts +++ b/src/lib-public/generators/FA1/Podmiot2Podmiot2k.ts @@ -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,9 +40,9 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot columnGap: 20, }); } - if(podmiot2K.Adres?.AdresPol || podmiot2K.Adres?.AdresZagr) { - firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana'); - secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca'); + if (podmiot2K.DaneIdentyfikacyjne) { + firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana'); + secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca'); } if (podmiot2.AdresKoresp) { diff --git a/src/lib-public/generators/FA1/Podmiot3Podmiot2k.ts b/src/lib-public/generators/FA1/Podmiot3Podmiot2k.ts index 7a2e1f8..b41d9f4 100644 --- a/src/lib-public/generators/FA1/Podmiot3Podmiot2k.ts +++ b/src/lib-public/generators/FA1/Podmiot3Podmiot2k.ts @@ -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) ); } diff --git a/src/lib-public/generators/FA1/PodmiotDaneIdentyfikacyjne.ts b/src/lib-public/generators/FA1/PodmiotDaneIdentyfikacyjne.ts index 5760eb9..00e0ea2 100644 --- a/src/lib-public/generators/FA1/PodmiotDaneIdentyfikacyjne.ts +++ b/src/lib-public/generators/FA1/PodmiotDaneIdentyfikacyjne.ts @@ -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)}` ) ); diff --git a/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.spec.ts b/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.spec.ts index b5f09b1..bdcc0c4 100644 --- a/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.spec.ts +++ b/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.spec.ts @@ -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', () => { diff --git a/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.ts b/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.ts index d121cca..61e8093 100644 --- a/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.ts +++ b/src/lib-public/generators/FA1/PodmiotDaneKontaktowe.ts @@ -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; diff --git a/src/lib-public/generators/FA1/PodsumowanieStawekPodatkuVat.ts b/src/lib-public/generators/FA1/PodsumowanieStawekPodatkuVat.ts index 05c48f3..4fe6811 100644 --- a/src/lib-public/generators/FA1/PodsumowanieStawekPodatkuVat.ts +++ b/src/lib-public/generators/FA1/PodsumowanieStawekPodatkuVat.ts @@ -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) { - data.push(item.taxRateString); + 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++; } diff --git a/src/lib-public/generators/FA1/Wiersze.spec.ts b/src/lib-public/generators/FA1/Wiersze.spec.ts index 7eca37a..24210ef 100644 --- a/src/lib-public/generators/FA1/Wiersze.spec.ts +++ b/src/lib-public/generators/FA1/Wiersze.spec.ts @@ -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({ diff --git a/src/lib-public/generators/FA1/Wiersze.ts b/src/lib-public/generators/FA1/Wiersze.ts index 29dc636..3cc4473 100644 --- a/src/lib-public/generators/FA1/Wiersze.ts +++ b/src/lib-public/generators/FA1/Wiersze.ts @@ -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' }, diff --git a/src/lib-public/generators/FA1/Zamowienie.ts b/src/lib-public/generators/FA1/Zamowienie.ts index 4ab817f..52f5f86 100644 --- a/src/lib-public/generators/FA1/Zamowienie.ts +++ b/src/lib-public/generators/FA1/Zamowienie.ts @@ -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' }, diff --git a/src/lib-public/generators/FA2/Platnosc.ts b/src/lib-public/generators/FA2/Platnosc.ts index 30bea00..22e3829 100644 --- a/src/lib-public/generators/FA2/Platnosc.ts +++ b/src/lib-public/generators/FA2/Platnosc.ts @@ -109,18 +109,21 @@ export function generatePlatnosc(platnosc: Platnosc | undefined): Content { table.push(tableZaplataCzesciowa.content); } - table.push( - generateTwoColumns( - generujRachunekBankowy( - getTable(platnosc.RachunekBankowy as Record[]), - 'Numer rachunku bankowego' - ), - generujRachunekBankowy( - getTable(platnosc.RachunekBankowyFaktora as Record[]), - 'Numer rachunku bankowego faktora' - ) - ) + const rachunekBankowy: Content[][] = getTable(platnosc.RachunekBankowy as Record[]).map( + (rachunek) => generujRachunekBankowy([rachunek], 'Numer rachunku bankowego') ); + const rachunekBankowyFaktora: Content[][] = getTable( + platnosc.RachunekBankowyFaktora as Record[] + ).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])); diff --git a/src/lib-public/generators/FA2/Podmiot1Podmiot1K.spec.ts b/src/lib-public/generators/FA2/Podmiot1Podmiot1K.spec.ts index 20c58ff..6926baf 100644 --- a/src/lib-public/generators/FA2/Podmiot1Podmiot1K.spec.ts +++ b/src/lib-public/generators/FA2/Podmiot1Podmiot1K.spec.ts @@ -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 }); }); }); diff --git a/src/lib-public/generators/FA2/Podmiot1Podmiot1K.ts b/src/lib-public/generators/FA2/Podmiot1Podmiot1K.ts index 1d5f8ad..5dc81f2 100644 --- a/src/lib-public/generators/FA2/Podmiot1Podmiot1K.ts +++ b/src/lib-public/generators/FA2/Podmiot1Podmiot1K.ts @@ -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'); diff --git a/src/lib-public/generators/FA2/Podmiot2Podmiot2k.spec.ts b/src/lib-public/generators/FA2/Podmiot2Podmiot2k.spec.ts index 0af2126..e30e7a4 100644 --- a/src/lib-public/generators/FA2/Podmiot2Podmiot2k.spec.ts +++ b/src/lib-public/generators/FA2/Podmiot2Podmiot2k.spec.ts @@ -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'); }); }); diff --git a/src/lib-public/generators/FA2/Podmiot2Podmiot2k.ts b/src/lib-public/generators/FA2/Podmiot2Podmiot2k.ts index 4e3d48c..2e964ff 100644 --- a/src/lib-public/generators/FA2/Podmiot2Podmiot2k.ts +++ b/src/lib-public/generators/FA2/Podmiot2Podmiot2k.ts @@ -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)); diff --git a/src/lib-public/generators/FA2/Podmiot3.ts b/src/lib-public/generators/FA2/Podmiot3.ts index 182857a..0f6c3ed 100644 --- a/src/lib-public/generators/FA2/Podmiot3.ts +++ b/src/lib-public/generators/FA2/Podmiot3.ts @@ -38,12 +38,14 @@ export function generatePodmiot3(podmiot: Podmiot3, index: number): Content[] { ...generateAdres(podmiot.AdresKoresp) ); } - if (podmiot.DaneKontaktowe) { - column2.push( - formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]), - ...generateDaneKontaktowe(podmiot.DaneKontaktowe), - createLabelText('Numer klienta: ', podmiot.NrKlienta) - ); + if (podmiot.DaneKontaktowe || podmiot.NrKlienta) { + column2.push(formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin])); + if (podmiot.DaneKontaktowe) { + column2.push(...generateDaneKontaktowe(podmiot.DaneKontaktowe)); + } + if (podmiot.NrKlienta) { + column2.push(createLabelText('Numer klienta: ', podmiot.NrKlienta)); + } } result.push(generateTwoColumns(column1, column2)); return result; diff --git a/src/lib-public/generators/FA2/Podmiot3Podmiot2k.spec.ts b/src/lib-public/generators/FA2/Podmiot3Podmiot2k.spec.ts index c186caa..9851748 100644 --- a/src/lib-public/generators/FA2/Podmiot3Podmiot2k.spec.ts +++ b/src/lib-public/generators/FA2/Podmiot3Podmiot2k.spec.ts @@ -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, + }]); }); }); diff --git a/src/lib-public/generators/FA2/Podmiot3Podmiot2k.ts b/src/lib-public/generators/FA2/Podmiot3Podmiot2k.ts index e9b75ba..8e6602f 100644 --- a/src/lib-public/generators/FA2/Podmiot3Podmiot2k.ts +++ b/src/lib-public/generators/FA2/Podmiot3Podmiot2k.ts @@ -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) ); } diff --git a/src/lib-public/generators/FA2/Podmioty.spec.ts b/src/lib-public/generators/FA2/Podmioty.spec.ts index 601f9ea..772b734 100644 --- a/src/lib-public/generators/FA2/Podmioty.spec.ts +++ b/src/lib-public/generators/FA2/Podmioty.spec.ts @@ -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', () => { diff --git a/src/lib-public/generators/FA2/Podmioty.ts b/src/lib-public/generators/FA2/Podmioty.ts index de28971..8a1f4fa 100644 --- a/src/lib-public/generators/FA2/Podmioty.ts +++ b/src/lib-public/generators/FA2/Podmioty.ts @@ -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, - }); - } - idx++; + result.push({ + fakturaPodmiotNDto: podmiot3, + podmiot2KDto: podmioty2K.find( + (podmiot) => getValue(podmiot.IDNabywcy) === getValue(podmiot3.IDNabywcy) + ) as Podmiot2K[] & { + Adres: Adres; + }, + }); } else { result.push({ fakturaPodmiotNDto: podmiot3, diff --git a/src/lib-public/generators/FA2/PodsumowanieStawekPodatkuVat.ts b/src/lib-public/generators/FA2/PodsumowanieStawekPodatkuVat.ts index be9a72a..cd7f286 100644 --- a/src/lib-public/generators/FA2/PodsumowanieStawekPodatkuVat.ts +++ b/src/lib-public/generators/FA2/PodsumowanieStawekPodatkuVat.ts @@ -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) { - data.push(item.taxRateString); + 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++; } diff --git a/src/lib-public/generators/FA2/Wiersze.spec.ts b/src/lib-public/generators/FA2/Wiersze.spec.ts index 5ff17d8..664896a 100644 --- a/src/lib-public/generators/FA2/Wiersze.spec.ts +++ b/src/lib-public/generators/FA2/Wiersze.spec.ts @@ -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({ diff --git a/src/lib-public/generators/FA2/Wiersze.ts b/src/lib-public/generators/FA2/Wiersze.ts index d10a9c1..97dc36d 100644 --- a/src/lib-public/generators/FA2/Wiersze.ts +++ b/src/lib-public/generators/FA2/Wiersze.ts @@ -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' }, diff --git a/src/lib-public/generators/FA2/Zamowienie.ts b/src/lib-public/generators/FA2/Zamowienie.ts index 11fc36a..7284530 100644 --- a/src/lib-public/generators/FA2/Zamowienie.ts +++ b/src/lib-public/generators/FA2/Zamowienie.ts @@ -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', diff --git a/src/lib-public/generators/FA3/Platnosc.ts b/src/lib-public/generators/FA3/Platnosc.ts index a001b49..2f9c812 100644 --- a/src/lib-public/generators/FA3/Platnosc.ts +++ b/src/lib-public/generators/FA3/Platnosc.ts @@ -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])); diff --git a/src/lib-public/generators/FA3/Podmiot1Podmiot1K.spec.ts b/src/lib-public/generators/FA3/Podmiot1Podmiot1K.spec.ts index 44a476b..a7841a3 100644 --- a/src/lib-public/generators/FA3/Podmiot1Podmiot1K.spec.ts +++ b/src/lib-public/generators/FA3/Podmiot1Podmiot1K.spec.ts @@ -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 }); }); diff --git a/src/lib-public/generators/FA3/Podmiot1Podmiot1K.ts b/src/lib-public/generators/FA3/Podmiot1Podmiot1K.ts index 86748ae..6a03b5c 100644 --- a/src/lib-public/generators/FA3/Podmiot1Podmiot1K.ts +++ b/src/lib-public/generators/FA3/Podmiot1Podmiot1K.ts @@ -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'); diff --git a/src/lib-public/generators/FA3/Podmiot2.ts b/src/lib-public/generators/FA3/Podmiot2.ts index 0703532..fde4142 100644 --- a/src/lib-public/generators/FA3/Podmiot2.ts +++ b/src/lib-public/generators/FA3/Podmiot2.ts @@ -41,13 +41,17 @@ export function generatePodmiot2(podmiot2: Podmiot2): Content[] { const daneKontaktowe = getTable(podmiot2.DaneKontaktowe); if (daneKontaktowe.length) { - createLabelText( - 'Faktura dotyczy jednostki podrzędnej JST: ', - daneKontaktowe[0].JST?._text === '1' ? 'TAK' : 'NIE' + result.push( + createLabelText( + 'Faktura dotyczy jednostki podrzędnej JST: ', + daneKontaktowe[0].JST?._text === '1' ? 'TAK' : 'NIE' + ) ); - createLabelText( - 'Faktura dotyczy członka grupy GV: ', - daneKontaktowe[0].GV?._text === '1' ? 'TAK' : 'NIE' + result.push( + createLabelText( + 'Faktura dotyczy członka grupy GV: ', + daneKontaktowe[0].GV?._text === '1' ? 'TAK' : 'NIE' + ) ); } } diff --git a/src/lib-public/generators/FA3/Podmiot2Podmiot2k.spec.ts b/src/lib-public/generators/FA3/Podmiot2Podmiot2k.spec.ts index 2a2d0a5..a7f5a8a 100644 --- a/src/lib-public/generators/FA3/Podmiot2Podmiot2k.spec.ts +++ b/src/lib-public/generators/FA3/Podmiot2Podmiot2k.spec.ts @@ -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'); }); diff --git a/src/lib-public/generators/FA3/Podmiot2Podmiot2k.ts b/src/lib-public/generators/FA3/Podmiot2Podmiot2k.ts index 0b5c019..42896af 100644 --- a/src/lib-public/generators/FA3/Podmiot2Podmiot2k.ts +++ b/src/lib-public/generators/FA3/Podmiot2Podmiot2k.ts @@ -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,9 +43,9 @@ export function generatePodmiot2Podmiot2K(podmiot2: Podmiot2, podmiot2K: Podmiot }); } - if(podmiot2K.Adres?.AdresL1?._text){ - firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana'); - secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca'); + if (podmiot2K.DaneIdentyfikacyjne) { + firstColumn = generateCorrectedContent(podmiot2K, 'Treść korygowana'); + secondColumn = generateCorrectedContent(podmiot2, 'Treść korygująca'); } if (podmiot2.AdresKoresp) { diff --git a/src/lib-public/generators/FA3/Podmiot3.ts b/src/lib-public/generators/FA3/Podmiot3.ts index 38bb1b7..4ec7e81 100644 --- a/src/lib-public/generators/FA3/Podmiot3.ts +++ b/src/lib-public/generators/FA3/Podmiot3.ts @@ -38,12 +38,14 @@ export function generatePodmiot3(podmiot: Podmiot3, index: number): Content[] { ...generateAdres(podmiot.AdresKoresp) ); } - if (podmiot.DaneKontaktowe) { - column2.push( - formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin]), - ...generateDaneKontaktowe(podmiot.DaneKontaktowe), - createLabelText('Numer klienta: ', podmiot.NrKlienta) - ); + if (podmiot.DaneKontaktowe || podmiot.NrKlienta) { + column2.push(formatText('Dane kontaktowe', [FormatTyp.Label, FormatTyp.LabelMargin])); + if (podmiot.DaneKontaktowe) { + column2.push(...generateDaneKontaktowe(podmiot.DaneKontaktowe)); + } + if (podmiot.NrKlienta) { + column2.push(createLabelText('Numer klienta: ', podmiot.NrKlienta)); + } } result.push(generateTwoColumns(column1, column2)); return result; diff --git a/src/lib-public/generators/FA3/Podmiot3Podmiot2k.spec.ts b/src/lib-public/generators/FA3/Podmiot3Podmiot2k.spec.ts index c186caa..81e7a19 100644 --- a/src/lib-public/generators/FA3/Podmiot3Podmiot2k.spec.ts +++ b/src/lib-public/generators/FA3/Podmiot3Podmiot2k.spec.ts @@ -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, + }]); }); }); diff --git a/src/lib-public/generators/FA3/Podmiot3Podmiot2k.ts b/src/lib-public/generators/FA3/Podmiot3Podmiot2k.ts index d2c4595..464d538 100644 --- a/src/lib-public/generators/FA3/Podmiot3Podmiot2k.ts +++ b/src/lib-public/generators/FA3/Podmiot3Podmiot2k.ts @@ -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) ); } diff --git a/src/lib-public/generators/FA3/Podmioty.spec.ts b/src/lib-public/generators/FA3/Podmioty.spec.ts index 2412cdc..db160cc 100644 --- a/src/lib-public/generators/FA3/Podmioty.spec.ts +++ b/src/lib-public/generators/FA3/Podmioty.spec.ts @@ -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', () => { diff --git a/src/lib-public/generators/FA3/Podmioty.ts b/src/lib-public/generators/FA3/Podmioty.ts index 42347a6..9c6609a 100644 --- a/src/lib-public/generators/FA3/Podmioty.ts +++ b/src/lib-public/generators/FA3/Podmioty.ts @@ -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 }, - }); - } - idx++; + result.push({ + fakturaPodmiotNDto: podmiot3, + podmiot2KDto: podmioty2K.find( + (podmiot) => getValue(podmiot.IDNabywcy) === getValue(podmiot3.IDNabywcy) + ) as Podmiot2K[] & { + Adres: Adres; + }, + }); } else { result.push({ fakturaPodmiotNDto: podmiot3, diff --git a/src/lib-public/generators/FA3/PodsumowanieStawekPodatkuVat.ts b/src/lib-public/generators/FA3/PodsumowanieStawekPodatkuVat.ts index e14e42f..a2cc9f9 100644 --- a/src/lib-public/generators/FA3/PodsumowanieStawekPodatkuVat.ts +++ b/src/lib-public/generators/FA3/PodsumowanieStawekPodatkuVat.ts @@ -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) { - data.push(item.taxRateString); + 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++; } diff --git a/src/lib-public/generators/FA3/Wiersze.spec.ts b/src/lib-public/generators/FA3/Wiersze.spec.ts index 702407a..62db299 100644 --- a/src/lib-public/generators/FA3/Wiersze.spec.ts +++ b/src/lib-public/generators/FA3/Wiersze.spec.ts @@ -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({ diff --git a/src/lib-public/generators/FA3/Wiersze.ts b/src/lib-public/generators/FA3/Wiersze.ts index d5ef1da..bc406ff 100644 --- a/src/lib-public/generators/FA3/Wiersze.ts +++ b/src/lib-public/generators/FA3/Wiersze.ts @@ -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' }, diff --git a/src/lib-public/generators/FA3/Zamowienie.ts b/src/lib-public/generators/FA3/Zamowienie.ts index bfe13ce..e3c5a64 100644 --- a/src/lib-public/generators/FA3/Zamowienie.ts +++ b/src/lib-public/generators/FA3/Zamowienie.ts @@ -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', diff --git a/src/lib-public/generators/common/Zalaczniki.spec.ts b/src/lib-public/generators/common/Zalaczniki.spec.ts index 4576132..04a4037 100644 --- a/src/lib-public/generators/common/Zalaczniki.spec.ts +++ b/src/lib-public/generators/common/Zalaczniki.spec.ts @@ -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); }); }); diff --git a/src/lib-public/generators/common/Zalaczniki.ts b/src/lib-public/generators/common/Zalaczniki.ts index 947c993..4a12de0 100644 --- a/src/lib-public/generators/common/Zalaczniki.ts +++ b/src/lib-public/generators/common/Zalaczniki.ts @@ -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(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(columns: T[]): T[][] { result.push(columns.slice(idx, idx + size)); idx += size; } + result[1].unshift(columns[0]); + result[2].unshift(columns[0]); return result; } } diff --git a/src/shared/PDF-functions.ts b/src/shared/PDF-functions.ts index 0f9b45f..ae32b59 100644 --- a/src/shared/PDF-functions.ts +++ b/src/shared/PDF-functions.ts @@ -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 = {}; 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];