Changelog

2026-08-23 – pojemność silnika w pojazdach

Dodatkowe pole kontraktu; brak zmian w strukturze.

  • engineCapacityCc w pojazdach. Żądania utworzenia i aktualizacji pojazdu akceptują opcjonalną pojemność silnika jako liczbę całkowitą w centymetrach sześciennych, a odpowiedź ze szczegółami oraz lista pojazdów ją zwracają. Pominięcie tego pola przy pełnej aktualizacji (pełne zastąpienie) czyści zapisaną wartość, dlatego należy przesłać ją ponownie, jeśli ma zostać zachowana.

2026-08-17 – locked raportuje teraz blokady dokumentów

Skorygowana semantyka wartości w istniejącym polu odpowiedzi; brak zmian w strukturze.

  • locked w odpowiedziach ze szczegółami i listą wpisów wcześniej raportowało tylko przestarzałą blokadę importu sprzed 2023 roku i miało wartość false dla dokumentów zablokowanych w aplikacji, w tym automatycznej blokady nakładanej przy wypłacie. Obecnie pole to przenosi ten sam pochodny stan blokady, który webhook entry.updated raportuje już w isLocked: true, gdy dokument jest zamknięty do zapisu. Należy interpretować to jako “ten wpis nie może być modyfikowany”, a nie jako znacznik konkretnego pochodzenia blokady.

2026-07-13 – identyfikatory miejsc, ręczne kursy wymiany walut, nadpisania diet, kierunek kursu wymiany

Dodatkowe, wstecznie kompatybilne pola kontraktu oraz nowy dyskryminator kursu wymiany walut.

  • Identyfikatory miejsc we wpisach. Żądania utworzenia i aktualizacji akceptują departureLocationPlaceId oraz destinationPlaceId (Google Places place_id), a odpowiedź dla wpisu je zwraca. Należy przesłać zapisane wartości ponownie przy pełnej aktualizacji (pełne zastąpienie), aby zachować tożsamość miejsca podczas edycji tekstu docelowego.
  • Kraj docelowy we wpisach. Żądania akceptują opcjonalny destinationCountryCode (ISO 3166-1 alpha-2). Po jego podaniu jest on zapisywany bezpośrednio, a zapasowe geokodowanie po stronie serwera jest pomijane.
  • Ręczne kursy wymiany walut. Żądania dotyczące wydatków i diet akceptują opcjonalny manualExchangeRate, a żądania dotyczące wpisów akceptują manualAdvanceExchangeRate dla zaliczki. Każdy z nich jest uwzględniany tylko wtedy, gdy dostawca kursów walut nie publikuje kursu dla daty referencyjnej; podanie go w sytuacji, gdy istnieje oficjalny kurs, skutkuje odrzuceniem żądania z błędem EXCHANGE_RATE_UNAVAILABLE.
  • Nadpisania diet. Żądanie dotyczące diety akceptuje overrideAmount oraz overrideReason, a modele odczytu diety je zwracają. Aby zachować istniejące nadpisanie przy pełnej aktualizacji (pełne zastąpienie), należy przesłać te wartości ponownie; ich pominięcie usuwa nadpisanie i przywraca stawkę ustawową wypłaty.
  • Kierunek kursu wymiany walut. GET /api/v1/reference/exchange-rates zawiera teraz dyskryminator direction: ForeignPerBase (HNB / ECB) oznacza, że należy podzielić przez kurs, aby przeliczyć na walutę bazową, a BasePerForeign (CNB) oznacza, że należy pomnożyć.

2026-07-08 – data wypłaty zaliczki, dostawca kursów walut dla CZ/SK

Dwie dodatkowe, wstecznie kompatybilne zmiany.

  • Data wypłaty zaliczki we wpisach. Żądania utworzenia i aktualizacji akceptują teraz opcjonalną advancePaymentDate (yyyy-MM-dd), a odpowiedź dla wpisu ją zwraca. W przypadku pominięcia przy tworzeniu, serwer domyślnie ustawia ją na datę wpisu. Określa ona datę kursu wymiany dla zaliczki oraz, w przypadku organizacji czeskich (tenants), referencyjną datę kursu wymiany dla diety.
  • Dostawca kursów walut dla CZ/SK. GET /api/v1/reference/exchange-rates dokumentuje teraz pełny zestaw dostawców: HNB dla HR, ECB dla SI i SK, CNB dla CZ. Pole source może mieć wartość "CNB", a baseCurrency to natywna waluta bazowa dostawcy (EUR dla HNB/ECB, CZK dla CNB). Zachowanie pozostaje bez zmian; dokumentacja odpowiada teraz rzeczywistemu działaniu systemu.

