member-training-count.test.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536
  1. import {test,before,after} from 'node:test';
  2. import assert from 'node:assert/strict';
  3. import {readFileSync} from 'node:fs';
  4. import vm from 'node:vm';
  5. import {PGlite} from '@electric-sql/pglite';
  6. const db=new PGlite(),query=async(sql,args=[])=>(await db.query(sql,args)).rows;
  7. const source=readFileSync(new URL('../deploy-admin-functions.mjs',import.meta.url),'utf8');
  8. const start=source.indexOf('async function queryUsers(context,input)');
  9. const code=source.slice(start,source.indexOf('\nfunction pageInput(',start));
  10. const ctx={Psql:{query,one:async(sql,args)=>(await query(sql,args))[0]},companyIdOf:c=>c.company,text:v=>String(v??'').trim(),number:(v,d=0)=>Number.isFinite(Number(v))?Number(v):d,legacyOf:r=>r.legacyUserData||{},displayName:r=>r.nickname,normalizeUser:r=>r,memberAppointmentStats:async()=>[],queryUsersLegacy:()=>{throw Error('Unexpected legacy request');}};
  11. vm.createContext(ctx);vm.runInContext(code,ctx);
  12. before(async()=>{
  13. await db.exec(`CREATE TABLE "_User"("objectId" text,company text,"legacyUserId" numeric,"legacyGroupId" numeric,"legacyUserData" jsonb,"identityType" text,"isDeleted" boolean,"isAdmin" boolean,username text,nickname text,"realName" text,"registeredAt" timestamptz,"createdAt" timestamptz);
  14. CREATE TABLE "Group"(company text,"groupId" numeric,"groupName" text);CREATE TABLE "Manager"(company text,"addUserId" numeric,"userName" text,"adminName" text);
  15. CREATE TABLE "CourseBinding"(company text,id numeric,yhid text,cksl text,yxx text);
  16. CREATE TABLE "DailyStudyRecord"(company text,"userId" numeric,"objectId" text,dsid text);
  17. CREATE TABLE "CommonModel"(company text,"objectId" text,"modelId" numeric,"itemId" numeric,"generalId" numeric,status numeric,"createdAt" timestamptz);
  18. CREATE TABLE "CourseAppointment"(company text,id numeric,jssj text);
  19. CREATE TABLE "LessonRecord"(company text,"objectId" text,id numeric,xymz text,yyds text,kclx text,"lessonAt" timestamptz,plpjsj text);
  20. INSERT INTO "_User" VALUES('student','co',1826,1,'{}','member',false,false,'student','学员','',now(),now());
  21. INSERT INTO "LessonRecord" SELECT 'co','lesson-'||i,i,'1826',(1000+i)::text,CASE WHEN i=1 THEN '3' ELSE '2' END,now(),'' FROM generate_series(1,36) i;
  22. INSERT INTO "CommonModel" SELECT 'co','common-'||i,59,i,2000+i,99,now() FROM generate_series(1,36) i;
  23. INSERT INTO "DailyStudyRecord" SELECT 'co',1826,'study-'||i,(1000+i)::text FROM generate_series(1,36) i;
  24. INSERT INTO "DailyStudyRecord" VALUES('co',1826,'second-word-batch','1002');`);
  25. });
  26. after(()=>db.close());
  27. test('会员概览按已上课次统计:36节课有37条学习明细仍显示36,原明细保留',async()=>{
  28. const result=await ctx.queryUsers({company:'co'},{});assert.equal(result[0].studyRecordCount,36);
  29. assert.equal((await query('SELECT count(*)::int n FROM "DailyStudyRecord"'))[0].n,37);
  30. });
  31. test('概览课次数排除作废、合并重复预约,保留无预约的独立课次并隔离帐套',async()=>{
  32. await db.exec(`INSERT INTO "LessonRecord" VALUES('co','duplicate',37,'1826','1002','2',now(),''),('co','void',38,'1826','9998','2',now(),''),('other','other-tenant',39,'1826','9999','2',now(),''),('co','unlinked-a',40,'1826',null,'2',now(),''),('co','unlinked-b',41,'1826','0','2',now(),'');
  33. INSERT INTO "CommonModel" VALUES('co','void-common',59,38,9998,-2,now());`);
  34. const result=await ctx.queryUsers({company:'co'},{});assert.equal(result[0].studyRecordCount,38);
  35. assert.equal((await ctx.queryUsers({company:'empty'},{})).length,0);
  36. });