Items
Columns are matched by header name. product and sold are required; model, serial, batch, months, customer, email, ref are picked up when present, and common aliases work. A row whose sale date is not a real date is reported and skipped, never stored — expiry is computed from it, so an item without one could never answer the question this register exists for. A duplicate serial is skipped too.