fix(activity): close Phase 14 KEEP-VERIFY/EXTEND — 11 backend + 3 frontend-contract + 2 test-fidelity defects
Phase 14 (multi-type public-welfare activities) verification closure. Backend (D1-D11): - D1 CRITICAL: ActivityMapper.countRemainingCapacity had no @Select and no XML -> activity detail / register / approve all threw Invalid bound statement. Removed the shell; unified on ActivityRegistrationMapper. - D2 CRITICAL: register & approve were read-then-write -> oversold under concurrency. Replaced with single atomic SQL (insertIfCapacityAvailable / approveIfCapacityAvailable, affectedRows==0 => full). - D3 HIGH: activityType / orgRole never validated against production chk_activity_type / chk_org_role -> 500 only on PostgreSQL. - D4 HIGH: ActivityListItemDTO had no activityType -> miniapp category tabs always empty (Gate failure). - D5: male/female counts were fabricated as approvedCount/2; now real aggregation over user_profiles.gender. - D6: minAge/maxAge was a TODO no-op; added assertAgeInRange. - D7: registration_policy write-only; per-type eligibility now enforced (identity / local eligibility / gender quota). - D8: POST /operator/activities dropped type, multi-org and capacity groups and set organizer_org_id to the operator user id; now delegates to createActivityFromAdmin (single implementation). - D9: three operator write endpoints were mounted on the user-side ActivityController (dual implementation, zero callers) -> moved. - D10: NPE on soft-deleted activity in getMyActivities; NPE/500 on missing admin form fields (Instant.parse(null)); tolerant time parsing added. - D11: DTO lacked registeredCount / status / coverFileId / description -> card always showed 0 registered, "view detail", no cover, no summary. Frontend contract (F1-F3): - F1: miniapp category code "classroom" is not in the production whitelist (should be relationship_education); three types had no tab at all. - F2: ui-activity-card read 7 fields that do not exist on the backend; now reads only real DTO fields, plus per-type badge and eligibility hint. - F3: admin-web had no activity management page at all; added ActivityManagementView.vue (type-driven dynamic form, multi-org, capacity groups, publish/cancel) + /activities route and nav entry. Test fidelity (T1-T2): - T1: deleted two assertTrue(true) placeholder tests (testNoOverbooking, testNoDuplicateRegistration) that covered the exact broken invariants. - T2: test schema lacked V023 columns/constraints and three tables; the activity tables were only in the OPTIONAL set (zero coverage) -> schema completed and moved to REQUIRED_IN_TEST_SCHEMA. Tests: ActivityPhase14Test (23 cases), ActivityConstraintGuardTest (9 cases, parses real db/migration/V*.sql plus miniapp source). Two negative-verification rounds proved both guard families actually turn red. Regression: 450 tests / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS (baseline 420). admin-web vue-tsc 0 error, vite build OK.
This commit is contained in:
@@ -217,7 +217,54 @@ CREATE TABLE activities (
|
||||
male_limit INT, female_limit INT, total_limit INT, min_age SMALLINT, max_age SMALLINT,
|
||||
registration_start_at TIMESTAMP WITH TIME ZONE, registration_end_at TIMESTAMP WITH TIME ZONE,
|
||||
need_review BOOLEAN, status VARCHAR(32), created_by VARCHAR(36),
|
||||
created_at TIMESTAMP WITH TIME ZONE, updated_at TIMESTAMP WITH TIME ZONE, deleted_at TIMESTAMP WITH TIME ZONE
|
||||
created_at TIMESTAMP WITH TIME ZONE, updated_at TIMESTAMP WITH TIME ZONE, deleted_at TIMESTAMP WITH TIME ZONE,
|
||||
-- V023(Phase 14):多类型活动扩展列。此前测试库完全缺失,
|
||||
-- 导致 Phase 14 全部新增逻辑零覆盖,且非法 activity_type 在测试期不可见
|
||||
-- (上到 PostgreSQL 才撞 chk_activity_type 返回 500)。
|
||||
activity_type VARCHAR(64) NOT NULL DEFAULT 'matchmaking',
|
||||
registration_policy CLOB,
|
||||
target_group VARCHAR(200),
|
||||
industry_scope VARCHAR(200),
|
||||
post_event_interest_enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
CONSTRAINT chk_activity_type CHECK (activity_type IN (
|
||||
'matchmaking', 'interest_social', 'relationship_education',
|
||||
'premarital_guidance', 'marriage_custom_culture', 'anti_fraud'
|
||||
))
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Phase 14(V001 + V023):活动组织与容量分组
|
||||
-- 此前测试库完全缺失 organizations / activity_organizations / activity_capacity_groups,
|
||||
-- 且 activities 缺 V023 全部新列 —— Phase 14 新增逻辑零覆盖。
|
||||
-- 约束与生产 V023 对齐(chk_org_role 白名单)。
|
||||
-- ============================================================================
|
||||
|
||||
-- V001: organizations 组织表(activity_organizations 的外键目标,且组织名用于活动详情展示)
|
||||
CREATE TABLE organizations (
|
||||
id VARCHAR(36) PRIMARY KEY, name VARCHAR(200), type VARCHAR(32),
|
||||
contact_name VARCHAR(100), contact_phone_enc VARCHAR(500), status VARCHAR(32),
|
||||
created_at TIMESTAMP WITH TIME ZONE, updated_at TIMESTAMP WITH TIME ZONE,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
-- V023: activity_organizations 活动多组织关联表
|
||||
CREATE TABLE activity_organizations (
|
||||
id VARCHAR(36) PRIMARY KEY, activity_id VARCHAR(36) NOT NULL, organization_id VARCHAR(36) NOT NULL,
|
||||
role VARCHAR(32) NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE, updated_at TIMESTAMP WITH TIME ZONE,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE,
|
||||
CONSTRAINT uk_activity_org UNIQUE (activity_id, organization_id),
|
||||
CONSTRAINT chk_org_role CHECK (role IN ('host', 'organizer', 'co_organizer', 'partner', 'venue_partner'))
|
||||
);
|
||||
|
||||
-- V023: activity_capacity_groups 活动容量分组表
|
||||
CREATE TABLE activity_capacity_groups (
|
||||
id VARCHAR(36) PRIMARY KEY, activity_id VARCHAR(36) NOT NULL,
|
||||
group_code VARCHAR(32) NOT NULL, rule_definition CLOB,
|
||||
capacity INT NOT NULL DEFAULT 0, approved_count INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP WITH TIME ZONE, updated_at TIMESTAMP WITH TIME ZONE,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE,
|
||||
CONSTRAINT uk_capacity_group UNIQUE (activity_id, group_code)
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user