Commit Graph

44 Commits

Author SHA1 Message Date
ecedb11db4 Archivage projet ERP - etat final avant pause (2026-08-03)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-08-28 13:43:58 +03:00
673f816d99 feat(products): promotion smeta→product + OZ57 comparison script (SPEC-STD-2)
ProductPromotionService: validate source smeta, create DRAFT product, clone
smeta LOCKED via cloneSmeta (reused as-is), init ACTIVE pricings for MATERIAL
lines from default supplier, best-effort image copy. Route POST /products/
promote-from-smeta (WRITE_ROLES). 13 Vitest + 13 clone non-regression green.
compare-oz57-smetas.cjs: DB-driven comparison script for smetas 18 vs 25.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-02 23:04:06 +04:00
f0e1be1592 chore(trud): remove temporary debug script debug-pouzlovoy-structure.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 21:33:57 +04:00
7fbc7e8c98 backup: n8n workflows + pg dump 20260627_020001 2026-06-27 02:00:06 +00:00
30488ff007 feat(work-log): native work accounting system (SPEC-TRUD-3-DECOMPTE)
Worker model + WorkLog with 3 payment modes (PIECE/HOURLY/AREA),
anti-sur-décompte ceiling alerts (non-bloquant), production
verification workflow (PENDING→VERIFIED→actualLabor recompute),
9 REST endpoints, 18 Vitest tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 17:06:26 +04:00
fca75994b5 feat(labor-bareme): barème travail auto-généré au lancement commande (SPEC-TRUD-2)
6 enums + 2 modèles Prisma (LaborConfig singleton, OrderLaborOperation).
Cascade NODE_PRICE→PAINT_RATE→DEFAULT 50%, snapshot config, cost guard,
override MANUAL, split LABOR_NODE. 7 routes REST. Câblé orders.service.ts
IN_PRODUCTION L942-944. 19 Vitest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-11 16:25:05 +04:00
02d96070f4 feat(smeta): add per-node welding cost parser (SPEC-TRUD-1-PARSER-POUZLOVOY)
Parse ПОУЗЛОВОЙ РАСЧЕТ СЕБЕСТОИМОСТИ ТРУДОЗАТРАТ section from smeta Excel.
SmetaLaborNode model (23 fields), state machine parser, image extractor,
proximity photo matching. Non-regressive: smetas without section unaffected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-11 15:49:47 +04:00
dcfdb8f142 fix(expense-codes): make all expense codes fully editable + move З11→Д, З12→Ж
Remove frontend-only restrictions: code/groupCode fields now editable in edit mode,
delete button enabled for all codes (soft-delete only). Move З11 (Аренда склада)
to group Д (Ремонт и обслуживание) and З12 (Логистика склад) to group Ж
(Производство субподряд) per financial director request.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-11 12:36:08 +04:00
8de7a72dc5 backup: n8n workflows + pg dump 20260611_020001 2026-06-11 02:00:05 +00:00
2b527e6c9f feat(supplier-channels): supplier notification dispatch with channel resolution (SPEC-MAX-3A)
SupplierNotificationService resolves preferred channel (MAX/Telegram/email fallback),
dispatches anodin notifications via MaxOutboundMessage queue or existing senders.
Hooked into tender send() + addAndSendToSupplier() + PO sendPOEmail(). Idempotent
via SupplierNotificationLog unique constraint. 11 Vitest tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-10 20:29:34 +04:00
b09e3bda21 feat(max-relay): SPEC-MAX-2B ERP relay endpoints for MAX messenger
3 relay endpoints guarded by X-Relay-Secret (constant-time comparison):
- GET /max-relay/outbound — pending messages for relay to poll
- POST /max-relay/outbound/:id/ack — idempotent ack (SENT/FAILED)
- POST /max-relay/inbound — persist + auto-dispatch pairing codes via linkChatToSupplier (Spec 1)

Admin test endpoint POST /max-relay/test-enqueue (normal ERP auth ADMIN).
2 Prisma models: MaxOutboundMessage (PENDING/SENT/FAILED), MaxInboundMessage (processed flag).
16 Vitest tests (guard secret, idempotence ack, pairing dispatch, error resilience).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-10 14:42:38 +04:00
d8b990f9d2 feat(supplier-channels): SPEC-MAX-1 opt-in mapping canal fournisseur↔messager
Appariement fournisseur↔messager par code jetable (XXXX-XXX, 14j, usage unique).
Rattachement idempotent: même chatId+supplier=no-op, chatId lié à autre supplier=CONFLICT (jamais de double rattachement silencieux — test reine T-SC-06).

