Lots and expiry dates, only where they matter
Turn them on per product. A tin of paint does not need a lot number; a pallet of yoghurt does, and the difference should not cost you two extra columns everywhere.
Each product carries two switches: lot required and expiry required. Stock of a product with those switches on cannot be registered without the data, which is what makes the field trustworthy later. Products without them stay simple.
On the way out, BasicInventory consumes the earliest expiry date first — FEFO — and falls back to first-in, first-out when there are no dates. That is the rule most food, cosmetics and pharmacy-adjacent businesses are supposed to follow, and doing it by hand in a spreadsheet is where the mistakes live.
The dashboard counts what expires within the next thirty days, and the stock list has an “expiring soon” filter, so the question “what do I need to move this week?” has an answer that takes one click rather than a sort and a squint.