|
|
@@ -34,7 +34,7 @@ LEFT JOIN "ReviewRewardRateCorrection" rc ON rc.company=r.company AND rc."reward
|
|
|
LEFT JOIN "ReviewRewardResolution" d ON d.company=r.company AND d."rewardId"=r."objectId";
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION xs_review_resolve(co text, actor text, items jsonb, reason text, historical_assignment boolean DEFAULT false) RETURNS jsonb LANGUAGE plpgsql AS $$
|
|
|
-DECLARE item jsonb; r "ReviewReward"; m "MemoryPracticeRecord"; canonical record; minutes integer; k text; outcome text; code text; snapshot jsonb; source jsonb; n integer:=0; existing integer:=0; prior text:=COALESCE(current_setting('xiaoshu.review_resolution',true),'');
|
|
|
+DECLARE item jsonb; r "ReviewReward"; m "MemoryPracticeRecord"; canonical record; minutes integer; k text; outcome text; code text; snapshot jsonb; source jsonb; coach_data jsonb; coach_profile jsonb; n integer:=0; existing integer:=0; prior text:=COALESCE(current_setting('xiaoshu.review_resolution',true),'');
|
|
|
BEGIN
|
|
|
PERFORM xs_review_manager(co,actor);
|
|
|
IF length(trim(COALESCE(reason,'')))<2 OR jsonb_typeof(items) IS DISTINCT FROM 'array' OR jsonb_array_length(items) NOT BETWEEN 1 AND 100 THEN RAISE EXCEPTION '需要明确核定依据和1至100条凭据'; END IF;
|
|
|
@@ -62,7 +62,27 @@ BEGIN
|
|
|
IF NOT historical_assignment THEN RAISE EXCEPTION '历史绑定老师核算口径未确认'; END IF;
|
|
|
IF COALESCE(r."completionRole",'') IN ('student','unknown','coach') OR NULLIF(r."completedBy",'') IS NOT NULL OR r."ineligibleReason"='self_study' THEN RAISE EXCEPTION '已有实际身份凭据不能按历史口径覆盖'; END IF;
|
|
|
IF COALESCE(m."sourceKey",'') NOT LIKE 'legacy:model:60:%' OR r."incomeMonth"<'2026-09' OR r."completedAt">now() OR xiaoshu_review_eligibility(r."plannedDate",r."completedAt")<>'eligible' OR r.exception NOT IN ('','来源复习任务重复') THEN RAISE EXCEPTION '历史来源或计划当天完成条件不满足'; END IF;
|
|
|
- IF NOT EXISTS(SELECT 1 FROM "_User" u WHERE u.company=co AND u."legacyUserId"=r."coachId" AND COALESCE(to_jsonb(u)->>'identityType','coach')='coach' AND COALESCE(to_jsonb(u)->>'legacyGroupId',u."legacyUserData"->>'GroupID')='3') OR NOT EXISTS(SELECT 1 FROM "_User" u WHERE u.company=co AND u."legacyUserId"=r."studentId") OR r."coachId"=r."studentId" THEN RAISE EXCEPTION '历史师生身份无效'; END IF;
|
|
|
+ IF (SELECT count(*) FROM "_User" u WHERE u.company=co AND u."legacyUserId"=r."coachId")<>1 OR NOT EXISTS(SELECT 1 FROM "_User" u WHERE u.company=co AND u."legacyUserId"=r."studentId") OR r."coachId"=r."studentId" THEN RAISE EXCEPTION '历史师生身份无效'; END IF;
|
|
|
+ SELECT to_jsonb(u) INTO coach_data FROM "_User" u WHERE u.company=co AND u."legacyUserId"=r."coachId";
|
|
|
+ IF COALESCE(coach_data->>'legacyGroupId',coach_data->'legacyUserData'->>'GroupID') IS DISTINCT FROM '3' THEN RAISE EXCEPTION '历史老师分组无效'; END IF;
|
|
|
+ IF COALESCE(coach_data->>'identityType','coach')<>'coach' THEN
|
|
|
+ -- Word-practice use alone can flag an otherwise verified legacy coach as conflict.
|
|
|
+ -- This narrow historical exception preserves the account's classification and login rules.
|
|
|
+ coach_profile:=item->'legacyCoachProfile';
|
|
|
+ IF coach_data->>'identityType' IS DISTINCT FROM 'conflict' OR coach_profile IS NULL
|
|
|
+ OR coach_profile->>'action' IS DISTINCT FROM 'user_info' OR coach_profile->>'userId' IS DISTINCT FROM r."coachId"::text
|
|
|
+ OR coach_profile->>'groupId' IS DISTINCT FROM '3' OR NULLIF(coach_profile->>'userName','') IS NULL
|
|
|
+ OR coach_profile->>'userName' IS DISTINCT FROM coach_data->>'username'
|
|
|
+ OR coach_profile->>'userName' IS DISTINCT FROM coach_data->'legacyUserData'->>'UserName'
|
|
|
+ OR coach_data->'legacyUserData'->>'UserID' IS DISTINCT FROM r."coachId"::text
|
|
|
+ OR coach_data->'legacyUserData'->>'GroupID' IS DISTINCT FROM '3'
|
|
|
+ OR EXISTS(SELECT 1 FROM "CourseAppointment" a WHERE a.company=co AND a.szyh::text=r."coachId"::text)
|
|
|
+ OR EXISTS(SELECT 1 FROM "DailyStudyRecord" d WHERE d.company=co AND d."userId"=r."coachId")
|
|
|
+ OR EXISTS(SELECT 1 FROM "CourseBinding" b WHERE b.company=co AND b.yhid::text=r."coachId"::text)
|
|
|
+ OR NOT EXISTS(SELECT 1 FROM "PracticeRecord" p WHERE p.company=co AND p.yhid::text=r."coachId"::text)
|
|
|
+ THEN RAISE EXCEPTION '历史师生身份冲突仍未核清'; END IF;
|
|
|
+ snapshot:=snapshot||jsonb_build_object('legacyCoachProfile',coach_profile,'identityReview','legacy_coach_with_word_practice_only');
|
|
|
+ END IF;
|
|
|
-- Existing earned receipts win; no second payout even if a duplicate has a null taskKey.
|
|
|
IF EXISTS(SELECT 1 FROM "ReviewRewardIncome" v JOIN "MemoryPracticeRecord" t ON t.company=v.company AND t."objectId"=v."taskId" WHERE v.company=co AND v.status='earned' AND t.yhid=m.yhid AND t.xxjlid=m.xxjlid AND left(t.kywrq::text,10)=left(m.kywrq::text,10)) THEN RAISE EXCEPTION '同一复习已经计薪'; END IF;
|
|
|
IF EXISTS(SELECT 1 FROM "MemoryPracticeRecord" t WHERE t.company=co AND t.yhid=m.yhid AND t.xxjlid=m.xxjlid AND left(t.kywrq::text,10)=left(m.kywrq::text,10) AND t.plid<>m.plid) THEN RAISE EXCEPTION '重复任务的老师归属冲突'; END IF;
|