Case Study: Automatyzacja przetwarzania dokumentów logistycznych dla firmy FMCG - File to order
Wyzwanie
Europejska firma z branży FMCG działająca na polskim rynku poświęcała znaczną część czasu pracowników na ręczne przepisywanie dokumentów logistycznych do formatów wymaganych przez operatora 3PL — firmę Raben. Proces obejmował dwa kluczowe obiegi:
Zamówienia wychodzące — firma otrzymuje zamówienia zakupowe od swoich partnerów handlowych. Każdy partner wysyła zamówienia w zupełnie innym formacie: jedni jako arkusze Excel, inni jako pliki PDF, a jeden jako pliki tekstowe. Każde zamówienie musiało być ręcznie przepisane do ustandaryzowanego 48-kolumnowego szablonu Raben, zanim można było zaplanować wysyłkę.
Dostawy przychodzące — awiza dostawcze od dostawcy przychodziły jako dwujęzyczne dokumenty PDF o złożonej zagnieżdżonej strukturze: bloki produktów zawierające wiele partii, każda z własną datą przydatności i liczbą kartonów. Dane te musiały być przetworzone do 21-kolumnowego szablonu Raben.
Kluczowe problemy
- 25+ różnych formatów wejściowych — każdy partner handlowy stosuje własny układ dokumentu, nazewnictwo kolumn, identyfikatory produktów i formaty dat
- Ręczne tłumaczenie kodów SKU — kody produktowe klientów musiały być wyszukiwane w wewnętrznej matrycy, aby znaleźć prawidłowe kody magazynowe
- Rozpoznawanie adresów wielu magazynów — ponad połowa partnerów dostarcza do wielu centrów dystrybucji; prawidłowy identyfikator magazynu musiał być wyszukiwany ręcznie dla każdego zamówienia
- Przeliczanie ilości — niektórzy partnerzy raportują ilości w kartonach, inni w sztukach, co wymagało mnożenia dla każdego produktu
- Wysoki poziom błędów — ręczne przepisywanie setek linii produktowych dziennie prowadziło do częstych pomyłek
- Presja czasowa — terminy logistyczne wymagały przetworzenia zamówień tego samego dnia
Rozwiązanie
Zbudowałem aplikację w Pythonie, która w pełni automatyzuje oba procesy. Rozwiązanie ma dziś dwie wersje o wspólnym silniku parsującym: aplikację desktopową oraz wersję działającą w przeglądarce jako pojedynczy plik HTML. W obu przypadkach dokumenty są przetwarzane na komputerze użytkownika — żadne dane nie są wysyłane do zewnętrznych serwisów ani chmury.
Jak to działa
Użytkownik wrzuca pliki źródłowe do wyznaczonego folderu, klika jeden przycisk i w ciągu kilku sekund otrzymuje gotowy plik XLSX zgodny z szablonem Raben. Przetworzone pliki są automatycznie archiwizowane według daty.
Wewnętrzna logika aplikacji:
- Identyfikacja źródła — analiza struktury pliku, sygnatur zawartości i formatu w celu określenia, od którego z partnerów handlowych (lub dostawcy) pochodzi dokument
- Ekstrakcja danych — dedykowany parser dla każdego formatu odczytuje odpowiednie pola za pomocą dopasowywania wzorców, ekstrakcji tabel i logiki maszyny stanów
- Rozwiązywanie kodów produktowych — tłumaczenie identyfikatorów produktów specyficznych dla klienta na wewnętrzne kody SKU magazynu na podstawie matrycy danych master
- Rozwiązywanie adresów dostawy — dla partnerów z wieloma magazynami, system określa prawidłowy identyfikator magazynu Raben na podstawie adresu dostawy, wykorzystując wielopoziomowy mechanizm rozmytego dopasowywania (kody pocztowe, nazwy miast, kody magazynów, znormalizowane dopasowywanie tekstu)
- Generowanie pliku wyjściowego — zapis kompletnego, gotowego do przesłania pliku XLSX z wszystkimi wartościami stałymi, sekwencyjnymi numerami zamówień i przeliczonymi ilościami
- Archiwizacja — przeniesienie przetworzonych plików do folderów z datą; pliki z błędami trafiają do kolejki do weryfikacji
Wersja przeglądarkowa — narzędzie dla całego zespołu
Pierwotna wersja desktopowa wymagała zainstalowanego środowiska Pythona, co w praktyce zawężało krąg użytkowników do jednej osoby — a to właśnie uzależnienie od jednego specjalisty było jednym z problemów, które rozwiązanie miało usunąć. Dlatego przeniosłem cały silnik parsujący do przeglądarki: ten sam kod Pythona uruchamia się przez WebAssembly wewnątrz karty przeglądarki. Efektem jest jeden samodzielny plik HTML (ok. 0,5 MB), który wystarczy wysłać mailem lub wdrożyć go na dysku współdzielonym np. OneDrive.
- Zero instalacji i uprawnień administratora — plik otwiera się jak zwykła strona internetowa
- Obsługa przez przeciągnięcie — pliki wrzuca się do okna; można też wrzucić całą wiadomość e-mail (.eml/.msg), z której załączniki wyciągane są automatycznie, również z wiadomości przekazanych dalej
- Samodzielna aktualizacja danych master — matryca produktowa i baza adresów są wbudowane w plik, ale użytkownik może podmienić je w panelu bez udziału programisty; podmieniona wersja zostaje zapamiętana w przeglądarce
- Brak serwera i backendu — dokumenty nie opuszczają komputera; przez internet pobierane jest wyłącznie środowisko Pythona, raz, przy pierwszym uruchomieniu
Obie wersje korzystają z tego samego kodu parserów, więc każda poprawka czy nowy partner handlowy trafia jednocześnie do aplikacji desktopowej i do pliku przeglądarkowego.
Automatyczna kontrola dokumentów
Z czasem narzędzie przestało być wyłącznie konwerterem formatów i zaczęło sprawdzać treść dokumentów — wyłapuje rzeczy, które przy ręcznym przepisywaniu przechodziły niezauważone. Każde ostrzeżenie pojawia się jako wyraźny baner nad wynikiem, a plik wyjściowy powstaje zawsze: decyzję podejmuje człowiek.
- Niepełne kartony — zamówiona ilość nie dzieli się na całe kartony; komunikat podaje najbliższe poprawne wielkości
- Rozbieżność zamówione / wydane — awizo dostawcy zawiera obie kolumny; różnica jest raportowana wraz z brakiem wyrażonym w kartonach i sztukach
- Świeżość partii — dla każdej partii liczony jest pozostały okres przydatności na dzień wysyłki jako udział pełnego terminu ważności; poniżej 80% pojawia się ostrzeżenie z datami i liczbą dni
- Brakujący identyfikator magazynu — gdy adres dostawy nie pasuje jednoznacznie do żadnego wpisu w bazie, pole zostaje puste i wyraźnie zgłoszone; system nigdy nie zgaduje „najbliższego" magazynu
Wyzwania techniczne
Python w przeglądarce — przeniesienie działającej aplikacji desktopowej do WebAssembly wymagało uniezależnienia jej od systemu plików i doboru bibliotek mających kompilację WASM; bibliotekę do odczytu PDF trzeba było przypiąć do konkretnej wersji, ponieważ nowsze wymagają komponentu binarnego, który w przeglądarce nie działa. Interfejs, dane master i czcionki są wkompilowane w jeden plik wynikowy przez własny skrypt budujący.
Kryptograficzne dekodowanie PDF — system jednego z partnerów handlowych generuje pliki PDF z niestandardowym kodowaniem czcionek (CID), w którym znaki zastąpione są kodami numerycznymi. Standardowe biblioteki PDF zwracają nieczytelny tekst. Opracowałem technikę, która wykorzystuje znane wzorce tekstowe osadzone w dokumencie (ścieżki plików, numery zamówień) do automatycznej rekonstrukcji mapowania znaków — de facto metoda known-plaintext, która dekoduje dokument bez żadnej interwencji ręcznej.
Parser dwujęzycznych awiz dostawczych — dwujęzyczne awiza PDF mają zagnieżdżoną strukturę, gdzie pojedynczy produkt może obejmować wiele partii, każda z inną datą przydatności i ilościami wyrażonymi w kartonach zamiast sztuk. Parser wykorzystuje maszynę stanów do śledzenia kontekstu między wierszami i prawidłowo przelicza ilości sztuk z liczby kartonów i współczynników pakowania.
Inteligentne dopasowywanie adresów — system rozwiązywania adresów radzi sobie z realnymi problemami: polskie znaki diakrytyczne gubione przez ekstrakcję PDF (Wyszków → Wyszkow), wiele magazynów w tym samym mieście wymagające rozróżnienia po kodach magazynowych, kolizje między klientami, gdy różne firmy mają magazyny w tym samym mieście. Osobnym przypadkiem okazały się kolizje wewnątrz jednego klienta: gdy wszystkie hale sieci nazywają się tak samo, wspólna część nazwy mówi tylko, czyj to magazyn, a nigdy który. Dopasowanie opiera się więc wyłącznie na słowach różnicujących, a remis między dwoma wpisami traktowany jest jako świadoma odmowa dopasowania — lepiej zgłosić brak adresu niż po cichu wysłać towar do niewłaściwej hali.
Dwuprocesowy interfejs — przejrzysty układ z zakładkami pozwala pracownikom nietechnicznym przełączać się między przetwarzaniem zamówień wychodzących a dostaw przychodzących. Wbudowane zarządzanie numeracją, podgląd postępu i raportowanie błędów. Ten sam podział obowiązuje w wersji desktopowej i przeglądarkowej, więc przejście między nimi nie wymaga przyuczenia.
Rezultaty
| Wskaźnik | Przed | Po |
|---|---|---|
| Czas przetwarzania partii | 45–90 min (ręcznie) | Poniżej 10 sekund |
| Poziom błędów | Częste (ręczne przepisywanie) | Bliski zeru (automatyczna walidacja) |
| Obsługiwane formaty | Wymagana wiedza specjalistyczna | W pełni automatyczna identyfikacja |
| Bezpieczeństwo danych | Nie dotyczy | 100% przetwarzanie lokalne, zero ekspozycji w chmurze |
| Zależność od pracownika | Wymagany przeszkolony operator | Każdy członek zespołu może obsługiwać |
| Udostępnienie narzędzia | Instalacja środowiska na komputerze | Jeden plik HTML — wysłany mailem, otwierany w przeglądarce |
| Kontrola treści dokumentów | Braki i przeterminowany towar wychodziły na jaw w magazynie | 4 automatyczne kontrole przed wysłaniem pliku |
| Aktualizacja danych master | Wymagany kontakt z programistą | Użytkownik podmienia pliki samodzielnie w panelu |
Co się zmieniło
- Odzyskane godziny tygodniowo — to, co wcześniej pochłaniało znaczną część dnia koordynatora logistyki, teraz zajmuje sekundy
- Eliminacja błędów ludzkich — automatyczne rozwiązywanie kodów SKU i przeliczanie ilości usunęły najczęstsze źródło pomyłek
- Zniwelowanie tzw. 'wąskiego gardła' — wcześniej tylko jedna przeszkolona osoba mogła przetwarzać zamówienia; teraz każdy w zespole może kliknąć przycisk
- Narzędzie realnie dostępne dla zespołu — wersja przeglądarkowa zniosła barierę instalacji; przekazanie narzędzia kolejnej osobie albo zastępstwo na czas urlopu to wysłanie jednego pliku
- Wychwytywanie błędów po stronie dostawcy i klienta — rozbieżności między ilością zamówioną a wydaną oraz partie z krótkim terminem przydatności są zgłaszane zanim dokument trafi do operatora logistycznego
- Samodzielność w danych master — nowy produkt czy nowy adres magazynu użytkownik dodaje sam, bez czekania na zmianę w kodzie
- Skalowalność — zastąpienie skomplikowanego procesu, który podczas nieobecności głównego specjalisty generował błędy, prostą automatyzacją
- Odporność na zmiany — gdy dostawca zmienił układ swojego PDF, modularna architektura pozwoliła na celową poprawkę bez wpływu na resztę systemu
Technologia
| Element | Szczegóły |
|---|---|
| Język | Python 3.11+ |
| Interfejs | Tkinter (wersja desktopowa) oraz jednoplikowy interfejs HTML (wersja przeglądarkowa) |
| Środowisko przeglądarkowe | Pyodide / WebAssembly — Python 3 uruchamiany w karcie przeglądarki |
| Przetwarzanie PDF | pdfplumber |
| Obsługa Excel i poczty | openpyxl, xlrd, xlwt; odczyt wiadomości .eml i .msg (Outlook) |
| Architektura | Modularny pipeline z wymiennymi parserami, wspólny dla obu wersji |
| Skala | +25 parserów zamówień + 2 układy awiz dostawczych; dane master: ponad 300 pozycji produktowych i ponad 200 adresów magazynów |
| Wdrożenie | Aplikacja lokalna lub pojedynczy plik HTML — bez serwera, bez backendu, bez chmury |
| Bezpieczeństwo danych | Przetwarzanie wyłącznie na urządzeniu; dokumenty nie opuszczają komputera |
To rozwiązanie zostało zbudowane jako dedykowany projekt automatyzacji procesów biznesowych. Aplikacja — zarówno w wersji desktopowej, jak i przeglądarkowej — przetwarza dokumenty wyłącznie na sprzęcie klienta, co gwarantuje, że wrażliwe dane handlowe — ceny, wolumeny zamówień, relacje z klientami — nigdy nie opuszczają jego kontroli.