2026-06-11 – liczba posiłków, pochodzenie kursu wymiany, kod niedostępności kursu walut

Trzy dodatkowe zmiany w interfejsie. Wszystkie są wstecznie kompatybilne: dotychczasowe payloady działają bez zmian, a nowe pola odpowiedzi to dodatki, które można zignorować, dopóki nie będą potrzebne.

  • Liczba posiłków przy tworzeniu/aktualizacji diety. Żądania dotyczące diet akceptują teraz pola breakfastsProvided, lunchesProvided oraz dinnersProvided (liczba poszczególnych posiłków jako liczba całkowita) oraz opcjonalne dzienne pole mealsProvidedAllocation. Stanowią one kanoniczny model zapisu: serwer ponownie oblicza pomniejszenie diety na podstawie tych wartości. Dotychczasowe zagregowane pole mealsProvided z wersji v1 jest nadal akceptowane; w przypadku braku szczegółowych pól posiłków serwer mapuje agregat tak jak dotychczas, dzięki czemu starsi klienci nie odczują zmian. Odpowiedzi nadal zwracają wyliczone mealsProvided (obiad + kolacja, zgodnie z chorwackim Pravilnikiem) obok szczegółowej liczby posiłków, więc ścieżki odczytu pozostają bez zmian.
  • Pochodzenie kursu wymiany w odpowiedziach. Odpowiedzi dla wydatków i diet otrzymują pole exchangeRateSource, a odpowiedź dla wpisu otrzymuje pole advancePaymentExchangeRateSource, rejestrujące pochodzenie zastosowanego kursu: kod dostawcy ("HNB", "ECB") dla oficjalnego kursu, "MANUAL" dla kursu podanego przez użytkownika lub null dla wiersza w tej samej walucie (brak konwersji) bądź historycznego wiersza zapisanego przed wprowadzeniem śledzenia pochodzenia. Pola tylko do odczytu; brak zmian w żądaniach.
  • Nowy kod błędu EXCHANGE_RATE_UNAVAILABLE (HTTP 400). Występuje, gdy dostawca kursów walut organizacji nie publikuje kursu dla danej waluty w żądanym dniu i nie istnieje żaden kurs historyczny, którego można użyć jako zapasowego. Jest to błąd z rodziny walidacji ze standardową strukturą errors kluczowaną polami, co pozwala na precyzyjne odróżnienie przypadku niedostępności kursu i poproszenie o podanie kursu ręcznego. Dodano do katalogu błędów.

2026-05-23 – czasy przebiegu podróży w dietach zapisywane jako rzeczywiste UTC (poprawka)

Czasy diet zapisywane za pomocą POST /api/v1/travel-entries/{id}/per-diems/from-itinerary są teraz przechowywane jako rzeczywiste punkty w czasie UTC. Poprzednio odjazd/przyjazd dla każdego odcinka trasy był zapisywany przy użyciu czasu zegarowego oznaczonego jako UTC bez przesunięcia (odcinek o godzinie 08:00 czasu lokalnego był zapisywany jako 08:00Z zamiast 07:00Z/06:00Z), przez co wiersze wygenerowane na podstawie przebiegu podróży różniły się od wierszy dodanych ręcznie o 1-2 godziny i wyświetlały się z opóźnieniem. Schematy żądań i odpowiedzi pozostają bez zmian, ale wartości departureTime/arrivalTime zwracane przez ten endpoint (oraz zwracane przy późniejszych odczytach tych samych wierszy) odzwierciedlają teraz poprawiony punkt w czasie UTC. Bezstanowy podgląd kalkulatora nadal zwraca czasy zegarowe. Kwoty diet pozostają bez zmian.

