import { Router, Response, NextFunction } from 'express' import { z } from 'zod' import prisma from '../lib/prisma' import { authMiddleware, AuthRequest } from '../middleware/auth' const router = Router() router.use(authMiddleware) const planSchema = z.object({ name: z.string().min(1), type: z.string(), provider: z.string().min(1), policyNo: z.string().optional(), premium: z.number().default(0), coverageAmount: z.number().default(0), effectiveFrom: z.string(), effectiveTo: z.string().optional(), description: z.string().optional(), }) // 方案列表 router.get('/plans', async (req: AuthRequest, res: Response, next: NextFunction) => { try { const plans = await prisma.commercialInsurancePlan.findMany({ where: { orgId: req.user!.orgId }, orderBy: { createdAt: 'desc' }, include: { _count: { select: { enrollments: { where: { status: 'ACTIVE' } } } } }, }) res.json({ success: true, data: plans }) } catch (err) { next(err) } }) // 方案详情(含参保人员) router.get('/plans/:planId/enrollments', async (req: AuthRequest, res: Response, next: NextFunction) => { try { const enrollments = await prisma.commercialInsuranceEnrollment.findMany({ where: { orgId: req.user!.orgId, planId: req.params.planId }, include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } }, }, orderBy: { createdAt: 'desc' }, }) const data = enrollments.map((e: any) => ({ id: e.id, employeeId: e.employeeId, name: e.employee.name, department: e.employee.department, idCardMasked: e.employee.idCardNumber ? e.employee.idCardNumber.slice(0, 3) + '****' + e.employee.idCardNumber.slice(-4) : null, premium: e.premium, effectiveFrom: e.effectiveFrom, effectiveTo: e.effectiveTo, status: e.status, })) res.json({ success: true, data }) } catch (err) { next(err) } }) // 创建方案 router.post('/plans', async (req: AuthRequest, res: Response, next: NextFunction) => { try { const data = planSchema.parse(req.body) const plan = await prisma.commercialInsurancePlan.create({ data: { ...data, orgId: req.user!.orgId, createdBy: req.user!.id }, }) res.json({ success: true, data: plan }) } catch (err) { next(err) } }) // 更新方案 router.put('/plans/:planId', async (req: AuthRequest, res: Response, next: NextFunction) => { try { const data = planSchema.partial().parse(req.body) const plan = await prisma.commercialInsurancePlan.update({ where: { id: req.params.planId, orgId: req.user!.orgId }, data, }) res.json({ success: true, data: plan }) } catch (err) { next(err) } }) // 删除方案 router.delete('/plans/:planId', async (req: AuthRequest, res: Response, next: NextFunction) => { try { await prisma.commercialInsurancePlan.delete({ where: { id: req.params.planId, orgId: req.user!.orgId }, }) res.json({ success: true }) } catch (err) { next(err) } }) // 批量参保 router.post('/plans/:planId/enroll', async (req: AuthRequest, res: Response, next: NextFunction) => { try { const { employeeIds, premium, effectiveFrom } = req.body as { employeeIds: string[]; premium: number; effectiveFrom: string } const plan = await prisma.commercialInsurancePlan.findFirst({ where: { id: req.params.planId, orgId: req.user!.orgId } }) if (!plan) return res.status(404).json({ success: false, error: { message: '方案不存在' } }) const existing = await prisma.commercialInsuranceEnrollment.findMany({ where: { planId: plan.id, employeeId: { in: employeeIds }, status: 'ACTIVE' }, select: { employeeId: true }, }) const existingIds = new Set(existing.map((e: any) => e.employeeId)) const newIds = employeeIds.filter((id) => !existingIds.has(id)) if (newIds.length > 0) { await prisma.commercialInsuranceEnrollment.createMany({ data: newIds.map((empId) => ({ orgId: req.user!.orgId, planId: plan.id, employeeId: empId, premium: premium || plan.premium, effectiveFrom: effectiveFrom || plan.effectiveFrom, })), }) } res.json({ success: true, data: { enrolled: newIds.length, skipped: existingIds.size } }) } catch (err) { next(err) } }) // 退保 router.post('/enrollments/:enrollmentId/terminate', async (req: AuthRequest, res: Response, next: NextFunction) => { try { const { effectiveTo } = req.body as { effectiveTo: string } const enrollment = await prisma.commercialInsuranceEnrollment.update({ where: { id: req.params.enrollmentId, orgId: req.user!.orgId }, data: { status: 'TERMINATED', effectiveTo: effectiveTo || new Date().toISOString().slice(0, 10) }, }) res.json({ success: true, data: enrollment }) } catch (err) { next(err) } }) // 员工商险汇总(按员工维度) router.get('/employee-summary', async (req: AuthRequest, res: Response, next: NextFunction) => { try { const enrollments = await prisma.commercialInsuranceEnrollment.findMany({ where: { orgId: req.user!.orgId, status: 'ACTIVE' }, include: { employee: { select: { id: true, name: true, department: true } }, plan: { select: { id: true, name: true, type: true, provider: true, coverageAmount: true } }, }, }) const summary: Record = {} for (const e of enrollments) { if (!summary[e.employeeId]) { summary[e.employeeId] = { employeeId: e.employeeId, name: e.employee.name, department: e.employee.department, insurances: [], totalPremium: 0, totalCoverage: 0, } } summary[e.employeeId].insurances.push({ planId: e.planId, planName: e.plan.name, type: e.plan.type, provider: e.plan.provider, premium: e.premium, coverageAmount: e.plan.coverageAmount, effectiveFrom: e.effectiveFrom, effectiveTo: e.effectiveTo, }) summary[e.employeeId].totalPremium += e.premium summary[e.employeeId].totalCoverage += e.plan.coverageAmount } res.json({ success: true, data: Object.values(summary) }) } catch (err) { next(err) } }) export default router