Plugins_view_admin_goods_save is an injection point, not a replacement point.
Save() accepts standard POST. Hook can intercept save flow.
Final recommendation: hook injection + JSON editor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug: regex '^([A-Za-z]+)(\d+)排(\d)座$' with $m[3] misparsed seat labels
like "A排10座" → colNum=1 (wrong). Fixed to '^([A-Za-z]+)排(\d+)座$' with $m[2].
Also clarified spec_base_id_map docblock: frontend expects flat integer,
not nested object.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verdict: [APPROVE] on FrontendDev P1 submit() refactor.
All P0/P1 code on main. Pending: container verification + FrontendDev consensus.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
[PASS] Interface contract: specBaseIdMap['A_1'] = int ✓
[PASS] goods_params: stock=1, seat-level spec_base_id ✓
[PASS] Fallback strategy for Plan B transition ✓
[PASS] Seat label format matches backend regex ✓
[PASS] Price sources align between frontend and backend ✓
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
[PASS] Interface contract: specBaseIdMap['A_1'] = int ✓
[PASS] goods_params: stock=1, seat-level spec_base_id ✓
[PASS] Fallback strategy for Plan B transition ✓
[PASS] Seat label format matches backend regex ✓
[PASS] Price sources align between frontend and backend ✓
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug 1: SeatSkuService.php:381 - regex has syntax error
'/^([A-Za-z]+)(\d+)排(\d+)座$/' → '/^([A-Za-z]+)(\d+)排(\d)座$/'
The third capture group only needs single digit (col number 1-9).
Bug 2: ticket_detail.html:416 - frontend accesses specBaseIdMap as object
but PHP returns flat integer: specBaseIdMap['A_1'] = 2001 (int), not {spec_base_id: 2001}.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. SeatSkuService: Fix regex in getExistingSpecBaseIds()
(\d+)排(\d+)座 → (\d+)排(\d)座
The original regex incorrectly captures 2 digit groups in "A排10座",
causing seatId parse failure for column >= 10.
2. ticket_detail.html: Fix specBaseIdMap access in submit()
(obj||{}).spec_base_id → direct numeric value
PHP returns integers (not objects), so drop the .spec_base_id accessor.
关联:Issue #9
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- renderSeatMap(): add data-row-label + data-col-num attrs for specBaseIdMap key format
- toggleSeat(): change seatKey from "0_0" (numeric) to "A_1" (label_colNum) to match specBaseIdMap
- removeSeat(): use [data-row-label][data-col-num] selector
- submit(): refactor from 1 goods_params (zone-level) to N entries (seat-level, stock=1)
- Plan B fallback: if specBaseIdMap[key] missing, use sessionSpecId
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Write council-output/ARCHITECTURE_DECISION.md with Q1-Q4 conclusions
- Update plan.md: mark Q3 done, final report done, consensus=YES
- Resolve rebase conflict from Round 2
- Final recommendation: 方案A (每座=SKU)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Q1: Batch SKU via direct SQL INSERT (bypass GoodsSpecificationsInsert)
- Q2: Solution B minimal fix (UPDATE is_exist_many_spec + INSERT $vr- spec_type + idempotency)
- Q3: $vr- prefix LOW risk (confirmed by SecurityEngineer + FrontendDev)
- Q4: All members recommend Plan A (one SKU per seat)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
P0-1: issueTicket() now checks for existing tickets by (order_id, spec_base_id)
before inserting. Prevents duplicate tickets on HTTP retry/multi-instance.
P0-3: Removed |raw from simple_desc and content in ticket_detail.html.
Prevents stored XSS via malicious admin content injection.
P0-4: getQrSecret() now throws exception if VR_TICKET_QR_SECRET is unset,
instead of falling back to insecure default key.
Resolve Round 4 merge conflict by restoring verifier views and ticket
detail from commit 6f49b8355. All 7 admin view files now confirmed on main.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>