Commit Graph

248 Commits

Author SHA1 Message Date
69aeab3626 refactor(planning): use S53A Option B link (PR→POLine→LotLine→Lot) instead of PR→Lot
All 3 planning query methods (getOverview, getProcurementTimeline,
getPositionsTimelineByCategory) now traverse via poLines relation
instead of the unreliable pr.lots path (which misses lots with
requirementId=NULL). Removes the orphan "PO-XXX — поставки" lane
and the 2nd-pass PO→lots workaround. Lot events are deduplicated
globally per category to prevent N× multiplication across PRs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 19:52:52 +03:00
4ad965bb03 fix(planning): remove duplicated PDL forecasts from category lanes + show PO lots as reception squares
Bug A: PlannedDeliveryLot (client delivery milestones) were injected into every
category lane, creating misleading orange diamonds on Лазер, Крепёж, etc.
Fix: keep PDL only on order-level timeline; remove from category and position levels.

Bug B: PurchaseLots with status=DELIVERED had no visible markers because receptions
were tracked via PurchaseLot.status, not PurchaseLineReception. Lots without
requirementId (linked via PO only) were invisible in the PR→lots query path.
Fix: emit reception_complete (green squares) for DELIVERED lots at category level
via PO→lots query; count DELIVERED lot quantities in progress/summary calculations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 19:13:14 +03:00
d340e8070d feat: SupplierDeliveryNote (УПД входящие) — reception-v2 workflow
- SupplierDeliveryNote model + enum DRAFT/SIGNED/CANCELLED in Prisma schema
- SDN service: create (atomic SDN + N receptions), sign (requires file, auto-verifies receptions), cancel (cascade)
- SDN routes: POST /, GET /, GET /:id, POST /:id/sign, POST /:id/cancel
- Guard on receptions.verify: refuses without linked signed УПД
- Receptions no longer auto-verify on create (ACHETEUR role) — verification goes through SDN sign
- Frontend: API client, UpdIncomingTab in Документооборот hub, SDN creation modal in PO drawer
- ReceptionsSection shows УПД column + "Оформить УПД" button alongside legacy "Приёмка без УПД"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 19:01:30 +03:00
115266ad6d feat(planning): add PlannedDeliveryLot forecasts + reception squares on timeline
- Backend: enrich getOverview, getProcurementTimeline, getPositionsTimelineByCategory
  with PlannedDeliveryLot events (type=forecast_delivery, CANCELLED filtered server-side,
  FULLY_SHIPPED colored grey, PLANNED/PARTIALLY_SHIPPED orange)
- Frontend OrderTimelineLane: orange diamonds for forecasts, green squares for receptions
- Frontend ExpandedOrderRow: include forecast events in collapsed category summary lanes
- Tooltips show label + status + date for forecast markers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 18:39:33 +03:00
5c408db03a fix: PO line finalPrice in all 4 creation paths + tender budget column + variance rounding
- createFromTender: add finalPrice from offer lines (was missing entirely)
- generateFromTender batch path: add finalPrice
- Tender drawer: add "Бюджет (смета)" column showing unit price × qty
- Budget drawer: round variance percentage to integer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 18:19:53 +03:00
4507a9883e fix: PO line prices — estimatedPrice=smeta, finalPrice=offer award price
awardLines/partialAward/generateFromTender now set estimatedPrice from
PR.estimatedPrice (smeta) and finalPrice from offer unitPrice (tender).
Also adds estimatedPrice to tender requirement selects and renames
Счёт-фактура → Счёт на оплату in PO drawer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 17:47:11 +03:00
9d4bed05c7 fix(s53a): set originalQuantity at every PR creation point
All 9 purchaseRequirement.create/createMany calls were missing
originalQuantity, causing it to stay null. consume() then set
quantity to 0 with no way to recover the original value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 17:23:14 +03:00
54ffcc91b0 feat(s53a): refactor PR lifecycle — unified consume/restore/revise, POLine FK, cascade cancel
- Prisma: PurchaseRequirement.originalQuantity, PurchaseOrderLine.purchaseRequirementId + consumedQuantity
- New PrMutationService with consume/restore/revise (centralizes all PR quantity mutations)
- tenders.service: awardLines/partialAward use prMutation.consume (no more residual PR creation)
- tenders.service: cancel cascades to PO cancel with line-by-line restore
- purchase-orders.service: cancel accepts opts.tx, restores PRs via consumedQuantity (Option B)
- purchase-orders.service: all create methods set purchaseRequirementId + consumedQuantity on POLines
- smeta-revision.service: ADDITIONAL_COST revises existing PR instead of creating "Доп:" duplicate
- planning/purchases/indirect: use originalQuantity ?? quantity for total calculations
- Eliminated: residual PR creation, notes contains pattern, fragile text matching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 14:51:12 +03:00
90dd68c879 feat(planning): expandable category lanes with position-level timelines
Backend: new endpoint GET /overview/:orderId/category/:category/positions-timeline
returning per-PurchaseRequirement timeline events (reception_partial, reception_complete).
Enriched getProcurementTimeline with per-category summary (firstEvent, lastEvent, counts).