Backend: SupplierChannelLink + ChannelPairingCode modèles Prisma, MessagingChannel + PairingStatus enums, Supplier.preferredChannel, SupplierChannelsService (generateCode, linkChatToSupplier, setPreferredChannel, deactivateLink, revokeCode, expireStaleCodes), 7 REST endpoints /api/v1/supplier-channels, 16 Vitest. Frontend: SupplierChannelsSection (preferred channel, active links, pending codes, generate modal RU/FR), intégré SuppliersTab drawer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-10 14:02:22 +04:00
122b07a880 docs: session 148 rapports + artefact D1-D5 + CLAUDE.md update
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-29 20:07:29 +04:00
bdd819efd0 docs(router): email channel diagnostic — no bug, quiet hours behavior
EMAIL channel works correctly. The 5 EXPIRED from supervisor test
were emails successfully sent but unacked (terminal channel).
URGENT bypasses quiet hours (22h-7h UTC) and EMAIL sends fine.
No code fix needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-29 02:37:34 +04:00
11cc64698e test(supervisor): 10/10 detectors validated + cleanup complete
Seed 10 tagged cases (D1-D10), triggered via admin route in digest
mode: 10 AgentAction EXECUTED, 25 NotificationDelivery across 4
channels (ERP_IN_APP/PWA_PUSH/TELEGRAM/EMAIL). Escalation chain
validated. All test data cleaned up (81 rows deleted, 0 remaining).
Override function kept for future test runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-29 02:26:35 +04:00
97736390b1 test(supervisor): seed 10 test cases + override routing to Louis
- Override function in supervisorTick: routes all reminders to
  SUPERVISOR_TEST_TARGET_USER_ID when both env vars are set
- Seed script creates 10 tagged cases (D1-D10), one per detector
- Cleanup script deletes all tagged data + agent artifacts
- Tag: TEST-SUPERVISOR-280526

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-29 00:42:45 +04:00
6f9a99344a feat(engagement): SPEC-BLOC-1H — 25 E2E tests engagement + docs + rapport final BLOC-1
25 nouveaux tests Playwright (6 decisions + 5 reminders + 5 agenda + 4 router-admin + 5 pwa-cross).
3 bugs backend corriges (Prisma relation logs→log, CalendarConfig field mapping, seed options).
Documentation: MANUAL-VALIDATION-BLOC-1.md, cleanup-demo-engagement.sh, BLOC-1-RAPPORT-FINAL.md.
47/47 engagement E2E green, 0 regressions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-28 09:36:43 +04:00
f5e83cc6ea feat(engagement): SPEC-BLOC-1G — Migration supervisor + dashboard admin + cleanup legacy notifications
1G.1: 3 supervisor M2 producers (reminder/escalation/report) migrated to RouterService with feature flag ROUTER_USE_FOR_SUPERVISOR
1G.2: Soak report script (npm run router:soak-report) — 7-point analysis
1G.3: Admin dashboard NotificationDeliveriesTab (KPIs + filterable table + detail drawer)
1G.4: NotificationHelper dual-dispatch bridge (NOTIFICATION_HELPER_ROUTER flag, best-effort)
1G.5: Legacy /notifications sidebar + page removed, routes redirect to /agenda
1G.6: PushSubscription weekly cleanup cron (failureCount >= 5 OR stale > 90d)
1G.7: LEGACY-NOTIFICATIONS-DEBT.md documentation
1G.8: 10 Vitest tests (4 supervisor + 3 dual-dispatch + 2 feature flag + 1 cleanup)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-27 23:27:42 +04:00
dae0fa0544 feat(engagement): SPEC-BLOC-1F — PWA installable + Web Push + Auth HTTPOnly cookies
Auth: migrate JWT from localStorage to HTTPOnly+Secure+SameSite=Strict cookies.
Bearer header fallback preserved for Playwright E2E compatibility.
Refresh token in dedicated cookie (path=/api/v1/auth/refresh).

PWA: vite-plugin-pwa injectManifest, manifest with shortcuts+icons,
service worker (push/notificationclick/notificationclose handlers),
PwaInstallPrompt + NotificationOptInBanner contextual components.

Push: PwaPushAdapter activated with web-push library (VAPID),
auto-cleanup expired subs on 410/404, TTL/urgency per priority.
PushSubscriptionService + usePushSubscription hook + Settings UI.

