Skip to content

feat: order numbers alongside tracking numbers, Stride Rite parser - #45

Merged
ljmerza merged 1 commit into
mainfrom
feat/order-numbers
Oct 21, 2026
Merged

ljmerza merged 1 commit into
mainfrom
feat/order-numbers

Conversation

@ljmerza

@ljmerza ljmerza commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Summary

A package can now carry the retailer order it belongs to, next to its tracking number:

  • order_number and order_link are optional package fields. link is still the carrier tracking page.
  • tracking_number stays the key, so stored packages, hidden numbers, services and live-status lookups are unchanged.

Card support: ljmerza/tracking-number-card (branch feat/order-numbers).

Changes

  • parsers_list.py: find_carrier() passes order_number/order_link through. It used to drop every key except tracking number, carrier, origin and link. Also registers the Stride Rite parser before generic.
  • coordinator.py:
    • Dedup priority: a store's parser beats a carrier's, which beats generic. A number seen in both a TCGplayer and a USPS email now shows retailer TCGplayer instead of USPS. Order fields and the earliest first_seen are merged in from the other duplicates.
    • Order-only entries: an entry where tracking_number == order_number is dropped once the same order has a real tracking number. Hidden tracking numbers count, so hiding the tracking number also hides the order.
    • Carry-forward: order fields are kept from the previous scan after the store's email ages out of the search window.
    • Generic fallback: the generic parser only runs on an email when no specific parser found anything in it. Before, it ran on every email, because its domain is ''.
  • parsers/tcgplayer.py:
    • Every package gets the order number and order-history link.
    • USPS/UPS numbers now link to the carrier instead of tcgp.shipment.co; shipment.co is kept for numbers no carrier pattern recognises.
    • Seller orders without tracking also set order_number, so they collapse into a tracking entry later.
  • parsers/stride_rite.py (new): parses the Shopify shipping email ("A shipment from order SR… is on the way"). It extracts the carrier tracking number, the SR order number and the "View your order" link. Before, only the generic parser picked these emails up, labelled "Generic".
  • scripts/run_parsers.py: mirrors the generic fallback, prints order numbers, and checks an optional expected.order_number.
  • Both READMEs: Stride Rite, a note on order fields, and the store-wins note on retailer.

Testing

  • python3 scripts/run_parsers.py → 35/35 fixtures pass. The fixtures are kept locally in the gitignored .data/.
    • Includes a new, trimmed Stride Rite shipping email.
    • Expected order numbers were added to the three TCGplayer fixtures (Direct, seller-shipped, Tracking Added).
  • A coordinator test with stubbed IMAP runs _fetch_and_parse_emails and _convert_to_packages: 14/14 checks pass. Against main, 8 of the 14 fail.
    • Stride Rite is not labelled Generic.
    • Store beats carrier, with the order merged and the earliest first_seen kept.
    • An order-only entry is dropped (also when the tracking number is hidden), and kept when it's alone.
    • Order fields carry forward.
    • Generic still catches unknown senders.
  • Ran live in Home Assistant against a real inbox. Stride Rite and a TCGplayer USPS package show the correct retailer, carrier link and order.
  • ruff check reports nothing new: the same 3 warnings as main.

Packages can now carry the retailer order they belong to:
- order_number / order_link are optional package fields. tracking_number
  stays the key, so stored packages and hidden numbers are unaffected.
- find_carrier() passes the order fields through (it used to drop every
  key except tracking_number/carrier/origin/link).
- Dedup prefers a store's parser over a carrier's over generic, so a
  number seen in both a TCGplayer and a USPS email shows retailer
  TCGplayer. Order fields and the earliest first_seen are merged in.
- An order-only entry (tracking_number == order_number) is dropped once
  the same order has a real tracking number, hidden ones included.
- Order fields are kept from the previous scan after the store email
  ages out of the search window.
- The generic parser only runs on an email when no specific parser
  found anything in it.

TCGplayer: every package gets the order number and order-history link.
USPS/UPS numbers link to the carrier instead of tcgp.shipment.co.

Stride Rite: new parser for the Shopify shipping email (carrier tracking
number, SR order number, "View your order" link). These emails were
previously only caught by the generic parser.

scripts/run_parsers.py mirrors the generic fallback, prints order
numbers, and can check an expected order_number.
@ljmerza
ljmerza merged commit 914cc44 into main Oct 21, 2026
4 checks passed
@ljmerza
ljmerza deleted the feat/order-numbers branch October 21, 2026 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant