Commit Graph

238 Commits

Author SHA1 Message Date
9747f8cbf5 [CLAUDE] Infra+App: Chunk C — Smart reject + Resume after reject (3 module)
Ràng buộc 2 (Phase 9): khi reject, trả về Drafter (DangSoanThao) + lưu phase
nguồn. Drafter sửa lại + trình lại → quay về phase đã reject (skip phase
trung gian).

Logic flow:

1. Reject (Decision=Reject):
   - entity.RejectedFromPhase = currentPhase  // snapshot phase đang reject
   - targetPhase override = DangSoanThao       // force về Drafter
   - Approval row: FromPhase=X, ToPhase=DangSoanThao, Decision=Reject
   - Notification cho Drafter

2. Resume after reject (Decision=Approve, fromPhase=DangSoanThao,
   RejectedFromPhase != null):
   - targetPhase override = entity.RejectedFromPhase!.Value
   - entity.RejectedFromPhase = null  // clear field
   - Skip policy guard (Drafter có quyền trình lại sau khi sửa)
   - Approval row: FromPhase=DangSoanThao, ToPhase=ResumePhase, Decision=Approve

3. Normal transition (chưa reject hoặc đã clear):
   - Logic cũ giữ nguyên — policy guard check + transition

Pattern unified cho 3 module:
- ContractWorkflowService.TransitionAsync: 2 case detect + override
- PurchaseEvaluationWorkflowService.TransitionAsync: tương tự
- TransitionBudgetCommandHandler.Handle: tương tự (Budget không có service riêng,
  logic ở handler)

Files:
- src/Backend/SolutionErp.Infrastructure/Services/ContractWorkflowService.cs
- src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs
- src/Backend/SolutionErp.Application/Budgets/BudgetFeatures.cs

Verify:
- Build pass (2 warning DocxRenderer cũ, không liên quan)
- 77 unit test pass — Domain policy không đổi, tests giữ nguyên

Note: Approval history giờ track đầy đủ cycle reject→sửa→resume:
  Approval 1: DangGopY → DangSoanThao, Decision=Reject (CCM reject)
  Approval 2: DangSoanThao → DangGopY, Decision=Approve (Drafter resume)

UI có thể detect "đã từng reject" qua RejectedFromPhase != null hoặc
qua Approval history (Decision=Reject row gần nhất). Hiển thị banner
đỏ "Phiếu đã bị reject từ phase X, lý do: Y" cho Drafter.

Smart reject hoàn tất Ràng buộc 2. Còn Ràng buộc 3 (2-stage dept approval)
ở Chunk D.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 12:20:21 +07:00
14f3c9f817 [CLAUDE] App: Chunk B — Lock edit guards (Phase != DangSoanThao) cho 17 handler
Ràng buộc 1 (Phase 9): khi đã trình duyệt → KHÔNG sửa được Header + Detail
+ Quote nữa. Phải reject để Drafter sửa lại.

Pattern dùng: extend helper EnsureContractType + tạo helper PurchaseEvaluationDraftGuard
mới cho PE + inline guard cho Budget. Single source of truth cho mỗi module.

Handlers added Phase guard (17 total):

Contract module (15) — qua EnsureContractType helper:
- 7 Add*DetailHandler (ThauPhu/GiaoKhoan/NhaCungCap/DichVu/MuaBan/NguyenTacNcc/NguyenTacDv)
- 7 Update*DetailHandler (cùng 7 type)
- DeleteContractDetailHandler (inline guard)

PE module (5) — qua PurchaseEvaluationDraftGuard helper mới:
- AddPurchaseEvaluationDetail
- UpdatePurchaseEvaluationDetail
- DeletePurchaseEvaluationDetail
- UpsertPurchaseEvaluationQuote
- DeletePurchaseEvaluationQuote

Budget module (3) — inline guard:
- AddBudgetDetail
- UpdateBudgetDetail (refactor: load Budget thay vì FirstOrDefault sau Detail
  load → bỏ null check không cần)
- DeleteBudgetDetail (refactor: tương tự)

KHÔNG lock (intentional):
- ContractComment (cần được trong DangGopY phase 3)
- ContractAttachment Upload/Delete (Drafter scan ký ở DangInKy phase 5)
- PE OpinionUpsert (Ý kiến 4 PB là sign-off, có thể nhập sau khi trình)
- PE Attachment (báo giá NCC upload xuyên suốt workflow)

Verify:
- Build pass (2 warning DocxRenderer cũ)
- 77 unit test pass (54 Domain + 23 Infra) — domain policy không đổi

Smart reject (ràng buộc 2) + 2-stage dept approval (ràng buộc 3) làm ở
Chunk C + D. WorkflowService transition guard chưa update.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 12:15:07 +07:00
5c200978cb [CLAUDE] Domain+Infra: Migration 16 — 2-stage dept approval + smart reject schema
Chunk A của feature 2-stage department approval (Phase 9). 3 ràng buộc gộp
1 migration để rollback atomic.

Schema changes:

1. Smart reject (3 ALTER):
   - Contracts.RejectedFromPhase int NULL
   - PurchaseEvaluations.RejectedFromPhase int NULL
   - Budgets.RejectedFromPhase int NULL
   Lưu phase nguồn khi reject để Drafter trình lại quay về đúng phase
   (skip phase trung gian đã duyệt) thay vì đi tuần tự từ DangSoanThao.

2. Bypass per-user (1 ALTER):
   - Users.CanBypassReview bit NOT NULL DEFAULT 0
   Khi true → NV được duyệt thay TPB (skip Stage Review, đẩy thẳng
   Stage Confirm). Audit qua DepartmentApproval.IsBypassed=true.

3. 2-stage dept approval (3 CREATE TABLE):
   - ContractDepartmentApprovals
   - PurchaseEvaluationDepartmentApprovals
   - BudgetDepartmentApprovals

   Schema (chung):
   - Id, *Id FK Cascade, PhaseAtApproval int, DepartmentId FK
   - Stage enum (1=Review NV, 2=Confirm TPB)
   - ApproverUserId, ApproverRoleSnapshot, Comment, ApprovedAt
   - IsBypassed bit (mark NV bypass)
   - AuditableEntity (CreatedAt/By/UpdatedAt/By/IsDeleted/...)

   Indexes:
   - UNIQUE (TargetId, PhaseAtApproval, DepartmentId, Stage)
   - Single: TargetId, DepartmentId, ApproverUserId

Files:
- Domain: 4 entity update (Contract/PE/Budget/User add field) + 1 enum mới
  ApprovalStage + 3 entity DepartmentApproval mới
- Infrastructure: 3 EntityConfiguration update + 1 file mới
  DepartmentApprovalsConfiguration với 3 config classes
- IApplicationDbContext: thêm 3 DbSet
- ApplicationDbContext: thêm 3 DbSet
- Migration 16: 3 file (.cs + Designer.cs + Snapshot.cs) — 3-file rule

Verify:
- Build pass (2 warning DocxRenderer cũ, không liên quan)
- 77 unit test pass (54 Domain + 23 Infra) — Domain policy chưa update,
  test pass nguyên không regression

Note: KHÔNG khác PurchaseEvaluationDepartmentOpinion (Migration 15) —
Opinion là sign-off block "Ý kiến 4 phòng ban" trên header phiếu.
DepartmentApproval mới là 2-stage approval workflow per phase.

Tổng sau Migration 16: 55 bảng (52+3), 16 migration. Chunk B-E sẽ implement
Application + FE + Tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 12:11:53 +07:00
dfb43fcbc6 [CLAUDE] Docs: chốt template session prompts (start + end) — iterate qua 5 AI
User dùng 2 prompt fixed cho mọi session SOLUTION_ERP:
- MỞ ĐẦU: LOAD context (5 mục — đọc MD core, list skill, verify test,
  check audit cadence, sub-rule consolidate)
- KẾT THÚC: UPDATE MD + commit (5 mục — update MD đã đổi, note skill,
  verify test count tăng, add memory entry nếu cần, sub-rule consolidate)

Iterate workflow:
- v1: đề xuất ban đầu (typo + 4 mục giống nhau Mở đầu vs Kết thúc)
- v2: tách action verb LOAD vs WRITE
- v3-v4: refine wording, fix typo, bỏ câu thừa
- v5 final: fix "thei"→"theo", "end từ"→"kết thúc lúc", "vào vào"→"vào"

Bài học: prompt template iterate cross-AI (5 AI cùng review) ra version
robust hơn 1 AI duy nhất. Template lưu 3 chỗ:
1. docs/_templates/session-prompts.md (canonical project)
2. memory/reference_session_prompts.md (cross-session pointer)
3. MEMORY.md index (session sau auto-load nhận diện trigger)

File: docs/_templates/session-prompts.md (NEW, docs-only → CI skip)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 03:04:12 +07:00
2675a3a674 [CLAUDE] Docs: rule §6.5 consolidate KEEP vs CUT + restore narrative migration-todos
Bài học session 6: compact -288 dòng nhanh nhưng paraphrase + collapse mất
narrative tích lũy qua sessions. User feedback: "viết MD gọn lại tý là mất
mẹ luôn tính cách cũ". Docs đọc 6 tháng sau như machine output.

