Просмотр исходного кода

fix companion courses after mapping confirmation

彭峰 3 недель назад
Родитель
Сommit
1760f30169

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
scripts/deploy-admin-functions.mjs


+ 1 - 1
scripts/sql/member-enrollment.sql

@@ -104,7 +104,7 @@ BEGIN
 END $$;
 
 -- Safely repair only unambiguous historical mappings. Preserve conflicting progress for review.
-UPDATE "CourseBinding" b SET "categoryKey"=p."categoryKey","enrollmentStatus"=CASE WHEN EXISTS(SELECT 1 FROM "CourseBinding" other WHERE other."company"=b."company" AND other."yhid"=b."yhid" AND other."kcid"=b."kcid" AND other."objectId"<>b."objectId" AND COALESCE(other."enrollmentStatus",'')<>'recycled' AND (other."categoryKey" IS NULL OR other."categoryKey"=p."categoryKey")) THEN 'pending' ELSE 'active' END
+UPDATE "CourseBinding" b SET "categoryKey"=p."categoryKey","categoryName"=CASE p."categoryKey" WHEN 'word' THEN '单词课' WHEN 'trial' THEN '体验课' WHEN 'primary_writing' THEN '小学语法写作课' WHEN 'middle_writing' THEN '中学语法写作课' WHEN 'high_writing' THEN '高中语法写作课' WHEN 'word_self_study' THEN '单词自学课' ELSE p."categoryKey" END,"enrollmentStatus"=CASE WHEN EXISTS(SELECT 1 FROM "CourseBinding" other WHERE other."company"=b."company" AND other."yhid"=b."yhid" AND other."kcid"=b."kcid" AND other."objectId"<>b."objectId" AND COALESCE(other."enrollmentStatus",'')<>'recycled' AND (other."categoryKey" IS NULL OR other."categoryKey"=p."categoryKey")) THEN 'pending' ELSE 'active' END
 FROM (SELECT "company","courseId",min("categoryKey") AS "categoryKey",true AS "confirmed" FROM "CourseTeachingProfile" WHERE "confirmed"=true GROUP BY "company","courseId" HAVING count(DISTINCT "categoryKey")=1) p WHERE b."company"=p."company" AND b."kcid"::text=p."courseId"::text AND p."confirmed"=true
 AND p."categoryKey" IN ('word','trial','primary_writing','middle_writing','high_writing','word_self_study') AND b."categoryKey" IS NULL;
 UPDATE "CourseBinding" SET "enrollmentStatus"=CASE WHEN "categoryKey" IN ('word','trial','primary_writing','middle_writing','high_writing','word_self_study') THEN 'active' ELSE 'pending' END WHERE "enrollmentStatus" IS NULL;

+ 16 - 6
scripts/tests/teaching-course-mapping.test.mjs

@@ -16,14 +16,16 @@ context.reasonOf = () => 'mapping test';
 context.newClassObjects = async name => name === 'CourseTeachingProfile' ? [profile(454, 'word'), profile(464, 'word'), profile(398, 'word')] : [];
 before(async () => {
   await db.exec(`
-    CREATE TABLE "Node" (company text,"nodeId" numeric,"parentId" numeric,"nodeName" text);
-    CREATE TABLE "CourseBinding" (company text,kcid text);
+    CREATE TABLE "Node" (company text,"nodeId" numeric,"parentId" numeric,"nodeName" text,zstatus numeric);
+    CREATE TABLE "_User" (company text,"legacyUserId" numeric,"isDisabled" boolean,"isDeleted" boolean);
+    CREATE TABLE "CourseBinding" ("objectId" text,company text,id numeric,yhid text,kcid text,"categoryKey" text,"categoryName" text,"enrollmentStatus" text,"updatedAt" timestamptz);
     CREATE TABLE "CourseAppointment" (company text,id numeric,kcid text);
-    CREATE TABLE "CommonModel" (company text,"modelId" numeric,"itemId" numeric,status numeric,subtitle text);
-    INSERT INTO "Node" VALUES ('company-a',8,0,'小学'),('company-a',81,8,'小学语法写作课'),('company-b',464,0,'其他帐套课程');
-    INSERT INTO "CourseBinding" VALUES ('company-a','81');
+    CREATE TABLE "CommonModel" ("objectId" text,company text,"modelId" numeric,"itemId" numeric,status numeric,subtitle text);
+    INSERT INTO "Node" VALUES ('company-a',8,0,'小学',99),('company-a',81,8,'小学语法写作课',99),('company-b',464,0,'其他帐套课程',99);
+    INSERT INTO "_User" VALUES ('company-a',20,false,false);
+    INSERT INTO "CourseBinding" ("objectId",company,id,yhid,kcid,"enrollmentStatus") VALUES ('binding-81','company-a',81,20,'81','pending'),('binding-active','company-a',82,99,'81','active');
     INSERT INTO "CourseAppointment" VALUES ('company-a',1,'398'),('company-a',2,'454'),('company-a',3,'464'),('company-a',4,'999'),('company-b',5,'455');
-    INSERT INTO "CommonModel" VALUES ('company-a',54,1,99,'阅读写作'),('company-a',54,2,99,'牛津上海版初中新课标'),('company-a',54,3,99,'体育单招1700词'),('company-a',54,4,-2,'已取消的缺失课程'),('company-b',54,5,99,'其他帐套课程');
+    INSERT INTO "CommonModel" VALUES ('appointment-1','company-a',54,1,99,'阅读写作'),('appointment-2','company-a',54,2,99,'牛津上海版初中新课标'),('appointment-3','company-a',54,3,99,'体育单招1700词'),('appointment-4','company-a',54,4,-2,'已取消的缺失课程'),('appointment-5','company-b',54,5,99,'其他帐套课程'),('binding-common','company-a',58,81,99,'');
   `);
 });
 after(() => db.close());
@@ -51,3 +53,11 @@ test('mapping rejects cross-stage writing, unknown courses and generic writing b
   await assert.rejects(context.commitCourseMappings({}, {}, { items: [{ courseId: 398, categoryKey: 'word' }] }), /语法写作课程缺少学段/);
   await assert.rejects(context.commitCourseMappings({}, {}, { items: [{ courseId: 999, categoryKey: 'word' }] }), /未找到该课程/);
 });
+test('confirmed course mapping activates a valid unambiguous historical binding', async () => {
+  const rows = await context.syncConfirmedCourseBindings({}, {}, 81, 'primary_writing', '小学语法写作课');
+  assert.deepEqual(rows.map(row => row.enrollmentStatus), ['active']);
+  const binding = (await db.query('SELECT "categoryKey","categoryName","enrollmentStatus" FROM "CourseBinding" WHERE "objectId"=\'binding-81\'')).rows[0];
+  assert.deepEqual(binding, { categoryKey: 'primary_writing', categoryName: '小学语法写作课', enrollmentStatus: 'active' });
+  const preserved = (await db.query('SELECT "categoryKey","enrollmentStatus" FROM "CourseBinding" WHERE "objectId"=\'binding-active\'')).rows[0];
+  assert.deepEqual(preserved, { categoryKey: null, enrollmentStatus: 'active' });
+});

Некоторые файлы не были показаны из-за большого количества измененных файлов