Automatyczne oznaczanie opłaconych faktur w inFakt

dogtronic.io 22 godzin temu

Jeśli prowadzisz firmę i wystawiasz faktury, prawdopodobnie znasz ten ból – codzienne sprawdzanie, które faktury zostały opłacone i manualne oznaczanie ich w systemie. Ja przez lata robiłem to samo, aż w końcu stworzyłem automatyzację, która robi to za mnie. Dziś podzielę się moim rozwiązaniem.

Problem – manualne oznaczanie faktur

Moja codzienna rutyna wyglądała tak:

  1. NestBank wysyłał mi maila w stylu: „Dzień dobry, dnia 01.07.2025 nastąpił wpływ 19500,00 PLN na konto BIZnest Konto 56187010452078105478980001, od Acme Spółka z ograniczoną odpowiedzialnością, tytułem 12/06/2025”
  2. Czytałem maila
  3. Logowałem się do inFakt
  4. Szukałem faktury 12/06/2025
  5. Weryfikowałem dane
  6. Oznaczałem jako opłaconą

Brzmi prosto? No właśnie. Problem w tym, iż trzeba to robić codziennie, a czasem kilka razy dziennie. I jak człowiek się spieszy albo ma gorszy dzień, to się zdarza, iż jakąś fakturę pominie. Efekt? Niepotrzebnie ruszamy proces windykacyjny do klienta, który już zapłacił. Niezręcznie.

Rozwiązanie – automatyczny workflow

Stworzyłem prosty workflow, który:

  • Automatycznie czyta maile od banku z powiadomieniami o wpłatach
  • Używa AI do wyciągnięcia kluczowych danych (numer faktury, klient, kwota)
  • Szuka pasującej faktury w bazie inFakt
  • Zmienia jej status na „opłacona” przez API
  • Wysyła mi powiadomienie, iż wszystko poszło OK

Czemu nie ma prostszej integracji?

Niestety, inFakt nie oferuje bezpośredniej integracji z NestBank. Gdyby oferował, pewnie bym z niej skorzystał.

Po co AI do parsowania maili?

Tu przyznaję się do lenistwa. Mogłem napisać regex’y do wyciągania danych z maili, ale:

  • AI radzi sobie z tym błyskawicznie
  • Nie muszę się martwić o różne formaty maili
  • Koszt API jest praktycznie niezauważalny przy tej skali
  • Jeśli bank zmieni format maila, wystarczy dostosować prompt

Jak wygląda workflow?

Na załączonym schemacie widać cały przepływ:

  1. Gmail Trigger – nasłuchuje na maile z odpowiednią etykietą
  2. Basic LLM Chain – AI parsuje treść maila i wyciąga dane
  3. Payment – formatuje dane do dalszego przetwarzania
  4. Get_invoices – pobiera listę niezapłaconych faktur z Google Sheets (musisz wcześniej zrobić integrację do pobierania FV z Infakt do Google Sheets)
  5. Check_if_paid – sprawdza czy znaleziono pasującą fakturę
  6. If – decyzja: znaleziono czy nie?
  7. Infakt_mark_as_paid – oznacza fakturę jako opłaconą przez API
  8. Send_notification – wysyła powiadomienie o sukcesie
  9. Mark_message_as_read – oznacza maila jako przeczytany

Czy warto?

Absolutnie tak. Jedna powtarzalna, irytująca czynność mniej. Zero pomyłek. Zero stresu, iż coś pominąłem. Wszystko dzieje się automatycznie w tle.

Jak samemu stworzyć taki work-flow w N8N?

Wymagania wstępne

Zanim zaczniemy, upewnij się iż masz:

  • Działającą instancję n8n (self-hosted lub cloud)
  • Konto Google z dostępem do Gmail i Google Sheets
  • Konto inFakt z dostępem do API
  • Konto OpenRouter (do AI) lub inny model LLM
  • Konto Mailgun (opcjonalnie – do powiadomień)

Krok 1: Przygotowanie Google Sheets

