sinake
2 天以前 49120f2b9db33455756a911e56cfefd7c3120a14
ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceFunddetailController.java
@@ -1,23 +1,34 @@
package com.ruoyi.web.controller.project;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.NotRepeatCommit;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.project.domain.FunddetailReqVo;
import com.ruoyi.project.domain.ServiceFunddetail;
import com.ruoyi.project.domain.SpStatBonus;
import com.ruoyi.project.domain.SpStatBonusDept;
import com.ruoyi.project.domain.SpStatBonusReq;
import com.ruoyi.project.domain.vo.TaxMoneyByItemEO;
import com.ruoyi.project.domain.vo.TaxMoneySumEO;
import com.ruoyi.project.domain.vo.TaxMoneyVO;
import com.ruoyi.project.service.IServiceFunddetailService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
/**
 * 费用申请明细Controller
@@ -25,6 +36,7 @@
 * @author ruoyi
 * @date 2022-01-25
 */
@Slf4j
@Api("费用申请明细")
@RestController
@RequestMapping("/project/funddetail")
@@ -37,7 +49,7 @@
     * 查询费用申请明细列表
     */
    @ApiOperation("查询费用申请明细列表")
    //@PreAuthorize("@ss.hasPermi('project:funddetail:list')")
    //// @PreAuthorize("@ss.hasPermi('project:funddetail:list')")
    @GetMapping("/list")
    public TableDataInfo list(ServiceFunddetail serviceFunddetail) {
        startPage();
@@ -50,7 +62,7 @@
     * 导出费用申请明细列表
     */
    @ApiOperation("导出费用申请明细列表")
    //@PreAuthorize("@ss.hasPermi('project:funddetail:export')")
    //// @PreAuthorize("@ss.hasPermi('project:funddetail:export')")
    @Log(title = "费用申请明细", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult export(ServiceFunddetail serviceFunddetail) {
@@ -63,7 +75,7 @@
     * 获取费用申请明细详细信息
     */
    @ApiOperation("获取费用申请明细详细信息")
    //@PreAuthorize("@ss.hasPermi('project:funddetail:query')")
    //// @PreAuthorize("@ss.hasPermi('project:funddetail:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(serviceFunddetailService.getById(id));
@@ -73,23 +85,50 @@
     * 新增费用申请明细
     */
    @ApiOperation("新增费用申请明细")
    //@PreAuthorize("@ss.hasPermi('project:funddetail:add')")
    //// @PreAuthorize("@ss.hasPermi('project:funddetail:add')")
    @Log(title = "费用申请明细", businessType = BusinessType.INSERT)
    @PostMapping
    @RepeatSubmit
    @PostMapping("/add")
    @NotRepeatCommit(key = "param:arg[1]", value = 30000)
    public AjaxResult add(@RequestBody ServiceFunddetail serviceFunddetail) {
        return toAjax(serviceFunddetailService.save(serviceFunddetail));
        // 2026-10-15:附件文件名规范二次校验(与前端 opo-web/src/utils/fileNameCheck.js 同口径,
        // 目的是防止绕过前端直接调接口保存不合规附件名)。新增场景没有历史附件,用严格模式。
        String nameError = com.ruoyi.project.common.AttachmentNameValidator
                .checkJsonList(serviceFunddetail.getInvoicefiles(), serviceFunddetail.getAnnexfiles());
        if (nameError != null) {
            return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError);
        }
        boolean save = serviceFunddetailService.save(serviceFunddetail);
        return AjaxResult.success(serviceFunddetail);
    }
    /**
     * 修改费用申请明细
     */
    @ApiOperation("修改费用申请明细")
    //@PreAuthorize("@ss.hasPermi('project:funddetail:edit')")
    //// @PreAuthorize("@ss.hasPermi('project:funddetail:edit')")
    @Log(title = "费用申请明细", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @RepeatSubmit
    @NotRepeatCommit(key = "param:arg[1]", value = 30000)
    public AjaxResult edit(@RequestBody ServiceFunddetail serviceFunddetail) {
        log.info("修改的数据信息:{}", serviceFunddetail);
        // 2026-10-15:附件文件名规范二次校验。修改场景按业务口径"只校验本次变更的附件":
        // 保存前该明细已存在的历史附件名不参与校验,否则老单据(历史不合规名占比很高)改个金额都存不进去。
        java.util.Set<String> existingNames = new java.util.HashSet<>();
        if (serviceFunddetail.getId() != null) {
            ServiceFunddetail oldDetail = serviceFunddetailService.getById(serviceFunddetail.getId());
            if (oldDetail != null) {
                existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator
                        .collectNames(oldDetail.getInvoicefiles()));
                existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator
                        .collectNames(oldDetail.getAnnexfiles()));
            }
        }
        String nameError = com.ruoyi.project.common.AttachmentNameValidator
                .checkJsonListForUpdate(existingNames, serviceFunddetail.getInvoicefiles(),
                        serviceFunddetail.getAnnexfiles());
        if (nameError != null) {
            return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError);
        }
        return toAjax(serviceFunddetailService.updateById(serviceFunddetail));
    }