5 Vitest tests PwaPushAdapter. 0 TS errors backend+frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-27 22:27:32 +04:00
7d99ca7f35 feat(engagement): SPEC-BLOC-1E — Multi-channel Outbound Router + frontend Engagement modules
RouterService multi-canal (ERP_IN_APP SSE, PWA_PUSH stub, TELEGRAM, EMAIL) avec quiet hours,
aggregation, escalation watchdog, ACK tokens HMAC. Frontend: Agenda, Decisions, Reminders pages.
52 Vitest, 0 erreurs TS.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-27 16:08:41 +04:00
31b8a11440 feat(engagement): SPEC-BLOC-1A — Foundation Prisma Engagement Layer
11 models (Task, Decision, Reminder, UserMemory, AgendaCalendarConfig,
EngagementAutoRule, NotificationDelivery + link/log/dependency tables),
17 enums, 10 Zod schemas for typed UserMemory categories, 8 auto-rule
seeds, auth hook for AgendaCalendarConfig on register, backfill script
for existing users, 12 Vitest tests green. Schema pushed to erp_local
and erp_test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-26 00:21:02 +04:00
b2c1ccbd98 feat(agent/m2c): weekly report distribution cron + admin UI tab
M2C.1: WeeklyReportDistributionService (orchestrate aggregate→commentary→mock distribute),
weekly-report.cron.ts (Monday 9:00 MSK, business day check, anti-duplicate 6d window),
POST /reports/:id/distribute (mock-only: logs recipients), GET /reports/recipients,
User.weeklyReportSubscribed field, WEEKLY_REPORT_ENABLED env var, 10 Vitest.

M2C.3: AgentReportsTab admin (table + drawer with react-markdown rendering,
KPI cards, download .md, regenerate commentary, distribute mock, archive/delete).

M2C.2 (email handler) intentionally NOT included — SMTP password rotation pending.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-25 12:54:26 +04:00
13cf51199f fix(agent): remove temperature param for Opus 4.7 + add M2B test script
Opus 4.7 API rejects the temperature parameter. Conditionally skip it
for opus models. Add E2E test script for weekly report M2B pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-22 18:56:22 +04:00
911d660b68 chore(comms): send Telegram username erratum to S109 BETA recipients
- ERRATUM-TG-BOTNAME-S109
- New: scripts/send-telegram-erratum-S109.ts
- Targets the 10 users who received an onboarding announcement today
- Uses shared email transporter (erp-bot@) and sendTelegramMessage helper
- Dry-run by default, --apply to execute

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-19 16:25:07 +04:00
274871a43a refactor(announcements): role-based template resolution + library partials (USER-ANNOUNCEMENT-FIX-S108)
Move 9 flat onboarding templates to library/ as Handlebars partials and create 8 role-based
templates that compose relevant partials per role. Server auto-resolves templateSlug from user
role for ONBOARDING category, with explicit override support. Script simplified to 1 email per user.
19 Vitest tests (15 updated + 4 new: T-ANN-16..19).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-19 11:04:06 +04:00
3c83004e0a feat(announcements): UserAnnouncement model + dual-channel send + 8 onboarding templates (USER-ANNOUNCEMENT-S108)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-19 10:20:29 +04:00
f1d9d88526 feat(seed): BETA-SEED-S107 — bootstrap scripts for VPS BETA opening
- seed-beta-users.ts: 7 users (1 per ERP role), bcrypt 12, idempotent by email
- seed-beta-demo-data.ts: 2 clients + 2 suppliers + 3 products ACTIVE (smeta LOCKED + 10 pricings)
- ADM_GENERAL absent from Role enum → mapped to USER
- All ДЕМО_ prefixed for visual identification
- Login test 7/7 PASS, re-run safe (password NOT overwritten)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-18 17:38:16 +04:00
1acadd82f1 feat: standard products catalogue + critical notifications + cancel cascade (STD-1A→CRIT-NOTIF-3)
Sessions 89-101: Product model + catalogue UI + pricing workflow + standard order auto-PO,
critical notification system (backend configs + frontend modal/banner + auto-ack + 11 E2E),
cancel order cascade (DRAFT PO cancel, CONFIRMED PO manual intervention, resolveIntervention),
notification audit 7 fixes across 11 modules, 20 Vitest cancel tests, 160/160 E2E green.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-15 15:22:04 +03:00
bf37d7b05e feat(staging): add VPS staging seed (10 users + 8 clients + 7 suppliers + 10 orders + 20 PR + 20 audit + 59 help) (SEED-VPS-STAGING)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 18:39:58 +03:00
c1ce29c55e feat(help): add HelpArticle model + CRUD endpoints + 5 seeded articles (HELP-MODULE-P0)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-10 23:23:52 +03:00
51bda9310d chore(scripts): add ACTUAL-X-VERIF auto-check script
Fix update hook: recompute actuals when PAID entry amount/code changes
(not just on status transitions). 15/15 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 15:46:15 +03:00
db6c43424c chore(scripts): add ORDER-IMG-VERIF auto-check script
Bash script for VPS automated verification of S62/S63 specs:
- ORDER-IMG-1 backend (upload/reject/serve/delete)
- ORDER-IMG-2 smeta extraction (idempotence, manual override)
- INVOICE-DOC-SYNC (create/issue/cancel/delete + Document cascade)
- Screenshots UI (5 pages)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-29 12:13:14 +03:00
4027cf0ee9 feat(client-invoices): INVOICE-DOC-SYNC sync ClientInvoice with Document
- create() wraps in $transaction, creates Document INVOICE/CLIENT alongside
- update() propagates invoiceNumber change to Document title/reference
- issue() sets Document.sentAt
- cancel() sets Document.closedAt
- delete() removes Document before deleting ClientInvoice
- Backfill script for existing invoices (idempotent)
- Downgrade @fastify/static to v7.0.4 (Fastify 4 compat)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-29 11:33:59 +03:00
fa07cc658b backup: n8n workflows + pg dump 20260429_020001 2026-04-29 02:00:04 +00:00
8cd97ebff7 feat: PO-POSTPAY-AUTO — auto PaymentRequest on SDN sign + postpay modes
- PostpayMode enum (SIMPLE/PER_DELIVERY) on POPaymentSchedule
- isPostDelivery flag on POInstallment (auto-set at creation)
- SDN.sign() → triggerPostpayOnSdnSign: creates/recalculates PaymentRequest
  - SIMPLE: 1 PR per postpay installment, dueDate = signedDate + postDeliveryDays
  - PER_DELIVERY: 1 PR per SDN, amount = deliveredAmount × postpayPercent/100
