Commit Graph
8 Commits
Author SHA1 Message Date
whqreza b1edf6eed3 feat(inventory)!: lock warehouses permanently to their parent project
Warehouses now belong strictly and exclusively to the project they were created under; cross-project reassignment is removed end-to-end.

Backend: PATCH /inventory/warehouses/{id} no longer applies project_id — any attempt to move a warehouse to a different project returns 400 with «پروژه‌ی انبار قابل تغییر نیست — انبار برای همیشه به پروژه‌ی والدش تعلق دارد» (sending the current project stays a harmless no-op). The WarehouseUpdate schema documents project_id as accept-only-to-reject; creation still requires project_id and delete is unchanged.

Frontend: the Organization page's per-warehouse project dropdown («انتقال به پروژه دیگر») and its moveWarehouse handler are removed — warehouses render statically inside their project card with only the dashboard link and delete; the warehouses.update API type no longer accepts project_id. WarehousesPage already had no move UI (rename/describe only).

Verified end-to-end against the running stack: rename 200; same-project project_id no-op 200; cross-project reassignment 400 with the guard message; warehouse remains in its original project; test data cleaned up. python compile + api/frontend builds clean.
2026-09-19 14:32:46 +03:30
whqreza 1f16e44874 feat(pm): multi-project PMs (1:N) with project switching, scoping validation and org multi-select
Task 1 — PM 1:N + access-loss handling:
- projects.pm_user_id had no UNIQUE constraint (verified live + in schema); added a lookup index via init_db
- auth: UserContext.project_ids = every project of a PM (oldest first); project_id stays the first for compatibility
- GET /users/me/projects — assigned projects of the caller (drives the switcher + revocation validation)
- login / /users/me / /users list now return the full projects array per user
- /inventory/* and /pm/* scopes accept an explicit ?project_id=… and verify the PM manages it (403 otherwise); without the param they fall back to the first project; admin/manager use it as an optional filter
- POST /users/{id}/project is multi-aware: assigns one project (replacing that project's previous PM) and KEEPS the user's other assignments; null clears all
- PATCH /projects/{id} accepts pm_user_id (admin / procurement manager only)
- frontend: auth store holds projects + the active project (persisted via the existing localStorage store); RequirePmProjects re-validates on load, falls back when the active project was revoked, and shows a dedicated no-projects screen with logout (no redirect loop, no re-auth)
- Panels menu: «مدیریت انبار» gets a ChevronDown accordion listing the PM's projects with «✓ فعلی»; selecting one switches only the active project and reloads the section data
- inventory/pm API calls now send the active project_id explicitly

Task 2 — Organization page:
- new searchable ProjectMultiSelect combobox (chips with ×, live Persian filtering via normalize, assigned projects hidden) replaces the single select for PM users
- add = PATCH project pm_user_id=<user>; × = pm_user_id=null; table and project cards sync immediately; RBAC unchanged (role column admin-only, combobox editable for admin + procurement manager)

Verified locally: 17 scripted checks — multi-project assignment without unique conflicts, /users/me/projects, explicit project_id authorization (foreign project 403 on /inventory, /pm/on-the-way, /pm/receipts), PM blocked from pm_user_id changes, legacy assign endpoint keeps other assignments, revocation removes the project from the list, zero-project PM gets an empty list and a guarded inventory endpoint. All test data cleaned up afterwards.
2026-09-15 19:23:50 +03:30
whqreza b45a6cd033 fix(inventory): keep Organization page actions within mobile bounds
On /inventory/org two container rows could not shrink or wrap and
overflowed past the left edge on phones (RTL), forcing horizontal
scrolling:

- the add-warehouse form was a non-wrapping flex row of fixed-width
  inputs (w-44 + w-52) plus the button (~500px total); it now stacks
  vertically below sm (full-width fields and button) and returns to the
  inline layout at sm+
- each warehouse row's action cluster (dashboard / move-project select /
  delete) is now flex-wrap with justify-end, and the name block is
  flex-1 so a long select option can no longer push the buttons out of
  the card on narrow viewports

Desktop layout is unchanged; containerized rows stay within the page.
2026-09-08 16:04:02 +03:30
ali_mohaghegh e4ae34ddbc feat(sync): live cross-module cache invalidation (no manual refresh)
- 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
2026-09-03 15:00:58 +03:30
ali_mohaghegh ac76af2ffe feat(frontend): fulfillment split, API-driven topics, hub-and-spoke nav, stock-count modal, FOUND ceiling, semantic colors
- bug1: quote header fulfillment counter («رسید: X از Y قلم» amber / «تکمیل
  شد» green / «در راه»); expanded line items visually split into the
  received part (رسید شده ✓ + date + target warehouse from the receipt
  allocations) and the in-transit remainder — quantities always sum to the
  original line (invariant D holds, display-only split)
- bug2: 8-topic grids (suppliers/wizard/units) now come from
  /material-categories via the store (new lib/topics.ts; fixed the mismatched
  «ابزار و تجهیزات ساخت» label); suppliers topic->category resolution no
  longer falls back to an arbitrary category; duplicate month/status lists
  reuse the shared dictionaries; TopicGrid gained a loading EmptyState
- bug3: hub-and-spoke — the tab strip renders only on the warehouse
  dashboard; sub-views hide it and navigate back via «بازگشت به داشبورد»;
  «افزایش موجود» became the «تغییر موجودی» entry button
- bug4: stock count goes through a confirmation modal (current vs counted
  vs variance with کسری/مازاد badges) before posting STOCK_COUNT; numbers
  parsed defensively
- bug5: found qty is capped client-side (red input + inline warning, submit
  disabled) and backend returns 422 when exceeding the missing balance;
  fully-recovered losses drop off the pending list
- bug6+7: quantities render as absolute values with semantic color coding
  (emerald inflow / rose outflow / blue neutral) across dashboard timeline,
  daily control and the change-inventory form
2026-09-02 18:15:32 +03:30
ali_mohaghegh c5997ac243 feat(frontend): unified warehouse UI, calendar fix, partial receipts, RBAC views, admin panel, dev-mode 3-step
- header: icon box + dynamic subheader '[user] | [role] – [project/همه پروژهها]'
  on every warehouse page; module context kept in the hamburger (items 1-2)
- project manager view: office button + inline logout removed; hamburger
  contains only «خروج از حساب»; sub-views get «بازگشت به داشبورد» (Header
  backTo/goBack); «افزایش موجود» primary button on the dashboard (item 8)
- daily control: cells render the day-of-month (was the Jalali year),
  month nav uses real Jalali months, header is pure Jalali
  «امروز ۸ شهریور ۱۴۰۵», today gets a blue accent (item 3)
- arrivals: partial (item/qty) receipt — any valid item is enough to submit,
  ceiling + allocation-sum validation with inline errors, Received/In-Transit
  badges; ledger shows «رسیده X از Y» / «در راه Z» + «رسید جزیی» badge (item 4)
- api client: multipart uploads no longer send Content-Type json (fixes the
  invoice/proforma 400 «دادهی ارسالشده نامعتبر است»); undefined query
  params are dropped (fixes empty admin project filter, item 5)
- organization: user-creation card removed, role column read-only for
  procurement manager, Casdoor sync button (item 6)
- admin panel (/admin): Casdoor user sync + grant/revoke «مدیر تدارکات»;
  Developer Mode is a 3-step admin-gated flow on the login page (item 7)
2026-09-01 17:28:19 +03:30
ali_mohaghegh f48f3752af feat(org): user and PM management - list/define users, roles, project assignment (API + organization panel) 2026-08-27 15:04:24 +03:30
ali_mohaghegh 4e105c5cd5 feat(frontend): add React UI — procurement office, wizard, suppliers, inventory panel (dash port), role-based login 2026-08-25 19:08:15 +03:30