← back to Eur Recrawl

parse_pricelist.py

63 lines

#!/usr/bin/env python3
"""
Parse the Osborne & Little INC April-2026 US trade price list (all brands) into
structured, colorway-aware trade prices. This is the authoritative cost source
for the whole EUR- universe (O&L, Nina Campbell, Designers Guild, Christian
Lacroix, + the rest of the list). retail = trade / 0.65 / 0.85 (x1.810).

Input : /tmp/oal_pl.txt  (pdftotext -layout of pdfs/myzt3fdy.1tk.pdf)
Output: prices.csv       (code, pattern, trade_price, collection, colorways, retail_x181)
"""
import re, csv, os

HERE = os.path.dirname(os.path.abspath(__file__))
SRC = "/tmp/oal_pl.txt"
MARKUP = 1 / 0.65 / 0.85  # 1.8100...

# CODE  PATTERN...  PRICE  COLLECTION  COLORWAYS  ...width/origin codes
LINE = re.compile(
    r'^\s*([A-Z]{1,5}\d{3,}(?:-\d+)?)\s+'   # 1 mfr code (W7907, PDG1107-01, PCL004, NCW4107...)
    r'(.+?)\s{2,}'                          # 2 pattern name (>=2 spaces before price col)
    r'(\d{1,4}\.\d{2})\s+'                  # 3 trade price
    r'([A-Za-z][\w&\' .-]*?)\s{2,}'         # 4 collection
    r'([\d]{1,3}(?:\s*,\s*[\d]{1,3})*)'     # 5 colorways (e.g. 01,03)
)

def main():
    rows, seen = [], set()
    for raw in open(SRC, encoding="utf-8", errors="replace"):
        m = LINE.match(raw)
        if not m:
            continue
        code, pattern, price, coll, cws = m.groups()
        price = float(price)
        if price <= 0 or price > 100000:
            continue
        colorways = [c.strip() for c in cws.split(",") if c.strip()]
        for cw in colorways:
            key = (code, cw)
            if key in seen:
                continue
            seen.add(key)
            rows.append({
                "code": code,
                "colorway": cw,
                "sku_code": f"{code}-{cw}",            # W7907-03 form (matches live mfr code)
                "pattern": pattern.strip(),
                "collection": coll.strip(),
                "trade_price": f"{price:.2f}",
                "retail_x181": f"{price * MARKUP:.2f}",
            })
    cols = ["code", "colorway", "sku_code", "pattern", "collection", "trade_price", "retail_x181"]
    with open(os.path.join(HERE, "prices.csv"), "w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=cols); w.writeheader(); w.writerows(rows)

    # validation: the canary W7907-03 must be trade 326.00 -> retail 590.05
    canary = [r for r in rows if r["sku_code"] == "W7907-03"]
    print(f"parsed price rows (code x colorway): {len(rows)}")
    print(f"distinct codes: {len(set(r['code'] for r in rows))}")
    print("CANARY W7907-03:", canary[0] if canary else "NOT FOUND")

if __name__ == "__main__":
    main()