Frontend: +/− toggle on category lanes, folded=2 summary markers with tooltip,
expanded=individual position lanes via CategoryPositionsLanes component.
SessionStorage persistence. Half-circle SVG marker for partial receptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 12:28:29 +03:00
bf3c2b0713 fix(s48): set contractTermId in legacy generateAdvanceInstallmentsForOrder
Aligns legacy generator with new syncOnSmetaLock to prevent future
installments from being orphaned from their contract term, which would
cause syncOnSmetaLock match-and-merge to create duplicates on next
smeta lock event. regenerateForOrder delegates to this method so all
3 call sites (Order.create, linkContract, changeContract) + admin
endpoint are covered by this one-line fix.

Manual backfill applied to existing data:
- UPDATE client_installments SET contract_term_id = 1 WHERE id = 34;
  (Order 4, regenerated via admin endpoint during S48 validation)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 11:15:07 +03:00
c69cf3279b feat(s48): syncOnSmetaLock hook — match-and-merge installments at smeta lock
New method OrderInstallmentsGenerator.syncOnSmetaLock() called from both
approveTechnical() and approve() in EstimateService. For each non-SHIPMENT_DATE
contract term, it creates or updates ClientInstallment with the correct amount
(selling_price × qty × percent). Handles paid > new (skip + audit log) and
ambiguous duplicates (skip + notification). Existing regenerateForOrder() and
all its call sites are untouched.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 11:03:50 +03:00
3f25fbc420 feat(s47-kpi-1): fix Cashflow KPIs to include ClientInstallment with anti-duplicate logic
- GET /cashflow/income-kpis returns income7d + overdue with breakdown
- income7d: CashflowEntry INCOME (excluding client/order linked) + ClientInstallment remaining
- overdue: ManualEntry1C DZ + ClientInstallment overdue remaining (amount - paid)
- Frontend: fetchCardData() uses new endpoint, overdueKpi state replaces dashboard-only source
- UTC date handling for @db.Date Prisma comparison

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 23:50:57 +03:00
0719d504a1 feat(s46-pdl-4.4): non-blocking duplicate warning on CashflowEntry INCOME with client/order
GET /cashflow/duplicate-check endpoint checks ClientPaymentReceived and
ClientInstallment within ±30d window and ±10% amount tolerance. Frontend
shows warning Alert in payment modal when type=INCOME and orderId set,
debounced at 500ms via Form.useWatch. Warning is non-blocking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 23:27:28 +03:00
7f5114e16c fix(forecast): SHIPMENT_SIGNED matching prefers forecasts linked to same PlannedDeliveryLot
handleShipmentSigned now prioritizes forecast candidates whose plannedLotId
matches the delivery lot's plannedLotId before falling back to date proximity.
Prevents orphan forecasts from being matched instead of PDL-specific ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 23:15:31 +03:00
ea3e4e748a feat(s46-pdl-4.3): PlannedDeliveryLot selector in UPD create form
Backend: plannedLotId added to create/update DeliveryLot schemas with
validation (same order, status not CANCELLED/FULLY_SHIPPED).
Frontend: PDL Select in УПД modal with auto-preselect when single active lot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 23:03:47 +03:00
492d6dace5 feat(s46-pdl-2): ForecastGenerator wired on PlannedDeliveryLot for SHIPMENT_DATE multi-lot
- computeExpectedDate: uses plannedLot.plannedDate as base for SHIPMENT_DATE
- handleOrderCreated: 1 forecast per PDL per SHIPMENT_DATE term, amount proportional to lot quantity
- handleSmetaLocked: recalculates with lot quantity ratio
- PlannedDeliveryLotsService: regenerateForecasts hook on create/update/cancel/delete
- Migration script: preserves REALIZED, backfills plannedLotId on manual forecasts, regenerates 3 orders

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 22:03:04 +03:00
d396f555d7 refactor(s46-pdl-1.5): rename planned_amount → amount_snapshot with physical total semantics
- Prisma: plannedAmount → amountSnapshot (nullable Decimal)
- Schema: added quantity (Decimal, default 1) and sortOrder (Int, default 0)
- Service: computeAmountSnapshot = sellingPrice × order.quantity (full order total)
- Backfill: 2 existing PDLs recalculated from SHIPMENT_DATE portion to full total

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 22:02:54 +03:00
0091e16204 feat(s46-pdl-1): PlannedDeliveryLot model + CRUD + default lot hook + backfill
- Prisma: PlannedDeliveryLotStatus enum (PLANNED/PARTIALLY_SHIPPED/FULLY_SHIPPED/CANCELLED)
- Prisma: PlannedDeliveryLot model with relations to Order, DeliveryLot (1:1), ForecastInstallment
- Prisma: plannedLotId FK on DeliveryLot (@unique) and ForecastInstallment
- Service: CRUD + cancel + delete + createDefaultLotForOrder (auto from contract SHIPMENT_DATE terms)
- Routes: 6 endpoints under /api/v1/planned-delivery-lots (READ: ADMIN+FIN+OPS+COMMERCIAL+COMPTABLE, WRITE: ADMIN+FIN+COMMERCIAL)
- Hook: OrderService.create() creates default PDL before forecast generation
- Backfill: 2 existing orders backfilled with planned lots

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 21:28:33 +03:00
41e8f444d8 feat(s46-pdl-3): SHIPMENT_SIGNED phase closes forecast→installment loop on UPD sign
- Add SHIPMENT_SIGNED to ForecastTriggerPhase enum
- Add contractTermId FK on ClientInstallment (+ index + backfill)
- ShipmentInstallmentsGenerator stores contractTermId at creation
- ForecastGeneratorService.handleShipmentSigned: match forecast→installment
  by contractTermId (strong) or date proximity (degraded), mark REALIZED
