Categories are kept only as the label each supplier carries (suppliers.category_id
+ the material_categories list it points at). Everything that treated category as
a shared key across materials, inventory, quotes and unit conversions is removed —
including two features that were never populated (0 rows on every volume).
Removed (backend):
- routers category_attributes, category_ref_units, unit_conversions + registration
- ?category_id= filters on /materials, /inventory and /quotes (the /suppliers one
stays — it filters suppliers by their own label)
- GET /inventory/materials/options: required a category and had no caller
- the material-payload category derivation (expand_service.category_by_material,
the inventory serializer lookup) and the material category on /pm/on-the-way;
the wire keys stay, now always null, so the payload shape is unchanged
- startup DDL: DROP the empty category_attributes / category_reference_units /
unit_conversions tables (idempotent) and their CREATE statements; seed.py
truncate list updated
Removed (frontend):
- the category-keyed conversion path: refUnitForCategory / findConversion /
refConverted, the categoryUnits + unitConversions store slices, api clients,
hooks and the "≈ converted quantity" line on quote detail and project pages
(it needed rows in those tables to render, and there were none)
- material.supplier_category and its read sites (the edit modal grew one
yesterday to restore labels; the label lives on the supplier now)
- the inventory page's category chips, the row filter and the «دسته» column,
plus the lookup's categories fetch and catName helper
Kept: supplier label + its list and picker, /suppliers?category_id=, the global
standard_conversions feature and the units page (material_units conversions).
Verified against a restore of the production dump: startup DDL drops exactly the
three tables, suppliers keep their label (3/3), material_categories still serves
its 8 rows, the removed endpoints 404, and materials/inventory/quotes/units/
standard-conversions all return 200 with quote line items intact.
- procurement store refreshes right after a warehouse receipt (arrivals) and
after role/project changes (organization/admin), so the ledger reflects
warehouse actions immediately
- refetchOnWindowFocus enabled on the shared query client
- BroadcastChannel (lib/crossTab.ts): mutations broadcast 'quotes' /
'inventory'; all warehouse pages + the store hook resync open tabs
automatically (receipt in one tab updates the ledger in another)
- warehouse mutations (stock changes) notify other tabs; same-page refresh
behavior unchanged