[CLAUDE] Docs: S85 closeout — CV PRO batch + clear-data + 6 UAT round + 2 root-cause + 5 SQL-fix
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m51s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m51s
STATUS/HANDOFF prepend S85 (Mig 57 · 88 tables · 374 test · gotcha 73 · bundle admin aKuNip19/user BUsL0HeQ Run #341). gotchas +2: #72 DateTime serialize no-Z -> FE +7h (UtcDateTimeJsonConverter UTC-with-Z) · #73 UPDATE absolute-set clears field on FE-omit (bug-class S42, null-safe guard). + session log + scripts/s85-wipe-uat-data.sql (prod UAT wipe, backup-first, executed) + agent-memory residuals (inv-codebase PE-recon, test-specialist baseline 374). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -70,6 +70,7 @@ Bearer từ `POST api.solutions.com.vn/api/auth/login` → status matrix expecte
|
||||
|
||||
## 📅 Recent activity (compressed — full verbatim → `archive/2026-06.md` via `archive/_INDEX.md`)
|
||||
|
||||
- **2026-06-23 PE UAT recon D2/D4/D5 (anh Kiệt FDC go-live):** ⭐ (D2-urgent authz) `PurchaseEvaluationUrgentFeatures.cs:49-50` BẤT-ĐỐI-XỨNG `isPro=IsUrgent?hasPro:(hasPro&&isDeptManager)` — GẮN=role-only / GỠ=DeptManager-only. NO DrafterUserId match (handler chỉ load entity, never reads DrafterUserId). Để drafter gỡ cờ mình: sửa :49-50 OR `actor.Id==entity.DrafterUserId`. Endpoint `PUT /purchase-evaluations/{id}/urgent` (controller:91). ⚠️ cờ KHÔNG split-by-drafter (PRO/CCM = role, drafter ≠ tất nhiên PRO/CCM). (D5) FE PE-create dropdown=`PeWorkspaceCreateView.tsx:94-104` GET `/approval-workflows-v2?applicableType={1|2}` filter `isUserSelectable`. **Dev DB: PE type1/type2 selectable=0** (6 selectable đều type3-9 Contract/Proposal/Leave/OT/Xe/Ticket NOT PE) → prod UNVERIFIED (SSH-paren-quote-trap). Validator REQUIRE workflow CẢ 2 tầng: `PurchaseEvaluationFeatures.cs:48` create NotEmpty (S83) + submit-guard `PurchaseEvaluationWorkflowService.cs:225` ConflictException. (D4 required) create-validator `:35-57`: Type/TenGoiThau≤500/ProjectId/WorkItemId/ApprovalWorkflowId NotEmpty + BudgetPeriodAmount>0-when-present. Submit-guard `:174-228`: SelectedSupplierId + winnerQuoteTotal>0 + BudgetPeriodAmount>0 + Bảng-so-sánh-attachment + ApprovalWorkflowId. → _INDEX.
|
||||
- **2026-06-20 governance-landing map (RC-sig + User-Mark H12/13 + objective-criteria):** ⭐ WHERE-to-land 3 AI_INFRA gov broadcasts. `harness-11-engine.md` = CANONICAL engine (D5/D6/D7 safety-tier + D8 one-direction-lock + D9 single-writer + D10 Bash-residual + CAVEAT no-OS-hook). `error-ledger.md` = §L.a AS-1..13 + §L.b 7-step. adap-report FORMAT richest = `2026-06-18-Governance-harness-11.md`. rules.md §6.6 = objective-criteria. **report-before-stamp ⊂ D7 (extend, đừng duplicate → C3 vocab-fork).** → _INDEX.
|
||||
- **2026-06-20 Harness-14 Eval/Budget/Outcome audit:** ⭐ H-14 = time/age/recency-decay KHÔNG được làm căn-cứ cắt feature. (1) BUDGET aligned: `memory-budget.json` 0 decay/TTL/age hit; `keep_floor=5`=newest-protection (drains OLDEST), cap seed-by-MEASURE. (2) detectors = canonical-anchor-vs-STATUS + disk-cross-check, ZERO age-window. (3) EVAL genuine: `eval/golden-set-solution_erp.jsonl` (14q) + `evaluator.md` recall@5≥0.7 — weekly-manual no-automation. (4) anti-downgrade = Harness-8 "all-inherit chất-lượng>chi-phí" PARTIAL (no generic rule in rules.md, grep 0). → _INDEX.
|
||||
- **PE recon cluster (S69→S76, → _INDEX):** "Giá chào thầu" mục-c = `WinnerQuoteTotal`=SUM(Quote.ThanhTien WHERE supplier==Selected) DERIVED (3 nơi đồng-predicate) — PRO-Min/Max+CCM-proposed = Mig 54 NEW field. **Budget gate = PURE ROLE no-phase** (`canEditPro=Admin||Procurement`/`canEditCcm=Admin||CostControl` `PurchaseEvaluationFeatures.cs:800-801`; comment "bảng NS=tài-liệu-sống như Excel"); **submission-count-lock NEXISTS** (grep 0) → "khóa Initial sau lần-trình-đầu" = feature-MỚI. **Value-threshold HOOK B** = `ApproveV2Async` advance `:816-845` (reuse skipToFinal mechanic); **urgent flag** = AddColumn mirror `ItTicketPriority`. Badge ✎NS = +2 bool DTO via `GetUsersInRoleAsync` batch (no-N+1) both sites. PRO/CCM/CEO = `Procurement/CostControl/Director` (domain-shorthand NOT constants); V2 routing IGNORES roles (= specific ApproverUserId), 100% LINEAR no value/threshold config.
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,73 @@
|
||||
# Session 85 — 2026-06-23 — PE UAT anh Kiệt FDC CỰC LỚN: CV PRO 6-fix + clear-data + 6 vòng UAT + 2 ROOT-CAUSE + 5 SQL-fix
|
||||
|
||||
> **~10 deploy prod-verified #334→#341 (anh Kiệt FDC + Tra Sol + long.chau UAT realtime, HMW-mode ON, ~12 spawn).** Anh `/session-start` → forward Zalo + file Excel `Cần chỉnh sửa CV PRO.xlsx` liên-tục realtime → `/session-end`.
|
||||
> State THẬT cuối: **Mig 57 · 88 bảng · 374 test · gotcha 73 · menu 54 · bundle admin `aKuNip19`/user `BUsL0HeQ` (Run #341, FE frozen #339+#341 BE-only).**
|
||||
|
||||
## Đợt 1 — Batch CV PRO 6-fix (Run #334 `5a61254`)
|
||||
|
||||
File `Cần chỉnh sửa CV PRO.xlsx` = **8 ảnh chú-thích nhúng** (zip xl/media/, KHÔNG phải bảng công thức) — đọc qua skill xlsx + giải-nén + Read ảnh. 6 fix → AskUserQuestion chốt 3 nhóm mơ-hồ:
|
||||
- **C1** ẩn "c.Giá chào thầu" + "d.Bảng so sánh giá" khỏi form TẠO (giữ ở Detail).
|
||||
- **C3** ô8 "Giá trị TH dự kiến còn lại" pre-fill từ dòng7 (Ngân sách còn lại).
|
||||
- **C4a** **live-recompute** — `VndInlineEdit +onLiveChange`, `PeBudgetSummaryTable draftRow3/draftRow8` → dòng 5/6/7/9 + % nhảy NGAY khi gõ ô3/8 (chưa cần Lưu).
|
||||
- **C4b** So-sánh=0 → "Bằng ngân sách"/"—" (chỉ khi base>0).
|
||||
- **C5** hủy/đổi NCC winner — BE `SelectWinnerBody(Guid?)` + Command/Handler clear-branch (null=clear bỏ-validate-list, no-migration vì SelectedSupplierId đã Guid?) + FE dropdown ""→null + nút ✓ toggle.
|
||||
- **C7** nút "Toàn màn hình" preview file báo giá (overlay inset-0 + Esc).
|
||||
|
||||
Test +10 (`PeSelectWinnerClearTests`) → 356→366. FE 3 file ×2 app SHA-identical (diff-confirm rồi cp).
|
||||
|
||||
## Đợt 2 — Clear sạch UAT data (`scripts/s85-wipe-uat-data.sql`)
|
||||
|
||||
anh Kiệt "Clear sạch giúp anh nhé. Clear truoc em, xong anh check." Quy-trình destructive-prod chuẩn S59: recon → AskUserQuestion chốt scope → script → chạy → verify exact-count.
|
||||
- **Recon prod:** 43 PE + 28 PeWorkItemBudgets + 1 HĐ + 32 notif + 43 Suppliers (22 gốc ≤06-09 + 21 test ≥06-11).
|
||||
- anh chốt: **xóa budgets (28)** + **xóa 21 NCC-test** (CreatedAt≥06-11, mốc cắt sạch 06-10 trống).
|
||||
- Script: **BACKUP bước 0** (registry backup-dir vì D:\ không tồn-tại VPS) + `SET QUOTED_IDENTIFIER ON` (filtered-index Mig19/20) + `SET XACT_ABORT ON` + `-b` (backup-fail→abort-trước-wipe). Verify exact: PE/budgets/contracts/notif=0, Suppliers=22, reset mã→A/001. DemoSeed:Disabled gate → app-recycle KHÔNG resurrect.
|
||||
- Orphan upload files **defer** (path CWD-relative chưa pin, vô-hình UAT).
|
||||
|
||||
## Đợt 3-6 — 6 vòng UAT (#335→#338)
|
||||
|
||||
- **R1 #335 `24f0083`:** D1 ẩn mục 3/4/5 (gỡ FormRow/LockedHint/Lock unused) + D5 auto-chọn quy trình khi 1 option (prod PE type-1 có đúng 1 selectable WF).
|
||||
- **R2 #336 `a5e936f`:** D2 drafter tự-gỡ cờ GẤP — BE restructure SET/UNSET (GẮN role-only; GỠ +drafter clear-CẢ-2) + FE `isDrafter` canToggle. D3 ngân-sách-kỳ-này tự-nhảy từ "Ban hành lần đầu" (`proInitialAmount`) — FE display + FE/BE submit-guard fallback `budgetPeriodAmount ?? proInitialAmount`. test +5 (`PeUrgentToggleAuthzTests` drafter-self-unset) → 366→371.
|
||||
- **R3 #337 `e3e40ae`:** ràng tạo-phiếu (hint đỏ "thiếu: Quy trình/Hạng mục/Dự án", anh "không chọn quy trình thì ko cho tạo phiếu") + D4 checklist xanh✓/đỏ✗ trường bắt-buộc gửi-duyệt (mirror missingForApproval). [JSX fragment fix: chèn nhầm conditional trùng → bọc `<>`.]
|
||||
- **R4 #338 `34218f0`:** checklist +"Quy trình duyệt" (sót → toàn-xanh-nhưng-submit-chặn misleading). [R4 auto-assign-at-submit thử → REVERT vì phá 2 test S83 + nới block ngược "ràng".]
|
||||
|
||||
## Đợt 7-8 — 2 ROOT-CAUSE (whack-a-mole → fix gốc)
|
||||
|
||||
**(R5 #339 `1263c0d`) Workflow MẤT khi bấm Sửa = bug-class S42** — gotcha #73.
|
||||
- long.chau + anh Kiệt vẫn kẹt "chưa chọn quy trình" DÙ SQL-fix 5 phiếu. Query prod: 2 phiếu workflow-less MỚI (A/005 14:54, A/010 15:08) tạo SAU SQL-fix → KHÔNG phải point-in-time, là systemic.
|
||||
- Truy: form Sửa header → `PUT /purchase-evaluations/{id}` (PeHeaderForm:112) KHÔNG gửi `approvalWorkflowId` → `UpdatePeDraftHandler:282` absolute-set `= null` = CLEAR. Field SÓT khỏi pattern null-safe mà BudgetPeriodAmount/WorkItemId cạnh đã có (S42).
|
||||
- Fix: `if (request.ApprovalWorkflowId is not null) entity.ApprovalWorkflowId = ...`. Test +3 (`PeUpdateDraftWorkflowPreserveTests`) → 371→374.
|
||||
|
||||
**(R6 #341 `49ac086`) "Mới tạo báo 7h trước" = TZ +7h** — gotcha #72.
|
||||
- timestamps UTC nhưng EF đọc `DateTimeKind.Unspecified` → System.Text.Json serialize KHÔNG 'Z' → FE `new Date(naive)`=local → lệch +7h.
|
||||
- Fix: global `UtcDateTimeJsonConverter` (AddControllers.AddJsonOptions) ép UTC-with-Z `.ToString("O")`. cicd verify API trả `createdAt:"…3154440Z"`. (= ops "tzutil UTC+7" pending S58, fix tầng-serialize chuẩn hơn đổi giờ máy-chủ.)
|
||||
|
||||
**5 SQL-fix** (2 đợt 3+2 phiếu workflow-less): `UPDATE PurchaseEvaluations SET ApprovalWorkflowId='E08E3DA6…' WHERE ApprovalWorkflowId IS NULL AND Type=1` (QT-DN-V2-001). Bridge tới khi R5 deploy.
|
||||
|
||||
## Cách chạy + spawn-record (§L.b(d) — ~12 spawn)
|
||||
|
||||
| Sub | Task | Nấc | Evidence |
|
||||
|---|---|---|---|
|
||||
| tooling-auditor (H1) | session-start RE-REPORT 4-mặt | verified | 0 new-alloc, ef-core/skills-README stale-cite defer-monthly |
|
||||
| harvest-curator (H2) | (skip — em-main proxy harvest closeout) | n-a | — |
|
||||
| implementer-backend | C5 BE select-winner Guid? clear | verified | build slnx 0-err, Run #334 |
|
||||
| implementer-frontend | (em-main did mirror) | n-a | — |
|
||||
| test-specialist ×3 | C5 +10 · urgent-authz +5 · workflow-preserve +3 | verified | 356→374, 0 fail |
|
||||
| reviewer ×2 | R2-batch + R5-batch | partial | truncated #53 → em-main self-gate (memory-lesson) |
|
||||
| cicd-monitor ×7 | #334/#335/#336/#337/#338/#339/#341 | verified | 7/7 PASS, ship-proof Last-Modified BE-only |
|
||||
| investigator-codebase | recon D2-GẤP-authz + D5-WF + validators | verified | found create-validator + IsUserSelectable prod=1 |
|
||||
|
||||
⚠️ **Residual-write reconcile (B3):** investigator-codebase + test-specialist ×2 tự ghi MEMORY (residual) — em-main review git-diff = legit findings, KEEP.
|
||||
|
||||
## §L closeout
|
||||
|
||||
- **§L.a RCA:** 2 production-bug = lỗi-KÉP → 2-fix mỗi cái: R5 (code null-safe + test regression #73) · R6 (code converter + gotcha-guard #72). AS-* không thêm class mới.
|
||||
- **§L.b(c)** archive-gate A7 GATE PASS 217/217 · test-specialist 28.4KB WATCH strike-1 (value-protect gotcha#/guard KEEP) · sleep-check 5d<7 skip.
|
||||
- **§L.b(h)** User-Mark: 4 Active-High hiển-thị, 0 governance-decision MỚI (product session) → n-a.
|
||||
- **Lesson NEW `feedback_root_cause_over_symptom`:** bug lặp-lại + band-aid (SQL/tzutil) không dứt → truy field/case LỆCH-quy-ước, đưa vào pattern đã-đúng = fix 1 chỗ hết tái-diễn.
|
||||
|
||||
## 🔴 NEXT
|
||||
|
||||
- **Anh:** ⚠️ restart CLI (carry budget v3 runtime + lệnh `/user-mark-*` + cadence). Báo anh Kiệt/long.chau Ctrl+F5.
|
||||
- **Em (carry):** curate test-specialist 28.4KB WATCH (value-protect KEEP) · monthly 2026-07-01 (doc-cite ef-core/skills-README Mig→57 · STATUS/HANDOFF re-tier · **SignalR TZ-check** nếu realtime-push lệch · **edit-form workflow-selector** defer = đóng dead-end "mở Sửa chọn quy trình" mà form chưa có ô · fix L1-essentials `vrapp` password prefix-thừa per cicd-flag).
|
||||
- **Pending product:** Ngưỡng giá CEO (Mig 54) Designer UAT · "C" chuyển phiếu→dự án chờ spec.
|
||||
- **Ops:** email typo anh Chương · 5 real-staff pw · gán CNTT.
|
||||
@ -1246,6 +1246,30 @@ for h in resp.points: # ← .points không phải iterable trực tiếp
|
||||
|
||||
---
|
||||
|
||||
### 72. DateTime serialize KHÔNG có 'Z' (EF đọc `Unspecified` kind) → FE `new Date()` hiểu là local → lệch +7h (Session 85)
|
||||
|
||||
**Triệu chứng:** anh Kiệt "mới tạo phiếu mà báo cách 7h trước" — relative-time thông-báo (`Date.now() - new Date(createdAt).getTime()`) lệch đúng +7h (VN UTC+7).
|
||||
|
||||
**Cơ chế:** timestamps lưu UTC (`DateTime.UtcNow`) nhưng EF Core đọc SQL Server `datetime2` về `DateTimeKind.Unspecified`. `AddControllers()` mặc-định (KHÔNG JSON config) → System.Text.Json serialize DateTime Unspecified-kind **KHÔNG có hậu-tố 'Z'** (`"2026-06-23T08:20:00"`). FE `new Date(naive)` hiểu chuỗi-không-TZ là **giờ LOCAL** → nhưng giá-trị là UTC → lệch +7h. Build PASS + test xanh (serialization không unit-test) → CÂM.
|
||||
|
||||
**Guard:** global `JsonConverter<DateTime>` ép UTC-with-Z: `Kind==Unspecified ? SpecifyKind(Utc) : ToUniversalTime()` → `.ToString("O")`. Đăng-ký `AddControllers().AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(new UtcDateTimeJsonConverter()))`. System.Text.Json tự áp cho `DateTime?` (Nullable non-null). **Verify:** curl authed endpoint → field `createdAt` JSON CÓ 'Z'. Lưu-UTC + convert-on-display (FE) là CHUẨN — KHÔNG band-aid `tzutil` đổi giờ máy-chủ (ảnh-hưởng GETUTCDATE + lệch khác). SignalR realtime-push dùng serializer RIÊNG (`AddJsonProtocol`) → nếu giờ realtime còn lệch thì áp converter tương-tự.
|
||||
|
||||
**References:** `src/Backend/SolutionErp.Api/Serialization/UtcDateTimeJsonConverter.cs` · `Program.cs` AddControllers · `fe-user/src/components/NotificationBell.tsx:23`.
|
||||
|
||||
---
|
||||
|
||||
### 73. UPDATE-handler absolute-set field → CLEAR khi FE KHÔNG gửi field (bug-class S42 recurrence) (Session 85)
|
||||
|
||||
**Triệu chứng:** phiếu tạo CÓ Quy trình duyệt → bấm "Sửa" (đổi tên/dự án) → MẤT workflow → kẹt submit "chưa chọn quy trình duyệt" (**whack-a-mole**: SQL-fix vá xong, ai bấm Sửa lại rụng tiếp). long.chau + anh Kiệt + nhiều account.
|
||||
|
||||
**Cơ chế:** `UpdatePeDraftHandler` absolute-set `entity.ApprovalWorkflowId = request.ApprovalWorkflowId`. Form Sửa (PeHeaderForm) KHÔNG gửi `approvalWorkflowId` → command bind `null` (default `Guid? = null`) → handler set `= null` = **CLEAR**. Field SÓT khỏi pattern null-safe (`if (request.X is not null)`) mà `BudgetPeriodAmount`/`ExpectedRemainingAmount`/`WorkItemId` NGAY DƯỚI đã có (comment "client không gửi → GIỮ giá trị cũ" — bug-class S42). 1 field lọt khỏi quy-ước đã-thiết-lập.
|
||||
|
||||
**Guard:** MỌI field optional trong UPDATE-handler PHẢI null-safe `if (request.X is not null) entity.X = request.X` (preserve khi không gửi); CHỈ field text-clearable CỐ-Ý (TenGoiThau/DiaDiem/MoTa) mới absolute-set. Khi thêm field vào UPDATE command → **đối-chiếu pattern null-safe của field cạnh**. Triệu-chứng "vá-điểm xong TÁI-DIỄN" = nghi field-clear-on-omit, truy root KHÔNG vá-data lặp (root-cause-over-symptom).
|
||||
|
||||
**References:** `src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs:~282` (UpdatePeDraftHandler) · `fe-user/src/components/pe/PeHeaderForm.tsx:112` (PUT no-workflow) · bug-class S42 (BudgetPeriodAmount null-safe S61) · `tests/.../PeUpdateDraftWorkflowPreserveTests.cs`.
|
||||
|
||||
---
|
||||
|
||||
## Checklist debug bug mới
|
||||
|
||||
1. Build pass không? → fail → check using + package version compat
|
||||
|
||||
102
scripts/s85-wipe-uat-data.sql
Normal file
102
scripts/s85-wipe-uat-data.sql
Normal file
@ -0,0 +1,102 @@
|
||||
-- ============================================================================
|
||||
-- S85 (2026-06-23) — Wipe UAT testing data ("clear sạch") trước UAT anh Kiệt FDC sáng nay
|
||||
-- Chỉ đạo: anh Kiệt FDC (Zalo "Clear sạch giúp anh nhé" + "Clear truoc em. Xong anh
|
||||
-- check một sáng nay em"). Quy trình destructive-prod chuẩn S59:
|
||||
-- recon -> AskUserQuestion chốt scope -> script committed -> chạy -> verify exact.
|
||||
--
|
||||
-- Anh chốt (AskUserQuestion S85):
|
||||
-- - PeWorkItemBudgets (28) -> XÓA (UAT sạch hoàn toàn, ô ngân sách trống lại).
|
||||
-- - Suppliers test thêm sau S59 -> XÓA 21 (CreatedAt >= 2026-06-11); GIỮ 22 gốc
|
||||
-- (CreatedAt < 2026-06-11: 19 demo 04/21-23 + 3 real S55 06-09). Mốc cắt SẠCH
|
||||
-- (06-10 trống — không nhập nhằng).
|
||||
--
|
||||
-- XÓA: 43 PurchaseEvaluations (cascade child ~700: Suppliers/Details/Quotes/Approvals/
|
||||
-- Changelogs/Attachments/LevelOpinions/DeptOpinions) · 28 PeWorkItemBudgets
|
||||
-- (loose-Guid per Dự-án×Hạng-mục — KHÔNG cascade theo PE -> DELETE riêng) · 1
|
||||
-- Contract (cascade) · 32 Notifications · 21 Suppliers test (CreatedAt >= 06-11)
|
||||
-- · PeSeq + CtSeq (reset -> generator INSERT lại LastSeq=1 -> phiếu thật đầu = .../001).
|
||||
-- GIỮ: 22 Suppliers gốc · Projects 70 · WorkItems 71 · Users 55 · Permissions/MenuItems/
|
||||
-- Roles · Workflows (7 active + Steps/Levels/Approvers — KHÔNG đụng config) ·
|
||||
-- ContractTemplates 9 · HRM/Office master (EmployeeProfiles/MeetingRooms/Vehicles/
|
||||
-- Drivers/LeaveTypes/Holidays/ShiftPatterns/OtPolicies) · EmployeeCodeSequences.
|
||||
-- FK: PE child ALL CASCADE (Quotes NO_ACTION dọn qua Details->Quotes, proven S59).
|
||||
-- Suppliers xóa SAU PE+Contracts (đã giải phóng SelectedSupplierId/Quotes/Contract).
|
||||
-- Safety: SET XACT_ABORT ON (lỗi -> rollback toàn bộ) + BACKUP bước 0 ngoài tran +
|
||||
-- chạy sqlcmd -b (backup fail -> abort TRƯỚC wipe). Resurrect-safe: DemoSeed:Disabled.
|
||||
-- Run: scp -> VPS C:\temp\s85.sql ; sqlcmd -S .\SQLEXPRESS -d SolutionErp -i C:\temp\s85.sql -f 65001 -b
|
||||
-- ============================================================================
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
SET ANSI_NULLS ON;
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
GO
|
||||
|
||||
-- ===== 0. BACKUP insurance (NGOÀI transaction; -b -> fail thì abort trước wipe) =====
|
||||
-- Lấy backup dir từ registry (SQL service account chắc chắn ghi được; D:\ KHÔNG tồn tại
|
||||
-- trên VPS này — chỉ ổ C:). xp_instance_regread auto-resolve path theo instance.
|
||||
DECLARE @bkdir nvarchar(512), @bkfile nvarchar(600);
|
||||
EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'BackupDirectory', @bkdir OUTPUT;
|
||||
SET @bkfile = @bkdir + N'\SolutionErp_S85_prewipe.bak';
|
||||
PRINT 'Backup device -> ' + @bkfile;
|
||||
BACKUP DATABASE [SolutionErp] TO DISK = @bkfile WITH INIT, CHECKSUM, NAME = N'SolutionErp-S85-pre-wipe';
|
||||
GO
|
||||
|
||||
PRINT '=== BEFORE ===';
|
||||
SELECT 'PE' AS T, COUNT(*) AS C FROM PurchaseEvaluations
|
||||
UNION ALL SELECT 'PeWorkItemBudgets', COUNT(*) FROM PeWorkItemBudgets
|
||||
UNION ALL SELECT 'Contracts', COUNT(*) FROM Contracts
|
||||
UNION ALL SELECT 'Notifications', COUNT(*) FROM Notifications
|
||||
UNION ALL SELECT 'Suppliers_total', COUNT(*) FROM Suppliers
|
||||
UNION ALL SELECT 'Suppliers_test(>=06-11)', COUNT(*) FROM Suppliers WHERE CreatedAt >= '2026-06-11'
|
||||
UNION ALL SELECT 'PeSeq', COUNT(*) FROM PurchaseEvaluationCodeSequences
|
||||
UNION ALL SELECT 'CtSeq', COUNT(*) FROM ContractCodeSequences;
|
||||
GO
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
-- 1. Phiếu PE (cascade child)
|
||||
DELETE FROM PurchaseEvaluations;
|
||||
PRINT ' PurchaseEvaluations deleted : ' + CAST(@@ROWCOUNT AS varchar);
|
||||
|
||||
-- 2. Ngân sách per-gói-thầu (loose-Guid, KHÔNG cascade theo PE)
|
||||
DELETE FROM PeWorkItemBudgets;
|
||||
PRINT ' PeWorkItemBudgets deleted : ' + CAST(@@ROWCOUNT AS varchar);
|
||||
|
||||
-- 3. Hợp đồng (cascade child)
|
||||
DELETE FROM Contracts;
|
||||
PRINT ' Contracts deleted : ' + CAST(@@ROWCOUNT AS varchar);
|
||||
|
||||
-- 4. Thông báo
|
||||
DELETE FROM Notifications;
|
||||
PRINT ' Notifications deleted : ' + CAST(@@ROWCOUNT AS varchar);
|
||||
|
||||
-- 5. NCC test thêm sau S59 (giữ 22 gốc CreatedAt < 2026-06-11)
|
||||
DELETE FROM Suppliers WHERE CreatedAt >= '2026-06-11';
|
||||
PRINT ' Suppliers test deleted : ' + CAST(@@ROWCOUNT AS varchar);
|
||||
|
||||
-- 6. Reset bộ đếm mã (DELETE row -> generator INSERT lại LastSeq=1 -> .../001)
|
||||
DELETE FROM PurchaseEvaluationCodeSequences;
|
||||
DELETE FROM ContractCodeSequences;
|
||||
PRINT ' Code sequences reset (Pe+Ct)';
|
||||
|
||||
PRINT '=== AFTER (expect transactional=0, Suppliers=22, master giữ) ===';
|
||||
SELECT 'PE' AS T, COUNT(*) AS C FROM PurchaseEvaluations
|
||||
UNION ALL SELECT 'PeWorkItemBudgets', COUNT(*) FROM PeWorkItemBudgets
|
||||
UNION ALL SELECT 'PeSuppliers', COUNT(*) FROM PurchaseEvaluationSuppliers
|
||||
UNION ALL SELECT 'PeQuotes', COUNT(*) FROM PurchaseEvaluationQuotes
|
||||
UNION ALL SELECT 'PeAttachments', COUNT(*) FROM PurchaseEvaluationAttachments
|
||||
UNION ALL SELECT 'PeChangelogs', COUNT(*) FROM PurchaseEvaluationChangelogs
|
||||
UNION ALL SELECT 'Contracts', COUNT(*) FROM Contracts
|
||||
UNION ALL SELECT 'Notifications', COUNT(*) FROM Notifications
|
||||
UNION ALL SELECT 'Suppliers_keep', COUNT(*) FROM Suppliers
|
||||
UNION ALL SELECT 'PeSeq', COUNT(*) FROM PurchaseEvaluationCodeSequences
|
||||
UNION ALL SELECT 'CtSeq', COUNT(*) FROM ContractCodeSequences
|
||||
UNION ALL SELECT 'KEEP_Projects', COUNT(*) FROM Projects
|
||||
UNION ALL SELECT 'KEEP_WorkItems', COUNT(*) FROM WorkItems
|
||||
UNION ALL SELECT 'KEEP_Users', COUNT(*) FROM Users
|
||||
UNION ALL SELECT 'KEEP_Workflows', COUNT(*) FROM ApprovalWorkflows
|
||||
UNION ALL SELECT 'KEEP_Templates', COUNT(*) FROM ContractTemplates;
|
||||
|
||||
COMMIT TRANSACTION;
|
||||
PRINT 'S85 wipe COMMITTED.';
|
||||
GO
|
||||
Reference in New Issue
Block a user