- DeliveryLotsService.sign() calls SHIPMENT_SIGNED phase after installments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 21:07:57 +03:00
47d8578563 feat(planning): add endpoint to list POs by order and material category
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 17:52:57 +03:00
dea891105f feat(calendar): add holidays API (public read + admin CRUD)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 17:32:40 +03:00
722954776a fix(planning): emit PO events in procurement-timeline endpoint
PurchaseOrders linked via clientOrderId now generate lot_ordered,
lot_planned and lot_delivered events in categoryLanes, grouped by
POLine.material. Only non-CANCELLED, non-DRAFT POs are included.

Previously only PurchaseLot-based events appeared — POs created via
the tender workflow had no timeline representation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 16:29:39 +03:00
9033427d23 fix(steel-refs): deduplicate SteelReference, add @@unique, AI self-verification
- Delete old seed (Russian profileType labels) causing weight duplicates
- Consolidate to single seed: 69 entries, 9 canonical types (SQUARE_TUBE etc.)
- Add @@unique([profileType, section]) constraint to prevent duplicates
- findWeightPerMeter prefers CANONICAL_PROFILE_TYPES over legacy labels
- bulkImport blocks duplicate sections across different profileTypes
- AI offer parser: self-verification ±1₽ per line, ±10₽ total, server-side validateRawArithmetic