Najpierw potrzebujemy arkusza z listą faktur:

  1. Stwórz nowy arkusz Google Sheets nazwany np. „Faktury: [Twoja Firma] 2025”
  2. Stwórz arkusz o nazwie „Infakt”
  3. Dodaj kolumny:
    • ID – unikalny identyfikator
    • Numer faktury – np. „12/06/2025”
    • Nazwa klienta – pełna nazwa firmy
    • Kwota brutto – kwota faktury
    • Waluta – np. „PLN”
    • Status – „sent” lub „printed” (dla nieopłaconych)
    • uuid – UUID faktury z inFakt
    • Pozostało do zapłaty – kwota do zapłaty
Musisz stworzyć automatyzację, która będzie pobierała faktury z inFakt do Google Sheet. jeżeli nie wiesz jak to zrobić daj znać w komentarzu - dopiszę instrukcję.

Krok 2: Konfiguracja Gmail

  1. W Gmail (lub w innej poczcie z której korzystasz) stwórz nową etykietę np. „Wpłaty-Bank„
  2. Stwórz filtr, który automatycznie oznacza maile od banku tą etykietą
  3. Upewnij się, iż maile z powiadomieniami o wpłatach trafiają do tej etykiety

Krok 3: Tworzenie workflow w n8n

3.1 Gmail Trigger

  1. Dodaj node Gmail Trigger
  2. Połącz swoje konto Google (OAuth2)
  3. Skonfiguruj:
    • Poll Times: Every Minute
    • Filters → Label IDs: Wybierz swoją etykietę (np. „Wpłaty-Bank”)
    • Read Status: Unread

3.2 Basic LLM Chain (parsowanie maila)

  1. Dodaj node Basic LLM Chain
  2. Połącz z Gmail Trigger
  3. W polu Prompt wklej:
Z poniższego tekstu wyciągnij mi do formatu JSON: - invoice_number - client - paid_date - amount Przykłady odpowiedzi: - invoice_number: 15/06/2025 - client: ESTA CLUSTER - paid_date: 01.07.2025 - amount: 1230,00 PLN #Tekst do analizy: {{ $json.snippet }}
  1. Zaznacz Has Output Parser

3.3 OpenRouter Chat Model

  1. Dodaj node OpenRouter Chat Model
  2. Połącz z Basic LLM Chain (połączenie AI)
  3. Skonfiguruj credentials OpenRouter

3.4 Code node – formatowanie danych

  1. Dodaj node Code
  2. Nazwij go „payment”
  3. Wklej kod:
// Pobierz odpowiedź z LLM const llmResponse = $input.first().json.text // Usuń markdown formatting i sparsuj JSON const jsonString = llmResponse.replace(/```json\n?/, '').replace(/\n?```/, ''); const parsedJson = JSON.parse(jsonString); return [{ json: parsedJson }];

3.5 Pobieranie faktur z Google Sheets

  1. Dodaj 2 node’y Google Sheets:
    • Nazwij pierwszy: „get_invoices_printed”
    • Nazwij drugi: „get_invoices_sent”
  2. W obu skonfiguruj:
    • Document ID: ID twojego arkusza
    • Sheet Name: „Infakt”
    • Credentials: Twoje konto Google
  3. W „get_invoices_printed”:
    • Filters: Status = „printed”
  4. W „get_invoices_sent”:
    • Filters: Status = „sent”

3.6 Merge node – łączenie wyników

  1. Dodaj node Merge
  2. Nazwij go „un_paid_invoices”
  3. Połącz oba node’y Google Sheets do niego

3.7 Code node – sprawdzanie czy opłacona

  1. Dodaj node Code
  2. Nazwij go „check_if_paid”
  3. Wklej kod:
