Commit Graph

66 Commits

Author SHA1 Message Date
e0b4e7f096 [CLAUDE] Docs: chốt session 4 — Budget BE module + 14 Solutions users
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s
- STATUS.md: header Phase 7 + 3 row Recently Done (Budget BE / 14 users / Docs cleanup) + cumulative cột mới (51 tables / 14 mig / ~124 endpoints)
- HANDOFF.md: TL;DR session 4 (2 milestone Budget BE + 14 users) + Cảnh báo session 5 + Priority 0 (FE Budget + PE/HD integration + PE feature gap) + Credentials 30 user
- migration-todos.md: Phase 7 thêm section D Budget done + Phase 8 mới (FE Budget pages + integration) + pending migrations Budget
- architecture.md: §10 Budget module mới (ERD + state machine + auto-recompute + integration roadmap)
- database/schema-diagram.md: migration history rows 13+14 + §12 Budget ERD chi tiết
- ef-core-migration SKILL: migration 14 entry + Phase 8 pending Budget refinement
- CLAUDE.md root + docs: modules table thêm Budget row + scope Budget + count 51 bảng / 14 mig
- Session log 2026-04-28-chot-session-4-budget.md (10+ section detailed)

Stats: 51 tables (+4 Budget), 14 migrations (+AddBudgets), ~124 endpoints (+11 Budget),
30 demo user (16 sample + 14 Solutions thật), 38 gotchas, ~340 LOC Budget CQRS.
FE Budget pages chưa làm — Priority 0 session 5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 12:36:31 +07:00
e65578a821 [CLAUDE] Docs: chot session 3 — PE polish iter 2 + domain rebrand + 5 gotcha moi
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m55s
User request: 'Chot lai toan bo MD de sang session moi'.

Session 3 (2026-04-24) — ~15 commit feat/fix PE module + domain migration:
 - Domain 3 subdomain huypham.vn → solutions.com.vn E2E live
 - PE rename 'Phuong An' → 'Giai phap' + backfill DB
 - Menu tree inheritance extend Pe_*/PeWf_*
 - Accordion mutex Pe_* + sidebar w-72 + label nowrap
 - NavLink queryMatches (fix 2 leaf cung highlight)
 - PE detail flat layout: Panel 2 = 4 section, Panel 3 + approvals/history
 - Upload file dinh kem per-NCC (SupplierAttachmentsCell) + Bang so sanh tong
 - readOnly mode menu 'Duyet' (pendingMe=1)
 - HD move Lich su dieu chinh → Panel 3
 - Demo email rebrand @solutionerp.local → @solutions.com.vn + BackfillUserEmailDomain