Root cause: tube 20x20x1.5 had weight 0.885 (old seed) vs 0.841 (correct ГОСТ)
causing 5% quantity/price error in KP analysis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 16:29:19 +03:00
91ccaa9c90 fix(planning): align OrderStatus filter with Prisma enum (11 values)
Zod schema had invalid values (CONFIRMED, DONE) causing 400 on status filter.
Replaced with all 11 actual OrderStatus enum values from schema.prisma.
Frontend now imports statusLabels/allStatuses from OrderStatusTag (DRY).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 00:56:49 +03:00
0146d94d40 fix(ts): eliminate all remaining downstream type errors from Order.constructor casts
Add explicit any types to query result variables and lambda params in 12 files
where as-any on Order select objects broke type inference. 52 errors → 0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 01:47:48 +03:00
e30639b24d fix(ts): resolve remaining downstream type inference errors from as-any casts
Cast order results to any in planning-overview, planning.service, orders.service,
orders.routes. Type Set<string> in tenders.service. Fixes VPS build.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 01:39:04 +03:00
44c37b6b63 fix(ts): resolve Order.constructor type conflicts across all modules + fix planning OrderStatus enum
Add `as any` casts to Order select/include objects in 36 files to work around
TypeScript conflict between Prisma's Order.constructor relation and JS built-in.
Fix planningOverviewQuerySchema to use actual Prisma OrderStatus enum values
(VALIDATED/LAUNCHED/DELIVERED/ARCHIVED) instead of invalid CONFIRMED/DONE/CANCELLED.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 01:34:52 +03:00
2b8bdf75bc fix(ts): resolve Order.constructor type conflicts in scripts + tenders
Cast selects with `as any` to work around Prisma's constructor property
collision with JS built-in constructor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 22:30:10 +03:00
f993e5330b feat(S42-PLANNING-1 P3): planning overview + category-notes + planning-fields
New GET /planning/overview with category matrix (5+OTHER), timeline, flags.
New GET /planning/overview/:orderId/procurement-timeline for expanded view.
New CRUD for OrderCategoryNote (PUT/DELETE/GET on /orders/:id/category-notes).
New PATCH /orders/:id/planning-fields for inline editing (5 fields).
Smoke tests all pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 21:46:23 +03:00
a4814d9734 feat(S42-PLANNING-1 P2): receptions backend module + RECEPTION_DOC_MISSING cron
New CRUD module for PurchaseLineReception: create, verify, account, cancel, list.
Auto-VERIFIED when ACHETEUR creates. FIFO lot inference. Role-based access control.
RECEPTION_DOC_MISSING notification branch in file-tracking cron.
Fix pre-existing TS errors (Order.constructor conflict) in budget + file-tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 21:36:27 +03:00
a0be2c22e5 feat(purchase-orders): auto-migrate legacy JSON items to PurchaseOrderLine records
getById() now converts old items[] JSON entries to proper PurchaseOrderLine rows on first access.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 21:36:20 +03:00
e087bcc50c fix(tenders): AI parser tonnes→metres conversion + steel ref disambiguation
normalizeUnit() now strips superscripts and handles more Russian unit variants (т¹, тн, мп).
pickBestProfile() disambiguates when multiple steel references share the same dimension.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 21:36:14 +03:00
ad61572e5a refactor(backend): remove PIPE_CUT references (unused duplicate of LASER_TUBE)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 20:41:00 +03:00
6857abd9c7 refactor(smeta): remap 'Труборез' from PIPE_CUT to LASER_TUBE
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 20:40:11 +03:00
55c2099eef feat(S42M+S42F-ter): refonte hub УПД/Invoices + shift négatif + cartes améliorées
S42M: fix ContractsTab filtre CONTRACT+APPENDIX, enrichissement API documents
avec entités liées et statut paiement, refonte colonnes UpdTab/ClientInvoicesTab,
drawer détail UPD avec DocumentFilesSection.