// Pobierz wszystkie items z un_paid_invoices const unpaidInvoices = $('un_paid_invoices').all(); // Pobierz payment data const paymentData = $('payment').first().json; console.log('Liczba nieopłaconych faktur:', unpaidInvoices.length); console.log('Szukana faktura:', paymentData.invoice_number); // Sprawdź każdy item z nieopłaconych faktur for (let i = 0; i < unpaidInvoices.length; i++) { const invoice = unpaidInvoices[i].json; console.log(`Sprawdzam fakturę ${i + 1}:`, invoice["Numer faktury"]); // Dopasuj numer faktury if (invoice["Numer faktury"] === paymentData.invoice_number) { console.log('Znaleziono dopasowanie!'); return [{ json: { found: true, invoice_id: invoice.ID, invoice_number: invoice["Numer faktury"], client_name: invoice["Nazwa klienta"], amount_due: invoice["Pozostało do zapłaty"], payment_amount: paymentData.amount, payment_date: paymentData.paid_date, matched_invoice: invoice } }]; } } // jeżeli nie znaleziono return [{ json: { found: false, searched_invoice: paymentData.invoice_number, searched_client: paymentData.client, available_invoices: unpaidInvoices.map(item => item.json["Numer faktury"]), message: "Nie znaleziono dopasowanej faktury" } }];

3.8 IF node – decyzja

  1. Dodaj node IF
  2. Skonfiguruj warunek:
    • Left Value: {{ $json.found }}
    • Operation: Boolean → is true

3.9 HTTP Request – oznaczanie w inFakt

  1. Dodaj node HTTP Request
  2. Nazwij go „infakt_mark_as_paid”
  3. Skonfiguruj:
    • Method: POST
    • URL: https://api.infakt.pl/api/v3/async/invoices/{{ $json.matched_invoice.uuid }}/paid.json
    • Headers:
      • Name: X-inFakt-ApiKey
      • Value: [TWÓJ_KLUCZ_API_INFAKT]
    • Body Type: JSON
    • JSON Body:
    json{ "paid_date": "{{ $json.payment_date.split('.').reverse().join('-') }}" }

3.10 Mailgun – powiadomienie

  1. Dodaj node Mailgun
  2. Nazwij go „send_notification”
  3. Skonfiguruj:
    • From Email: noreply@twojafirma.pl
    • To Email: twoj@email.pl
    • Subject: Faktura {{ $('check_if_paid').item.json.matched_invoice['Numer faktury'] }} została opłacona
    • HTML: (możesz użyć szablonu z przykładu)

3.11 Gmail – oznacz jako przeczytany

  1. Dodaj node Gmail
  2. Nazwij go „mark_message_as_read”
  3. Skonfiguruj:
    • Operation: Mark as Read
    • Message ID: {{ $('Gmail Trigger').first().json.id }}

Krok 4: Połączenia między node’ami

Połącz node’y zgodnie ze schematem:

  • Gmail Trigger → Basic LLM Chain
  • Basic LLM Chain → payment
  • payment → oba Google Sheets
  • oba Google Sheets → un_paid_invoices
  • un_paid_invoices → check_if_paid
  • check_if_paid → If
  • If (true) → infakt_mark_as_paid → send_notification → mark_message_as_read
  • If (false) → No Operation

Krok 5: Testowanie

  1. Wyślij sobie testowego maila z banku
  2. Uruchom workflow manualnie (Execute Workflow)
  3. Sprawdź każdy krok w podglądzie
  4. Upewnij się, iż faktura została oznaczona w inFakt

Krok 6: Aktywacja

  1. Kliknij przełącznik Active w prawym górnym rogu
  2. Workflow będzie teraz działał automatycznie co minutę

Wskazówki i rozwiązywanie problemów

Klucz API inFakt

Znajdziesz go w inFakt: Ustawienia → API → Wygeneruj klucz

Format daty

Zwróć uwagę na konwersję daty z polskiego formatu (DD.MM.YYYY) na format API (YYYY-MM-DD)

Debugowanie

  • Używaj console.log() w Code node’ach
  • Sprawdzaj zakładkę „Output” każdego node’a
  • Testuj na pojedynczych mailach

Różne formaty maili bankowych

Dostosuj prompt w LLM Chain do formatu swojego banku

Idź do oryginalnego materiału