import {test} from 'node:test';import assert from 'node:assert/strict';import fs from 'node:fs';import vm from 'node:vm'; async function run({model=59,repaired=true,student='1828',order='840456'}={}){ let result;const db={none:async()=>{},any:async()=>[],one:async()=>({fingerprint:'f'}),oneOrNone:async(sql,args)=>{ if(sql.includes('LegacyDirectBatch'))return null; if(sql.includes('FROM "LessonRecord"')&&sql.includes('sourceKey'))return repaired&&args[1]==='840456'?{objectId:'repair',xymz:'1828',sourceKey:'repair:legacy-completed-appointment:co:840456'}:null; if(sql.startsWith('SELECT to_jsonb(c)'))return null;if(sql.startsWith('SELECT to_jsonb(a)'))return null;throw Error('STOP_BEFORE_INSERT');},tx:async f=>f(db)}; const source=fs.readFileSync(new URL('../cloud/legacy-direct-sync.js',import.meta.url),'utf8').replaceAll('__COMPANY_ID__',"'co'").replaceAll('__SPECS__',JSON.stringify({59:{className:'LessonRecord'},56:{className:'DailyStudyRecord'}})).replaceAll('__WINDOWS__','[]'); const ctx=vm.createContext({Psql:db,directLease:async()=>{},console});vm.runInContext(source,ctx); const user={fetch:async()=>{},get:k=>k==='adminRoleKey'?'super-admin':k==='company'?{id:'co'}:false};const res={status(){return this},json(j){result=j;return j}}; await ctx.handler({user,body:{params:{modelId:model,action:'append',runId:'r',batchKey:'b',rows:[{generalId:999,addon:{id:999,xymz:student,yyds:order}}]}}},res);return result; } test('旧课后记录重新出现时,同预约已补录课次被保护并留下冲突',async()=>{const r=await run();assert.equal(r.success,true);assert.equal(r.data.createdAddon,0);assert.equal(r.data.conflicts.length,1);assert.match(r.data.conflicts[0].reason,/补录/);}); test('同预约来源学生错误也必须保留补录并要求复核',async()=>{const r=await run({student:'999'});assert.equal(r.success,true);assert.equal(r.data.conflicts.length,1);}); test('正常历史课次和单词学习明细仍进入原导入流程',async()=>{for(const opts of [{repaired:false},{order:'other'},{model:56}]){const r=await run(opts);assert.equal(r.success,false);assert.match(r.message,/Missing object IDs/);}});