S42F-ter: shift négatif autorisé (-365..+365), confirmation modale propagate+négatif,
cartes forecast avec montant principal, badge Получено, tooltip enrichi (Заказ, Остаток,
Триггер), ellipsis labels, bandeaux Alert dans modals link/backfill, bouton auto-match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 14:26:25 +03:00
804d90894e feat(S42-REBALANCE): rolling rebalance prévisionnel lors de la liaison УПД→prогноз
Ajout du mécanisme transactionnel de perequation automatique des écarts
entre montant attendu et réalisé sur le dernier prогноз non-lié du même
ordre+triggerPhase. Inversion auditable via ForecastRebalanceLog au unlink.
Modals frontend pour REBALANCE_NO_CANDIDATE et REBALANCE_NEGATIVE_REMAINING.
38/38 tests E2E passent (scénario "1000 chariots").

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 13:43:21 +03:00
2e568f79aa feat(S42F-bis): UX forecast + tooltip cashflow + aggregator reliquat partiel
Backend: fix aggregator partial installment residual (received + remaining contracted)
Frontend: timeline avec axe mois/semaines + bandes alternées + dates sous cards
Labels: Прогноз ДДС→Прогноз поступлений, По отгрузке→После отгрузки, enums russes
Fix: sync drawer après shift via query refresh (plus de date désynchronisée)
DB: Predoplata→Предоплата, По отгрузке→После отгрузки (10 rows)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 12:54:50 +03:00
0bcf5c3357 feat(S42K): file tracking — Documents sans fichier avec notifications automatiques
Prisma: FileTrackingConfig singleton + Document.lastFileReminderAt/fileReminderCount
Backend: FileTrackingService scan+notify, 4 endpoints REST, cron quotidien
Frontend: onglet Ожидают файла (table+filtres+badge), admin config page
Backfill script, 2 catégories notification DOCUMENT_TRACKING/_ESCALATED

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 12:35:40 +03:00
bca2327895 feat(S42H): intégration entrées clients dans cashflow forecast
- ClientIncomesAggregator: 3-source dedup (received > installment > forecast)
- GET /cashflow/forecast enrichi avec incomeBreakdown par semaine
- Frontend: tooltip CashflowTab avec 4 catégories (réalisé/contractuel/prévision/1C)
- Tests E2E: 18/18 passed, 14.97M ₽ client incomes intégrés

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 20:51:57 +03:00
19a551405f feat(S42L): multi-contrats par Order — sélection + modification
- POST /orders accepte contractId optionnel (explicit ou auto-detect)
- PATCH /orders/:id/contract unifié (change/link/unlink + guard paiements + audit)
- Frontend: Select contrat dans CreateOrderDrawer + Изменить договор modal
- Tests E2E: 18/18 passed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 20:43:35 +03:00
e6c03e8455 feat(delivery-lot): SIGNED_BY_CLIENT status + sign-by-client endpoint
- Enum: +SIGNED_BY_CLIENT dans DeliveryLotStatus
- Schema: +signedByClientAt DateTime? sur DeliveryLot
- Backend: signByClient() method + POST /:id/sign-by-client route
- Frontend: bouton "Подписан клиентом" (SHIPPED→SIGNED_BY_CLIENT)
- Tag vert pour SIGNED_BY_CLIENT, label "Подписан клиентом"
- regenerateInstallments accepte SIGNED_BY_CLIENT
- getShipmentRemaining inclut SIGNED_BY_CLIENT dans aggregate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 20:23:30 +03:00
219b644cee feat(delivery-lot): guard creation requires Order.IN_PRODUCTION
- Backend: check order.status === IN_PRODUCTION avant création УПД
- Frontend: bouton "+ УПД" grisé + tooltip si order pas IN_PRODUCTION

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 20:20:22 +03:00
0b0e92cb22 fix(DocumentFilesSection): versions modal + uploadedBy display
- Backend getVersions(): retourne {originalName, versions} au lieu d'un array brut
- Frontend uploadedBy: utilise .name (pas firstName/lastName qui n'existent pas)
- Type DocumentFile: corrigé uploadedBy shape

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 19:42:25 +03:00
db81759ae2 fix(document): direction CLIENT default + clientId propagation + auto-reference + sentAt
- delivery-lot direction: SUPPLIER → CLIENT (УПД émis vers client)
- clientId résolu depuis entity (direct ou via Order FK)
- documentReference auto depuis contractNumber/updNumber/invoiceNumber
- sentAt = now() à la création

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 19:38:52 +03:00
f41fb97198 feat(document): nested routes for 3 client cashflow entities
9 endpoints: GET/POST/DELETE for client-contracts/:id/documents,
delivery-lots/:id/documents, client-invoices/:id/documents.
Global listing now filters out soft-deleted documents.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 18:21:56 +03:00
08a5e36582 feat(document): EntityDocumentsService + autoTitle + soft-delete cascade
list/create/delete for Document attached to ClientContract, DeliveryLot,
ClientInvoice. Auto-titles from entity fields. Soft-delete cascades to
DocumentFile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 18:20:14 +03:00
d668d0226a feat(frontend): API client documents
listDocuments() with full filter support, reuses ContractDocument type.
Backend response aligned to PaginatedResponse shape (items, total, page, limit, totalPages).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 17:59:57 +03:00
46b18086d1 feat(documents): global list endpoint with full filters
GET /api/v1/documents — supports documentType (single or comma-separated),
direction, from/to dates, responsibleId, orderId, supplierId, clientId,
trackingOnly, search (title + reference), page, pageSize.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 17:59:09 +03:00
31aac851e2 fix(contract-tracking): remove hardcoded trackingStatus filter
Add trackingOnly query param (default false) so GET /api/v1/contract-tracking
returns all Documents when unset, and only tracked ones when trackingOnly=true.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 17:57:21 +03:00
9a8c9cf408 chore(s42f): polish + non-régression — 0 erreurs tsc backend+frontend
Fix: SALES_MANAGER → COMMERCIAL, client.name → client.companyName, orderWhere typé Prisma.OrderWhereInput. Backend + frontend tsc 0 erreurs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 17:22:58 +03:00