Automatyczne oznaczanie opłaconych faktur w inFakt

Spis treści

Jeśli prowadzisz firmę i wystawiasz faktury, zapewne znasz ten ból – codzienne sprawdzanie, które faktury zostały opłacone i ręczne 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 – ręczne 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, że trzeba to robić codziennie, a czasem kilka razy dziennie. I jak człowiek się spieszy albo ma gorszy dzień, to się zdarza, że 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, że 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, że coś pominąłem. Wszystko dzieje się automatycznie w tle.

Jak samemu stworzyć taki work-flow w N8N?

Wymagania wstępne

Zanim zaczniemy, upewnij się że 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śli 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ę, że 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śli 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 ręcznie (Execute Workflow)
  3. Sprawdź każdy krok w podglądzie
  4. Upewnij się, że 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

Marek Golan

CEO Dogtronic, Prezes ESTA Cluster, dumny opiekun Borysa. Ma prawie 20 lat doświadczenia w branży IT zarówno jako programista jak i właściciel firm technologicznych.

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

1 × 3 =

Przekształć
swoje pomysły
w rzeczywistość

Skontaktuj się z nami i pozwól nam sprawdzić jak możemy Ci pomóc.

Najciekawsze treści na Blogu

Zobacz wszystkie
💬 Porozmawiaj z AI!
🎉 Świetnie! Zaraz nasz agent AI do Ciebie zadzwoni.
❌ Wystąpił błąd podczas wysyłania formularza. Spróbuj ponownie.

🤖 AI Agent

Hej! Zostaw swoje dane, a nasz inteligentny agent zadzwoni i pokaże Ci swoje możliwości. To tylko zajmie chwilę! 🚀

Imię jest wymagane
Wprowadź poprawny numer telefonu
Wprowadź poprawny adres email
Zgoda na przetwarzanie danych jest wymagana