import assert from 'node:assert/strict'; import { test } from 'node:test'; import { PGlite } from '@electric-sql/pglite'; import { legacyLessonPayEvidence, legacyLessonPayPreviewSql, legacyLessonPayApplySql } from '../reconcile-legacy-lesson-pay.mjs'; const date = '2026-11-04 21:40'; const lesson = { GeneralID: 300, yyds: '200', xymz: '20', jsmz: '30', kclx: '2', plpjsj: date }; const order = { GeneralID: 200, szyh: '20', pl: '30', dslx: '2', dszt: '30', yongjin: '45' }; test('旧课酬取销课原金额,并拒绝重复、取消和身份不一致的来源', () => { const evidence = legacyLessonPayEvidence([lesson], [order], 30); assert.equal(evidence.length, 1); assert.equal(evidence[0].amount, 45); assert.equal(legacyLessonPayEvidence([lesson], [{ ...order, yongjin: '0' }], 30)[0].amount, 0); for (const changes of [{ szyh: '21' }, { pl: '31' }, { dslx: '1' }, { dszt: '0' }, { yongjin: '' }]) { assert.deepEqual(legacyLessonPayEvidence([lesson], [{ ...order, ...changes }], 30), []); } assert.deepEqual(legacyLessonPayEvidence([lesson, { ...lesson, GeneralID: 301 }], [order], 30), []); assert.deepEqual(legacyLessonPayEvidence([lesson], [order, order], 30), []); }); test('仅补记原始课次缺失的快照,按版本更新并保护现有快照和工资单', async () => { const db = new PGlite(); try { await db.exec(` CREATE TABLE "CommonModel" (company text, "modelId" numeric, "generalId" numeric, "itemId" numeric, status numeric, "sourceKey" text); CREATE TABLE "LessonRecord" (company text, id numeric, "objectId" text, "sourceKey" text, "updatedAt" timestamptz, xymz text, jsmz text, yyds text, kclx text, plpjsj text, "teacherPaySnapshot" numeric); CREATE TABLE "CourseAppointment" (company text, id numeric, "sourceKey" text, szyh text, pl text, "teacherPaySnapshot" numeric); CREATE TABLE "PayrollLine" (company text, kind text, "standardLessonKey" text, "lessonId" text); INSERT INTO "CommonModel" VALUES ('co',59,300,301,99,'legacy:model:59:general:300'),('co',54,200,201,99,'legacy:model:54:general:200'); INSERT INTO "LessonRecord" VALUES ('co',301,'lesson','legacy:model:59:general:300','2026-11-07T00:00:00Z','20','30','200','2','${date}',NULL); INSERT INTO "CourseAppointment" VALUES ('co',201,'legacy:model:54:general:200','20','30',NULL); `); const evidence = legacyLessonPayEvidence([lesson], [order], 30); const preview = () => db.query(legacyLessonPayPreviewSql, ['co', JSON.stringify(evidence)]).then(r => r.rows); const apply = version => db.query(legacyLessonPayApplySql, ['co', JSON.stringify(evidence.map(r => ({ ...r, version })))]).then(r => r.rows); assert.equal((await preview()).length, 1); await db.exec(`INSERT INTO "PayrollLine" VALUES ('co','lesson','legacy:300','lesson')`); assert.deepEqual(await preview(), []); await db.exec(`DELETE FROM "PayrollLine"; UPDATE "CourseAppointment" SET "teacherPaySnapshot"=0`); assert.deepEqual(await preview(), []); await db.exec(`UPDATE "CourseAppointment" SET "teacherPaySnapshot"=NULL; UPDATE "LessonRecord" SET "sourceKey"='cloud:completed'`); assert.deepEqual(await preview(), []); await db.exec(`UPDATE "LessonRecord" SET "sourceKey"='legacy:model:59:general:300'; UPDATE "CommonModel" SET status=-2 WHERE "modelId"=54`); assert.deepEqual(await preview(), []); await db.exec(`UPDATE "CommonModel" SET status=99 WHERE "modelId"=54`); assert.deepEqual(await apply('old version'), []); const [ready] = await preview(); const [written] = await apply(ready.version); assert.equal(Number(written.amount), 45); assert.deepEqual(await preview(), []); assert.deepEqual(await apply(ready.version), []); assert.equal((await db.query('SELECT "teacherPaySnapshot" FROM "CourseAppointment"')).rows[0].teacherPaySnapshot, null); } finally { await db.close(); } });