Docs updated (6 file):
 - STATUS.md: +9 row Recently Done session 3. In Progress tick 10+ done. Phase
   hien tai = 'UX polish hoan thien, UAT-ready'.
 - HANDOFF.md: TL;DR session 3 summary. Priority 0 = 3 task MISSING cuoi
   (Designer UI, Y kien 4 phong ban, Export PDF). Login email moi.
 - gotchas.md: +5 entry (#34 NavLink query, #35 menu inheritance extend,
   #36 Vite env rebuild, #37 PS 5.1 ASCII, #38 Identity rename 4 field) +
   checklist debug +5 entry.
 - ef-core-migration SKILL: migration 13 AddPurchaseEvaluationCodeSequences
   + Phase 6 update section (ComparisonTable enum + BackfillUserEmail).
 - skills/README: ef-core-migration 13 migration label updated.
 - docs/changelog/sessions/2026-04-24-chot-session-3-pe-polish.md: session log
   15 commit + bugs + stats + next priorities session 4.

Memory project_solution_erp.md: Phase 6 iter 2 DONE. Domain rebrand DONE.
Session 4 priority 3 PE gap remaining.

Stats: 47 DB tables (+1 MaPhieu seq), ~113 endpoint (+3 PE attachments),
13 migrations, 38 gotchas, ~85 commits total.
2026-04-25 00:37:30 +07:00
c48ac2116d [CLAUDE] PurchaseEvaluation: demo seed 4 phieu + MaPhieu atomic sequence + Pe_* perm defaults
Polish session tiep cua PE module skeleton (commit 2c6f0ca..3990066):
3 task A (MISSING in MVP) khac STATUS.md In Progress:

1. Demo PE data seed (SeedDemoPurchaseEvaluationsAsync)
   - 4 phieu varied A/B x phase: A-001 DangSoanThao (mo), A-002
     ChoCEODuyetNCC (winner+9 quotes), A-003 DaDuyet (chua tao HD,
     PaymentTerms JSON), B-001 ChoDuAn (5-step giua chung).
   - Idempotent: skip-if-[DEMO]-exists.
   - Approval history dung policy A (3-step) hoac B (5-step).

2. MaPhieu atomic sequence — Migration 13
   - Format PE/{YYYY}/{TypeLetter}/{Seq:D3} (vd PE/2026/A/001).
   - PurchaseEvaluationCodeSequence entity (Prefix PK).
   - IPurchaseEvaluationCodeGenerator + impl SERIALIZABLE
     transaction (mirror ContractCodeGenerator 1:1).
   - Replace Random.Shared trong CreatePurchaseEvaluationCommandHandler.
   - Migration AddPurchaseEvaluationCodeSequences (1 bang).

3. Pe_* permission defaults
   - SeedPurchaseEvaluationPermissionDefaultsAsync — 7 role business x 9 menu key.
   - Drafter/DeptManager/Procurement: R+C+U; CostControl/PM/Director/AuthorizedSigner: R+U.
   - DeptManager them Delete (xoa nhap).
   - Idempotent per-(roleId x menuKey).

Build: 0 error, 2 warning (pre-existing DocxRenderer).

Files: 4 new + 8 modified (1 migration + entity + generator + DI + 2 ctx + 2 features).

Resolves: STATUS.md In Progress §A — 3 item PE MISSING.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:41:17 +07:00
66c1a5c170 [CLAUDE] Rebrand: 3 domain huypham.vn → solutions.com.vn + migrate script
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m52s
User request: anh trỏ 3 subdomain mới về VPS IP 103.124.94.38:
  - api.huypham.vn        → api.solutions.com.vn
  - admin.huypham.vn      → admin.solutions.com.vn
  - user.huypham.vn       → eoffice.solutions.com.vn

Verified DNS: cả 3 resolve 103.124.94.38 ✓

Update 17 file repo:
FE (4): fe-admin/.env.production + fe-user/.env.production
        (VITE_API_BASE_URL → https://api.solutions.com.vn)
        fe-admin/src/lib/{api,realtime}.ts + fe-user equivalents (comment)
BE (1): appsettings.Production.json.example — CORS AllowedOrigins
CI/CD (1): .gitea/workflows/deploy.yml — smoke test URL
Scripts (3): setup-iis-sites (DomainApi/Admin/User), setup-ssl (3 host),
             deploy-all (verify curls)
Docs (5): STATUS, HANDOFF, PROJECT-MAP, vps-setup, gotchas
Skill (1): iis-deploy-runbook — 3 site table + description
Email admin@huypham.vn giữ nguyên (Let's Encrypt contact — không phải
domain serve).

Thêm scripts/migrate-domains.ps1 — 1-shot VPS migration:
  1. Pre-flight: resolve DNS 3 domain → verify IP VPS khớp
  2. Add HTTP binding mới cho 3 IIS site (giữ binding cũ làm fallback)
  3. Run win-acme xin 3 cert Let's Encrypt qua HTTP-01 challenge
     (auto add HTTPS binding + http→https redirect)
  4. Verify /health/live + /health/ready + 2 FE endpoint
  5. (Optional -RemoveOld) xóa binding huypham.vn sau verify OK
Rollback: nếu fail, binding cũ vẫn active → site serve qua huypham.vn.

Anh chạy trên VPS:
  cd C:\solution-erp\scripts  ;  .\migrate-domains.ps1
  # Sau 1-2 ngày verify stable:
  .\migrate-domains.ps1 -RemoveOld -SkipCert
2026-04-24 09:43:05 +07:00
7ca6c914fa [CLAUDE] Docs: chốt session 2 — PE skeleton + G-084 + skill audit
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m55s
User feedback: "phần Duyệt NCC chưa xong đâu đấy nhé, còn chỉnh nhiều"
→ mark PE module skeleton (not feature-complete), liệt kê chi tiết chức
năng/UX/edge-case còn missing cho session tiếp.

Update 7 file:
 - STATUS.md — phase = "PE skeleton + refinement WIP", In Progress liệt
   kê 4 nhóm: A Chức năng MISSING (9 item), B UX/Polish (6 item),
   C Edge case (4 item), D Deploy/Ops (1 item). +G-084 row Recently Done.
 - HANDOFF.md — TL;DR "PE skeleton, còn chỉnh nhiều" + Priority 0 section
   cho session tiếp (9 task PE refinement) + cảnh báo runner + G-084.
 - migration-todos.md — Phase 7 checklist (A/B/C/D nhóm) trước Phase 8
   post-launch. Pending migrations: PaymentTermFields + DepartmentOpinions
   + CodeSequences.
 - architecture.md — Section 9 PurchaseEvaluation module (ERD + workflow
   A/B + kế thừa HĐ flow).
 - CLAUDE.md (root) — 5 file đọc đầu (thêm HANDOFF), Modules table, 12
   migration 46 bảng, +PurchaseEvaluation commit scope.
 - .claude/skills/ — 4 skill cross-ref Phase 6:
   * README: trạng thái updated với Phase 6 note
   * contract-workflow: note PE workflow tách table riêng
   * permission-matrix: +Pe_*/PeWf_* menu keys + TODO grant non-admin
   * ef-core-migration: 12 migration history + Phase 7 pending
 - docs/changelog/sessions/2026-04-23-2359-chot-session-pe-skeleton.md —
   session log full commits + MD files updated + session tiếp priorities
   + notes (PE là skeleton, runner check, G-084 rule, MaPhieu format).
2026-04-23 17:46:41 +07:00
aaf03be8d7 [CLAUDE] Docs: chốt Phase 6 — Module Duyệt NCC E2E
Update 5 file:
 - STATUS.md: phase hiện tại + recently done 4 entry + cumulative stats
   (46 tables, ~110 endpoints, 12 migrations, ~26 FE pages)
 - HANDOFF.md: TL;DR + thêm row "Module Duyệt NCC E2E" 
 - changelog/migration-todos.md: thêm Phase 6 section với checklist
   done/optional (PE Workflow admin UI + Attachments + Auto-map
   Details skip MVP)
 - database/schema-diagram.md: Migration 12 row + section 11 "PurchaseEvaluation
   module" full (10 bảng + state machine + kế thừa HĐ flow)
 - changelog/sessions/2026-04-23-2300-purchase-evaluations.md: session
   log đầy đủ (user input + design + 4 commit + stats + skip MVP notes)
2026-04-23 17:01:53 +07:00
a7ea6ad3d6 [CLAUDE] Docs: chốt session 2026-04-23 tối — UAT-ready 100%
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m48s
5 commit feature work session 2 (072ad6dbcdc007) — clear hết task
pending high-impact, sẵn sàng UAT.

## Session log mới

`docs/changelog/sessions/2026-04-23-2200-roles-demo-pending-cleanup.md`
~270 dòng — outcome A→G (RolesPage + 7 demo HĐ + User-kind guard +
Warning SLA + Edit detail + Master expand + Deps script), stats,
architectural notes, next priority.

## STATUS.md

- Last updated 2026-04-23 22:30 — UAT-ready 100%
- Header phase: "Pending tasks cleared — UAT-ready"
- 5 Recently Done row mới (RolesPage, demo HĐ, user-kind+SLA, edit
  detail+deps, master expand+backfill)
- Cumulative table thêm cột "+RolesPg+Demo+Pending":
  - LOC ~7800 → ~8800
  - Endpoints ~80 → ~93
  - FE pages ~22 → ~23 (RolesPage)
  - Scripts 4 → 5 (deps-audit.ps1)
  - Demo data 5+3 → 15+8+7+13+4 (NCC/Project/HĐ/User/Catalogs)
  - Commits ~47 → ~52
- Session log link mới
- Skills count = 14 file

## HANDOFF.md

- TL;DR cập nhật: UAT-ready 100%, demo data đầy đủ inventory
- Phase table thêm 6 row Done (RolesPage, demo HĐ, user-kind+SLA,
  edit detail, master expand, deps script)
- Git state 8 commit gần nhất

## migration-todos.md

- Section "Session 2026-04-23 (tối)" với 8 ticked checkbox + commit refs
- 3 Roles CRUD checkbox legacy → ticked với commit 072ad6d ref

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:07:20 +07:00
ff5e35f279 [CLAUDE] Docs: chốt session 2026-04-23 chiều — toolkit + 4-bảng + master + roles VN
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m47s
11 commit feature work (b75448eae59cfe) → docs sync.

## STATUS.md

- Last updated 2026-04-23 16:00
- Phase header: Tier 3 + 4-bảng + master catalogs + roles VN
- 7 Recently Done row mới (3-panel layout, 4-bảng overhaul, Thao tác
  2-panel, Mã HĐ gen Create, master catalogs, roles VN demo users)
- Cumulative table thêm cột "+Toolkit/Catalogs/Roles" (DB 36, endpoints
  ~80, migrations 11, commits ~47)
- Session log link mới
- Skill list count = 13 file

## HANDOFF.md

- TL;DR cập nhật: 36 tables, 80 endpoints, 11 migrations
- Phase table thêm 5 row Done (3-panel, 4-bảng, mã HĐ, master, roles)
- Git state 18 commit gần nhất
- Credentials block thêm 13 demo user (User@123456) — warn rotate trước UAT

## migration-todos.md

Section "Session 2026-04-23 (chiều)" với 14 ticked checkbox + commit refs.

## schema-diagram.md

- Header: 24 → 36 bảng
- Migration table thêm row 9-11 (highlighted)
- Section 8bis mới: chi tiết 7 Details + ContractChangelogs + 4 Catalogs +
  Role.ShortName + User.DepartmentId/Position

## Session log mới

`docs/changelog/sessions/2026-04-23-1500-toolkit-data-roles.md` (~270
dòng) — outcome A→I, stats cumulative, 6 architectural decisions, next
session priority.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:39:48 +07:00
d43d2c0024 [CLAUDE] Docs: chốt session 2026-04-23 — skill governance + cron audit
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m46s
- Session log 2026-04-23-0900-skill-governance.md (A→E):
  khảo sát alirezarezvani/claude-skills + quyết định không bulk-clone,
  3 skill ops mới (dependency-audit-erp, ef-core-migration,
  iis-deploy-runbook), rules §9 + audit cadence cron 1/tháng,
  touch-points 6 file index
- STATUS: Recently Done 2 row mới (b904a25 governance + 661f859
  3 skill), header phase = "Tier 3 + skill governance",
  session log count → 12 file, link skills README.md
- HANDOFF: Last updated → 2026-04-23 09:30, TL;DR mention skill
  governance setup, table phase tier thêm row Skill governance ,
  Skills callout "PHẢI dùng khi task khớp" + audit cron next 2026-05-01,
  git state cập nhật 3 commit gần nhất

Cron task verified live qua list_scheduled_tasks: nextRunAt =
2026-05-01T02:05:48.000Z (jitter 348s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:30:37 +07:00
b904a25dc1 [CLAUDE] Skill: governance + audit định kỳ hàng tháng
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m48s
- rules.md §9 mới: liệt kê 6 skill (3 domain + 3 ops) với trigger,
  nguyên tắc tạo skill project-specific (không clone generic),
  format SKILL.md bắt buộc, audit workflow §9.4 chi tiết 7 bước,
  4 anti-patterns
- CLAUDE.md (root): block "🛠️ Skills" callout 6 skill + audit cadence
  + commit scope thêm `Skill`
- HANDOFF.md: section A1 — định kỳ audit, lần kế tiếp 2026-05-01
- migration-todos: section "Skill governance (recurring)" với checkbox
  audit hàng tháng

Cron task tạo qua scheduled-tasks (ID: solution-erp-skill-audit-
monthly): chạy 9:00 AM ngày 1 mỗi tháng. Self-contained prompt cold-
start để session tự audit + log vào docs/changelog/skill-audit-
{YYYY-MM}.md. Auto-refresh stale skill nhỏ, đề xuất add/archive cho
human approve.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:12:54 +07:00
fbca83264c [CLAUDE] Docs: chốt session Tier 3 feature-complete + versioned workflow
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m33s
- Session log 2026-04-22-0300 (A→K): attachment, SignalR, form builder,
  PDF, dynamic + versioned workflow, nested menu, 3-panel permissions,
  seed master, brand identity, content polish, Gitea fix
- STATUS: Tier 3 feature-complete snapshot + cumulative stats (24 tables,
  ~50 endpoints, 8 migrations); next-up = UAT + Email SMTP (blocked) +
  rotate creds + SQL backup schedule
- HANDOFF: rewrite brief cho session mới — phase 5 prod done, Tier 3
  đóng gói, quick sanity-check 2 app, versioned workflow quick ref,
  file active hiện trạng, git state
- migration-todos: tick Tier 3 items (attachment/realtime/form builder/
  PDF/dynamic+versioned workflow/nested menu) + thêm iter-3 versioned
  workflow section + post-launch list
- schema-diagram: +5 table (Notifications, WorkflowTypeAssignments,
  WorkflowDefinitions, WorkflowSteps, WorkflowStepApprovers); indexes
  mới, cardinality FK restrict cho pinned policy, truy vấn tiêu biểu
- workflow-contract: +section 7bis resolution order, 7ter admin
  designer flow, updated data model + code pointers Tier 3
- PROJECT-MAP: module map post-Tier-3 (3 box mới Notification/
  Attachment/Branding + Infra/DevOps box), API namespace đầy đủ,
  architectural wins 5 điểm
- contract-workflow skill: versioned workflow section, policy
  resolution code snippet, admin designer flow, code pointers Tier 3,
  tier 4+ backlog
- gotchas +7 bẫy mới (#26-32): SignalR WebSocket headers, interceptor
  2-phase pattern, LibreOffice mirror 404, PS 5.1 UTF-16 GITHUB_PATH,
  PS 5.1 diacritics parse, Dialog size TS, NavLink end query-params

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 10:25:02 +07:00
11e61c9c39 [CLAUDE] Phase5.1: Security headers + account lockout + Users management
Security hardening:
- Api/Middleware/SecurityHeadersMiddleware MOI: remove server fingerprint (Server, X-Powered-By, ...), add X-Content-Type-Options:nosniff, X-Frame-Options:DENY, Referrer-Policy:strict-origin-when-cross-origin, Permissions-Policy (disable geolocation/mic/cam/payment), X-Permitted-Cross-Domain-Policies:none, CSP (default-src 'self' + img data: + style inline for Tailwind + frame-ancestors 'none'). Skip CSP tren /swagger (dung inline script).
- Program.cs wire UseMiddleware SecurityHeadersMiddleware first in pipeline
- Infrastructure/DependencyInjection Identity options:
  - Password.RequiredLength config-driven (Identity:Password:RequiredLength, default 8 dev, override 12+ prod)
  - Lockout: DefaultLockoutTimeSpan (15min), MaxFailedAccessAttempts (5), AllowedForNewUsers=true — all config-driven
- LoginCommandHandler: IsLockedOutAsync check truoc → throw voi deadline message, AccessFailedAsync khi sai password, ResetAccessFailedCountAsync khi login thanh cong

Users management:
- Application/Users/UserFeatures.cs: 8 CQRS (ListUsersQuery paging+search, GetUserQuery, CreateUserCommand + Validator, UpdateUserCommand voi self-disable protection, AssignRolesCommand voi self-demote protection (khong tu go Admin), ResetPasswordCommand (invalidate refresh token + unlock), UnlockUserCommand)
- UserDto: Id, Email, FullName, IsActive, IsLocked (computed tu LockoutEnd), CreatedAt, Roles
- Api/Controllers/UsersController: 7 endpoint (Users.Read/Create/Update policies):
  - GET / (list paged), GET /{id}, POST /, PUT /{id}, PUT /{id}/roles, POST /{id}/reset-password, POST /{id}/unlock
- using alias ValidationException = Application.Common.Exceptions.ValidationException (fix ambiguity voi FluentValidation)

Frontend fe-admin:
- types/users.ts MOI: User type + AVAILABLE_ROLES 12 role (match BE AppRoles.cs) + RoleLabel Vietnamese
- pages/system/UsersPage.tsx MOI:
  - DataTable columns: Email (mono), FullName, Roles (badge chips voi Vietnamese label), IsActive (CheckCircle/XCircle), IsLocked (KeyRound red), CreatedAt
  - Actions per row (PermissionGuard Users.Update wrap): Gan role (Shield icon → Dialog grid 12 checkbox), Reset password (KeyRound → Dialog voi warning user se bi logout), Unlock (Unlock icon, chi hien khi isLocked), Toggle active (XCircle/CheckCircle)
  - Create user dialog: email + fullName + password (min 8) + grid 12 role checkbox
- Route /system/users vao App.tsx

E2E verified:
- Security headers present tren moi response (check qua curl -I)
- POST /api/users voi roles: [Drafter] → 201 + id
- GET /api/users → paged voi 2 user (admin + new test.drafter)
- TS check fe-admin → pass
- dotnet build → 0 errors

Docs:
- docs/STATUS.md: Phase 5.1 xong, cumulative BE 3700 LOC, 42 endpoints, 17 FE pages
- docs/HANDOFF.md: phase table update row Phase 5.1, last updated timestamp
- docs/changelog/migration-todos.md: tick 6 items Phase 5.1 + 4 items remaining (IDOR, deps scan, admin warning, Roles CRUD)
- docs/changelog/sessions/2026-04-21-1630-phase5-1-security-users.md: session log

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
2026-04-21 13:06:46 +07:00
f3fb3fd565 [CLAUDE] Phase5 prep: production infra + deploy scripts + 4 guides + FE refresh token
Backend production infra:
- Packages: Serilog.Sinks.File, HealthChecks.EntityFrameworkCore (RateLimiting built-in .NET 10)
- appsettings.Production.json MOI: placeholder __SET_VIA_SECRETS__, AllowedOrigins, Serilog File sink rolling daily retention 30d, RateLimit config
- appsettings.json + Development.json: them Serilog WriteTo Console
- Program.cs REWRITE:
  - Serilog ReadFrom.Configuration (prod file / dev console)
  - Rate limiter: policy auth-login 5/min/IP (AuthController.Login) + GlobalLimiter 300/min/IP
  - Health checks: /health/live liveness (empty predicate) + /health/ready DB probe (AddDbContextCheck)
  - HSTS production 1 year
  - CORS origins from config AllowedOrigins (default dev 2 localhost)
- AuthController.Login gắn [EnableRateLimiting("auth-login")]

Deploy scripts:
- scripts/deploy-iis.ps1: stop pool → backup current → clean+extract artifact → start pool → health check loop 30s timeout → rollback instruction if fail
- scripts/backup-sql.ps1: BACKUP DATABASE voi INIT+COMPRESSION+CHECKSUM + retention 30d auto cleanup
- .gitea/workflows/deploy.yml MOI: 4 job build BE (Windows) + build 2 FE (Ubuntu, pin .nvmrc 20) + deploy-iis qua WinRM PSSession (secrets IIS_HOST/USER/PASSWORD/JWT_SECRET/DB_CONNECTION)

Docs guides MOI (4 file):
- deployment-iis.md: prereqs (IIS features, Hosting Bundle, SQL, WinRM) + setup lan dau (app pool, 3 site, HTTPS win-acme, user-secrets) + deploy hang ngay (CI/CD + manual) + rollback + monitoring + troubleshooting + SPA web.config sample
- cicd.md: pipeline overview 4 job, secrets setup, runner Windows+Ubuntu, branch strategy, build optimizations, common CI/CD issues
- security-checklist.md: OWASP top 10 2021 mapping voi status + pre go-live checklist + incident response
- runbook.md: daily ops (health/logs), restart/rollback, DB backup/restore/migration revert, user management (reset password, unlock, disable), monitoring (CPU/disk/connection pool), deployment checklist, common gotcha

Frontend refresh token (ca 2 app fe-admin + fe-user):
- lib/api.ts REWRITE: them REFRESH_KEY, axios response interceptor 401 → POST /auth/refresh → retry request goc. Queue pattern cho nhieu request song song chi 1 refresh call chay. Skip retry /auth/login + /auth/refresh tranh infinite loop. _retry flag tren original config.
- contexts/AuthContext.tsx: luu+xoa REFRESH_KEY trong login/logout

E2E verified:
- GET /health/live → 200 Healthy
- GET /health/ready → 200 Healthy (DB probe)
- Rate limit flood 7 POST /auth/login → #1-5 HTTP 400 (cred sai) + #6-7 HTTP 429 Too Many Requests 
- TS check fe-admin + fe-user → pass
- dotnet build → 0 errors

Docs updates:
- docs/STATUS.md: Phase 5 prep done, next Phase 5 deploy production + Phase 5.1 security hardening, cumulative stats 8 commits
- docs/HANDOFF.md: phase table them Phase 5 prep row, file tree update voi guides + scripts + workflows, git state commit 8
- docs/changelog/migration-todos.md: tick Phase 5 prep items (12 items done) + Phase 5 deploy items remaining + Phase 5.1 security hardening list
- docs/changelog/sessions/2026-04-21-1530-phase5-prep.md: session log chi tiet

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:57:12 +07:00
fe7ad8e4a3 [CLAUDE] Phase4: Report MVP + Docs Consolidation (rules, architecture, schema-diagram)
Backend Report:
- Application/Reports/Dtos/DashboardStatsDto: 5 KPI + PhaseCount + SupplierCount + ProjectCount + MonthlyValue
- Application/Reports/Queries/GetDashboardStats handler: total/active/overdue/published this month/totalValueActive + byPhase + top 5 NCC/du an + 12 thang monthly (fill zero khi thang empty)
- Application/Reports/Services/IContractExcelExporter interface
- Infrastructure/Reports/ContractExcelExporter: ClosedXML workbook 10 cot, header style bold+blue, number format #,##0, formula SUM, auto-fit, freeze header
- Application/Reports/Commands/ExportContractsToExcelCommand: filter phase/supplier/project/date range
- Api/Controllers/ReportsController: GET /reports/dashboard, GET /reports/contracts/export
- DI register IContractExcelExporter (Scoped)

Frontend fe-admin:
- types/reports.ts: DashboardStats type
- components/BarChart.tsx: generic horizontal bar chart — chi Tailwind, khong thu vien ngoai
- pages/DashboardPage.tsx REWRITE: 5 KPI card (FileText/TrendingUp/AlertTriangle/CheckCircle2/Coins) + by-phase bar + monthly 12-month chart + top 5 NCC + top 5 du an + skeleton loader
- pages/ReportsPage.tsx MOI: filter phase/fromDate/toDate → export Excel button
- Route /reports vao App.tsx

E2E verified:
- GET /api/reports/dashboard → 200 voi day du KPI + monthly fill 12 thang
- GET /api/reports/contracts/export → 200 xlsx 7229 bytes (Microsoft Excel 2007+)

Docs consolidation (theo yeu cau user):
- docs/rules.md MOI: 9 section coding conventions (ngon ngu UI/code/DB/docs, BE Clean Arch, CQRS+MediatR, Validation FluentValidation, Error handling, Async, Entity rules, DI, Package pinning, FE React/TS erasableSyntaxOnly, path alias, TanStack Query, Permission guard, Toast+error, DB convention, Git commit format, Docs structure, Testing, Security)
- docs/architecture.md MOI: layered overview ASCII art, request lifecycle (1 POST/api/contracts qua 10 step), workflow state machine 9 phase, permission model, data flow sequence diagram 4 actor (Drafter/Manager/CCM/BOD/HRA), deployment architecture Phase 5, skill library, non-functional table
- docs/database/schema-diagram.md MOI: full ERD 19 table mermaid + data flow diagram + vong doi 1 HD (create → 7 transition → gen ma → publish) + index strategy table + relationship cardinality + soft delete behavior + SQL queries (inbox/dashboard/gen ma) + migration history
- docs/gotchas.md UPDATE: 17 → 26 pitfalls, them section "Claude Code harness quirks" (Edit File not read, DI build pass nhung runtime fail) + "Contract workflow" (ma HD gen 2 lan, BE-FE NEXT_PHASES sync, race condition) + "Permission matrix" (cache real-time, MenuKey typo)
- docs/STATUS.md: Phase 4 MVP done, docs entry points section liet ke het, next Phase 5 Production
- docs/HANDOFF.md: phase table them Phase 4 row, file tree update voi Reports, test points day du, git state commit 7
- docs/changelog/migration-todos.md: tick Phase 4 MVP items + them iteration 2 list
- docs/changelog/sessions/2026-04-21-1430-phase4-report.md: session log voi thong so cumulative (BE 3100 LOC, 30 docs)
- CLAUDE.md root: update Tai lieu quan trong section them rules.md, architecture.md, schema-diagram.md, .claude/skills (13 links now)

Bug fix:
- TS unused import ContractPhaseLabel trong DashboardPage
- DI thieu register IContractExcelExporter — build pass but runtime would fail (added)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:42:46 +07:00
7e957a7654 [CLAUDE] Phase3: Workflow MVP — 9-phase state machine + code gen + FE Inbox/Detail
Backend Contracts domain (5 entities):
- Contract aggregate: Phase (9 enum), SlaDeadline, MaHopDong, BypassProcurementAndCCM, DraftData, SlaWarningSent
- ContractApproval: FromPhase → ToPhase, ApproverUserId (null = system auto-approve), Decision, Comment
- ContractComment: thread theo Phase current
- ContractAttachment: FileName + StoragePath + Purpose (DraftExport/ScannedSigned/SealedCopy)
- ContractCodeSequence: Prefix PK + LastSeq — atomic gen

EF configs:
- Unique MaHopDong filtered [MaHopDong] IS NOT NULL
- Indexes: Phase+IsDeleted, SupplierId, ProjectId, SlaDeadline, ContractId+ApprovedAt, ContractId+CreatedAt
- Cascade delete Approvals/Comments/Attachments khi Contract xoa
- Query filter IsDeleted
- Migration AddContractsWorkflow (DB 19 tables)

Workflow service:
- IContractWorkflowService.TransitionAsync:
  - Adjacency check qua Transitions Dict<(from,to), roles[]> (12 transitions)
  - Role guard: user phai co role ∈ allowed
  - Admin bypass (role Admin pass moi check)
  - System bypass (userId=null + Decision=AutoApprove → cho SLA job sau nay)
  - Bypass CCM: BypassProcurementAndCCM=true cho phep DangInKy → DangTrinhKy skip phase 6
  - Gen ma HD khi chuyen DangDongDau (idempotent — khong gen lai neu da co)
  - Reset SlaDeadline = UtcNow + PhaseSla
  - Insert ContractApproval row

Code generator (RG-001):
- 7 format theo ContractType: HDTP / HDGK / NCC / HDDV / MB + 2 framework (year prefix)
- BeginTransactionAsync(Serializable) + ContractCodeSequences UPSERT → atomic
- Idempotent: neu MaHopDong da co thi skip

CQRS (8 feature, ContractFeatures.cs):
- CreateContractCommand + Validator + Handler (set SlaDeadline = +7d)
- UpdateContractDraftCommand (chi khi Phase=DangSoanThao)
- TransitionContractCommand (delegate → WorkflowService)
- AddCommentCommand (phase = hien tai)
- ListContractsQuery (PagedResult + filter phase/supplier/project/search)
- GetMyInboxQuery (map Phase → actor roles, filter theo role user)
- GetContractQuery (detail + approvals + comments + attachments + resolve user names)
- DeleteContractCommand (soft, block > DangInKy)

Controller:
- ContractsController 8 endpoint: GET list/inbox/detail, POST create/transition/comment, PUT update, DELETE

Frontend fe-admin (2 page moi):
- types/contracts.ts: ContractPhase const + Label + Color maps + types
- components/PhaseBadge.tsx
- pages/contracts/ContractsListPage.tsx: filter phase + search + click → detail
- pages/contracts/ContractDetailPage.tsx: 2-col layout (info+comments | timeline), action dialog select target phase + comment

Frontend fe-user (4 page moi + 14 file shared):
- cp 14 file shared tu fe-admin (menuKeys, types/*, DataTable, PhaseBadge, Dialog, Textarea, Select, apiError, usePermission, PermissionGuard)
- AuthContext update: load menu tu /menus/me + cache
- Layout: menu fixed 3 muc + user info + roles display
- InboxPage: list HD cho role user xu ly (sort theo SLA)
- ContractCreatePage: form chon loai + template + NCC + du an + gia tri + bypass CDT
- ContractDetailPage: duplicate fe-admin pattern (convention)
- MyContractsPage: list HD cua toi
- App.tsx: 4 route moi

E2E verified:
- Setup Supplier + Project
- POST /contracts → 201 + phase=2
- POST /contracts/{id}/transitions x7 → di het 9 phase
- Final: MaHopDong = "FLOCK 01/HĐGK/SOL&PVL2026/01" dung format RG-001
- Approvals: 7 rows audit day du

Docs:
- .claude/skills/contract-workflow/SKILL.md: placeholder → full spec voi state machine, SLA table, role matrix, 7 code format, code pointers, API, E2E workflow, pitfalls
- docs/changelog/sessions/2026-04-21-1330-phase3-workflow.md: session log
- docs/STATUS.md: Phase 3 MVP done, next Phase 4
- docs/HANDOFF.md: update phase status + file tree + commit log + testing points
- docs/changelog/migration-todos.md: tick Phase 3 MVP items + add iteration 2 list

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:26:09 +07:00
5113e4c771 [CLAUDE] Phase2: Form Engine MVP + docs (gotchas, skill, handoff)
Backend Forms:
- Domain/Forms: ContractTemplate (FormCode, Name, ContractType, FileName, StoragePath, Format, FieldSpec JSON, IsActive) + ContractClause
- EF config voi unique FormCode + query filter IsDeleted
- DbSets + IApplicationDbContext update
- Migration AddForms (bang 14 total)
- Packages: DocumentFormat.OpenXml 3.x + ClosedXML 0.105+
- Application/Forms:
  - IFormRenderer interface + RenderResult record
  - FormFeatures.cs: List/Get/Render CQRS
  - IWebHostEnvironmentLocator (abstract IWebHostEnvironment)
- Infrastructure/Forms:
  - DocxRenderer: OpenXml-based placeholder {{field}} replace, handle split runs (gom text tat ca <w:t> trong paragraph, replace, gan lai text dau + clear rest)
  - XlsxRenderer: ClosedXML cell value replace
  - FormRenderer router theo format docx/xlsx
- Api:
  - FormsController: GET /templates (filter type, onlyActive), GET /templates/{id}, POST /templates/{id}/render (return file)
  - WebHostEnvironmentLocator impl
- DbInitializer SeedContractTemplatesAsync: seed 8 template metadata, IsActive=true chi khi file ton tai

Templates vat ly:
- Copy 5 .docx/.xlsx tu FORM/ sang wwwroot/templates/
- 3 .doc (FO-002.02/03/06) chua convert: IsActive=false (Word COM bi stuck luc test, can retry voi DisplayAlerts=0 hoac LibreOffice)
- scripts/convert-doc-to-docx.ps1 (Word COM automation)

Frontend fe-admin:
- types/forms.ts: ContractTemplate + ContractTypeLabel
- pages/forms/FormsPage.tsx: list templates + Render dialog (paste JSON data → download .docx/.xlsx)
- Route /forms them vao App.tsx

Bug fix:
- SpaceProcessingModeValues namespace: wrap EnumValue<> full path
- SaveAs2($path, 16) thay vi SaveAs([ref], [ref]) — PowerShell type issue
- Word COM stuck: kill process, skip .doc cho MVP

Docs (theo yeu cau user):
- docs/gotchas.md MOI: 17 pitfalls nhom theo tech stack / EF Core / OpenXml / JSON / dev workflow
- .claude/skills/form-engine/SKILL.md: placeholder → full spec (algorithm + code pointers + API + limitations)
- .claude/skills/permission-matrix/SKILL.md: placeholder → full spec (BE policy + FE guard + seed + pitfalls)
- docs/HANDOFF.md MOI: brief 5 phut cho session sau (run quickstart + where we are + next steps + file tree + gotchas ref)
- docs/STATUS.md: update cumulative stats + next up Phase 3
- docs/changelog/migration-todos.md: tick Phase 2 iteration 1 items + add iteration 2 list
- docs/changelog/sessions/2026-04-21-1200-phase2-form-engine.md: session log
- CLAUDE.md root: them reference den gotchas + HANDOFF

E2E verified:
- GET /api/forms/templates (onlyActive=false) → 8 templates
- POST /api/forms/templates/{FO-002.05}/render voi data dict → HTTP 200 + file .docx 482KB (Microsoft Word 2007+ OK)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:01:11 +07:00