import { beforeEach, describe, expect, it, vi } from 'vitest'; import { generateSzczegoly } from './Szczegoly'; import * as PDFFunctions from '../../../shared/PDF-functions'; import FormatTyp from '../../../shared/enums/common.enum'; import { TRodzajFaktury } from '../../../shared/consts/const'; import { Fa } from '../../types/fa3.types'; vi.mock('../../../shared/PDF-functions', () => ({ createHeader: vi.fn(), createLabelText: vi.fn(), createLabelTextArray: vi.fn(), createSection: vi.fn(), generateTwoColumns: vi.fn(), getContentTable: vi.fn(), getDifferentColumnsValue: vi.fn(), getTable: vi.fn(), getValue: vi.fn(), hasColumnsValue: vi.fn(), hasValue: vi.fn(), })); describe(generateSzczegoly.name, () => { beforeEach(() => { vi.clearAllMocks(); }); const mockFaVat: Fa = { FaWiersz: [], Zamowienie: { ZamowienieWiersz: [], }, RodzajFaktury: TRodzajFaktury.VAT, OkresFa: { P_6_Od: { _text: '' }, P_6_Do: { _text: '' }, }, P_1: { _text: '2024-01-01' }, P_1M: { _text: 'Warsaw' }, OkresFaKorygowanej: { _text: '' }, P_6: { _text: '2024-01-15' }, KodWaluty: { _text: 'PLN' }, KursWalutyZ: { _text: '' }, } as any; beforeEach(() => { vi.mocked(PDFFunctions.getTable).mockReturnValue([]); vi.mocked(PDFFunctions.createHeader).mockReturnValue(['header'] as any); vi.mocked(PDFFunctions.createLabelText).mockReturnValue('label' as any); vi.mocked(PDFFunctions.createLabelTextArray).mockReturnValue('labelArray' as any); vi.mocked(PDFFunctions.createSection).mockReturnValue('section' as any); vi.mocked(PDFFunctions.generateTwoColumns).mockReturnValue('columns' as any); vi.mocked(PDFFunctions.getContentTable).mockReturnValue({ content: null, fieldsWithValue: [], }); vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([]); vi.mocked(PDFFunctions.getValue).mockReturnValue('PLN'); vi.mocked(PDFFunctions.hasColumnsValue).mockReturnValue(false); vi.mocked(PDFFunctions.hasValue).mockReturnValue(false); }); it('should call createHeader with "Szczegóły"', () => { generateSzczegoly(mockFaVat); expect(PDFFunctions.createHeader).toHaveBeenCalledWith('Szczegóły'); }); it('should call createSection and return result', () => { const mockSection = 'section'; vi.mocked(PDFFunctions.createSection).mockReturnValue(mockSection as any); const result = generateSzczegoly(mockFaVat); expect(PDFFunctions.createSection).toHaveBeenCalledWith(expect.any(Array), true); expect(result).toEqual(mockSection); }); it('should call getTable for FaWiersz', () => { generateSzczegoly(mockFaVat); expect(PDFFunctions.getTable).toHaveBeenCalledWith(mockFaVat.FaWiersz); }); it('should call getTable for ZamowienieWiersz', () => { generateSzczegoly(mockFaVat); expect(PDFFunctions.getTable).toHaveBeenCalledWith(mockFaVat.Zamowienie?.ZamowienieWiersz); }); describe('P_6 label', () => { it('should use "Data otrzymania zapłaty" label for ZAL invoice', () => { const data = { ...mockFaVat, RodzajFaktury: TRodzajFaktury.ZAL, } as any; generateSzczegoly(data); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Data otrzymania zapłaty: ', data.P_6, FormatTyp.Date ); }); it('should use "Data otrzymania zapłaty" label for KOR_ZAL invoice', () => { const data = { ...mockFaVat, RodzajFaktury: TRodzajFaktury.KOR_ZAL, } as any; generateSzczegoly(data); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Data otrzymania zapłaty: ', data.P_6, FormatTyp.Date ); }); it('should use "Data dokonania lub zakończenia dostawy" label for other invoice types', () => { const data = { ...mockFaVat, RodzajFaktury: TRodzajFaktury.VAT, } as any; generateSzczegoly(data); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Data dokonania lub zakończenia dostawy towarów lub wykonania usługi: ', data.P_6, FormatTyp.Date ); }); }); describe('P_6 scope', () => { it('should generate P_6 scope when both P_6_Od and P_6_Do exist', () => { const data = { ...mockFaVat, OkresFa: { P_6_Od: { _text: '2024-01-01' }, P_6_Do: { _text: '2024-01-31' }, }, } as any; vi.mocked(PDFFunctions.hasValue).mockImplementation( (value: any) => value === data.OkresFa.P_6_Od || value === data.OkresFa.P_6_Do ); generateSzczegoly(data); expect(PDFFunctions.createLabelTextArray).toHaveBeenCalledWith([ { value: 'Data dokonania lub zakończenia dostawy towarów lub wykonania usługi: od ', }, { value: data.OkresFa.P_6_Od, formatTyp: FormatTyp.Value }, { value: ' do ' }, { value: data.OkresFa.P_6_Do, formatTyp: FormatTyp.Value }, ]); }); it('should generate P_6 scope when only P_6_Od exists', () => { const data = { ...mockFaVat, OkresFa: { P_6_Od: { _text: '2024-01-01' }, P_6_Do: { _text: '' }, }, } as any; vi.mocked(PDFFunctions.hasValue).mockImplementation((value: any) => value === data.OkresFa.P_6_Od); generateSzczegoly(data); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Data dokonania lub zakończenia dostawy towarów lub wykonania usługi: od ', data.OkresFa.P_6_Od ); }); it('should generate P_6 scope when only P_6_Do exists', () => { const data = { ...mockFaVat, OkresFa: { P_6_Od: { _text: '' }, P_6_Do: { _text: '2024-01-31' }, }, } as any; vi.mocked(PDFFunctions.hasValue).mockImplementation((value: any) => value === data.OkresFa.P_6_Do); generateSzczegoly(data); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Data dokonania lub zakończenia dostawy towarów lub wykonania usługi: do ', data.OkresFa.P_6_Do ); }); it('should not generate P_6 scope when both are empty', () => { vi.mocked(PDFFunctions.hasValue).mockReturnValue(false); vi.mocked(PDFFunctions.createLabelTextArray).mockClear(); generateSzczegoly(mockFaVat); const calls = vi.mocked(PDFFunctions.createLabelTextArray).mock.calls; const p6Call = calls.find((call) => call[0].some((item: any) => item.value?.includes('Data dokonania lub zakończenia')) ); expect(p6Call).toBeUndefined(); }); }); describe('ceny labels', () => { it('should add "netto" label when P_11 exists in FaWiersz', () => { vi.mocked(PDFFunctions.getTable).mockReturnValue([]); vi.mocked(PDFFunctions.hasColumnsValue).mockImplementation((column: string) => column === 'P_11'); generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Faktura wystawiona w cenach: ', 'netto'); }); it('should add "netto" label when P_11 exists in ZamowienieWiersz', () => { vi.mocked(PDFFunctions.getTable).mockReturnValue([]); vi.mocked(PDFFunctions.hasColumnsValue).mockImplementation((column: string) => column === 'P_11'); generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Faktura wystawiona w cenach: ', 'netto'); }); it('should add "brutto" label when P_11 does not exist', () => { vi.mocked(PDFFunctions.getTable).mockReturnValue([]); vi.mocked(PDFFunctions.hasColumnsValue).mockReturnValue(false); generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Faktura wystawiona w cenach: ', 'brutto'); }); it('should add currency code label', () => { vi.mocked(PDFFunctions.getTable).mockReturnValue([]); generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Kod waluty: ', mockFaVat.KodWaluty); }); it('should not add ceny labels when FaWiersz or ZamowienieWiersz exist', () => { vi.mocked(PDFFunctions.getTable).mockImplementation((field: any) => { if (field === mockFaVat.FaWiersz) return [{}]; return []; }); vi.mocked(PDFFunctions.createLabelText).mockClear(); generateSzczegoly(mockFaVat); const calls = vi.mocked(PDFFunctions.createLabelText).mock.calls; const cenyCall = calls.find((call) => call[0] === 'Faktura wystawiona w cenach: '); expect(cenyCall).toBeUndefined(); }); }); describe('P_12_XII label', () => { it('should add OSS label when P_12_XII exists in FaWiersz', () => { vi.mocked(PDFFunctions.hasColumnsValue).mockImplementation((column: string) => column === 'P_12_XII'); generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Procedura One Stop Shop', ' '); }); it('should add OSS label when P_12_XII exists in ZamowienieWiersz', () => { vi.mocked(PDFFunctions.hasColumnsValue).mockImplementation((column: string) => column === 'P_12_XII'); generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Procedura One Stop Shop', ' '); }); it('should not add OSS label when P_12_XII does not exist', () => { vi.mocked(PDFFunctions.hasColumnsValue).mockReturnValue(false); vi.mocked(PDFFunctions.createLabelText).mockClear(); generateSzczegoly(mockFaVat); const calls = vi.mocked(PDFFunctions.createLabelText).mock.calls; const ossCall = calls.find((call) => call[0] === 'Procedura One Stop Shop'); expect(ossCall).toBeUndefined(); }); }); describe('kurs waluty labels', () => { it('should add currency rate from KursWalutyZ when exists', () => { const data = { ...mockFaVat, KodWaluty: { _text: 'EUR' }, KursWalutyZ: { _text: '4.50' }, } as any; vi.mocked(PDFFunctions.hasValue).mockImplementation( (value: any) => value === data.KodWaluty || value === data.KursWalutyZ ); vi.mocked(PDFFunctions.getValue).mockImplementation((value: any) => value === data.KodWaluty ? 'EUR' : '' ); generateSzczegoly(data); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Kurs waluty wspólny dla wszystkich wierszy faktury', ' ' ); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Kurs waluty: ', data.KursWalutyZ, FormatTyp.Currency6 ); }); it('should add currency rate from common KursWaluty when KursWalutyZ does not exist', () => { const data = { ...mockFaVat, KodWaluty: { _text: 'EUR' }, KursWalutyZ: { _text: '' }, } as any; vi.mocked(PDFFunctions.hasValue).mockImplementation((value: any) => value === data.KodWaluty); vi.mocked(PDFFunctions.getValue).mockImplementation((value: any) => value === data.KodWaluty ? 'EUR' : '' ); vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([{ value: '4.50' }] as any); generateSzczegoly(data); expect(PDFFunctions.getDifferentColumnsValue).toHaveBeenCalledWith('KursWaluty', []); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Kurs waluty wspólny dla wszystkich wierszy faktury', ' ' ); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Kurs waluty: ', '4.50', FormatTyp.Currency6); }); it('should not add currency rate when KodWaluty is PLN', () => { vi.mocked(PDFFunctions.hasValue).mockReturnValue(true); vi.mocked(PDFFunctions.getValue).mockReturnValue('PLN'); vi.mocked(PDFFunctions.createLabelText).mockClear(); generateSzczegoly(mockFaVat); const calls = vi.mocked(PDFFunctions.createLabelText).mock.calls; const currencyCall = calls.find((call) => call[0] === 'Kurs waluty: '); expect(currencyCall).toBeUndefined(); }); it('should not add currency rate when multiple different rates exist', () => { const data = { ...mockFaVat, KodWaluty: { _text: 'EUR' }, KursWalutyZ: { _text: '' }, } as any; vi.mocked(PDFFunctions.hasValue).mockImplementation((value: any) => value === data.KodWaluty); vi.mocked(PDFFunctions.getValue).mockImplementation((value: any) => value === data.KodWaluty ? 'EUR' : '' ); vi.mocked(PDFFunctions.getDifferentColumnsValue).mockReturnValue([ { value: '4.50' }, { value: '4.60' }, ] as any); vi.mocked(PDFFunctions.createLabelText).mockClear(); generateSzczegoly(data); const calls = vi.mocked(PDFFunctions.createLabelText).mock.calls; const currencyCall = calls.find((call) => call[0] === 'Kurs waluty: '); expect(currencyCall).toBeUndefined(); }); }); describe('standard labels', () => { it('should add data wystawienia label', () => { generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Data wystawienia, z zastrzeżeniem art. 106na ust. 1 ustawy: ', mockFaVat.P_1, FormatTyp.Date ); }); it('should add miejsce wystawienia label', () => { generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith('Miejsce wystawienia: ', mockFaVat.P_1M); }); it('should add okres rabat label', () => { generateSzczegoly(mockFaVat); expect(PDFFunctions.createLabelText).toHaveBeenCalledWith( 'Okres, którego dotyczy rabat: ', mockFaVat.OkresFaKorygowanej ); }); }); describe('columns generation', () => { it('should call generateTwoColumns', () => { generateSzczegoly(mockFaVat); expect(PDFFunctions.generateTwoColumns).toHaveBeenCalledWith(expect.any(Array), expect.any(Array)); }); it('should distribute labels between two columns', () => { generateSzczegoly(mockFaVat); const calls = vi.mocked(PDFFunctions.generateTwoColumns).mock.calls; expect(calls.length).toBeGreaterThanOrEqual(1); const firstCall = calls[0]; expect(Array.isArray(firstCall[0])).toBe(true); expect(Array.isArray(firstCall[1])).toBe(true); }); }); describe('zaliczka czesciowa', () => { it('should generate zaliczka czesciowa table when data exists', () => { const data = { ...mockFaVat, ZaliczkaCzesciowa: [ { P_6Z: { _text: '2024-01-01' }, P_15Z: { _text: '1000' }, KursWalutyZW: { _text: '4.50' }, }, ], } as any; vi.mocked(PDFFunctions.getTable).mockImplementation((field: any) => { if (field === data.ZaliczkaCzesciowa) return [ { P_6Z: { _text: '2024-01-01' }, P_15Z: { _text: '1000' }, KursWalutyZW: { _text: '4.50' }, }, ] as any; return []; }); vi.mocked(PDFFunctions.getContentTable).mockReturnValueOnce({ content: null, fieldsWithValue: [], }); vi.mocked(PDFFunctions.getContentTable).mockReturnValueOnce({ content: { table: 'zaliczka' } as any, fieldsWithValue: ['P_6Z'], }); generateSzczegoly(data); expect(PDFFunctions.getContentTable).toHaveBeenCalledWith( expect.arrayContaining([ expect.objectContaining({ name: 'P_6Z', title: 'Data otrzymania płatności' }), expect.objectContaining({ name: 'P_15Z', title: 'Kwota płatności' }), expect.objectContaining({ name: 'KursWalutyZW', title: 'Kurs waluty' }), ]), expect.any(Array), 'auto' ); }); it('should not generate zaliczka czesciowa when data is undefined', () => { const data = { ...mockFaVat, ZaliczkaCzesciowa: undefined, } as any; const contentTableCalls = vi.mocked(PDFFunctions.getContentTable).mock.calls.length; generateSzczegoly(data); expect(vi.mocked(PDFFunctions.getContentTable).mock.calls.length).toBe(contentTableCalls); }); it('should not include zaliczka czesciowa when content is null', () => { const data = { ...mockFaVat, ZaliczkaCzesciowa: [ { P_6Z: { _text: '' }, }, ], } as any; vi.mocked(PDFFunctions.getTable).mockImplementation((field: any) => { if (field === data.ZaliczkaCzesciowa) return [{ P_6Z: { _text: '' } }] as any; return []; }); vi.mocked(PDFFunctions.getContentTable).mockReturnValue({ content: null, fieldsWithValue: [], }); const section = generateSzczegoly(data); expect(section).toBeDefined(); }); }); describe('faktura zaliczkowa', () => { it('should generate faktura zaliczkowa table when data exists', () => { const data = { ...mockFaVat, FakturaZaliczkowa: [ { NrKSeFFaZaliczkowej: { _text: 'FA001' }, }, ], } as any; vi.mocked(PDFFunctions.getTable).mockImplementation((field: any) => { if (field === data.FakturaZaliczkowa) return [ { NrKSeFFaZaliczkowej: { _text: 'FA001' }, }, ] as any; return []; }); vi.mocked(PDFFunctions.getContentTable).mockReturnValueOnce({ content: null, fieldsWithValue: [], }); vi.mocked(PDFFunctions.getContentTable).mockReturnValueOnce({ content: { table: 'faktura' } as any, fieldsWithValue: ['NrKSeFFaZaliczkowej'], }); generateSzczegoly(data); expect(PDFFunctions.getContentTable).toHaveBeenCalledWith( expect.arrayContaining([ expect.objectContaining({ name: 'NrFaZaliczkowej', title: 'Numery wcześniejszych faktur zaliczkowych', }), ]), expect.any(Array), 'auto', [0, 4, 0, 0] ); }); it('should not generate faktura zaliczkowa when data is undefined', () => { const data = { ...mockFaVat, FakturaZaliczkowa: undefined, } as any; const contentTableCalls = vi.mocked(PDFFunctions.getContentTable).mock.calls.length; generateSzczegoly(data); expect(vi.mocked(PDFFunctions.getContentTable).mock.calls.length).toBe(contentTableCalls); }); it('should not include faktura zaliczkowa when content is null', () => { const data = { ...mockFaVat, FakturaZaliczkowa: [ { NrKSeFFaZaliczkowej: { _text: '' }, }, ], } as any; vi.mocked(PDFFunctions.getTable).mockImplementation((field: any) => { if (field === data.FakturaZaliczkowa) return [{ NrKSeFFaZaliczkowej: { _text: '' } }] as any; return []; }); vi.mocked(PDFFunctions.getContentTable).mockReturnValue({ content: null, fieldsWithValue: [], }); const section = generateSzczegoly(data); expect(section).toBeDefined(); }); }); });