初次提交代码

This commit is contained in:
2026-05-27 14:12:10 +08:00
parent 321aa5b319
commit ca32aa87e7
88 changed files with 19000 additions and 1 deletions

View File

@@ -0,0 +1,133 @@
import { prismaClient } from '@/lib/prisma';
import dayjs from 'dayjs'
/**
* 根据开票日期获取对应的项目号
* @param kai_piao_ri_qi 开票日期,格式为 YYYY-MM-DD
* @returns 匹配的项目号数组
*/
/**
* 根据开票日期或日期范围获取对应的项目号
* 支持:
* - 单个日期字符串:'YYYY-MM-DD'
* - JSON数组字符串'["2025-09-01","2025-09-30",""]'
* - 直接数组:['2025-09-01','2025-09-30']
*/
export async function getProjectIdsByInvoiceDate(kai_piao_ri_qi: unknown): Promise<string[]> {
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
const normalizeDate = (input: unknown): string | undefined => {
if (input === null || input === undefined) return undefined;
if (typeof input === 'number' && Number.isFinite(input)) {
const parsed = dayjs(input);
return parsed.isValid() ? parsed.format('YYYY-MM-DD') : undefined;
}
const s = String(input).trim();
if (!s) return undefined;
if (dateRegex.test(s)) return s;
const parsed = dayjs(s);
if (parsed.isValid()) return parsed.format('YYYY-MM-DD');
return undefined;
};
let start: string | undefined;
let end: string | undefined;
if (Array.isArray(kai_piao_ri_qi)) {
start = normalizeDate(kai_piao_ri_qi[0]);
end = normalizeDate(kai_piao_ri_qi[1]);
} else if (kai_piao_ri_qi && typeof kai_piao_ri_qi === 'object') {
const obj = kai_piao_ri_qi as any;
start = normalizeDate(obj?.start ?? obj?.startTime ?? obj?.begin ?? obj?.beginTime ?? obj?.[0]);
end = normalizeDate(obj?.end ?? obj?.endTime ?? obj?.finish ?? obj?.finishTime ?? obj?.[1]);
} else if (typeof kai_piao_ri_qi === 'string') {
const raw = kai_piao_ri_qi.trim();
if (dateRegex.test(raw)) {
start = normalizeDate(raw);
} else if (raw.startsWith('[')) {
// 尝试解析 JSON 数组字符串,例如 '["2025-09-03","2025-09-05",""]'
try {
const arr = JSON.parse(raw);
if (Array.isArray(arr)) {
start = normalizeDate(arr[0]);
end = normalizeDate(arr[1]);
}
} catch {
// 非法 JSON后续会走错误提示
}
} else {
const parts = raw.split(/[,,、\s]+/).map(s => s.trim()).filter(Boolean);
if (parts.length >= 2) {
start = normalizeDate(parts[0]);
end = normalizeDate(parts[1]);
}
}
}
// 组装 where 条件:区间或单点
// 由于数据库中日期可能以 YYYY-MM-DD 或 YYYY/MM/DD 存储,需要同时支持两种格式
let whereClause: any;
if (start && end) {
const startDash = start.replace(/\//g, '-');
const endExclusiveDash = dayjs(end).add(1, 'day').format('YYYY-MM-DD');
const startSlash = start.replace(/-/g, '/');
const endExclusiveSlash = dayjs(end).add(1, 'day').format('YYYY/MM/DD');
whereClause = {
OR: [
{ kai_piao_ri_qi: { gte: startDash, lt: endExclusiveDash } },
{ kai_piao_ri_qi: { gte: startSlash, lt: endExclusiveSlash } }
]
};
} else if (start) {
const startDash = start.replace(/\//g, '-');
const startSlash = start.replace(/-/g, '/');
whereClause = {
OR: [
{ kai_piao_ri_qi: { startsWith: startDash } },
{ kai_piao_ri_qi: { startsWith: startSlash } }
]
};
} else {
throw new Error('开票日期格式不正确,应为 YYYY-MM-DD 或 ["YYYY-MM-DD","YYYY-MM-DD",""]');
}
const voidRecords = await prismaClient.dingding_oa_invoice_application.findMany({
where: {
remark: {
in: ['发票作废', '作废']
}
},
select: { dataId: true }
});
const voidIds = voidRecords.map(r => r.dataId).filter(Boolean);
const invoiceRows = await prismaClient.invoice_data.findMany({
where: {
...whereClause
},
select: {
dataid: true
}
});
const dataIdsRaw = Array.from(new Set(invoiceRows.map(r => String(r.dataid ?? '').trim()).filter(Boolean)));
const voidIdSet = new Set(voidIds.map(id => String(id).trim()).filter(Boolean));
const dataIds = voidIdSet.size > 0 ? dataIdsRaw.filter(id => !voidIdSet.has(id)) : dataIdsRaw;
if (dataIds.length === 0) return [];
const apps = await prismaClient.dingding_oa_invoice_application.findMany({
where: {
dataId: { in: dataIds }
},
select: {
projectNumber: true
}
});
const projectIds = Array.from(new Set(
apps.flatMap(item => ((item.projectNumber || '') as string)
.split(/[,,、\s]+/)
.filter(Boolean))
));
return projectIds;
}