feat: 发薪日期多选+提前N天提醒+电子签设置区域修复
- Schema: 去掉 payrollFrequency,新增 payrollDays (JSON数组) + payrollReminderDays (Int) - 设置页: 发薪日期改为1-28号多选按钮,新增提前提醒天数设置 - 设置页: 恢复电子签署设置区域(3个开关:规章制度/工资条/入职文件) - 工作日历: 发薪日期作为 PAYROLL_DAY 事件显示 - 工作台: 提前N天提醒发薪日期,N可配置 - TaskCenter: 新增发薪提醒分类图标 - seed文件: 更新为 payrollDays 格式
This commit is contained in:
@@ -285,6 +285,43 @@ router.get('/workspace/next-actions', authMiddleware, async (req: AuthRequest, r
|
||||
take: 10,
|
||||
})
|
||||
|
||||
// 5. 发薪日提前提醒
|
||||
const org = await prisma.organization.findUnique({
|
||||
where: { id: orgId },
|
||||
select: { payrollDays: true, payrollReminderDays: true },
|
||||
})
|
||||
const payrollDays = Array.isArray(org?.payrollDays) ? org.payrollDays as number[] : []
|
||||
const reminderDays = org?.payrollReminderDays ?? 3
|
||||
const payrollReminderItems: any[] = []
|
||||
const currentYear = now.getFullYear()
|
||||
const currentMonth = now.getMonth() // 0-indexed
|
||||
for (const day of payrollDays) {
|
||||
// 本月发薪日
|
||||
const thisMonthPayday = new Date(currentYear, currentMonth, day)
|
||||
const diffDays = Math.floor((thisMonthPayday.getTime() - now.getTime()) / 86400000)
|
||||
if (diffDays >= 0 && diffDays <= reminderDays) {
|
||||
payrollReminderItems.push({
|
||||
id: `payroll-${currentYear}-${currentMonth + 1}-${day}`,
|
||||
title: `发薪日(每月${day}号)${diffDays === 0 ? '今天' : `${diffDays}天后`}`,
|
||||
subtitle: diffDays === 0 ? '今天发薪' : `还有${diffDays}天`,
|
||||
link: '/money',
|
||||
})
|
||||
}
|
||||
// 下月发薪日(如果当月已过,看下月)
|
||||
if (diffDays < 0) {
|
||||
const nextMonthPayday = new Date(currentYear, currentMonth + 1, day)
|
||||
const nextDiffDays = Math.floor((nextMonthPayday.getTime() - now.getTime()) / 86400000)
|
||||
if (nextDiffDays >= 0 && nextDiffDays <= reminderDays) {
|
||||
payrollReminderItems.push({
|
||||
id: `payroll-${currentYear}-${currentMonth + 2}-${day}`,
|
||||
title: `发薪日(下月${day}号)${nextDiffDays === 0 ? '今天' : `${nextDiffDays}天后`}`,
|
||||
subtitle: `还有${nextDiffDays}天`,
|
||||
link: '/money',
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按优先级分组
|
||||
const actions: Array<{ category: string; priority: 'high' | 'medium' | 'low'; items: any[] }> = [
|
||||
{
|
||||
@@ -333,6 +370,11 @@ router.get('/workspace/next-actions', authMiddleware, async (req: AuthRequest, r
|
||||
link: '/special-status',
|
||||
})),
|
||||
},
|
||||
{
|
||||
category: '发薪提醒',
|
||||
priority: 'medium',
|
||||
items: payrollReminderItems,
|
||||
},
|
||||
]
|
||||
|
||||
// 过滤空分类
|
||||
|
||||
@@ -115,7 +115,7 @@ router.get('/orgs', async (req: AuthRequest, res, next) => {
|
||||
select: {
|
||||
id: true, name: true, plan: true, maxEmployees: true,
|
||||
city: true, contactName: true, contactPhone: true,
|
||||
payrollFrequency: true, retirementReminderEnabled: true,
|
||||
payrollDays: true, retirementReminderEnabled: true,
|
||||
createdAt: true, updatedAt: true,
|
||||
_count: {
|
||||
select: { employees: true, users: true, contracts: true, payslips: true },
|
||||
|
||||
@@ -28,7 +28,7 @@ router.get('/org', async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const org = await prisma.organization.findUnique({
|
||||
where: { id: req.user!.orgId },
|
||||
select: { id: true, name: true, plan: true, maxEmployees: true, city: true, contactName: true, contactPhone: true, payrollFrequency: true, retirementReminderEnabled: true, esignPolicyEnabled: true, esignPayslipEnabled: true, esignOnboardingEnabled: true, createdAt: true },
|
||||
select: { id: true, name: true, plan: true, maxEmployees: true, city: true, contactName: true, contactPhone: true, payrollDays: true, payrollReminderDays: true, retirementReminderEnabled: true, esignPolicyEnabled: true, esignPayslipEnabled: true, esignOnboardingEnabled: true, createdAt: true },
|
||||
})
|
||||
res.json({ success: true, data: org })
|
||||
} catch (err) {
|
||||
@@ -39,10 +39,11 @@ router.get('/org', async (req: AuthRequest, res, next) => {
|
||||
// 更新企业信息
|
||||
router.put('/org', requireAdmin, async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const { name, payrollFrequency, city, contactName, contactPhone, retirementReminderEnabled, esignPolicyEnabled, esignPayslipEnabled, esignOnboardingEnabled } = req.body as { name?: string; payrollFrequency?: number; city?: string; contactName?: string; contactPhone?: string; retirementReminderEnabled?: boolean; esignPolicyEnabled?: boolean; esignPayslipEnabled?: boolean; esignOnboardingEnabled?: boolean }
|
||||
const { name, payrollDays, payrollReminderDays, city, contactName, contactPhone, retirementReminderEnabled, esignPolicyEnabled, esignPayslipEnabled, esignOnboardingEnabled } = req.body as { name?: string; payrollDays?: number[]; payrollReminderDays?: number; city?: string; contactName?: string; contactPhone?: string; retirementReminderEnabled?: boolean; esignPolicyEnabled?: boolean; esignPayslipEnabled?: boolean; esignOnboardingEnabled?: boolean }
|
||||
const updateData: any = {}
|
||||
if (name) updateData.name = name
|
||||
if (payrollFrequency !== undefined) updateData.payrollFrequency = payrollFrequency
|
||||
if (payrollDays !== undefined) updateData.payrollDays = payrollDays
|
||||
if (payrollReminderDays !== undefined) updateData.payrollReminderDays = payrollReminderDays
|
||||
if (city !== undefined) updateData.city = city
|
||||
if (contactName !== undefined) updateData.contactName = contactName
|
||||
if (contactPhone !== undefined) updateData.contactPhone = contactPhone
|
||||
@@ -53,7 +54,7 @@ router.put('/org', requireAdmin, async (req: AuthRequest, res, next) => {
|
||||
const org = await prisma.organization.update({
|
||||
where: { id: req.user!.orgId },
|
||||
data: updateData,
|
||||
select: { id: true, name: true, plan: true, maxEmployees: true, city: true, contactName: true, contactPhone: true, payrollFrequency: true, retirementReminderEnabled: true, esignPolicyEnabled: true, esignPayslipEnabled: true, esignOnboardingEnabled: true },
|
||||
select: { id: true, name: true, plan: true, maxEmployees: true, city: true, contactName: true, contactPhone: true, payrollDays: true, payrollReminderDays: true, retirementReminderEnabled: true, esignPolicyEnabled: true, esignPayslipEnabled: true, esignOnboardingEnabled: true },
|
||||
})
|
||||
res.json({ success: true, data: org })
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user