Changes:
1. docs/rules.md §6.5 mới — Consolidate MD đúng cách (KEEP vs CUT):
   - KEEP cấm cắt: narrative, rationale, gotcha context, anecdote, "decision why"
   - CUT được: duplicate cross-ref, list>30 row archive, phase>1 tháng collapse
   - CẤM: paraphrase, summary đoạn có narrative, "đẹp hóa" bằng cắt
   - Decision tree + Validation 3 câu sau consolidate

2. docs/changelog/migration-todos.md restore Phase 6-7 nguyên văn từ b874743:
   - Phase 6 iter 1 (10 task chi tiết: Migration 12, Domain 2 enum, Application
     CQRS ~900 LOC, PurchaseEvaluationWorkflowService, Controller 17 endpoint,
     FE 2 app, Kế thừa HĐ guard, Migration 13 atomic seq, Demo PE seed)
   - Phase 6 iter 2 (8 task UX polish: rename Phương Án→Giải pháp, menu
     inheritance #35, accordion mutex, queryMatches #34, flat layout, per-NCC
     attachment, readOnly mode, email rebrand #38)
   - Domain rebrand 4 task chi tiết (gotcha #30 ASCII-only, 18 file repo,
     CI/CD auto rebuild, "Old fallback chưa remove" rationale)
   - Phase 7 PE feature gap A/B/C/D/E section đầy đủ:
     A. 3 task PE feature gap với file path + Option A/B reasoning
     B. 4 optional polish carry over Phase 9
     C. 6 ops task carry over Phase 9 hard blockers
     D. Budget BE 7 task chi tiết (Migration 14, ~340 LOC, 11 endpoint, 14 demo)
     E. 4 pending migration với rationale "khi nào cần"
   - Tick [x] task đã DONE S5 (PE WF Designer + Ý kiến 4 PB) + giữ [ ] chưa làm

Net change migration-todos: 136 → 217 (+81 dòng narrative)

Files: docs/rules.md + docs/changelog/migration-todos.md (docs-only → CI skip)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 01:56:29 +07:00
2abbc1d867 [CLAUDE] Docs+Skill: chốt session 6 — 3 skill refresh + 2 rule audit định kỳ
Pure docs work — 0 thay đổi code/test. 77 test vẫn pass (Domain 54 + Infra 23).

3 skill refresh stale (audit định kỳ §6.4 + §9.4 phát hiện):
- form-engine: "Phase 2 MVP missing PDF + form builder" → "Tier 3 feature-complete"
  + bỏ section duplicate "Gen mã HĐ chưa implement" (đã DONE Phase 3+6)
- permission-matrix: 12 menu cũ → ~60 menu key (Bg_*/Pe_*/PeWf_*/Catalogs)
  + inheritance roots 4 group + Budgets KHÔNG inherit (gotcha #35)
- ef-core-migration: "24 DbSet" → "52 bảng (15 migration)"

2 rule mới chốt:
- rules.md §6.4 — Audit + compact MD định kỳ (cadence + checklist + anti-pattern)
  Triết lý: KHÔNG rewrite toàn bộ. Compact + patch drift.
  Cron solution-erp-skill-audit-monthly mở rộng scope (skill + doc drift combined)
- rules.md §9.4 mở rộng cross-ref §6.4

Update STATUS Session 7+ priority + HANDOFF cảnh báo session 7 + migration-todos
Phase 9 Session 6 done sub.

Cron 2026-05-01 fire mai → combined audit theo checklist §6.4 + §9.4.

Session log đầy đủ: docs/changelog/sessions/2026-04-30-chot-session-6-md-audit-compact.md

Commit MD-only → CI skip (path filter gotcha #41).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 01:18:51 +07:00
f24acb699a [CLAUDE] Docs: compact 3 file core (-273 dòng tổng)
STATUS.md (-52 dòng, -27%): archive 51 row Recently Done Phase 0-7 cũ
  → changelog/recently-done-archive-2026-04.md (file mới)
  Giữ 12 row mới nhất Phase 8/Session 5 + pointer archive.

HANDOFF.md (-147 dòng, -32%): bỏ 3 section duplicate
  - Versioned workflow quick ref → cross-ref workflow-contract.md §7bis
  - File đang active (90 dòng tree) → cross-ref PROJECT-MAP.md
  - Git state snapshot stale → cross-ref `git log --oneline -10`

migration-todos.md (-74 dòng, -35%): collapse Phase 6 iter 1+2 + Phase 7
  done parts thành 4 dòng paragraph. Giữ Phase 8/9 active + skill audit.

Quy tắc compact (rules.md §6 implicit):
  - Recently Done > 30 row → archive cũ vào changelog/recently-done-archive-{YYYY-MM}.md
  - Phase done >= 1 tháng → collapse thành 1 paragraph + cross-ref session log
  - Section duplicate file khác → cross-ref thay vì copy

Commit MD-only → CI skip (path filter gotcha #41).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 01:10:03 +07:00
d2298fa614 [CLAUDE] Docs: chốt rule timing unit test (1 bảng 5-row compact)
- rules.md §7: thêm section "Khi nào viết test — timing rule"
  4 case (feature mới/bug fix/critical algorithm/spec change) + 1 skip list
- CLAUDE.md root: 1 dòng quick reference timing rule
- User confirm pattern Phase 1-8 (test-after pragmatic) là default cho solo dev
- Test-before BẮT BUỘC chỉ khi: bug fix (regression test) + critical algorithm
- Spec change KHÔNG ngừng test — update test cũ + code, commit chung

Commit MD-only → CI skip (path filter gotcha #41), 0s deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 00:40:24 +07:00
b874743081 [CLAUDE] Docs+Tests: chốt final session 5 — 77 test (Phase 3 mini PE WF) + 3 gotcha CI + 8 doc updates
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m21s
Final close session 5 — bao gồm:

==== Tests Phase 3 mini (NEW) ====
tests/SolutionErp.Infrastructure.Tests/Application/PeWorkflowAdminTests.cs
- 6 test CreatePeWorkflowDefinitionCommandHandler:
  - First version → IsActive=true, Version=1, ActivatedAt set
  - Second version same Code → auto-increment v2 + deactivate v1 (atomic)
  - Different EvaluationType (A vs B) → independent active state
  - Persists steps ordered by Order field
  - Persists approvers per step
  - Third version → v1 + v2 deactivate, v3 active

Total tests: 71 → 77 pass / ~2s (54 Domain + 23 Infra).
Skip Phase 3 full (UpsertOpinion + Budget link validation) — cần
Identity UserManager DI helper, defer session sau.

==== 3 gotcha CI mới (#39 #40 #41) ====
- #39 act_runner github.com TCP timeout 21s → manual checkout fix (run #108/#109 fail, #110 pass)
- #40 npm junction cache `tsc not found` after Move-Item — rolled back, hypothesis nested junctions
  trong node_modules disrupt .bin/ paths. TODO debug session sau với robocopy hoặc act_runner cache.host
- #41 Gitea Actions paths-ignore behavior — workflow file change vẫn trigger (correct), commit
  MD-only skip 100% (verify 512880c → no run #113)
+ Checklist debug bug mới items 18-20 referencing 3 gotcha trên.

==== Doc updates (8 file) ====
- STATUS.md: header Phase 8 update + 3 row Recently Done CI fixes + cumulative test 71→77
- HANDOFF.md: TL;DR + CI optimize section + Phase status + gotcha count 38→41
- migration-todos.md: Phase 8 §E updated với Phase 3 mini done + CI fixes
- rules.md §7 Testing: rewrite full — stack + test pyramid + quy tắc bổ sung mỗi feature +
  workflow user end-of-task (`dotnet test` local trước push) + CI gate behavior
- architecture.md §11: update test pyramid + phased priority + CI optimization sub-section
  (3 fix manual checkout / path filter / npm cache rollback) + tốc độ deploy table
- gotchas.md: + #39 #40 #41 đầy đủ (triệu chứng + nguyên nhân + fix + reference)
- ef-core-migration SKILL: Phase 8 update note thêm CI fixes + 77 test
- CLAUDE.md root: test count 71→77 + folder structure + CI/CD pipeline 3 fix section
- memory project_solution_erp.md: session 5 summary + workflow user mới
- session log 2026-04-29-2300-chot-final-ci-tests-gotchas.md (NEW — 9 section detail)

==== Skill audit cron ====
`solution-erp-skill-audit-monthly` next fire 2026-05-01 (2 ngày sau).
Cron survives across sessions (setup commit b904a25). Khi fire sẽ:
- Cross-check 6 skill với STATUS/gotchas/migration-todos
- Auto-refresh stale + đề xuất add/archive cho human approve
- Log vào docs/changelog/skill-audit-2026-05.md
- ABORT nếu repo dirty

==== Verify ====
- dotnet test SolutionErp.slnx → 77 pass / ~2s (54 Domain + 23 Infra)
- git status clean sau commit này
- CI: commit này chứa code (test + workflow) → trigger CI test gate

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:43:42 +07:00
512880c5cb [CLAUDE] Docs: STATUS — note CI path filter live (test docs-only commit skip)
Test path filter on:push:paths-ignore — commit này CHỈ touch docs/STATUS.md.
Expected: Gitea Actions KHÔNG trigger run mới.
Verify bằng cách check Actions UI sau ~30s — vẫn ở run #112 (a21790d).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:39:44 +07:00
a21790d58d [CLAUDE] CICD: rollback npm junction cache (giữ path filter), fix #111 fail tsc not found
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m0s
Run #111 (commit 29eb5d9) FAIL với `'tsc' is not recognized` ở step Build fe-admin.
Symptoms confusing:
- VPS check: cache dir C:\npm-cache-erp\ chưa có (cold)
- Log: KHÔNG có Write-Host "cache MISS" hay "added 239 packages"
- Timing: 1.6s từ end-of-BE-build → start-of-fe-admin-build (impossible cho npm install 49s)
- Test gate (Domain 54 + Infra 17) PASS nên không phải code regression

Khả năng cao: junction Move-Item disrupted node_modules .bin/ structure HOẶC
act_runner PowerShell stream capture có quirk với cache MISS branch. Cần debug
riêng — không nên block deploy chính.

Decision:
- Rollback npm cache logic về fresh install như cũ (49s + 33s)
- GIỮ path filter on:push:paths-ignore (đây mới là win lớn nhất — 100% saving cho MD-only commit)
- Document gotcha cho session sau (sẽ thử robocopy thay vì junction, hoặc dùng act_runner cache server local)

Path filter behavior (giữ lại):
- Commit chỉ docs/MD/skill/gitignore → SKIP CI hoàn toàn (~196s/commit saved)
- Commit code OR cùng commit có code+docs → vẫn trigger (đúng)

Verify dotnet test local: 71 pass / 1s (BE không thay đổi).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:34:04 +07:00
29eb5d99a0 [CLAUDE] CICD: path filter docs-only + npm junction cache (Option C optimize ~2/3 deploy time)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 59s
Optimize CI/CD theo Option C bàn trong chat:

==== Path filter (saving 100% time cho commit MD-only) ====
on: push: paths-ignore mới — skip CI khi commit chỉ docs/skill/MD/gitignore.
- 'docs/**'
- '**/*.md'
- '.claude/skills/**'
- '.gitignore'
- 'scripts/**.md'

Commit 'Docs: chốt session' và similar sẽ KHÔNG trigger workflow → save 196s/commit.
Nếu cùng commit thay đổi cả MD + code → vẫn trigger (đúng behavior expected).
Workflow file `.gitea/workflows/**` chính NÓ thì không trong paths-ignore →
vẫn trigger khi sửa CI config (an toàn).

==== npm junction cache (saving ~70-80s code commit) ====
Replace Build fe-admin + fe-user steps với cache-aware version.

Strategy:
- Cache key = SHA256(package.json) 16-char prefix → đổi deps = miss → fresh
- Cache stored: C:\npm-cache-erp\<app>\<hash>\node_modules (ngoài workspace)
- Junction `fe-admin\node_modules → cache` (instant, không file copy)
- Lần đầu (cold): 49s + 33s = 82s (như cũ)
- Lần sau (warm): mklink instant + skip npm install → ~3s + 3s = 6s (saving ~76s)

Safety:
- Trước Deploy: convert junction → nothing (cmd /c rmdir /q chỉ remove ref,
  không follow target). Tránh trường hợp act_runner cleanup workspace
  follow junction + delete cache.
- Pruning: keep top 5 cache per app (~250MB × 5 × 2 = 2.5GB max disk usage).
  Stale evicted FIFO theo LastWriteTime DESC.

Vite 8 rolldown native binding gotcha (#20) vẫn respect: cache install trên
runner Windows nên rolldown binding match → reuse được.

==== Expected ====
- Commit MD-only: 0s CI (skip hoàn toàn)
- Commit code lần đầu sau cache miss (vd npm update): ~3min (như cũ)
- Commit code thường (cache hit): ~120s = 2 phút (giảm 38%)

Verify dotnet test local: 71 pass / 2s (BE không thay đổi).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:24:09 +07:00
14b7d18ecc [CLAUDE] CICD: bỏ uses: actions/* — manual git checkout từ Gitea (fix #108/#109 fail)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m16s
Vấn đề persistent (run #108#109 đều fail trong 21-22s):
  Get "https://github.com/actions/checkout/info/refs?service=git-upload-pack":
    dial tcp 20.205.243.166:443: connectex: connection failed/timeout

act_runner v0.2.13 mỗi run đều `git fetch` actions/checkout từ github.com
để check update — VPS network → github.com TCP timeout 21s liên tục →
toàn job fail TRƯỚC khi tới test gate.

Fix: thay actions ngoài bằng native shell, eliminate github.com dependency.

- Replace `uses: actions/checkout@v4` → manual `git init` + `git fetch`
  từ Gitea internal network (luôn ổn định, không qua public internet)
  - Auth: github.token (act_runner cũng dùng tên này) — tự sẵn per job
  - Fetch by ref (branch) thay vì SHA, depth=30 đủ buffer nếu main commit
    thêm trong lúc job pickup
  - Checkout đúng commit SHA của event push
  - Log 1-line để confirm checkout đúng

- Replace `uses: actions/upload-artifact@v4` (cũng phụ thuộc github.com)
  → step "List test results" local. TRX file vẫn save trong workspace
  test-results/, đọc qua runner workspace nếu cần debug.

Test gate giữ nguyên (Domain + Infra). dotnet test local 71 pass / 2s.

Long-term option (nếu Gitea Actions thêm hỗ trợ): config `github_mirror`
trong gitea-runner config.yaml để mirror github.com → Gitea internal,
hoặc pre-cache actions/* repos vào runner cache dir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 16:21:12 +07:00
26075c40f3 [CLAUDE] CICD: re-trigger deploy after transient github.com network timeout (commit 52999f3)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 21s
Run #108 failed in 22s với:
  Get "https://github.com/actions/checkout/info/refs?service=git-upload-pack":
  dial tcp 20.205.243.166:443: connectex: A connection attempt failed
  because the connected party did not properly respond...

Network từ VPS → github.com bị timeout transient lúc act_runner clone
`actions/checkout@v4` source. Test gate chưa kịp chạy.

Verify network giờ đã ok (TcpTestSucceeded: True) + dotnet test local
71 pass / 2s. Empty commit để re-trigger CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 16:13:45 +07:00
52999f33fa [CLAUDE] Docs: chốt session 5 — Budget FE + PE feature complete + Tests Phase 1-2 + CI gate
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 22s
Session 5 (29/04) — 6 commit feature + 1 chốt MD này.

==== Stats sau session 5 ====
- 52 DB tables (+1 PEDeptOpinions)
- 15 migrations (+`AddPurchaseEvaluationDepartmentOpinions`)
- ~128 API endpoints (+4)
- ~31 FE pages (+5 Budget + 1 PeWorkflowsPage)
- 71 unit test pass (54 Domain + 17 Infra) — CI gate live, fail → no deploy
- ~13050 BE LOC (+1300)
- 30 demo user, 38 gotchas, 6 skill (no change)

==== MD touched ====
- STATUS.md: header Phase 8 + 6 row Recently Done session 5 + cumulative cột S5 + In Progress S6 (Hard blockers + Optional polish + Tests Phase 3-5 + Ops)
- HANDOFF.md: TL;DR 6 milestone S5 + Cảnh báo S6 (CI test gate workflow mới) + Priority 0 S6 (UAT + Ops focus) + Phase status table cập nhật
- migration-todos.md: Phase 8 done với A/B/C/D/E (FE Budget / PE-HD integration / PE WF Designer / Ý kiến 4 PB / Tests Phase 1-2) + Phase 9 active (UAT + Ops + carry over)
- architecture.md: §11 Testing strategy mới (test pyramid bottom-heavy + stack + CI gate + phased priority + quy tắc bổ sung mỗi feature)
- database/schema-diagram.md: Migration 15 row + total 52 tables + §13 PE Department Opinion (1 bảng UNIQUE PEId+Kind + Upsert behavior + SQL DDL)
- ef-core-migration SKILL: migration 15 entry + 52 tables total + Phase 8 update note
- CLAUDE.md (root): modules table + Tests row + scope `Tests` + Tests section mới + count update 15/52
- docs/CLAUDE.md: 7 module bullet + ERD 52 bảng + Roadmap Phase 8 done + Phase 9 active S6
- memory project_solution_erp.md: Phase 8 summary + Session 6 priority + workflow user mới (dotnet test → commit → push)
- session log 2026-04-29-chot-session-5-budget-fe-pe-tests.md (NEW — 10+ section detail)

==== Verify ====
- dotnet test SolutionErp.slnx → 71 pass / 2s
- git status clean sau commit này

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:50:54 +07:00
df5988b7a9 [CLAUDE] Tests Phase 2: Code generator format + sequence tests (SQLite in-memory)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m16s
Phase 2 — chống regression code generator. 17 test mới integration với
DB thật (SQLite in-memory) tổng cộng 71 test pass < 3 giây.

Test project:
- tests/SolutionErp.Infrastructure.Tests/ (xUnit + FluentAssertions + EF SQLite 10)
- ProjectReference SolutionErp.Infrastructure (transitively get Application + Domain)
- Added vào SolutionErp.slnx

Test fixtures:
- Common/SqliteDbFixture.cs:
  - SQLite ":memory:" + shared connection + EnsureCreated() từ DbContext model
  - TestApplicationDbContext subclass — override OnModelCreating replace
    'nvarchar(max)' → 'TEXT' (SQLite không support max keyword)
  - FixedDateTime stub IDateTime cho deterministic year boundary test

Test files:
- Services/ContractCodeGeneratorTests.cs (10 test):
  - Format per ContractType (5 type × Project scope) — RG-001 spec
  - Framework HĐ (NguyenTacNCC + NguyenTacDV) → year scope thay vì project
  - Sequence increment per prefix (3 calls → /01, /02, /03)
  - Different prefixes (project / supplier) → independent sequences
  - Year change (2026 → 2027) → reset sequence vì prefix khác
  - PersistsSequenceRow LastSeq verification
- Services/PurchaseEvaluationCodeGeneratorTests.cs (7 test):
  - Format A/B (DuyetNcc → 'A', DuyetNccPhuongAn → 'B')
  - Seq là 3-digit padded (001..012)
  - Type A và B sequence độc lập trong cùng năm
  - Year boundary reset cả A và B

CI gate update (.gitea/workflows/deploy.yml):
- Step "Run integration tests (Infrastructure)" thêm sau Domain tests
- TRX log saved riêng (infra-tests.trx)
- Cả 2 step đều exit non-zero → no deploy

Verify local:
- dotnet test SolutionErp.slnx → Total tests: 71 (54 Domain + 17 Infra) / Passed: 71 / 2.1s
- dotnet build SolutionErp.slnx → 0 error

Phase 3+ pending:
- Application handler tests (CQRS) với EF InMemory hoặc SQLite (~1 ngày)
- API smoke tests qua WebApplicationFactory (~0.5 ngày)
- FE Vitest cho lib utility (~0.5 ngày)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:29:06 +07:00
d3f9346840 [CLAUDE] Tests Phase 1: Domain unit tests + CI gate (xUnit + FluentAssertions)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m25s
Phase 1 (MVP) — chống regression Workflow state machine. 54 test pure
function (no DB / IO), all pass < 7 giây.

Test project:
- tests/SolutionErp.Domain.Tests/ (xUnit 2.9.3 + FluentAssertions 7.2 — pin trước v8 commercial license)
- ProjectReference SolutionErp.Domain
- Added vào SolutionErp.slnx folder /tests/

Test files:
- Contracts/WorkflowPolicyTests.cs (~17 test):
  - Standard policy 9-phase: role transitions, CCM check, BOD signing, terminal
  - SkipCcm policy 7-phase: bypass CCM verify, no DangKiemTraCCM transition
  - Registry: DefaultPolicyName per ContractType (7 type), bypass flag override
  - FromDefinition versioned: build từ ordered steps + reject path + TuChoi auto-add + UserKindApprover populate UserTransitions
- PurchaseEvaluations/PurchaseEvaluationPolicyTests.cs (~17 test):
  - NccOnly (A) 3-step: skip ChoDuAn + ChoCEODuyetPA, CCM đẩy thẳng CEO duyệt NCC
  - NccWithPlan (B) 5-step: có ChoDuAn (PM) + ChoCEODuyetPA (Director) trước
  - Reject path cả 2 quy trình về DangSoanThao
  - Registry mapping per PEType
- Budgets/BudgetPolicyTests.cs (~13 test):
  - Default 3-step (Drafter→CCM→CEO) role guard
  - Reject paths về DangSoanThao
  - DaDuyet + TuChoi terminal (no NextPhases)
  - SLA spec 5d/3d/2d cho 3 phase đầu

CI gate (.gitea/workflows/deploy.yml):
- Step "Run unit tests (Domain)" thêm TRƯỚC build/publish/deploy
- Test fail (LASTEXITCODE != 0) → exit → KHÔNG deploy
- TRX log saved + upload artifact (continue-on-error nếu Gitea runner thiếu actions/upload-artifact)

Verify local:
- dotnet test tests/SolutionErp.Domain.Tests → Total tests: 54 / Passed: 54 / 6.4s
- dotnet build SolutionErp.slnx (full solution incl. test project) → 0 error

Phase 2-5 pending (xem plan ở chat):
- Code generator atomic concurrency tests (Infra)
- DbInitializer reconcile drift tests (Infra)
- Application handler smoke tests (CQRS) với EF InMemory
- API smoke tests qua WebApplicationFactory
- FE Vitest cho lib utility (queryMatches, fmtMoney)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:19:15 +07:00
5d94bb449a [CLAUDE] PE: Workflow designer admin UI + Ý kiến 4 phòng ban (P1 Session 5)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m51s
==== Task 1: PE Workflow Designer admin ====

BE (mirror Contract WorkflowAdminFeatures pattern):
- Application/PurchaseEvaluations/PeWorkflowAdminFeatures.cs ~250 LOC:
  - GetPeWorkflowAdminOverviewQuery → list 2 EvaluationType (DuyetNcc / DuyetNccPhuongAn) với Active + History versions + count phiếu đang dùng
  - CreatePeWorkflowDefinitionCommand + Validator: auto-increment Version per Code, deactivate Active cũ trong cùng EvaluationType (1 active per type invariant)
  - DTOs: PeWorkflowStepApproverDto / PeWorkflowStepDto / PeWorkflowDefinitionDto / PeWorkflowTypeSummaryDto / PeWorkflowAdminOverviewDto
  - Phase validation 1..7 (state thường, không bao gồm 99=TuChoi)
- Api/Controllers/PeWorkflowsController.cs: 2 endpoint GET /api/pe-workflows + POST. Reuse policy "Workflows.Read" + "Workflows.Create" (admin chung quyền cho cả 2 nhóm WF).

FE:
- pages/system/PeWorkflowsPage.tsx ~500 LOC mirror WorkflowsPage:
  - Landing 2-card grid khi /system/pe-workflows (chưa pick type)
  - TypePanel khi /system/pe-workflows/:typeCode (DuyetNcc / DuyetNccPhuongAn)
  - DefinitionCard read-only view với active badge + version + steps + approvers (Role/User chip)
  - PeWorkflowDesigner dialog: clone từ existing, edit Code/Name/Description, add/remove steps, +Role / +User approvers per step, save → version mới + deactivate cũ
- App.tsx route /system/pe-workflows + /system/pe-workflows/:typeCode
- Layout đã có resolver PeWf_<Code> → /system/pe-workflows/<code> từ session 3

==== Task 2: Ý kiến 4 phòng ban PE ====

Domain:
- PurchaseEvaluationDepartmentOpinion entity (AuditableEntity) — PEId + Kind + Opinion text + SignedAt + UserId + UserName denorm
- PeDepartmentKind enum (PheDuyet / Ccm / MuaHang / SmPm)
- PE entity + collection navigation DepartmentOpinions

Infrastructure:
- PurchaseEvaluationDepartmentOpinionConfiguration EF: UNIQUE(PEId, Kind) — max 1 row per phòng ban per phiếu (UPDATE in-place)
- ApplicationDbContext + IApplicationDbContext DbSet
- Migration 15 AddPurchaseEvaluationDepartmentOpinions (15 migration total / 52 DB tables)

Application:
- PeDepartmentOpinionFeatures.cs: UpsertPeDepartmentOpinionCommand (sign=true → set SignedAt+UserId, sign=false chỉ lưu text giữ chữ ký cũ) + DeletePeDepartmentOpinionCommand
- DTO bundle update: + DepartmentOpinions list trong PurchaseEvaluationDetailBundleDto
- GetPurchaseEvaluationQueryHandler load DepartmentOpinions + KindLabel resolution

API:
- POST /api/purchase-evaluations/{id}/opinions (upsert)
- DELETE /api/purchase-evaluations/{id}/opinions/{kind}

FE:
- types/purchaseEvaluation.ts: + PeDepartmentKind enum + PeDepartmentKindLabel + PeDepartmentOpinion type + departmentOpinions vào bundle
- PeDetailTabs Section "5. Ý kiến 4 phòng ban (sign-off)" — 2x2 grid OpinionBox per kind:
  - Read mode (readOnly menu Duyệt): hiển thị text + chữ ký
  - Edit mode: textarea + 2 button "Lưu text" / "Lưu & Ký"
  - Badge "Đã ký" emerald + tên người ký + ngày khi signedAt != null

==== Task 3: User seed verify ====

Seed `SeedDemoUsersAsync` đã match đúng user list authoritative (5 PRO TPB+NV / 7 CCM TPB+NV / 1 ISO / 1 CEO) từ prior commit. DbInitializer reconcile sẽ tự sync khi API restart. Typo trong list user (soluttions / trương) đã fixed sensibly trong seed.

==== Build verify ====
- dotnet build clean (0 error)
- fe-admin TS build pass (1 module mới PeWorkflowsPage)
- fe-user TS build pass (PE detail mirror)

Total: 8 file mới (BE 4 + FE 1 + Migration 2 + 1 Domain) + 13 file modified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:17:14 +07:00
7e36241db9 [CLAUDE] FE PE: restructure InfoTab theo spec PHIẾU TRÌNH KÝ CHỌN TP/NCC
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m3s
Match form chính thức 4 section đánh số:

1. Thông tin gói thầu — chỉ a. Tên gói thầu + b. Dự án (Địa điểm + Mô tả compact bên dưới nếu có).

2. Chọn NCC / TP — đúng a/b/c/d:
   a. NCC/TP được chọn — selectedSupplierName badge xanh
   b. Ngân sách — link Budget với mã + tên + tổng
   c. Giá chào thầu — tự compute = sum quotes của winner supplier (filter quotes.purchaseEvaluationSupplierId === winnerRowId)
   d. Bản so sánh — embed GeneralAttachmentsSection (attachments không gắn supplier-row, purpose=ComparisonTable)
   + ĐKTT + HĐ kế thừa link bonus
   + Banner emerald 'Tạo HĐ từ phiếu' khi DaDuyet + chưa có Contract

3. NCC/TP tham gia — section riêng giữ table 5 cột (NCC/Liên hệ/ĐKTT/File/Action — nhiều info hơn spec table 3 cột, useful cho UX web).

4. Hạng mục + Báo giá — matrix với cột 'NS link · Δ' + footer aggregate (giữ nguyên).

Side change:
- FormRow helper mới (label 176px + value flex) thay cho dl grid 2-col cũ — match style form giấy
- Drop Field helper cũ (now unused)
- InfoTab signature đổi: bỏ readOnly param (chỉ display, action move sang ChonNccSection)

TS build pass cả 2 app. Mirror fe-user identical.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:02:45 +07:00
61e5d4d503 [CLAUDE] PE+Contract+Budget integration — link Budget vào PE/HĐ + cột So với ngân sách
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m51s
BE wire BudgetId nullable FK qua command + DTO bundle:
- Budgets.Dtos: + BudgetSummaryDto (compact header snapshot, không kèm Details — gọi /budgets/{id} riêng nếu cần đối chiếu chi tiết)
- PurchaseEvaluations.Dtos: + BudgetId? + Budget? BudgetSummaryDto vào PurchaseEvaluationDetailBundleDto
- Contracts.Dtos: + BudgetId? + Budget? BudgetSummaryDto vào ContractDetailDto
- CreatePE + UpdatePEDraft + handlers: + BudgetId? param + validate (cùng Project + Phase=DaDuyet) + persist
- CreateContract + UpdateContractDraft + handlers: + BudgetId? param + validate + persist + log diff
- GetPE + GetContract handlers: load BudgetSummary nếu có link
- CreateContractFromEvaluation: carry forward pe.BudgetId → contract.BudgetId (nếu phiếu PE đã link)

FE PE (cả 2 app):
- types/purchaseEvaluation.ts: + BudgetSummary type + budgetId/budget vào PeDetailBundle
- PurchaseEvaluationCreatePage: thêm Select 'Ngân sách' filter Phase=DaDuyet + Project match (BE-side filter qua /budgets?projectId=&phase=4). Disabled khi chưa pick Project. Edit mode preserve.
- PeDetailTabs InfoTab: hiển thị Budget link với mã + tên + tổng (clickable → /budgets?id=)
- PeDetailTabs ItemsTab: thêm cột 'NS link · Δ' chỉ hiện khi ev.budgetId. Match per-row qua key groupCode|itemCode → fetch /budgets/{id} riêng. Footer aggregate row 'Tổng' + delta indicator (xanh dưới / đỏ vượt / xám khớp). No-match cell hiện '—'.

FE Contract (cả 2 app):
- types/contracts.ts: + ContractBudgetSummary + budgetId/budget vào ContractDetail
- ContractCreatePage HeaderForm: thêm Budget Select sau FormFields, useEffect reset khi đổi project
- ContractCreatePage EditForm: Select khi isDraft / read-only link card khi !isDraft

TS build pass cả 2 app + dotnet build clean. No new migration (BudgetId? nullable FK đã có từ migration 14).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 16:41:11 +07:00
df12fb19c8 [CLAUDE] FE-Admin+FE-User: Module Ngân sách (Budget) FE — 3-panel List + Create + Detail tabs + Workflow timeline
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m59s
Mirror pattern PE 3-panel cho 2 app (admin + user):

- types/budget.ts (BudgetPhase 5-state enum + label/color, BudgetListItem, BudgetDetailRow, BudgetApproval, BudgetWorkflowSummary, BudgetChangelog, BudgetDetailBundle, BudgetDetailBody)
- components/budgets/BudgetDetailTabs.tsx — flat render Section "Thông tin" Header + Section "Hạng mục" table CRUD inline (Add/Edit/Delete dialog với auto-compute ThanhTien = KL × DonGia). Export BudgetApprovalsSection + BudgetHistorySection cho Panel 3 reuse.
- components/budgets/BudgetWorkflowPanel.tsx — Panel 3 timeline activePhases + nextPhases buttons (Approve/Reject color coding) + Dialog xác nhận có comment + sub-section Approvals + Changelog.
- pages/budgets/BudgetsListPage.tsx — 3-panel [340px_1fr_360px] với search + filter Phase + filter NamNganSach. ?phase=Pending alias FE filter 2 phase ChoCCM/ChoCEO. SlaTimer per row + readOnly mode khi pendingMe.
- pages/budgets/BudgetCreatePage.tsx — form Header (TenNganSach/Năm/Dự án/Phòng ban/Mô tả). Edit mode khóa Project+Department.
- App.tsx routes /budgets, /budgets/new, /budgets/:id cả 2 app
- Layout.tsx menu resolver Bg_List → /budgets, Bg_Create → /budgets/new, Bg_Pending → /budgets?phase=Pending. NavLink active dùng queryMatches helper (gotcha #34 — không conflict Bg_List vs Bg_Pending cùng pathname).

TS build: cả fe-admin + fe-user pass clean (1918 + 1901 modules).
BE: dùng 11 endpoint Budgets từ migration 14 (Phase 7 BE đã deploy commit a05c57b).

Tổng FE: +12 file (5 fe-admin + 5 fe-user + 2 mod App/Layout × 2). ~1100 LOC TSX.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 16:25:22 +07:00
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
a05c57b081 [CLAUDE] Domain+App+Api: Module Ngan sach (Budget) - 4 bang + workflow simple
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m11s
User request: 'Them cho tao 4 bang luu ve ngan sach: Header / Chi tiet
/ Quy trinh duyet / Lich su thay doi'.

Domain (5 file + 1 enum):
 - Budget (header) — Aggregate root, AuditableEntity. Field: MaNganSach,
   TenNganSach, Description, NamNganSach, ProjectId FK, DepartmentId?,
   DrafterUserId, Phase (BudgetPhase 5-state), TongNganSach (sum auto
   tu Details), SlaDeadline, SlaWarningSent.
 - BudgetDetail — flat row pattern (GroupCode/GroupName + Item +
   KhoiLuong/DonGia/ThanhTien). 18,4 precision KhoiLuong, 18,2 money.
 - BudgetApproval — workflow history (FromPhase/ToPhase/Decision/Comment)
 - BudgetChangelog — audit log unified (EntityType: Header/Detail/Workflow)
 - BudgetPhase enum 5 state: DangSoanThao(1) → ChoCCM(2) → ChoCEO(3) →
   DaDuyet(4) | TuChoi(99)
 - BudgetPolicy hardcoded (no versioned WF, simple default per user
   confirm 'tam thoi don gian'): Drafter/DeptManager → CCM → CEO/
   AuthorizedSigner. Reject path back to DangSoanThao.

Migration 14 AddBudgets:
 - 4 bang moi: Budgets + BudgetDetails + BudgetApprovals + BudgetChangelogs
 - Index: Phase+IsDeleted, ProjectId, NamNganSach, SlaDeadline,
   MaNganSach unique filtered. Cascade delete child.
 - +2 cot FK ngoai bang (per user 'lien ket ca 3'):
   * Contracts.BudgetId Guid? + index
   * PurchaseEvaluations.BudgetId Guid? + index
   Cho phep doi chieu chi phi HD/PE vs ngan sach goi thau.

Application CQRS (BudgetFeatures.cs ~340 line):
 - CreateBudget + UpdateBudgetDraft + TransitionBudget + ListBudgets
   (filter Phase/Project/Year + search + paging) + GetBudget bundle
   (Header + Details + Approvals + Workflow summary)
 - DeleteBudget (only DangSoanThao/TuChoi)
 - AddBudgetDetail + UpdateBudgetDetail + DeleteBudgetDetail (auto
   recompute TongNganSach = sum Details.ThanhTien)
 - ListBudgetChangelogs

Api: BudgetsController 11 endpoint REST /api/budgets:
 - GET /  /{id}  /{id}/changelogs
 - POST /  /{id}/transitions  /{id}/details
 - PUT /{id}  /{id}/details/{detailId}
 - DELETE /{id}  /{id}/details/{detailId}

DbContext + IApplicationDbContext: 4 DbSet new (Budgets/Details/
Approvals/Changelogs).

MenuKeys + DbInitializer: 4 menu key (Budgets root + Bg_List/Create/
Pending leaves) seed dau order=27 'Ngan sach' icon Wallet. Auto-grant
admin permission via SeedAdminPermissionsAsync (MenuKeys.All).

MaNganSach format don gian 'NS-YYYYMM-NNNN' Random.Shared (chua atomic
sequence - user said 'tam thoi chua co').

Workflow chua versioned, hardcode BudgetPolicy.Default. Tuong lai admin
config qua UI: them BudgetWorkflowDefinition tables tuong tu PE.
2026-04-28 11:37:45 +07:00
8097892d20 [CLAUDE] Infra: them 14 demo users Solutions company (PRO 5 + CCM 7 + ISO 1 + CEO 1)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m11s
User cung cap danh sach nhan vien thuc te. Add vao SeedDemoUsersAsync,
idempotent (FindByEmail trong reconcile pattern). Pass = User@123456
(matching demo pattern, policy 12 char + digit + lower + upper + special).

PRO (5):
 - tra.bui — Bui Le Thuy Tra — TP Cung ung (Procurement+DeptManager)
 - phuong.nguyen — Nguyen Thi Bich Phuong (Procurement+Drafter)
 - thanh.lethanh — Le Thanh Binh (Procurement+Drafter)
 - long.chau — Chau Ta Kim Long (Procurement+Drafter)
 - duy.nguyen — Nguyen Van Duy (Procurement+Drafter)

CCM (7):
 - chuong.phan — Phan Van Chuong — TP Kiem soat Chi phi (CostControl+DeptManager)
 - binh.le — Le Van Binh (CostControl)
 - luu.tran — Tran Xuan Luu (CostControl)
 - nguyen.ho — Ho Thi Nu Nguyen (CostControl)
 - anh.nguyen — Nguyen Thi Kim Anh (CostControl)
 - tring.le — Le Tu Dang Trinh (CostControl) — giu literal user provided
 - truong.le — Le Tran Dang Truong (CostControl)

ISO (1):
 - long.nguyen — Nguyen Hoang Chanh Long — Dep HRA, role HrAdmin (dong dau HD)

CEO (1):
 - truong.nguyen — Nguyen Van Truong — Dep BOD, role Director (ASCII fix tu 'truong.nguyen' co dau)

Email typo fix:
 - 'phuong.nguyen@soluttions.com' → 'phuong.nguyen@solutions.com.vn'
 - 'truong.nguyen' co dau → 'truong.nguyen' ASCII (KHONG conflict voi truong.le CCM)

Reconcile pattern dam bao: neu user da exist (email collision), update
dept/position/role thay vi error. Pass khong overwrite cho existing user.
2026-04-28 10:51:56 +07:00
309dcd9768 [CLAUDE] Docs: chot final session 3 — audit MD + session log + minor fixes
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m58s
Audit toan bo MD theo yeu cau 'review cap nhat va tai cau truc'.

Minor fixes outdated:
 - docs/database/database-guide.md: header note '47 bang 13 migration' +
   redirect schema-diagram cho actual schema. Email demo +
   admin@solutions.com.vn (thay solutionerp.local).
 - docs/guides/runbook.md: reset-password email moi.

Session log moi: docs/changelog/sessions/2026-04-25-1430-chot-session-3-
final-cleanup.md
 - Cleanup outcomes: archive 2 raw + compact migration-todos -71% +
   compact STATUS In Progress -50% + update outdated refs.
 - Skill audit 6 skill: tat ca Active (3 skill da update voi PE/G-084
   cross-ref session truoc).
 - Stats session 3 cong don 3 phien 23-24-25: 47 DB tables, 13 migrations,
   ~113 endpoints, 38 gotchas, ~30 commits.
 - Priority 0 session 4: 3 PE feature gap (Designer UI, Y kien 4 phong
   ban, Export PDF) + Ops blockers.
 - Notes session 4: email moi, 3 domain prod, old fallback, G-084, SSH.
2026-04-25 23:40:11 +07:00
e71e0eba65 [CLAUDE] Docs: tai cau truc cleanup — archive raw, compact migration-todos, update CLAUDE+flows
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s
User request: 'review cap nhat va tai cau truc lai MD sao cho phu hop
voi hien tai, cac phan thua va da dieu chinh co the bo ra luon hoac
cap nhat lai'.

Cleanup highlights:
1. Archive 2 file Phase 0 raw dump → docs/_archive/ (forms-spec-raw 657
   line + workflow-raw 62 line). Update link reference 2 file goc.
2. Compact migration-todos.md 386 → 114 line (-71%). Collapse Phase 0-5
   + Tier 3 + Sessions detailed thanh 1 bang summary. Detail xem session
   logs. Phase 6 iter 1+2 + Phase 7 active checklist.
3. Compact STATUS.md In Progress: bo ~17 row  done (giu chỉ 5+ task
   pending: 3 PE feature gap + 4 optional polish + 2 Ops). Recently Done
   table giu day du history.
4. Update flows/README — tat ca 6 flow  Implemented + them PE row
   reference architecture.md §9.
5. Update docs/CLAUDE.md — project layout co PurchaseEvaluations, _archive,
   skills 6 (3 dom + 3 ops). Roadmap them Phase 6  + Phase 7 WIP. Lien
   he them prod URL solutions.com.vn + SSH config + login admin.
6. Skill ef-core-migration: 13 migration label.

Net delta: -800 line docs (chu yeu archive + collapse migration-todos).
2026-04-25 14:17:53 +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
a336997cfe [CLAUDE] PE: section Bang so sanh + rename demo email @solutions.com.vn
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m10s
PART A: Section 'Bang so sanh' (file tong ho so so sanh)

User request: 'theo them cho thong tin ve Bang so sanh, cho dinh kem
file so sanh tong len'.

BE:
 - PurchaseEvaluationAttachmentPurpose.ComparisonTable = 4 (new enum value)
   Backend validator IsInEnum pass, khong can migration (int column).

FE types (2 app):
 - PeAttachmentPurpose.ComparisonTable + Label '4: Bang so sanh'.

FE PeDetailTabs:
 - Them section thu 4 'Bang so sanh (file tong)' sau 'Hang muc + Bao gia'.
 - Component GeneralAttachmentsSection: upload KHONG truyen supplierRowId
   (BE luu NULL) → purpose=ComparisonTable default. Filter attachments
   co supplierRowId===null de render.
 - Card layout khac SupplierAttachmentsCell: full-width card + brand color
   + purpose chip + date. Upload button to hon ([+ Tai len bang so sanh]).
 - readOnly hide upload + delete, giu download.

PART B: Demo email rebrand @solutionerp.local → @solutions.com.vn

User request: 'tao nguoi dung demo theo email cua ben nay'.

BE DbInitializer:
 - Rename 18 email in source: AdminEmail const + 17 demo users
   (bod/pm/ccm/pro/fin/act/equ/hra/qs/nv) — keep password + role unchanged.
 - Them BackfillUserEmailDomainAsync (idempotent): scan user co email
   @solutionerp.local, rename sang @solutions.com.vn, update Email +
   NormalizedEmail + UserName + NormalizedUserName. Skip neu co conflict
   user da ton tai voi email moi. Chay truoc SeedAdmin de tranh tao
   duplicate admin.

Admin permission tao user da co san qua /system/users page.
Comment input khi duyet da co san o PeWorkflowPanel (Ghi chu tuy chon
Textarea) + ContractDetailContent (Yeu cau sua / Duyet tiep dialog).
2026-04-24 15:08:00 +07:00
eda9e84187 [CLAUDE] PE: readOnly mode cho menu 'Duyet' (pendingMe=1)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m50s
User request: 'Menu duyet cua NCC -> chi de duyet thoi nhe khong co cac
action them sua j vao'.

Them readOnly prop vao PeDetailTabs — propagate xuong 3 sub-component
(InfoTab / SuppliersTab / ItemsTab) + SupplierAttachmentsCell. URL
pendingMe=1 (menu 'Duyet') → set readOnly=true.

Hide khi readOnly:
 - Header: [Sua header] [Xoa] button
 - SuppliersTab: [+ Them NCC] button + action column (Check winner/Pencil
   edit/Trash delete per row)
 - ItemsTab: [+ Them hang muc] button + action column (Pencil/Trash per
   row) + click cell bao gia popup
 - SupplierAttachmentsCell: [+ Them file] button + Trash delete icon
   (giu download tren file name)
 - InfoTab: [Tao HD tu phieu] button

Giu:
 - Moi thong tin doc-only
 - Download file dinh kem (click ten file)
 - Panel 3: Quy trinh + transition button (de action duyet phase)
 - [Dong] button
 - Chip 'che do duyet' gan phase badge de user biet mode

Mirror fe-admin + fe-user.
2026-04-24 13:13:40 +07:00
8cf1fe214a [CLAUDE] FE: HĐ move Lich su dieu chinh sang Panel 3 duoi Lich su duyet
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m55s
User request: 'cho hop dong dua cac thong tin lich su dieu chinh sang
duoi lich su duyet nhen'.

ContractDetailContent (Panel 2): xoa section 'Lich su dieu chinh' (cot
3/10 grid 7/3) → Chi tiet HD gio full-width. Remove import History +
ContractChangelogsTab.

WorkflowHistoryPanel (Panel 3): them section Lich su dieu chinh duoi
Lich su duyet. Import History icon + ContractChangelogsTab. Reuse same
component, chi doi vi tri render.

Mirror fe-admin + fe-user.
2026-04-24 13:06:18 +07:00
d1090843a2 [CLAUDE] PE: upload file dinh kem per-NCC (doi chieu bao gia)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m9s
User request: 'cho cac NCC 1,2 va 3 thi cho them cho upload file dinh
kem cho tung NCC de co the doi chieu'.

Entity PurchaseEvaluationAttachment + PurchaseEvaluationSupplierId nullable
da thiet ke san tu migration 12 — gio wire up BE + FE.

BE (Application/Api):
 - PurchaseEvaluationAttachmentFeatures: Upload (multipart + supplierRowId
   optional) + Download + Delete. Reuse IFileStorage + LocalFileStorage.
   Validator 20MB + MIME whitelist (pdf/doc/docx/xls/xlsx/png/jpg/webp).
 - Upload log vao PurchaseEvaluationChangelogs (Attachment + Insert).
 - PurchaseEvaluationAttachmentDto + them field Attachments vao bundle.
 - GetPurchaseEvaluationQueryHandler Include(x => x.Attachments) +
   OrderByDescending(a => a.CreatedAt) projection.
 - PurchaseEvaluationsController 3 endpoint:
   POST /attachments (IFormFile + [FromForm] supplierRowId/purpose/note)
   GET /attachments/{attId}/download (File stream)
   DELETE /attachments/{attId}
 - Storage path: wwwroot/uploads/purchase-evaluations/{id}/{attId}_{safeName}

FE (fe-admin + fe-user):
 - Type PeAttachment + PeAttachmentPurpose/Label (QuoteDocument default)
 - PeDetailBundle.attachments: PeAttachment[]
 - SuppliersTab thay column Hien thi + Ghi chu bang column File dinh kem
   (per-NCC upload + list N attachments + download + delete).
 - SupplierAttachmentsCell component: <input type=file> hidden + [+ Them
   file] button + inline list attachments voi Paperclip icon + filename
   (click tai ve) + size + purpose chip + Trash2 delete.
2026-04-24 12:44:08 +07:00
68938a521a [CLAUDE] FE: PE detail flat layout — Panel 2 gop 3 section, Panel 3 them approvals + history
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m59s
User request: 'cho tat ca cai nay the hien tren dung 1 man hinh nhe, cai
duyet va lich su thi dua sang panel 3'.

Panel 2 (PeDetailTabs): truoc 5 tab (Info/NCC/Items/Approvals/History).
Sau bo tabs, flat render 3 section stack doc voi divider + title uppercase:
  Thong tin → NCC tham gia (N) → Hang muc + Bao gia (N)

Panel 3 (PeWorkflowPanel): truoc chi workflow timeline + transition btn.
Sau them 2 section ben duoi:
  Workflow timeline → Lich su duyet (PeApprovalsSection) → Lich su thay doi
  (PeHistorySection)

Export PeApprovalsSection + PeHistorySection tu PeDetailTabs — reuse
ApprovalsTab + HistoryTab logic cu, wrap them <h3> section title.

Dong bo ca fe-admin + fe-user (copy identical file).
2026-04-24 11:44:19 +07:00
fc4b3d6078 [CLAUDE] FE: NavLink active check query string (khong chi pathname)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m51s
Bug: click leaf 'Duyet' (/purchase-evaluations?type=2&pendingMe=1) khien
leaf 'Danh sach' (/purchase-evaluations?type=2) cung highlight cung luc.
Nguyen nhan: NavLink 'end' prop chi match pathname. 2 leaf cung pathname
/purchase-evaluations → ca 2 active.

Fix: custom isActive voi queryMatches helper — compare query string dang
key-value set (thu tu param khong quan trong). 2 leaf chi active khi
pathname + query dung khop.

Dong bo ca fe-admin + fe-user. Anh huong tat ca menu leaf co ?query=
variants: Ct_* (Danh sach /contracts?type=N vs Duyet /contracts?type=N&
pendingMe=1), Pe_* (tuong tu /purchase-evaluations), admin workflow leaf
Wf_* + PeWf_* (khong dinh vi path khong query params).
2026-04-24 11:23:56 +07:00
79398fb41f [CLAUDE] FE: accordion mutex Pe_* + sidebar width w-72 + label nowrap
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m56s
2 fix user session 3:

1. Accordion mutex cho Pe_ groups (2 phieu Duyet NCC + Duyet NCC va
   Giai phap) — truoc chi Ct_ (7 HD) co mutex, Pe_ dung localOpen rieng
   → user click 1 Pe_ group xong click Pe_ khac → ca 2 expanded cung luc.
   Fix: extend AccordionContextValue + expandedPeCode + INT_TO_PE_CODE
   map. MenuGroup branch: isCtAccordion || isPeAccordion (families doc
   lap — user co the mo 1 Ct_ + 1 Pe_ cung luc). useEffect URL sync:
   /purchase-evaluations?type → Pe; /contracts* ?type → Ct.

2. Sidebar width w-64 (256px) → w-72 (288px) de label QUY TRINH CHON
   THAU PHU - NCC (30 char uppercase tracking-wide) fit single-line
   thay vi wrap 2 dong. Top-level group class:
     text-xs tracking-wider → text-[11px] tracking-wide + whitespace-nowrap
   Dong bo ca fe-admin + fe-user.
2026-04-24 11:13:29 +07:00
7783bd6005 [CLAUDE] App: menu tree inheritance mo rong Pe_* + PeWf_*
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m54s
GetMyMenuTreeQuery truoc chi inherit Contracts (Ct_*) va Workflows
(Wf_*). Extend 2 root moi PurchaseEvaluations (Pe_*) + PeWorkflows
(PeWf_*) de admin co PurchaseEvaluations.Read auto thay 2 group Pe_* +
6 leaf (Danh sach/Thao tac/Duyet x 2 type) + 2 PeWf_* leaf admin designer
UI, khong can add per-subitem permission row.

Verify bug: /menus/me cho admin hien chi root 'PurchaseEvaluations'
+ 'PeWorkflows' nhung khong co Pe_DuyetNcc group / Pe_DuyetNccPhuongAn
group children du DB co 12 row (sqlcmd confirm). Root cause: hardcoded
2 inherit roots trong BuildChildren switch.

Fix: expand switch cover 4 inherit roots. Propagate nextInherit xuong
tat ca descendants.
2026-04-24 11:03:07 +07:00
7ee105df12 [CLAUDE] PE: rename menu + workflow Phuong An -> Giai phap
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m27s
User request session 3 mở đầu: đổi label menu:
  'Quy trình Duyệt NCC - Phương Án' -> 'Duyệt NCC và Giải pháp'
  'Quy trình Duyệt NCC' -> 'Duyệt NCC' (bỏ prefix 'Quy trình')

Giữ nguyên (không breaking):
  - Enum value PurchaseEvaluationType.DuyetNccPhuongAn = 2
  - Menu key Pe_DuyetNccPhuongAn_* (FK ref)
  - typeCode string 'DuyetNccPhuongAn' (URL routing)
  - Policy name 'NccWithPlan' + WorkflowDefinition.Code QT-DN-B

Changed (display-only):
  - DbInitializer SeedMenuTreeAsync peTypeLabels: 2 entry
  - DbInitializer SeedPurchaseEvaluationWorkflowsAsync WF name B
  - PurchaseEvaluationPolicy.cs NccWithPlan Description
  - fe-admin + fe-user types PurchaseEvaluationTypeLabel[2]

Backfill existing DB (seed idempotent skip-if-exists không update):
  - MenuItems Pe_DuyetNcc group + Pe_DuyetNccPhuongAn group + PeWf_* leaf
    → UPDATE Label nếu khác expected
  - WorkflowDefinitions QT-DN-B v01 → UPDATE Name Replace 'Phương Án' → 'và Giải pháp'
  Run mỗi start API — idempotent, fast no-op sau lần đầu.
2026-04-24 10:43:26 +07:00
de1ddc233d [CLAUDE] Docs: STATUS — backfill commit hash c48ac21 cho PE polish row
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:41:44 +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
0048a2e83a [CLAUDE] Docs: STATUS + HANDOFF domain migration E2E done (huypham.vn → solutions.com.vn)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 29s
2026-04-24 10:25:41 +07:00
a6676658a4 [CLAUDE] Infra: SeedDemoUsersAsync robust reconcile pattern + 16 demo users
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m48s
User feedback: prod chỉ thấy admin user, 13 demo seed cũ chưa apply →
fix robust + add thêm.

## Vấn đề trước

- Skip-if-exists pattern: nếu user nào đó tạo fail trước đó → never retry
- Không log error chi tiết khi CreateAsync hoặc AddToRoleAsync fail
- Không tự sửa khi user exists nhưng thiếu dept/position/roles (drift)
- 1 exception abort cả batch

## Fix: RECONCILE PATTERN

Mỗi run, per-user:
- **Nếu chưa có** → CreateAsync + AddToRoleAsync với detailed error log
- **Nếu đã có** → verify + fix nếu drift:
  * DepartmentId mismatch → update
  * Position mismatch → update
  * FullName mismatch → update
  * !IsActive → reactivate
  * Roles missing → AddToRoleAsync supplement
- **Try-catch per-user** → 1 fail không abort 15 còn lại
- **Detailed logging** — counts created/fixed/failed cuối cùng

## 16 demo users (3 thêm)

Trước 13 → giờ 16:
- BOD (3) — bod.huynh + bod.le + **bod.tran** (Phó GĐ Kỹ thuật NĐUQ thứ 2)
- PM (2) — pm.nguyen + **pm.le** (GĐ Vinhomes Ocean Park)
- TPB (6) — CCM/PRO/FIN/ACT/EQU/HRA — 1 mỗi (giữ nguyên)
- Drafter (5) — qs.hoang + qs.ngo + nv.cao + nv.dinh + **nv.truong**
  (NV CCM, làm cho ccm.tran)

Bổ sung: NĐUQ thứ 2 (test multi-AuthorizedSigner), PM thứ 2 (test
multi-project), Drafter trong CCM (test cùng dept với CCM TPB).

## Build

dotnet build BE pass (0 error).

## Note deploy

Khi deploy lên prod:
- HĐ user đã có → reconcile (sửa dept/position/role nếu drift)
- 13 user cũ chưa được tạo → CreateAsync với password User@123456
- 3 user mới (bod.tran, pm.le, nv.truong) → tạo mới
- Log: "Demo users reconcile xong: X created, Y fixed, Z failed.
  (Total demo: 16, password=User@123456 — ⚠ rotate prod)"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:20:43 +07:00
b93dacff44 [CLAUDE] Scripts: fix migrate-domains.ps1 ASCII-only (gotcha #30 PS 5.1)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m46s
2026-04-24 09:55:57 +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
3990066b04 [CLAUDE] Scripts+Skill+Docs: hardening G-084 IPv4/IPv6 port hijack
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s
Bài học từ VietReport VPS shared (2026-04-23): Next.js app hijack port
3000 IPv4 → Gitea bị đẩy IPv6-only → IIS ARR localhost:3000 resolve
IPv4 first → git.baocaogiaoduc.vn trả homepage VietReport.

Apply 3 rules G-084 preemptively cho SOLUTION_ERP (risk thấp vì API
in-process IIS, nhưng vẫn chuẩn hóa):

1. `scripts/deploy-iis.ps1` — HealthUrl `localhost` → `127.0.0.1`
2. `.claude/skills/iis-deploy-runbook/SKILL.md` — 7 ref localhost →
   127.0.0.1 + section Hardening mới giải thích G-084 + 3 rules + note
   SOLUTION_ERP relevance (risk thấp vì no standalone Kestrel/no ARR
   proxy hiện tại, nhưng tương lai thêm phải tuân)
3. `docs/gotchas.md` — thêm entry #33 G-084 full writeup (triệu chứng,
   root cause, 3 rules, SOLUTION_ERP relevance) + update debug
   checklist

3 rules:
- Reverse-proxy luôn IP literal 127.0.0.1, không localhost
- Backend services bind loopback IPv4 explicit, không 0.0.0.0
- Service dependency cho boot order khi nhiều service cùng port family
2026-04-23 17:34:22 +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
a385d70c2e [CLAUDE] App+Api+FE: Kế thừa HĐ từ phiếu Duyệt NCC (Phase 4)
BE:
 - CreateContractFromEvaluationCommand: guard DaDuyet + SelectedSupplier
   + ContractId=null → tạo Contract draft mới với SupplierId/ProjectId/
   DepartmentId kế thừa từ PE. GiaTri = sum(details.thanhTienNganSach).
   DraftData = PE.PaymentTerms. Gen MaHopDong ngay + pin WorkflowDefinitionId
   theo ContractType user chọn. Log Changelog cả 2 bảng (Contract +
   PurchaseEvaluation), link 2 chiều PE.ContractId = contract.Id.
 - ListApprovedPurchaseEvaluationsQuery: DaDuyet + ContractId=null cho
   FE picker.
 - 2 endpoint mới:
   GET  /api/purchase-evaluations/approved-pending-contract
   POST /api/purchase-evaluations/{id}/create-contract

FE:
 - PeDetailTabs InfoTab: nếu Phase=DaDuyet && !ContractId && SelectedSupplierId
   → banner emerald + button "Tạo HĐ từ phiếu" → CreateContractDialog
   (pick ContractType dropdown 7 loại + TenHopDong + bypass CCM flag)
 - Sau khi tạo → navigate /contracts/{newId}
 - Mirror fe-user.

KHÔNG auto-map PE Details → Contract Details per-type (PE schema ≠ 7
ContractType details schemas — user điền lại sau). PE → Contract link
qua FK ContractId cho navigation + history.
2026-04-23 16:58:41 +07:00
a737196b21 [CLAUDE] FE-Admin+FE-User: PurchaseEvaluation pages (3-panel list + tabs detail)
Types + pages + components cho module Duyệt NCC ở cả 2 FE (copy-share).

Pages:
 - PurchaseEvaluationsListPage: 3-panel lg:grid-cols-[340px_1fr_360px]
   * Panel 1: list filter theo type/phase/search + pendingMe inbox mode
   * Panel 2: PeDetailTabs (Thông tin/NCC/Hạng mục/Duyệt/Lịch sử)
   * Panel 3: PeWorkflowPanel với timeline + nextPhase buttons
   * Mobile fallback fullpage /purchase-evaluations/:id
 - PurchaseEvaluationCreatePage: form create/edit header (Type / Tên gói thầu
   / Dự án / Địa điểm / Mô tả / PaymentTerms JSON). Suppliers+Details+Quotes
   thêm sau khi save ở Detail tabs.

Components:
 - PeDetailTabs: 5 tab + dialogs (AddSupplier/EditSupplier/DetailDialog/
   QuoteDialog) + matrix N NCC × M hạng mục clickable cells + select winner
 - PeWorkflowPanel: policy timeline từ BE workflow.activePhases + transition
   confirmation dialog với comment

Routes (cả 2 app):
 - /purchase-evaluations (+ ?type=1|2&pendingMe=1&id=...)
 - /purchase-evaluations/new (+ ?type / ?id để edit)
 - /purchase-evaluations/:id (mobile fullpage)

Menu resolver:
 - Pe_<Code>_List → /purchase-evaluations?type=N
 - Pe_<Code>_Create → /purchase-evaluations/new?type=N
 - Pe_<Code>_Pending → /purchase-evaluations?type=N&pendingMe=1
 - PeWf_<Code> (fe-admin only) → /system/pe-workflows/<code>

Skip MVP: PE Workflow admin designer UI, PE Attachments. TS build pass
cả 2 app.
2026-04-23 16:56:26 +07:00
4678d192e2 [CLAUDE] App+Api: PurchaseEvaluation CQRS + Controller + WorkflowService
Application (4 file, ~900 lines):
 - IPurchaseEvaluationWorkflowService + PurchaseEvaluationDtos
 - PurchaseEvaluationFeatures: Create / UpdateDraft / Transition / List /
   Inbox / GetDetail (bundle Suppliers+Details+Quotes+Approvals+Workflow) /
   Delete / ListChangelogs. IDOR filter role-based phase eligibility.
 - PurchaseEvaluationSupplierFeatures: Add / Update / Remove supplier
   (N:M Phiếu × Supplier). Block remove nếu còn Quote FK reference.
 - PurchaseEvaluationDetailFeatures: Add/Update/Delete hạng mục +
   Upsert/Delete Quote + SelectWinner (set SelectedSupplierId).

Infrastructure:
 - PurchaseEvaluationWorkflowService: policy load pinned definition →
   guard role + transition rules. Emit Notification drafter khi
   state-change. Tạo PurchaseEvaluationApproval + Changelog row.

Api:
 - PurchaseEvaluationsController ~15 endpoint: CRUD phiếu, N:M supplier,
   hạng mục CRUD, Quote upsert, SelectWinner, Changelog list.
   Route /api/purchase-evaluations.

DI: đăng ký IPurchaseEvaluationWorkflowService scoped.

Skip MVP: Attachments upload, Admin PeWorkflows designer UI (sẽ phase sau
— framework versioned WF table đã sẵn, designer pattern copy từ HĐ).
2026-04-23 16:43:47 +07:00
2c6f0cabfb [CLAUDE] Domain+Infra: PurchaseEvaluation module — 10 bảng + 2 workflow seed (migration 12)
Module Duyệt NCC (tiền-HĐ): phiếu trình duyệt so sánh giá N NCC × M hạng
mục trước khi ký HĐ. 2 quy trình: A DuyetNcc (3-step: Purchasing→CCM→CEO),
B DuyetNccPhuongAn (5-step: Purchasing→DựÁn→CCM→CEO PA→CEO NCC).

Domain (7 core + 3 workflow admin):
 - PurchaseEvaluation (header, AuditableEntity, pin WorkflowDefinitionId,
   SelectedSupplierId, PaymentTerms JSON, ContractId? FK kế thừa)
 - PurchaseEvaluationSupplier (N:M Phiếu × Supplier + contact + payment term)
 - PurchaseEvaluationDetail (hạng mục + ngân sách, group A.I/A.II/...)
 - PurchaseEvaluationQuote (báo giá per NCC per hạng mục + IsSelected)
 - PurchaseEvaluationApproval (workflow history, reuse ApprovalDecision)
 - PurchaseEvaluationChangelog (audit log, reuse ChangelogAction)
 - PurchaseEvaluationAttachment (file upload — báo giá NCC + spec...)
 - PurchaseEvaluationWorkflowDefinition/Step/StepApprover (config y như HĐ,
   tách table riêng vì Phase là PurchaseEvaluationPhase enum riêng)

Policy:
 - PurchaseEvaluationPolicy record + PurchaseEvaluationPolicies.NccOnly/
   NccWithPlan (default hardcoded) + FromDefinition(def) build runtime policy
   từ DB admin-authored. Default SLA: soạn 3d, step 1-2d, CEO 1d.

EF: 10 configurations với index phase+isDeleted, SupplierId, ProjectId,
SlaDeadline, WorkflowDefinitionId, ContractId. UX index (PeId, SupplierId)
+ (DetailId, SupplierId). HasQueryFilter soft delete cho header.

Migration 12 AddPurchaseEvaluations tạo 10 bảng. Idempotent seed:
 - SeedMenuTreeAsync +13 menu item (Pe_* root + 2 group + 6 action leaf
   + PeWorkflows root + 2 admin leaf)
 - SeedPurchaseEvaluationWorkflowsAsync seed QT-DN-A-v01 + QT-DN-B-v01
2026-04-23 16:37:55 +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