|
@@ -3,7 +3,7 @@
|
|
|
CREATE OR REPLACE FUNCTION xs_prepare_legacy_appointment(co text,aid text,actor text,seed_rules jsonb) RETURNS jsonb LANGUAGE plpgsql AS $$
|
|
CREATE OR REPLACE FUNCTION xs_prepare_legacy_appointment(co text,aid text,actor text,seed_rules jsonb) RETURNS jsonb LANGUAGE plpgsql AS $$
|
|
|
DECLARE c "CommonModel";a "CourseAppointment";b "CourseBinding";u "_User";op "_User";
|
|
DECLARE c "CommonModel";a "CourseAppointment";b "CourseBinding";u "_User";op "_User";
|
|
|
category text;category_name text;course text;day date;minutes numeric;mode text;rule jsonb;costs jsonb;cost jsonb;
|
|
category text;category_name text;course text;day date;minutes numeric;mode text;rule jsonb;costs jsonb;cost jsonb;
|
|
|
- matches integer;notes_legacy boolean=false;existing "CourseCreditReservation";before_data jsonb;changed boolean=false;
|
|
|
|
|
|
|
+ matches integer;notes_legacy boolean=false;legacy_trial boolean=false;existing "CourseCreditReservation";before_data jsonb;changed boolean=false;
|
|
|
BEGIN
|
|
BEGIN
|
|
|
PERFORM pg_advisory_xact_lock(hashtext('xs-credit:'||co));
|
|
PERFORM pg_advisory_xact_lock(hashtext('xs-credit:'||co));
|
|
|
SELECT * INTO op FROM "_User" WHERE company=co AND "objectId"=actor;
|
|
SELECT * INTO op FROM "_User" WHERE company=co AND "objectId"=actor;
|
|
@@ -24,6 +24,9 @@ BEGIN
|
|
|
course=a.kcid::text;
|
|
course=a.kcid::text;
|
|
|
IF NULLIF(a.yykcid::text,'') IS NOT NULL AND a.yykcid::text<>course THEN RAISE EXCEPTION '预约课程编号与排课课程不一致,请管理员核实';END IF;
|
|
IF NULLIF(a.yykcid::text,'') IS NOT NULL AND a.yykcid::text<>course THEN RAISE EXCEPTION '预约课程编号与排课课程不一致,请管理员核实';END IF;
|
|
|
category=NULLIF(a."courseCategoryKey",'');
|
|
category=NULLIF(a."courseCategoryKey",'');
|
|
|
|
|
+ -- The legacy lesson type identifies a trial; the textbook profile describes its words, not its price.
|
|
|
|
|
+ legacy_trial=a.dslx::text='3' AND (category IS NULL OR category='trial');
|
|
|
|
|
+ IF legacy_trial THEN category='trial'; END IF;
|
|
|
-- The legacy writing course has no vocabulary binding; only a per-appointment human confirmation is sufficient.
|
|
-- The legacy writing course has no vocabulary binding; only a per-appointment human confirmation is sufficient.
|
|
|
notes_legacy=COALESCE(course='398' AND category IN ('primary_writing','middle_writing','high_writing') AND length(trim(COALESCE(to_jsonb(a)->>'categoryEvidence','')))>=2 AND NULLIF(a."bindingId",'') IS NULL,false);
|
|
notes_legacy=COALESCE(course='398' AND category IN ('primary_writing','middle_writing','high_writing') AND length(trim(COALESCE(to_jsonb(a)->>'categoryEvidence','')))>=2 AND NULLIF(a."bindingId",'') IS NULL,false);
|
|
|
IF notes_legacy THEN
|
|
IF notes_legacy THEN
|
|
@@ -32,14 +35,14 @@ BEGIN
|
|
|
PERFORM xs_course_size(co,course);
|
|
PERFORM xs_course_size(co,course);
|
|
|
SELECT count(*) INTO matches FROM "CourseBinding" cb JOIN "CommonModel" bc ON bc.company=cb.company AND bc."modelId"=58 AND bc."itemId"=cb.id
|
|
SELECT count(*) INTO matches FROM "CourseBinding" cb JOIN "CommonModel" bc ON bc.company=cb.company AND bc."modelId"=58 AND bc."itemId"=cb.id
|
|
|
WHERE cb.company=co AND cb.yhid::text=a.szyh::text AND cb.kcid::text=course AND bc.status=99
|
|
WHERE cb.company=co AND cb.yhid::text=a.szyh::text AND cb.kcid::text=course AND bc.status=99
|
|
|
- AND COALESCE(cb."enrollmentStatus",'pending') IN ('active','pending') AND (category IS NULL OR cb."categoryKey"=category OR cb."categoryKey" IS NULL)
|
|
|
|
|
|
|
+ AND COALESCE(cb."enrollmentStatus",'pending') IN ('active','pending') AND (category IS NULL OR cb."categoryKey"=category OR cb."categoryKey" IS NULL OR (legacy_trial AND cb."categoryKey"='word' AND cb."enrollmentStatus"='active'))
|
|
|
AND (NULLIF(a."bindingId",'') IS NULL OR cb."objectId"=a."bindingId");
|
|
AND (NULLIF(a."bindingId",'') IS NULL OR cb."objectId"=a."bindingId");
|
|
|
IF matches<>1 THEN RAISE EXCEPTION '预约缺少唯一开课记录,请由管理员确认分类';END IF;
|
|
IF matches<>1 THEN RAISE EXCEPTION '预约缺少唯一开课记录,请由管理员确认分类';END IF;
|
|
|
SELECT cb.* INTO b FROM "CourseBinding" cb JOIN "CommonModel" bc ON bc.company=cb.company AND bc."modelId"=58 AND bc."itemId"=cb.id
|
|
SELECT cb.* INTO b FROM "CourseBinding" cb JOIN "CommonModel" bc ON bc.company=cb.company AND bc."modelId"=58 AND bc."itemId"=cb.id
|
|
|
WHERE cb.company=co AND cb.yhid::text=a.szyh::text AND cb.kcid::text=course AND bc.status=99
|
|
WHERE cb.company=co AND cb.yhid::text=a.szyh::text AND cb.kcid::text=course AND bc.status=99
|
|
|
- AND COALESCE(cb."enrollmentStatus",'pending') IN ('active','pending') AND (category IS NULL OR cb."categoryKey"=category OR cb."categoryKey" IS NULL)
|
|
|
|
|
|
|
+ AND COALESCE(cb."enrollmentStatus",'pending') IN ('active','pending') AND (category IS NULL OR cb."categoryKey"=category OR cb."categoryKey" IS NULL OR (legacy_trial AND cb."categoryKey"='word' AND cb."enrollmentStatus"='active'))
|
|
|
AND (NULLIF(a."bindingId",'') IS NULL OR cb."objectId"=a."bindingId") FOR UPDATE OF cb;
|
|
AND (NULLIF(a."bindingId",'') IS NULL OR cb."objectId"=a."bindingId") FOR UPDATE OF cb;
|
|
|
- category=COALESCE(category,NULLIF(b."categoryKey",''));category_name=b."categoryName";
|
|
|
|
|
|
|
+ category=COALESCE(category,NULLIF(b."categoryKey",''));category_name=CASE WHEN legacy_trial THEN '体验课' ELSE b."categoryName" END;
|
|
|
IF category IS NULL THEN
|
|
IF category IS NULL THEN
|
|
|
SELECT min(p."categoryKey") INTO category FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true HAVING count(DISTINCT p."categoryKey")=1;
|
|
SELECT min(p."categoryKey") INTO category FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true HAVING count(DISTINCT p."categoryKey")=1;
|
|
|
IF category NOT IN ('word','trial','word_self_study') THEN RAISE EXCEPTION '语法写作开课需按学员确认';END IF;
|
|
IF category NOT IN ('word','trial','word_self_study') THEN RAISE EXCEPTION '语法写作开课需按学员确认';END IF;
|
|
@@ -47,8 +50,8 @@ BEGIN
|
|
|
category_name=COALESCE(NULLIF(category_name,''),CASE category WHEN 'word' THEN '单词课' WHEN 'trial' THEN '体验课' WHEN 'word_self_study' THEN '单词自学课' WHEN 'primary_writing' THEN '小学语法写作课' WHEN 'middle_writing' THEN '中学语法写作课' WHEN 'high_writing' THEN '高中语法写作课' END);
|
|
category_name=COALESCE(NULLIF(category_name,''),CASE category WHEN 'word' THEN '单词课' WHEN 'trial' THEN '体验课' WHEN 'word_self_study' THEN '单词自学课' WHEN 'primary_writing' THEN '小学语法写作课' WHEN 'middle_writing' THEN '中学语法写作课' WHEN 'high_writing' THEN '高中语法写作课' END);
|
|
|
IF category IS NULL OR category NOT IN ('word','trial','word_self_study','primary_writing','middle_writing','high_writing') THEN RAISE EXCEPTION '开课分类尚未确认';END IF;
|
|
IF category IS NULL OR category NOT IN ('word','trial','word_self_study','primary_writing','middle_writing','high_writing') THEN RAISE EXCEPTION '开课分类尚未确认';END IF;
|
|
|
IF COALESCE(b."enrollmentStatus",'pending')='pending' AND (COALESCE(b."sourceKey",'') !~ '^legacy[:\-]' OR NOT EXISTS(
|
|
IF COALESCE(b."enrollmentStatus",'pending')='pending' AND (COALESCE(b."sourceKey",'') !~ '^legacy[:\-]' OR NOT EXISTS(
|
|
|
- SELECT 1 FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true AND p."categoryKey"=category)
|
|
|
|
|
- OR EXISTS(SELECT 1 FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true AND p."categoryKey"<>category)) THEN RAISE EXCEPTION '历史开课分类需管理员核实';END IF;
|
|
|
|
|
|
|
+ SELECT 1 FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true AND (p."categoryKey"=category OR (legacy_trial AND b."categoryKey" IS NULL AND p."categoryKey"='word')))
|
|
|
|
|
+ OR EXISTS(SELECT 1 FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true AND p."categoryKey"<>category AND NOT (legacy_trial AND b."categoryKey" IS NULL AND p."categoryKey"='word'))) THEN RAISE EXCEPTION '历史开课分类需管理员核实';END IF;
|
|
|
END IF;
|
|
END IF;
|
|
|
IF EXISTS(SELECT 1 FROM "TeachingCourseCategory" tc WHERE tc.company=co AND tc.key=category AND tc.active=false) THEN RAISE EXCEPTION '该课程分类已停用';END IF;
|
|
IF EXISTS(SELECT 1 FROM "TeachingCourseCategory" tc WHERE tc.company=co AND tc.key=category AND tc.active=false) THEN RAISE EXCEPTION '该课程分类已停用';END IF;
|
|
|
minutes=COALESCE(a."durationMinutes",CASE a.dslx WHEN '1' THEN 30 ELSE 60 END);
|
|
minutes=COALESCE(a."durationMinutes",CASE a.dslx WHEN '1' THEN 30 ELSE 60 END);
|
|
@@ -72,7 +75,11 @@ BEGIN
|
|
|
SELECT * INTO existing FROM "CourseCreditReservation" WHERE company=co AND "appointmentId"=aid AND state IN ('reserved','consumed') FOR UPDATE;
|
|
SELECT * INTO existing FROM "CourseCreditReservation" WHERE company=co AND "appointmentId"=aid AND state IN ('reserved','consumed') FOR UPDATE;
|
|
|
IF FOUND AND (existing.state IS DISTINCT FROM 'reserved' OR existing."studentId"::text IS DISTINCT FROM a.szyh::text OR existing."creditCosts"::jsonb IS DISTINCT FROM costs) THEN RAISE EXCEPTION '现有课时凭据冲突,请管理员核实';END IF;
|
|
IF FOUND AND (existing.state IS DISTINCT FROM 'reserved' OR existing."studentId"::text IS DISTINCT FROM a.szyh::text OR existing."creditCosts"::jsonb IS DISTINCT FROM costs) THEN RAISE EXCEPTION '现有课时凭据冲突,请管理员核实';END IF;
|
|
|
IF NOT notes_legacy AND (COALESCE(b."enrollmentStatus",'pending')='pending' OR b."categoryKey" IS NULL) THEN
|
|
IF NOT notes_legacy AND (COALESCE(b."enrollmentStatus",'pending')='pending' OR b."categoryKey" IS NULL) THEN
|
|
|
- UPDATE "CourseBinding" SET "enrollmentStatus"='active',"categoryKey"=category,"categoryName"=category_name,"updatedAt"=now() WHERE "objectId"=b."objectId";changed=true;
|
|
|
|
|
|
|
+ -- A legacy trial may use a shared word textbook; preserve its word classification for later ordinary lessons.
|
|
|
|
|
+ UPDATE "CourseBinding" SET "enrollmentStatus"='active',
|
|
|
|
|
+ "categoryKey"=CASE WHEN legacy_trial AND b."categoryKey" IS NULL AND EXISTS(SELECT 1 FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true AND p."categoryKey"='word') THEN 'word' ELSE category END,
|
|
|
|
|
+ "categoryName"=CASE WHEN legacy_trial AND b."categoryKey" IS NULL AND EXISTS(SELECT 1 FROM "CourseTeachingProfile" p WHERE p.company=co AND p."courseId"::text=course AND p.confirmed=true AND p."categoryKey"='word') THEN '单词课' ELSE category_name END,
|
|
|
|
|
+ "updatedAt"=now() WHERE "objectId"=b."objectId";changed=true;
|
|
|
END IF;
|
|
END IF;
|
|
|
IF a."bindingId" IS DISTINCT FROM b."objectId" OR a.kcid::text IS DISTINCT FROM course OR a."courseCategoryKey" IS NULL OR a."teacherPaySnapshot" IS NULL OR COALESCE(jsonb_array_length(a."creditCostsSnapshot"::jsonb),0)=0 OR a."creditHoldStatus" IS DISTINCT FROM 'ready' THEN
|
|
IF a."bindingId" IS DISTINCT FROM b."objectId" OR a.kcid::text IS DISTINCT FROM course OR a."courseCategoryKey" IS NULL OR a."teacherPaySnapshot" IS NULL OR COALESCE(jsonb_array_length(a."creditCostsSnapshot"::jsonb),0)=0 OR a."creditHoldStatus" IS DISTINCT FROM 'ready' THEN
|
|
|
UPDATE "CourseAppointment" SET "bindingId"=b."objectId",kcid=course,"courseCategoryKey"=category,"courseCategoryName"=COALESCE(NULLIF("courseCategoryName",''),category_name),
|
|
UPDATE "CourseAppointment" SET "bindingId"=b."objectId",kcid=course,"courseCategoryKey"=category,"courseCategoryName"=COALESCE(NULLIF("courseCategoryName",''),category_name),
|