- SDN.cancel() → rejects PENDING/APPROVED PRs, preserves PAID PRs
- Frontend: postpayMode Radio in PO drawer, "После отгрузки" tag on installments
- Rename УПД tabs: исходящие → Клиенты, входящие → Поставщики
- Backfill: 2 installments marked isPostDelivery=true

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-28 13:27:57 +03:00
3fbb92b2aa fix: FinancialTracking.budgetX × Order.quantity — 3 sites + backfill
Bug: budgetX stored per-unit smeta costs instead of totals, causing
absurd overrun percentages (7140% for qty=1700, 3831% for qty=100).

Fix 3 write sites:
- estimates.service.ts syncFinancialTracking: .mul(qty)
- financial.service.ts applyRevision: revision.delta*.mul(qty)
- revisions.service.ts applyRevisionToBudget: (smeta + deltas) * qty

financial.service.ts initFromSmeta was already correct (L36-40).
committedX/actualX from PO.totalAmount — already totals, no fix needed.

Backfill: 2 FTs corrected, alertLevel RED→NONE for both.
Script is one-shot non-idempotent (never re-run).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-28 11:23:57 +03:00
44635e4a04 feat: PO delivery date mandatory + planning UX fixes + backfill
- PO confirm: require expectedDeliveryDate for direct POs, auto-create
  lots+LotLines when confirming PO without any lots
- createLotsForPO: no longer skips items without requirementId, creates
  PurchaseLotLine records for each lot
- generateFromTender: pre-fill expectedDeliveryDate from offerDeliveryDays
- Frontend: disable confirm button without delivery date set
- Planning: diamond size d=7 for PDL forecasts (visually distinct from
  7×7 reception squares), fix empty status filter Validation error
- Backfill script: po-delivery-backfill.ts (2 POs fixed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 20:52:27 +03:00
c6eae3a77e fix(s53a-mig): step 1 reconstructs originalQuantity from POLine consumed
Two-pass backfill: cas 1 (non-consumed, origQty=qty) and cas 2
(consumed, origQty=qty+SUM(POLine.consumedQuantity) for active POs).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 17:28:25 +03:00
eb8c951b42 feat(s53a-mig): data migration script for PR lifecycle refactor
4-step migration: backfill originalQuantity, link POLines to PRs via lotLines,
create retro PRs for orphan POLines, merge residual PRs.
Dry-run by default, --apply for real execution. Idempotent.

Local DB results: 54 PRs backfilled, 4 retro PRs created, 4 residuals merged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 14:51:20 +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
d552cb32b5 fix: remove duplicate СРОЧНО priority — keep only Срочный (session 34)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:48:24 +03:00
3053cd32ad fix: align supplier tags with all MaterialCategory values + add specific service tags
- Added 8 specific service tags (LASER_CUTTING, TUBE_BENDING_SVC, etc.)
- Added PIPE_CUT to category_tag_mappings (was missing)
- Updated all 14 category mappings with both generic + specific tags
- Updated fallback categoryToTag in tenders.service.ts
- SQL migration script: scripts/fix-supplier-tags.sql

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:48:23 +03:00
f6e5d96796 fix: analyzeImpact matches PR by description instead of sourceId — fixes P0 quantity corruption and P1 mass ПОМЕНЯТЬ tag (session 34)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:48:17 +03:00
357017f706 feat: add spec_32b module (auto-pipeline) 2026-03-25 17:11:49 +00:00