package com.ruoyi.web.controller.project; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.DtoConversionUtils; import com.ruoyi.project.domain.ServiceReimbursementdetailVO; import com.ruoyi.project.service.IServiceReimbursementdetailSharedService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.project.domain.ServiceReimbursementdetail; import com.ruoyi.project.service.IServiceReimbursementdetailService; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.core.page.TableDataInfo; /** * 报销申请明细Controller * * @author ruoyi * @date 2022-01-24 */ @Api("报销申请明细") @RestController @RequestMapping("/project/reimbursementdetail") public class ServiceReimbursementdetailController extends BaseController { @Autowired private IServiceReimbursementdetailService serviceReimbursementdetailService; @Autowired private IServiceReimbursementdetailSharedService detailSharedService; /** * 查询报销申请明细列表 */ @ApiOperation("查询报销申请明细列表") //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:list')") @GetMapping("/list") public TableDataInfo list(ServiceReimbursementdetail serviceReimbursementdetail) { startPage(); //List list = serviceReimbursementdetailService.queryList(serviceReimbursementdetail); List list = serviceReimbursementdetailService.selectServiceReimbursementdetailList(serviceReimbursementdetail); return getDataTable(list); } /** * 导出报销申请明细列表 */ @ApiOperation("导出报销申请明细列表") //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:export')") @Log(title = "报销申请明细", businessType = BusinessType.EXPORT) @GetMapping("/export") public AjaxResult export(ServiceReimbursementdetail serviceReimbursementdetail) { List list = serviceReimbursementdetailService.queryList(serviceReimbursementdetail); ExcelUtil util = new ExcelUtil(ServiceReimbursementdetail.class); return util.exportExcel(list, "报销申请明细数据"); } @GetMapping("/deleteByRBId/{rbid}") public AjaxResult removeAllDetail(@PathVariable("rbid") Long rbid) { List ids = serviceReimbursementdetailService.getAllIds(rbid); Long[] arr = (Long[]) ids.toArray(new Long[ids.size()]); return remove(arr); } /** * 获取报销申请明细详细信息 */ @ApiOperation("获取报销申请明细详细信息") //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:query')") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { return AjaxResult.success(serviceReimbursementdetailService.getById(id)); } /** * 新增报销申请明细 */ @ApiOperation("新增报销申请明细") //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:add')") @Log(title = "报销申请明细", businessType = BusinessType.INSERT) @PostMapping("/add") @RepeatSubmit public AjaxResult add(@RequestBody ServiceReimbursementdetailVO serviceReimbursementdetailVO) { // 2026-10-15:附件文件名规范二次校验(与前端 opo-web/src/utils/fileNameCheck.js 同口径, // 目的是防止绕过前端直接调接口保存不合规附件名)。新增场景没有历史附件,用严格模式。 // 注意:List 为空时必须回退校验字符串字段(annexfiles / invoicefiles), // 否则只传字符串字段就能绕过校验(接口层面的绕过口)。 String invoiceJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList()) ? serviceReimbursementdetailVO.getInvoicefiles() : JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList()); String annexJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList()) ? serviceReimbursementdetailVO.getAnnexfiles() : JSON.toJSONString(serviceReimbursementdetailVO.getAnnexfilesList()); String nameError = com.ruoyi.project.common.AttachmentNameValidator .checkJsonList(invoiceJson, annexJson); if (nameError != null) { return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError); } ServiceReimbursementdetail serviceReimbursementdetail = DtoConversionUtils.sourceToTarget(serviceReimbursementdetailVO, ServiceReimbursementdetail.class); //将前端传来的附件集合转成字符串 if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList())) { serviceReimbursementdetail.setAnnexfiles(JSON.toJSONString(serviceReimbursementdetailVO.getAnnexfilesList())); } if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList())) { serviceReimbursementdetail.setInvoicefiles(JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList())); } boolean save = serviceReimbursementdetailService.save(serviceReimbursementdetail); return AjaxResult.success(serviceReimbursementdetail); } /** * 修改报销申请明细 */ @ApiOperation("修改报销申请明细") //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')") @Log(title = "修改申请明细", businessType = BusinessType.UPDATE) @PostMapping("/updateRDlList") public AjaxResult updateRDlList(@RequestBody List serviceReimbursementdetails) { for (ServiceReimbursementdetail serviceReimbursementdetail : serviceReimbursementdetails) { // 2026-10-15:附件文件名规范二次校验(只校验本次变更的附件,历史附件放行) java.util.Set existingNames = new java.util.HashSet<>(); if (serviceReimbursementdetail.getId() != null) { ServiceReimbursementdetail oldDetail = serviceReimbursementdetailService .getById(serviceReimbursementdetail.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, serviceReimbursementdetail.getInvoicefiles(), serviceReimbursementdetail.getAnnexfiles()); if (nameError != null) { return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError); } serviceReimbursementdetailService.saveOrUpdate(serviceReimbursementdetail); } return null; } /** * 修改报销申请明细 */ @ApiOperation("修改报销申请明细") //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')") @Log(title = "报销申请明细", businessType = BusinessType.UPDATE) @PostMapping("/reimbursementdetailEdit") //@RepeatSubmit public AjaxResult edit(@RequestBody ServiceReimbursementdetailVO serviceReimbursementdetailVO) { // 2026-10-15:附件文件名规范二次校验(与前端 fileNameCheck 同口径,防止绕过前端)。 // 修改场景按业务口径"只校验本次变更的附件":保存前已存在的历史附件名不参与校验,避免卡住老单据。 java.util.Set existingNames = new java.util.HashSet<>(); if (serviceReimbursementdetailVO.getId() != null) { ServiceReimbursementdetail oldDetail = serviceReimbursementdetailService .getById(serviceReimbursementdetailVO.getId()); if (oldDetail != null) { existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator .collectNames(oldDetail.getInvoicefiles())); existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator .collectNames(oldDetail.getAnnexfiles())); } } // List 为空时回退校验字符串字段(annexfiles / invoicefiles),堵住"只传字符串字段"的绕过口 String invoiceJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList()) ? serviceReimbursementdetailVO.getInvoicefiles() : JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList()); String annexJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList()) ? serviceReimbursementdetailVO.getAnnexfiles() : JSON.toJSONString(serviceReimbursementdetailVO.getAnnexfilesList()); String nameError = com.ruoyi.project.common.AttachmentNameValidator .checkJsonListForUpdate(existingNames, invoiceJson, annexJson); if (nameError != null) { return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError); } if (serviceReimbursementdetailVO.getTrafficexpense() == null) { serviceReimbursementdetailVO.setTrafficexpense(new BigDecimal(0)); } if (serviceReimbursementdetailVO.getCityfee() == null) { serviceReimbursementdetailVO.setCityfee(new BigDecimal(0)); } if (serviceReimbursementdetailVO.getHotelexpense() == null) { serviceReimbursementdetailVO.setHotelexpense(new BigDecimal(0)); } if (serviceReimbursementdetailVO.getFoodexpenses() == null) { serviceReimbursementdetailVO.setFoodexpenses(new BigDecimal(0)); } if (serviceReimbursementdetailVO.getFoodallowance() == null) { serviceReimbursementdetailVO.setFoodallowance(new BigDecimal(0)); } if (serviceReimbursementdetailVO.getOtherexpense() == null) { serviceReimbursementdetailVO.setOtherexpense(new BigDecimal(0)); } if (serviceReimbursementdetailVO.getOtherfeeamount() == null) { serviceReimbursementdetailVO.setOtherfeeamount(new BigDecimal(0)); } ServiceReimbursementdetail serviceReimbursementdetail = DtoConversionUtils.sourceToTarget(serviceReimbursementdetailVO, ServiceReimbursementdetail.class); if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList())) { //对前端传过来的数组,进行JSON序列化,并赋值给Annexfiles serviceReimbursementdetail.setAnnexfiles(JSON.toJSONString(serviceReimbursementdetailVO.getAnnexfilesList())); } else { serviceReimbursementdetail.setAnnexfiles(null); } if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList())) { //对前端传过来的数组,进行JSON序列化,并赋值给Invoicefiles serviceReimbursementdetail.setInvoicefiles(JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList())); } else { serviceReimbursementdetail.setInvoicefiles(null); } return toAjax(serviceReimbursementdetailService.updateById(serviceReimbursementdetail)); } /** * 删除报销申请明细 */ @ApiOperation("删除报销申请明细") //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:remove')") @Log(title = "报销申请明细", businessType = BusinessType.DELETE) @GetMapping("/remove/{ids}") public AjaxResult remove(@PathVariable Long[] ids) { return toAjax(serviceReimbursementdetailService.removeByIds(Arrays.asList(ids))); } /** * 删除报销申请明细并修改金额 */ @ApiOperation("删除报销申请明细并修改金额") @Log(title = "报销申请明细", businessType = BusinessType.DELETE) @GetMapping("/deleteDetail/{id}") public AjaxResult deleteDetail(@PathVariable Long id) { return AjaxResult.success(serviceReimbursementdetailService.deleteDetail(id)); } }