feat: 批量获取操作跨批次重复检查 + 加班费改为获取 + 排除预入职
后端: - 5个批量获取接口(加班费/绩效/奖金/违纪/考勤)加 force 参数 - 非force模式下检查同月其他批次是否已有非零值,有则返回 needConfirm - 加班费接口改用 calcBatchEntry 重算(含税/社保),不再手动算 totalPay - 批次创建用当前日期判断是否已入职,排除预入职人员 前端: - 5个 mutation 支持 force 参数,needConfirm 时弹确认框 - 加班费按钮文字从'导入加班费'改为'获取加班费'
This commit is contained in:
@@ -488,20 +488,20 @@ export const payrollApi = {
|
||||
syncOvertimeFromAttendance: (month: string) =>
|
||||
post('/payroll/overtime/sync-from-attendance', { month }).then(unwrap<any>()),
|
||||
/** 导入加班费到批次 */
|
||||
importOvertimeToBatch: (batchId: string) =>
|
||||
post(`/payroll/overtime/import-to-batch/${batchId}`).then(unwrap<any>()),
|
||||
importOvertimeToBatch: (batchId: string, force?: boolean) =>
|
||||
post(`/payroll/overtime/import-to-batch/${batchId}`, force ? { force: true } : {}).then(unwrap<any>()),
|
||||
/** 获取提成奖金到批次 */
|
||||
fetchBonusToBatch: (batchId: string) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-bonus`).then(unwrap<any>()),
|
||||
fetchBonusToBatch: (batchId: string, force?: boolean) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-bonus`, force ? { force: true } : {}).then(unwrap<any>()),
|
||||
/** 获取绩效工资到批次(按考核系数计算) */
|
||||
fetchPerformanceToBatch: (batchId: string) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-performance`).then(unwrap<any>()),
|
||||
fetchPerformanceToBatch: (batchId: string, force?: boolean) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-performance`, force ? { force: true } : {}).then(unwrap<any>()),
|
||||
/** 获取违纪扣款到批次 */
|
||||
fetchDisciplinaryToBatch: (batchId: string) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-disciplinary`).then(unwrap<any>()),
|
||||
fetchDisciplinaryToBatch: (batchId: string, force?: boolean) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-disciplinary`, force ? { force: true } : {}).then(unwrap<any>()),
|
||||
/** 获取考勤扣款到批次 */
|
||||
fetchAttendanceDeductionToBatch: (batchId: string) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-attendance-deduction`).then(unwrap<any>()),
|
||||
fetchAttendanceDeductionToBatch: (batchId: string, force?: boolean) =>
|
||||
post(`/payroll2/batches/${batchId}/fetch-attendance-deduction`, force ? { force: true } : {}).then(unwrap<any>()),
|
||||
/** 加班费配置 */
|
||||
overtimeConfig: () =>
|
||||
get('/payroll/overtime/config').then(unwrap<any>()),
|
||||
|
||||
@@ -562,25 +562,37 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
})
|
||||
|
||||
const importOvertimeMutation = useMutation({
|
||||
mutationFn: () => payrollApi.importOvertimeToBatch(batchId),
|
||||
onSuccess: (res: any) => {
|
||||
mutationFn: (force?: boolean) => payrollApi.importOvertimeToBatch(batchId, force),
|
||||
onSuccess: async (res: any) => {
|
||||
if (res.data?.needConfirm) {
|
||||
if (await confirm({ title: '跨批次重复提醒', message: res.data.message, variant: 'primary' })) {
|
||||
importOvertimeMutation.mutate(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['batches'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['overtime-records'] })
|
||||
if (res.data?.imported > 0) {
|
||||
toast.success(`成功导入 ${res.data.imported} 条加班费记录`)
|
||||
toast.success(`成功获取 ${res.data.imported} 条加班费记录`)
|
||||
} else {
|
||||
toast.info(res.data?.message || '没有可导入的加班记录')
|
||||
toast.info(res.data?.message || '没有可获取的加班记录')
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
toast.error('导入失败,请重试')
|
||||
toast.error('获取失败,请重试')
|
||||
},
|
||||
})
|
||||
|
||||
const fetchBonusMutation = useMutation({
|
||||
mutationFn: () => payrollApi.fetchBonusToBatch(batchId),
|
||||
onSuccess: (res: any) => {
|
||||
mutationFn: (force?: boolean) => payrollApi.fetchBonusToBatch(batchId, force),
|
||||
onSuccess: async (res: any) => {
|
||||
if (res.data?.needConfirm) {
|
||||
if (await confirm({ title: '跨批次重复提醒', message: res.data.message, variant: 'primary' })) {
|
||||
fetchBonusMutation.mutate(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['batches'] })
|
||||
if (res.data?.filled > 0) {
|
||||
@@ -595,8 +607,14 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
})
|
||||
|
||||
const fetchPerformanceMutation = useMutation({
|
||||
mutationFn: () => payrollApi.fetchPerformanceToBatch(batchId),
|
||||
onSuccess: (res: any) => {
|
||||
mutationFn: (force?: boolean) => payrollApi.fetchPerformanceToBatch(batchId, force),
|
||||
onSuccess: async (res: any) => {
|
||||
if (res.data?.needConfirm) {
|
||||
if (await confirm({ title: '跨批次重复提醒', message: res.data.message, variant: 'primary' })) {
|
||||
fetchPerformanceMutation.mutate(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['batches'] })
|
||||
if (res.data?.filled > 0) {
|
||||
@@ -611,8 +629,14 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
})
|
||||
|
||||
const fetchDisciplinaryMutation = useMutation({
|
||||
mutationFn: () => payrollApi.fetchDisciplinaryToBatch(batchId),
|
||||
onSuccess: (res: any) => {
|
||||
mutationFn: (force?: boolean) => payrollApi.fetchDisciplinaryToBatch(batchId, force),
|
||||
onSuccess: async (res: any) => {
|
||||
if (res.data?.needConfirm) {
|
||||
if (await confirm({ title: '跨批次重复提醒', message: res.data.message, variant: 'primary' })) {
|
||||
fetchDisciplinaryMutation.mutate(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['batches'] })
|
||||
if (res.data?.filled > 0) {
|
||||
@@ -627,8 +651,14 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
})
|
||||
|
||||
const fetchAttendanceDeductionMutation = useMutation({
|
||||
mutationFn: () => payrollApi.fetchAttendanceDeductionToBatch(batchId),
|
||||
onSuccess: (res: any) => {
|
||||
mutationFn: (force?: boolean) => payrollApi.fetchAttendanceDeductionToBatch(batchId, force),
|
||||
onSuccess: async (res: any) => {
|
||||
if (res.data?.needConfirm) {
|
||||
if (await confirm({ title: '跨批次重复提醒', message: res.data.message, variant: 'primary' })) {
|
||||
fetchAttendanceDeductionMutation.mutate(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['batches'] })
|
||||
if (res.data?.filled > 0) {
|
||||
@@ -854,16 +884,16 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => importOvertimeMutation.mutate()}
|
||||
onClick={() => importOvertimeMutation.mutate(undefined)}
|
||||
disabled={importOvertimeMutation.isPending}
|
||||
>
|
||||
<Calculator className="w-4 h-4 mr-1" />
|
||||
{importOvertimeMutation.isPending ? '导入中...' : '导入加班费'}
|
||||
{importOvertimeMutation.isPending ? '获取中...' : '获取加班费'}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => fetchBonusMutation.mutate()}
|
||||
onClick={() => fetchBonusMutation.mutate(undefined)}
|
||||
disabled={fetchBonusMutation.isPending || isArchived}
|
||||
title="从提成奖金模块按月拉取填充奖金字段"
|
||||
>
|
||||
@@ -873,7 +903,7 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => fetchPerformanceMutation.mutate()}
|
||||
onClick={() => fetchPerformanceMutation.mutate(undefined)}
|
||||
disabled={fetchPerformanceMutation.isPending || isArchived}
|
||||
title="按考核等级系数计算绩效工资(A=1.2/B=1.0/C=0.8/D=0.6),无考核记录按1.0"
|
||||
>
|
||||
@@ -883,7 +913,7 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => fetchDisciplinaryMutation.mutate()}
|
||||
onClick={() => fetchDisciplinaryMutation.mutate(undefined)}
|
||||
disabled={fetchDisciplinaryMutation.isPending || isArchived}
|
||||
title="按批次月份从违纪记录中汇总扣款金额(action=DEDUCTION)"
|
||||
>
|
||||
@@ -893,7 +923,7 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => fetchAttendanceDeductionMutation.mutate()}
|
||||
onClick={() => fetchAttendanceDeductionMutation.mutate(undefined)}
|
||||
disabled={fetchAttendanceDeductionMutation.isPending || isArchived}
|
||||
title="按批次月份从考勤确认中获取扣款金额(需先在考勤确认中填写)"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user