Logistics Document Processing Automation for Raben 3PL
The Challenge
A European FMCG company operating in the Polish market spent a significant amount of employee time manually rewriting logistics documents into the formats required by their 3PL operator — Raben. The process involved two key workflows:
Outbound orders — the company receives purchase orders from its trading partners. Every partner sends orders in a completely different format: some as Excel spreadsheets, others as PDFs, and one as text files. Each order had to be manually retyped into Raben's standardized 48-column template before shipping could be scheduled.
Inbound deliveries — delivery advices from the supplier arrived as bilingual PDF documents with a complex nested structure: product blocks containing multiple batches, each with its own expiration date and number of cartons. This data had to be processed into Raben's 21-column template.
Key issues
- 25+ different input formats — each trading partner uses their own document layout, column naming, product identifiers, and date formats.
- Manual SKU translation — client product codes had to be looked up in an internal matrix to find the correct warehouse SKU codes.
- Multi-warehouse address resolution — over half of the partners deliver to multiple distribution centers; the correct warehouse ID had to be manually identified for each order.
- Quantity conversion — some partners report quantities in cartons, others in units, which required manual multiplication for every single product.
- High error rate — manually retyping hundreds of product lines a day frequently led to mistakes.
- Time pressure — logistics deadlines required same-day order processing.
The Solution
I built a Python application that fully automates both processes. The solution now ships in two versions sharing one parsing engine: a desktop application and a browser version delivered as a single HTML file. In both cases documents are processed on the user's own computer — no data is sent to external services or the cloud.
How it works
The user drops the source files into a designated folder, clicks a single button, and within seconds receives a ready-to-use XLSX file fully compliant with the Raben template. Processed files are automatically archived by date.
Internal application logic:
- Source identification — analyzing the file structure, content signatures, and format to determine which trading partner (or supplier) the document came from.
- Data extraction — a dedicated parser for each format reads the relevant fields using pattern matching, table extraction, and state machine logic.
- Product code resolution — translating client-specific product identifiers into internal warehouse SKUs based on a master data matrix.
- Delivery address resolution — for multi-warehouse partners, the system determines the correct Raben warehouse ID based on the delivery address using a multi-level fuzzy matching engine (postal codes, city names, warehouse codes, normalized text matching).
- Output file generation — writing a complete, ready-to-upload XLSX file populated with all constant values, sequential order numbers, and converted quantities.
- Archiving — moving processed files into date-stamped folders; files containing errors are sent to a verification queue.
Browser version — a tool the whole team can use
The original desktop version required an installed Python environment, which in practice narrowed the user base back down to a single person — the very specialist dependency the project set out to remove. So I moved the entire parsing engine into the browser: the same Python code runs through WebAssembly inside a browser tab. The result is one self-contained HTML file (about 0.5 MB) that can simply be e-mailed or dropped on a shared drive.
- No installation, no admin rights — the file opens like an ordinary web page.
- Drag-and-drop operation — files are dropped straight into the window; a whole e-mail (.eml/.msg) can be dropped too, and its attachments are extracted automatically, including from forwarded messages.
- Self-service master data — the product matrix and the address base are embedded in the file, but the user can replace them from a panel without involving a developer; the replacement is remembered by the browser.
- No server, no backend — documents never leave the computer; the only thing fetched over the internet is the Python runtime itself, once, on first launch.
Both versions run the same parser code, so every fix and every new trading partner lands in the desktop application and the browser file at the same time.
Automated document checks
Over time the tool stopped being a pure format converter and started checking what the documents say — catching things that slipped through unnoticed during manual retyping. Every warning appears as a prominent banner above the result, and the output file is always produced: the decision stays with the human.
- Partial cartons — an ordered quantity that does not divide into whole cartons; the message gives the nearest valid quantities.
- Ordered vs delivered mismatch — the supplier's delivery advice states both columns; any difference is reported together with the shortfall in cartons and units.
- Batch freshness — for every batch the remaining shelf life on the shipping day is calculated as a share of the full shelf life; below 80% a warning appears with the dates and the days left.
- Missing warehouse ID — when a delivery address does not unambiguously match any entry in the address base, the field is left empty and flagged; the system never guesses the "nearest" warehouse.
Technical Challenges
Python in the browser — moving a working desktop application to WebAssembly meant decoupling it from the file system and selecting libraries that have a WASM build; the PDF library had to be pinned to a specific version, because newer releases depend on a binary component that does not run in the browser. The interface, the master data and the fonts are compiled into a single output file by a custom build script.
Cryptographic PDF decoding — one trading partner's system generates PDFs with custom font encoding (CID), where characters are replaced by numeric codes. Standard PDF libraries returned unreadable gibberish. I developed a technique that uses known embedded text patterns (file paths, order numbers) to automatically reconstruct the character mapping — essentially a known-plaintext attack that decodes the document without any manual intervention.
Bilingual delivery advice parser — bilingual PDF delivery advices have a nested structure where a single product might span multiple batches, each with a different expiration date and quantities expressed in cartons instead of individual units. The parser utilizes a state machine to track context across rows and accurately calculates the unit quantities based on carton counts and packaging ratios.
Intelligent address matching — the address resolution system handles real-world data issues: Polish diacritics lost during PDF extraction (Wyszków → Wyszkow), multiple warehouses in the same city requiring disambiguation by warehouse codes, and cross-client collisions when different companies have warehouses in the identical city. Collisions within a single client turned out to be a category of their own: when every hall of a chain carries the same name, the shared part of that name only says whose warehouse it is, never which one. Matching therefore relies exclusively on discriminating words, and a tie between two entries is treated as a deliberate refusal to match — flagging a missing address beats quietly shipping goods to the wrong hall.
Dual-process interface — a clean, tabbed layout allows non-technical employees to easily switch between processing outbound orders and inbound deliveries. It includes built-in numbering management, progress tracking, and error reporting. The same split applies to the desktop and browser versions, so moving between them requires no retraining.
Results
| Metric | Before | After |
|---|---|---|
| Batch processing time | 45–90 min (manual) | Under 10 seconds |
| Error rate | Frequent (manual rewriting) | Near zero (automated validation) |
| Supported formats | Required domain expertise | Fully automated identification |
| Data security | N/A | 100% local processing, zero cloud exposure |
| Employee dependency | Trained operator required | Any team member can operate |
| Handing the tool over | Environment installed on the machine | One HTML file — e-mailed, opened in a browser |
| Document content checks | Shortfalls and short-dated stock surfaced at the warehouse | 4 automated checks before the file is sent |
| Master data updates | Required a developer | The user swaps the files in a panel |
What changed
- Reclaimed hours weekly — what used to consume a significant portion of the logistics coordinator's day now takes seconds.
- Elimination of human error — automated SKU resolution and quantity conversions removed the most common source of mistakes.
- Removal of specialist dependency — previously, only one trained person could process orders; now anyone on the team can click the button.
- A tool the team can actually reach — the browser version removed the installation barrier; onboarding another person, or covering for someone on leave, is a matter of sending one file.
- Supplier and customer errors caught early — mismatches between ordered and delivered quantities, and batches with a short remaining shelf life, are flagged before the document reaches the logistics operator.
- Self-sufficiency on master data — a new product or a new warehouse address is added by the user, without waiting for a code change.
- Scalability — adding a new trading partner only requires a new parser module; the rest of the pipeline functions automatically.
- Resilience to changes — when a supplier modified their PDF layout, the modular architecture allowed for a targeted fix without affecting the rest of the system.
Technology
| Component | Details |
|---|---|
| Language | Python 3.11+ |
| Interface | Tkinter (desktop version) and a single-file HTML interface (browser version) |
| Browser runtime | Pyodide / WebAssembly — Python 3 running inside a browser tab |
| PDF processing | pdfplumber |
| Excel and e-mail handling | openpyxl, xlrd, xlwt; reads .eml and .msg (Outlook) messages |
| Architecture | Modular pipeline with interchangeable parsers, shared by both versions |
| Scale | 25+ order parsers + 2 delivery-advice layouts; master data: 300+ product entries and 200+ warehouse addresses |
| Deployment | Local application or a single HTML file — serverless, backendless, cloudless |
| Data security | On-device processing only; documents never leave the computer |
This solution was built as a dedicated business process automation project. The application — in both its desktop and browser form — processes documents entirely on the client's own hardware, guaranteeing that sensitive commercial data — pricing, order volumes, customer relationships — never leaves their control.