76f266645d
含 Phase 1.1 IM seq 排序、断线重连、多端已读同步与微信式语音转文字 UI。 排除 node_modules、构建产物、安装包与 .env 密钥。 Co-authored-by: Cursor <cursoragent@cursor.com>
37 lines
1.4 KiB
TypeScript
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);
|
|
});
|