import {test} from 'node:test';import assert from 'node:assert/strict';import {readFileSync} from 'node:fs';import {PGlite} from '@electric-sql/pglite'; test('批量取消要求未开始且版本匹配,防止选择后已上课的预约被取消',async()=>{ const db=new PGlite();try{ await db.exec(`CREATE TABLE "CommonModel"(company text,"objectId" text,"modelId" numeric,"itemId" numeric,"updatedAt" timestamptz,status numeric); CREATE TABLE "CourseAppointment"(company text,id numeric,dszt text); INSERT INTO "CommonModel" VALUES('co','one',54,1,'2026-11-04 10:00+08',99),('co','active',54,2,'2026-11-04 10:00+08',99); INSERT INTO "CourseAppointment" VALUES('co',1,'0'),('co',2,'10'); CREATE FUNCTION xs_schedule_cancel(co text,aid text,restore boolean,actor text,reason text,expected text) RETURNS jsonb LANGUAGE plpgsql AS $$DECLARE v timestamptz;BEGIN SELECT "updatedAt" INTO v FROM "CommonModel" WHERE company=co AND "objectId"=aid;IF date_trunc('milliseconds',v)<>expected::timestamptz THEN RAISE EXCEPTION '预约已变更';END IF;UPDATE "CommonModel" SET status=-2 WHERE company=co AND "objectId"=aid;RETURN jsonb_build_object('targetId',aid);END$$;`); const src=readFileSync(new URL('../sql/member-enrollment.sql',import.meta.url),'utf8'),def=src.match(/CREATE OR REPLACE FUNCTION xs_schedule_cancel_unstarted\([\s\S]*?\$\$;/)?.[0];assert.ok(def,'缺少未开始预约保护函数');await db.exec(def); const run=(id,version='2026-11-04T02:00:00.000Z')=>db.query('SELECT xs_schedule_cancel_unstarted($1,$2,$3,$4,$5)',['co',id,'manager','批量调整',version]); await assert.rejects(run('active'),/未开始/);await assert.rejects(run('one',''),/版本/);await assert.rejects(run('one','2026-11-03'),/变更/); await run('one');assert.equal((await db.query('SELECT status FROM "CommonModel" WHERE "objectId"=\'one\'')).rows[0].status,'-2');assert.equal((await db.query('SELECT status FROM "CommonModel" WHERE "objectId"=\'active\'')).rows[0].status,'99'); }finally{await db.close();} });