@@ -97,7 +136,7 @@
     * 删除费用申请明细
     */
    @ApiOperation("删除费用申请明细")
    //@PreAuthorize("@ss.hasPermi('project:funddetail:remove')")
    //// @PreAuthorize("@ss.hasPermi('project:funddetail:remove')")
    @Log(title = "费用申请明细", businessType = BusinessType.DELETE)
    @GetMapping("/remove/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
@@ -154,11 +193,11 @@
        return AjaxResult.success(serviceFunddetailService.getFundDetail(id));
    }
    @ApiOperation("根据条件算税")
    @PostMapping("/calculateTax")
    public AjaxResult calculateTax(@RequestBody List<ServiceFunddetail> serviceFunddetails) {
        return AjaxResult.success(serviceFunddetailService.calculateTax(serviceFunddetails));
    }
//    @ApiOperation("根据条件算税")
//    @PostMapping("/calculateTax")
//    public AjaxResult calculateTax(@RequestBody List<ServiceFunddetail> serviceFunddetails) {
//        return AjaxResult.success(serviceFunddetailService.calculateTax2(serviceFunddetails));
//    }
//    /**
//     * 绩效计算
@@ -175,4 +214,80 @@
//        return AjaxResult.success(serviceFunddetailService.performance(serviceFunddetail));
//    }
    /**
     * 查询绩效奖金统计
     */
    @ApiOperation("查询绩效奖金统计")
    @PostMapping("/getListBySpStatBonus")
    public TableDataInfo getListBySpStatBonus(@RequestBody SpStatBonusReq spStatBonusReq) {
        startPage();
        return getDataTable(serviceFunddetailService.getListBySpStatBonus(spStatBonusReq));
    }
    /**
     * 导出绩效奖金统计
     */
    @ApiOperation("导出绩效奖金统计")
    @Log(title = "绩效统计", businessType = BusinessType.EXPORT)
    @GetMapping("/exportBonus")
    public AjaxResult exportBonus(SpStatBonusReq spStatBonusReq) {
        List<SpStatBonus> list = serviceFunddetailService.getListBySpStatBonus(spStatBonusReq);
        // 金额 0.00 不显示
        for (SpStatBonus row : list) {
            row.setAmount(blankZero(row.getAmount()));
            row.setMamount(blankZero(row.getMamount()));
            row.setSamount(blankZero(row.getSamount()));
            row.setYamount(blankZero(row.getYamount()));
        }
        ExcelUtil<SpStatBonus> util = new ExcelUtil<SpStatBonus>(SpStatBonus.class);
        return util.exportExcel(list, "绩效统计数据");
    }
    /**
     * 导出绩效统计(按业务组)
     */
    @ApiOperation("导出绩效统计(按业务组)")
    @Log(title = "绩效统计", businessType = BusinessType.EXPORT)
    @GetMapping("/exportBonusDept")
    public AjaxResult exportBonusDept(SpStatBonusReq spStatBonusReq) {
        List<SpStatBonus> list = serviceFunddetailService.getListBySpStatBonus(spStatBonusReq);
        Map<String, SpStatBonusDept> grouped = new LinkedHashMap<String, SpStatBonusDept>();
        for (SpStatBonus row : list) {
            String key = row.getDeptId() != null ? String.valueOf(row.getDeptId()) : row.getDeptName();
            if (key == null) {
                key = "";
            }
            SpStatBonusDept dept = grouped.get(key);
            if (dept == null) {
                dept = new SpStatBonusDept();
                dept.setDeptname(row.getDeptName() == null ? "未分组" : row.getDeptName());
                dept.setAmount(BigDecimal.ZERO);
                dept.setMamount(BigDecimal.ZERO);
                dept.setSamount(BigDecimal.ZERO);
                dept.setYamount(BigDecimal.ZERO);
                grouped.put(key, dept);
            }
            dept.setAmount(dept.getAmount().add(nz(row.getAmount())));
            dept.setMamount(dept.getMamount().add(nz(row.getMamount())));
            dept.setSamount(dept.getSamount().add(nz(row.getSamount())));
            dept.setYamount(dept.getYamount().add(nz(row.getYamount())));
        }
        List<SpStatBonusDept> result = new ArrayList<SpStatBonusDept>(grouped.values());
        for (SpStatBonusDept dept : result) {
            dept.setAmount(blankZero(dept.getAmount()));
            dept.setMamount(blankZero(dept.getMamount()));
            dept.setSamount(blankZero(dept.getSamount()));
            dept.setYamount(blankZero(dept.getYamount()));
        }
        ExcelUtil<SpStatBonusDept> util = new ExcelUtil<SpStatBonusDept>(SpStatBonusDept.class);
        return util.exportExcel(result, "绩效统计(按业务组)");
    }
    private BigDecimal nz(BigDecimal value) {
        return value == null ? BigDecimal.ZERO : value;
    }
    private BigDecimal blankZero(BigDecimal value) {
        return (value == null || value.compareTo(BigDecimal.ZERO) == 0) ? null : value;
    }
}