2026-05-23 – kalkulator diet + zapis całej podróży

Interfejs obliczania diet został skonsolidowany i zyskał możliwość zapisu całej podróży, analogicznie do aplikacji webowej locco.

  • Nowy POST /api/v1/utilities/per-diems/calculate - bezstanowy kalkulator. Wyślij przebieg podróży (jeden odcinek = przebieg podróży z 2 punktami trasy) i otrzymaj obliczone wiersze z zastosowaną redystrybucją na poziomie przebiegu podróży. Brak kontekstu wpisu, nic nie jest zapisywane.
  • Nowy POST /api/v1/travel-entries/{id}/per-diems/from-itinerary - odbuduj diety wpisu na podstawie przebiegu podróży w jednym wywołaniu. Serwer ponownie uruchamia własny silnik dla punktów trasy (przesłane kwoty nigdy nie są traktowane jako zaufane), stosuje posiłki dla poszczególnych odcinków kluczowane przez (countryCode, departureTime) (pary zwracane przez kalkulator), a następnie atomowo zastępuje diety wpisu. Pozwala to na odtworzenie redystrybucji na poziomie przebiegu podróży oraz podwyższeń stawek krajowych, czego nie da się osiągnąć, przesyłając wiersze pojedynczo.
  • Usunięto POST /api/v1/travel-entries/{id}/per-diems/compute oraz POST /api/v1/per-diems/calculate-simple. Oba zostały zastąpione przez utilities/per-diems/calculate - pojedynczy odcinek to po prostu przebieg podróży z 2 punktami trasy. Należy przenieść integracje na nowy kalkulator.

2026-05-22 – obsługa rynku słoweńskiego

Wstępna obsługa słoweńskich organizacji (tenants). Zaktualizuj swojego klienta na podstawie odświeżonej migawki OpenAPI pod adresem /api-reference/:

  • Słoweńskie gminy - nowy GET /api/v1/reference/slovenian-municipalities zwraca listę gmin SURS dla rozwijanych list miejsc na słoweńskich formularzach podróży. Możliwość wywołania z poziomu dowolnej organizacji.
  • Rezydencja podatkowa pracownika - rekordy pracowników otrzymują pole residency (Resident / NonResident) na potrzeby raportowania słoweńskich diet i podatku od wynagrodzeń. Domyślna wartość to Resident.

2026-04-28 – uruchomienie wersji v1.0

Pierwsze stabilne wydanie partnerskiego API locco. Każdy obszar jest połączony, otypowany i objęty migawką OpenAPI pod adresem /api-reference/:

  • Wpisy - pełny CRUD oraz przejścia przepływu pracy (wyślij, zatwierdź, odrzuć, anuluj, zwróć do poprawy), z atomowym tworzeniem, które akceptuje zagnieżdżone wydatki, diety, alokacje miejsc powstawania kosztów oraz załączniki w jednym wywołaniu.
  • Załączniki - bezpośrednie przesyłanie do wpisu za pomocą POST /api/v1/travel-entries/{id}/attachments. Format multipart, do 5 plików na żądanie.
  • Webhooki - rejestracja subskrypcji z jednorazowym ujawnieniem klucza podpisywania (signing secret), historia dostarczeń dla każdej subskrypcji oraz endpoint ponawiania prób dla nieudanych lub wyczerpanych dostarczeń.
  • Wypłaty - lista wpisów gotowych do wypłaty, tworzenie paczek, lista historii, usuwanie paczki.
  • Pracownicy, Działy, Pojazdy, Miejsca powstawania kosztów - CRUD + lista, z wartościami pól niestandardowych dla pracowników.
  • Dane referencyjne - chorwackie gminy, kursy wymiany walut HNB, tabela stawek diet, listy dozwolonych krajów i walut włączone dla firmy.
  • Firma - odczyt profilu.

Wartości enum dla Status, TravelType, PayoutMethod i pozostałych są udokumentowane w schemacie OpenAPI jako listy dozwolonych wartości enum: [...], dzięki czemu wygenerowani klienci opierają się na kanonicznych ciągach znaków ("PendingApproval", "BankTransfer" itp.), a nie na niejasnych wartościach.