Adcoar Ltd
← All posts

07 Aug 2026 · Adcoar News Editor

Case study: turning messy PDF rate sheets into clean, bookable data

A recurring problem for every tour operator we've worked with on Adcoar Tours: their pricing doesn't start out as data. It starts out as a PDF or an Excel sheet from an accommodation partner — laid out for a human to read at a glance, with merged cells, seasonal headers, and inconsistent formatting from one property to the next. Getting that into a system where a quote can be generated automatically means someone has to turn it into structured rows: property, room type, season, board basis, adult/child rate.

Done by hand, that's hours of repetitive, error-prone data entry every time a partner sends an updated rate sheet — which, in peak season, can be often.

The pipeline

Adcoar Tours' rate import tool handles this in a few stages, each one deliberately kept separate so a mistake at one stage doesn't corrupt the next:

  1. Upload. The operator uploads the PDF or XLSX rate sheet from a Filament page in their dashboard, which creates an import batch record to track the job.
  2. Extraction. A queued job hands the file to a Python script running in its own virtual environment, which parses the document's tables — PDF layout extraction and spreadsheet parsing are different enough problems that this stage does the heavy lifting in the language and libraries best suited to each format, rather than forcing one code path to do both badly.
  3. Staging. The extracted rows land in a staging table, not directly in the live rate catalog. Nothing the parser produces is trusted until a human looks at it.
  4. Review. The operator reviews the staged rows in their dashboard — catching the occasional merged-cell misread or an ambiguous season label — and approves what's correct.
  5. Promotion. Only approved rows get promoted into the live rate catalog that quotations and bookings actually read from.

Why the staging step matters more than the extraction step

It would be tempting to treat this as purely a parsing problem — get the extraction accurate enough and skip straight to updating live rates. We deliberately didn't build it that way. PDF table extraction is never going to be 100% reliable against real-world documents designed by dozens of different partners with no shared format, and a wrong rate that reaches a live quotation is a real cost to the operator's business, not just an annoying bug. The staging-and-review step means the tool's job is to make a human's review fast, not to make the human's judgement unnecessary.

That's the same principle behind a lot of what we build: automate the tedious part, keep a human decision at the point where being wrong actually costs something.

Where this shows up elsewhere

The shape of this problem — turning a document or feed meant for humans into clean data a system can act on, without silently trusting a lossy conversion — comes up constantly outside tour rate sheets too: bank statement reconciliation, supplier price lists, CSV exports from someone else's system. It's one of the more common requests behind the systems integration work we take on for other businesses now, precisely because we've already had to solve it properly once.