win b99bcbd06f docs(01-core-pnl-functions): create phase 1 plans
4 plans across 3 waves:
- 01-01 (wave 1): package scaffold — types.go, service.go, service_test.go
- 01-02 (wave 2): QueryUserProfitLoss — query_user.go + user integration tests
- 01-03 (wave 2, parallel): QueryActivityProfitLoss — query_activity.go + activity tests
- 01-04 (wave 3): phase verification — static checks + full test suite gate

Covers all 20 Phase 1 requirements: PNL-01..08, DIM-01..04, RET-01/03,
AST-01, QUA-01..05.
2026-03-21 17:27:58 +08:00

195 lines
8.0 KiB
Markdown

---
phase: 01-core-pnl-functions
plan: 04
type: execute
wave: 3
depends_on:
- 01-02
- 01-03
files_modified: []
autonomous: true
requirements:
- QUA-01
- QUA-02
- QUA-03
- QUA-04
- QUA-05
- PNL-06
- RET-01
- RET-03
- AST-01
must_haves:
truths:
- "Full test suite passes: go test -v ./internal/service/finance/... exits 0"
- "Full build passes: go build ./... exits 0"
- "No GetDbW() call exists anywhere in the finance package"
- "All Scan() calls in query_user.go and query_activity.go have corresponding error checks"
- "finance.* utility functions (ClassifyOrderSpending, ComputeProfit, etc.) are called from query_*.go, not reimplemented"
- "Fan-out pattern: query_user.go has >= 4 Scan calls; query_activity.go has >= 4 Scan calls"
- "All monetary struct fields in types.go are int64 (no float64 for monetary values except ProfitRate)"
artifacts:
- path: "internal/service/finance/types.go"
provides: "Verified: all monetary fields int64, ProfitRate float64 only"
- path: "internal/service/finance/query_user.go"
provides: "Verified: >=4 Scan calls, all error-checked, finance functions called"
- path: "internal/service/finance/query_activity.go"
provides: "Verified: >=4 Scan calls, all error-checked, finance functions called"
key_links:
- from: "internal/service/finance package"
to: "existing profit_metrics_test.go"
via: "go test -v ./internal/service/finance/... — all tests including profit_metrics tests must pass"
pattern: "PASS"
---
<objective>
Run all verification checks for Phase 1. No new files are created — this plan executes a series of automated checks to confirm that all 20 requirements (PNL-01 through QUA-05) are satisfied before declaring Phase 1 complete.
Purpose: Gate phase completion. Catches any drift between plans that ran in parallel (Plans 02 and 03), verifies static code properties that tests alone cannot guarantee, and confirms the full build is green.
Output: Evidence that all Phase 1 requirements are met. Creates no new files.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/phases/01-core-pnl-functions/1-CONTEXT.md
@.planning/phases/01-core-pnl-functions/01-02-SUMMARY.md
@.planning/phases/01-core-pnl-functions/01-03-SUMMARY.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Run full test suite and static code checks</name>
<read_first>
- internal/service/finance/query_user.go (verify 4+ Scan calls and finance function calls before running checks)
- internal/service/finance/query_activity.go (verify 4+ Scan calls and finance function calls)
- internal/service/finance/types.go (verify int64 monetary fields)
- internal/service/finance/service.go (verify no GetDbW — both stubs should dispatch to queryUser/queryActivity)
</read_first>
<files></files>
<action>
Run the following verification sequence in order. For each check, output PASS or FAIL with evidence.
**Check 1: Full test suite (QUA-03, QUA-04, QUA-05)**
```bash
go test -v --cover ./internal/service/finance/...
```
Expected: All tests PASS, 0 failures.
**Check 2: Full project build (QUA-01)**
```bash
go build ./...
```
Expected: exits 0, no errors.
**Check 3: No GetDbW() in finance package (QUA-02)**
```bash
grep -r "GetDbW" ./internal/service/finance/
```
Expected: empty output (zero matches). If any match found, FAIL — locate and remove the call.
**Check 4: Fan-out scan count — user (QUA-05)**
```bash
grep -c "Scan(&" ./internal/service/finance/query_user.go
```
Expected: >= 4.
**Check 5: Fan-out scan count — activity (QUA-05)**
```bash
grep -c "Scan(&" ./internal/service/finance/query_activity.go
```
Expected: >= 4.
**Check 6: Scan errors all checked (QUA-03)**
```bash
grep -B1 "Scan(&" ./internal/service/finance/query_user.go | grep -c "if err :="
grep -B1 "Scan(&" ./internal/service/finance/query_activity.go | grep -c "if err :="
```
Expected: count matches the number of Scan calls in each file. If any Scan is not wrapped in `if err :=`, locate and fix.
**Check 7: Finance utility functions reused (QUA-04)**
```bash
grep -E "ClassifyOrderSpending|ComputeGamePassValue|ComputePrizeCostWithMultiplier|ComputeProfit" ./internal/service/finance/query_user.go | wc -l
grep -E "ClassifyOrderSpending|ComputeGamePassValue|ComputePrizeCostWithMultiplier|ComputeProfit" ./internal/service/finance/query_activity.go | wc -l
```
Expected: >= 3 matches in each file.
**Check 8: No SQL-embedded CAST AS SIGNED (SQLite test compat)**
```bash
grep "AS SIGNED" ./internal/service/finance/query_user.go ./internal/service/finance/query_activity.go | wc -l
```
Expected: 0. Multipliers must be applied in Go via ComputePrizeCostWithMultiplier.
**Check 9: int64 monetary fields (RET-03)**
```bash
grep -E "Revenue|Cost|Profit\b" ./internal/service/finance/types.go | grep "float64"
```
Expected: 0 matches. Only `ProfitRate float64` is allowed; all Revenue/Cost/Profit fields must be int64.
**Check 10: AssetType constants (AST-01)**
```bash
grep -A7 "AssetTypeAll" ./internal/service/finance/types.go
```
Expected: shows All=0, Points=1, Coupon=2, ItemCard=3, Product=4, Fragment=5.
If any check fails:
1. Identify which file has the issue from the check output
2. Read the file
3. Make the targeted fix (do not rewrite the whole file)
4. Re-run the failing check to confirm it now passes
5. Re-run `go test -v ./internal/service/finance/...` to confirm tests still pass
</action>
<verify>
<automated>go test -v --cover ./internal/service/finance/... && go build ./... && echo "ALL PHASE 1 CHECKS PASSED"</automated>
</verify>
<acceptance_criteria>
- `go test -v --cover ./internal/service/finance/...` exits 0 with PASS for all tests
- `go build ./...` exits 0
- `grep -r "GetDbW" ./internal/service/finance/` returns empty (0 matches)
- `grep -c "Scan(&" ./internal/service/finance/query_user.go` returns >= 4
- `grep -c "Scan(&" ./internal/service/finance/query_activity.go` returns >= 4
- `grep -E "ClassifyOrderSpending|ComputeProfit" ./internal/service/finance/query_user.go | wc -l` returns >= 2
- `grep -E "ClassifyOrderSpending|ComputeProfit" ./internal/service/finance/query_activity.go | wc -l` returns >= 2
- `grep "AS SIGNED" ./internal/service/finance/query_*.go | wc -l` returns 0
- `grep -E "Revenue|Cost|Profit\b" ./internal/service/finance/types.go | grep "float64" | wc -l` returns 0
- All 10 verification checks above show PASS or expected result
</acceptance_criteria>
<done>All 10 static and automated checks pass. Phase 1 is complete — QueryUserProfitLoss and QueryActivityProfitLoss are implemented, tested, and meet all 20 Phase 1 requirements.</done>
</task>
</tasks>
<verification>
Phase 1 is complete when ALL of the following are simultaneously true:
1. `go test -v --cover ./internal/service/finance/...` — all PASS, coverage reported
2. `go build ./...` — exits 0
3. `grep -r "GetDbW" ./internal/service/finance/` — 0 matches
4. `grep -c "Scan(&" query_user.go` — >= 4
5. `grep -c "Scan(&" query_activity.go` — >= 4
6. All finance.* utility functions called (not reimplemented) in query_*.go
7. All monetary fields in types.go are int64 (ProfitRate is the only float64)
8. VALIDATION.md nyquist_compliant updated to true
</verification>
<success_criteria>
- All 20 Phase 1 requirements (PNL-01 through QUA-05) verified as complete
- Full test suite green including existing profit_metrics tests
- Full project build clean
- Finance package has zero write-DB references
- Phase 1 ready for hand-off to Phase 2
</success_criteria>
<output>
After completion:
1. Create `.planning/phases/01-core-pnl-functions/01-04-SUMMARY.md`
2. Update `.planning/phases/01-core-pnl-functions/01-VALIDATION.md`: set `nyquist_compliant: true` and `wave_0_complete: true`
3. Update `.planning/ROADMAP.md`: mark Phase 1 plans list with actual plan files
4. Update `.planning/STATE.md`: set current plan to 4/4 complete, progress ~50%
</output>