Home Projects Roadmap Blog GitHub Contact
Active Python · Desktop app · Automation

Jobalots Ingester

A local desktop app that turns a Jobalots invoice PDF into clean, verified stock rows in the sales tracker, so a won lot can be logged in minutes instead of being retyped by hand.

PythonTkinterPDF parsingExcelPyInstallermacOS

Objective

Remove the manual retyping involved in logging a won Jobalots lot: import the invoice, review and correct the items, and append them to the Excel sales tracker safely.

Current status

Version 1 is built and in real use: the first genuine invoice was added to the tracker with it on the day it was finished. It has also been packaged as a single standalone Windows executable that needs no Python install, with spreadsheet-specific settings moved into editable layout files so other workbooks can be supported without code changes or a rebuild. It now ships for both platforms from the same code: Windows v1.0.1 and a first macOS release, published on a private GitHub repo with separate release tags per platform.

Architecture

Invoice PDF (or zip) → table-cell parser → review & edit tree → layout-driven writer → Excel sales tracker (with backup)
StageRoleNotes
ImportReads one or more invoice PDFs or zips, or the newest downloadThe invoice is the downloadable manifest; sign-in stays manual in the browser
ParseExtracts each invoice line (title, SKU, quantity, prices)Line prices reconcile exactly with the invoice's net product value across all test invoices
ReviewEdit, change quantity, split, remove or add itemsLot cost is split evenly per unit, with leftover pennies assigned so totals still match
WriteAppends rows using a JSON layoutCopies row formulas and styling, and extends totals and summary formulas when rows are inserted

Completed work

  • Built a Tkinter desktop app covering the full flow: import, review and edit, preview, and append to the workbook.
  • Wrote an invoice parser based on PDF table cells, handling wrapped titles and suffix clean-up, and validated it against every sample invoice on hand.
  • Implemented the stock rules: one row per unit, even cost splitting for lots, and delivery logged as its own row, optionally switched off per invoice.
  • Added safe writing: it refuses to write while the workbook is open, takes a timestamped backup first, and warns on re-imports of invoices already added.
  • Packaged it as a one-file executable built through a script that runs the tests first and refuses to build if they fail.
  • Introduced JSON layout files that define the sheet, key column, end marker and per-column content, so other spreadsheets can be supported by configuration alone.
  • Added command-line diagnostics for checking an invoice or testing an append without opening the GUI.
  • Fixed packaging issues along the way, including a lazily-imported GUI module being skipped by the bundler.
  • Built a macOS app from the same code on the bare-metal Hackintosh, and verified parsing, writing (identical totals to Windows), the open-workbook check and the GUI layout there.
  • Adapted the open-workbook check for Mac Excel, which doesn't lock files the way Windows does, and worked around a dependency with no Intel-Mac build.
  • Fixed a bug found during Mac testing, where no spreadsheet was chosen, and shipped the same fix to Windows as v1.0.1.
  • Published to a private GitHub repo with Windows and macOS releases attached.

Risks and open items

  • The target tracker has pre-existing faults unrelated to the app: a broken delivery-cost reference on its summary sheet and an unfilled row-number column after a certain point.
  • Parsing is tuned to one invoice format, so a change in the supplier's PDF layout would need a parser update.
  • Rows cannot yet be traced back to the lot they came from.
  • The Mac build is Intel-only; Apple Silicon Macs run it under Rosetta.

Next actions

  1. Generate short item names automatically from the long marketplace-style titles.
  2. Pick up invoices straight from the browser's download folder as they land.
  3. Add a date or invoice column to the tracker so each row traces back to its lot.