Commit Graph
15 Commits
Author SHA1 Message Date
MMD 5400588751 Merge pm (panel-based access, supervisor role) onto the restored RBAC base
Reverting 253c922 first made this merge small — only two conflicts:
- MobileTabBar: supervisor null-check combined with v7's /review hiding
- ArrivalsPage: pm's PM+supervisor scoping combined with v8's 3-way fetch
  (transfers) and its transfer-receive helpers, plus pm's canAccess gate
2026-10-01 15:36:57 +03:30
MMD 0ea0322967 Revert 253c922: restore the PM/RBAC work to the integration
Reverting the production revert so the pm branch can merge cleanly on
top of the restored RBAC base. Conflicts against newer integration work
resolved by combining:
- App.tsx: v7's bot-draft wizard bypass + login returnUrl kept alongside
  the supervisor gating (no-project block screen, panel scoping)
- LoginPage: returnUrl navigation kept, supervisor routing added
- migration.sql: bot_drafts table kept, unified-projects ALTERs restored
2026-10-01 15:24:56 +03:30
MMD a84b33dde3 Merge prod-v8 (multi-project allocation, inter-project transfers) into the all-branches integration
Conflicts (all keep-both):
- init_db.py: v7 added ensure_bot_drafts_table, v8 added
  ensure_project_transfers_table at the same anchor — both functions and
  both startup calls kept
- main.py: same, both ensure calls kept
- ChangeInventoryPage.canSubmit: v9's WITHDRAWAL branch and v8's
  PROJECT_TRANSFER branch — both validation branches kept
2026-10-01 15:05:09 +03:30
MMD fbd34277c0 Merge remote-tracking branch 'origin/prod-v7' into integration-all 2026-10-01 14:43:02 +03:30
Milad 4a3c226518 feat(org): panel-based access system replacing roles (procurement/inventory)
- new tables user_panels (panel: procurement/inventory/pm + level full/limited)
  and user_project_members (M:N membership, separate from pm responsibility)
- UserContext carries panels + member_project_ids; /users/me and the users
  list include them
- admin endpoints: PUT /users/{id}/panels, PUT /users/{id}/panel-projects
- inventory scope: panel inventory 'full' -> manager scope (all projects, NO
  stock change); 'limited' -> supervisor scope (own memberships, stock change
  allowed); legacy roles kept as migration fallback; admin untouched
- procurement writes: _procurement_writer is now panel-aware (admin, legacy
  procurement_manager, or procurement 'full') across all 18 write routers;
  quote CREATE additionally allows 'limited' users restricted to their member
  projects (validated server-side)
- frontend: panel-aware HomeRoute (inventory -> warehouse panel, procurement
  limited -> minimal RequesterHome), wizard project options restricted for
  limited users, change-inventory button/route gated to inventory 'limited',
  organization panel gains the panels & access-levels management section
2026-09-29 13:37:59 +03:30
whqreza d85ede7d11 feat(inventory): display all warehouse items on selection and track withdrawal recipient
- Show all available inventory items immediately when selecting a warehouse in withdrawal form
- Add vertical scrolling container with max height to prevent layout overflow for large item lists
- Add Material column to the inventory rows table for clear item identification
- Add required 'delivered_to' recipient field in withdrawal form with frontend validation
- Track delivered_to in database, models, schemas, and API
- Display recipient badge on withdrawal cards in daily control page
- Group daily control withdrawals by inventory ID and recipient
2026-09-28 22:54:02 +03:30
ZCode 253c922280 revert: restore production to the state before 730d0bd (PM/RBAC work moved to 'pm')
Their three commits (730d0bd, 5a9b543, 387edfb) reached production by push and
auto-deployed. 387edfb expects a users.username column that the live database does
not have, so POST /api/v1/auth/login was returning HTTP 500. Their schema changes
never applied either (projects still has only id, name, description, start_date,
pm_user_id, created_at), so nothing depends on the reverted code.

