Files
Public/apps/api/prisma/backfill-tech-travel.ts
T
daiyongkang 76f266645d Initial commit: 风影 OA 全栈源码(API/Web/Flutter/IM)
含 Phase 1.1 IM seq 排序、断线重连、多端已读同步与微信式语音转文字 UI。
排除 node_modules、构建产物、安装包与 .env 密钥。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 10:04:03 +00:00

37 lines
1.4 KiB
TypeScript

import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const techPeople = await prisma.employee.findMany({
where: { department: { deptType: 'TECH' } },
select: { name: true, department: { select: { deptType: true, name: true } } },
});
const names = techPeople.map((e) => e.name).filter((n) => n && n.length >= 2);
const rows = await prisma.expenseClaim.findMany({
where: { tenantId: '1', costType: 'PROJECT', budgetCategory: 'TRAVEL' },
include: {
applicant: { select: { employee: { select: { name: true, department: { select: { deptType: true } } } } } },
lines: { select: { remark: true } },
},
});
let n = 0;
for (const row of rows) {
const dept = row.applicant.employee?.department?.deptType || '';
const text = [row.purpose, row.remark, ...row.lines.map((l) => l.remark)].filter(Boolean).join(' ');
const forTech = names.some((name) => text.includes(name));
if (dept !== 'TECH' && !forTech) continue;
await prisma.expenseClaim.update({ where: { id: row.id }, data: { budgetCategory: 'TECH' } });
n += 1;
}
console.log(`reclassified ${n} / ${rows.length} travel expenses into tech budget; tech staff ${names.length}`);
}
main()
.then(async () => prisma.$disconnect())
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});