This commit sets the tree back to exactly a02b3ea — verified with git diff against
it — while keeping history linear: the work itself is preserved on 'pm' at 387edfb.
2026-09-26 17:41:07 +00:00
Milad 387edfb1ab feat(org,rbac): dedicate organization panel, enforce role permissions, subheader info, and fix supervisor project sync 2026-09-26 18:51:37 +03:30
whqreza b326cf64bf feat(inventory): implement inter-project material transfer backend
- Add ProjectTransfer database model and migration
- Implement project transfer service with immediate stock deduction on creation
- Support 100% full delivery receipt logic across destination warehouses
- Enforce canonical_specs_hash matching for cross-project stock merge
- Add RBAC guards and status lock on received transfers (409 Conflict)
- Register API router for transfers with on-the-way integration
2026-09-23 22:30:31 +03:30
whqreza 6ee0822a96 feat(drafts): add bot_drafts schema, automatic table bootstrap, and sync REST endpoints 2026-09-21 20:06:28 +03:30
MMD b6cbcc30a5 Merge prod_v5 (catalog v2.7, warehouse locking, per-project accept) into integration
Conflict in init_db.py resolved keeping the audit_log table ensure
function (new-one) — prod_v5 predates it and its side was empty.
Both sides' SQL lands: audit_log table plus the category-free materials
model.
2026-09-19 18:36:29 +03:30
whqreza 8adfd2267f refactor(catalog)!: decouple materials from categories (v2.7)
Materials are now global and category-free. The category lives only on the supplier (suppliers.category_id); every category-facing query goes through the supplier edge instead of the material row.

Schema (migration.sql + init_db DDL):
- drop the materials.category_id column, its FK, and the v2.5 first-link-wins automation (fn_derive_material_category + trg_supplier_materials_derive_category) — the DDL runs idempotently at API startup

Backend:
- GET /materials?category_id=… now filters via EXISTS(supplier_materials ⋈ suppliers.category_id)
- quote category filters (quotes list) use the quote's supplier category
- /pm/on-the-way derives the display category from the supplier of the quote
- supplier_materials links no longer derive/return a material category
- expand_service: material expand=category resolves to null (kept for contract compatibility)
- material create/update no longer validates or stores category_id; seed.py aligned

Frontend:
- material creation no longer sends category_id
- formatMaterialTitle reworked to a strict order with « . » separator: [Brand] . [Material] . [Spec 1] . [Spec 2], brand deduped when the stored name already starts with it; specs separator switched from « · » to « . »

Validated: python compile, api + frontend image builds (tsc + vite) clean; branch cut from the tip of prod_v4 (= origin/production, 5a9ef40 — the team's merge made them identical).
2026-09-19 13:19:26 +03:30
MMD e5d6c77c3c feat(data-safety): scheduled DB backups + audit trail + verified actor attribution
- db-backup sidecar: pg_dump -Fc of procurement+casdoor every
  BACKUP_INTERVAL_SECONDS into BACKUP_DIR, retention via BACKUP_KEEP_DAYS
- audit_log table (migration.sql + runtime ensure_audit_table) with
  model + transactional helper (utils/audit.record) — wired into user
  create/role-change and inventory transaction creation
- get_actor: quote_events.actor now stores the VERIFIED user's display
  name instead of the raw bearer token
2026-09-18 22:23:34 +03:30
ali_mohaghegh 8825f333a7 infra: single postgres instance (casdoor DB merged) + Traefik v3 edge
- remove the separate casdoor-postgres container; casdoor uses the main
  postgres (db casdoor, created by sql/02-casdoor-db.sql on fresh volumes);
  data migrated via pg_dump/pg_restore (backups kept outside the repo)
- Traefik v3.6 as the public edge (ports 80/443): docker provider pinned to
  the dedicated traefik_network (fixed-name network), host rules for
  app/api/auth/s3/storage (env-overridable, localhost defaults), frontend
  nginx demoted to internal SPA server; docker-compose.prod.yml adds real
  domains + Let's Encrypt + HTTP→HTTPS redirect (redirect middleware in
  infra/traefik-dynamic.yml)
- v3.6 required (Traefik <=3.3 fails against Docker Engine 29.x); socket
  mounted rw (Docker Desktop rejects :ro)
- start.ps1: app URL now http://localhost, casdoor + db notes
2026-09-01 17:28:33 +03:30
ali_mohaghegh c8a9b66395 feat(db): add v2.6 schema migration — global materials, supplier categories, inventory ledger, PM arrival flow, triggers 2026-08-25 19:08:13 +03:30