| | |
| | | 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.ServiceReimbursementdetailShared; |
| | | 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; |
| | |
| | | |
| | | /** |
| | | * 报销申请明细Controller |
| | | * |
| | | * |
| | | * @author ruoyi |
| | | * @date 2022-01-24 |
| | | */ |
| | | @Api("报销申请明细") |
| | | @RestController |
| | | @RequestMapping("/project/reimbursementdetail") |
| | | public class ServiceReimbursementdetailController extends BaseController |
| | | { |
| | | public class ServiceReimbursementdetailController extends BaseController { |
| | | @Autowired |
| | | private IServiceReimbursementdetailService serviceReimbursementdetailService; |
| | | @Autowired |
| | |
| | | * 查询报销申请明细列表 |
| | | */ |
| | | @ApiOperation("查询报销申请明细列表") |
| | | //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:list')") |
| | | //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:list')") |
| | | @GetMapping("/list") |
| | | public TableDataInfo list(ServiceReimbursementdetail serviceReimbursementdetail) |
| | | { |
| | | public TableDataInfo list(ServiceReimbursementdetail serviceReimbursementdetail) { |
| | | startPage(); |
| | | //List<ServiceReimbursementdetail> list = serviceReimbursementdetailService.queryList(serviceReimbursementdetail); |
| | | List<ServiceReimbursementdetail> list = serviceReimbursementdetailService.selectServiceReimbursementdetailList(serviceReimbursementdetail); |
| | |
| | | * 导出报销申请明细列表 |
| | | */ |
| | | @ApiOperation("导出报销申请明细列表") |
| | | //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:export')") |
| | | //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:export')") |
| | | @Log(title = "报销申请明细", businessType = BusinessType.EXPORT) |
| | | @GetMapping("/export") |
| | | public AjaxResult export(ServiceReimbursementdetail serviceReimbursementdetail) |
| | | { |
| | | public AjaxResult export(ServiceReimbursementdetail serviceReimbursementdetail) { |
| | | List<ServiceReimbursementdetail> list = serviceReimbursementdetailService.queryList(serviceReimbursementdetail); |
| | | ExcelUtil<ServiceReimbursementdetail> util = new ExcelUtil<ServiceReimbursementdetail>(ServiceReimbursementdetail.class); |
| | | return util.exportExcel(list, "报销申请明细数据"); |
| | | } |
| | | |
| | | |
| | | @DeleteMapping("/deleteByRBId/{rbid}") |
| | | public AjaxResult removeAllDetail(@PathVariable("rbid") Long rbid){ |
| | | @GetMapping("/deleteByRBId/{rbid}") |
| | | public AjaxResult removeAllDetail(@PathVariable("rbid") Long rbid) { |
| | | List<Long> ids = serviceReimbursementdetailService.getAllIds(rbid); |
| | | Long[] arr = (Long[])ids.toArray(new Long[ids.size()]); |
| | | Long[] arr = (Long[]) ids.toArray(new Long[ids.size()]); |
| | | return remove(arr); |
| | | } |
| | | |
| | |
| | | * 获取报销申请明细详细信息 |
| | | */ |
| | | @ApiOperation("获取报销申请明细详细信息") |
| | | //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:query')") |
| | | //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:query')") |
| | | @GetMapping(value = "/{id}") |
| | | public AjaxResult getInfo(@PathVariable("id") Long id) |
| | | { |
| | | public AjaxResult getInfo(@PathVariable("id") Long id) { |
| | | return AjaxResult.success(serviceReimbursementdetailService.getById(id)); |
| | | } |
| | | |
| | |
| | | * 新增报销申请明细 |
| | | */ |
| | | @ApiOperation("新增报销申请明细") |
| | | //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:add')") |
| | | //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:add')") |
| | | @Log(title = "报销申请明细", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | @PostMapping("/add") |
| | | @RepeatSubmit |
| | | public AjaxResult add(@RequestBody ServiceReimbursementdetail serviceReimbursementdetail) |
| | | { |
| | | return toAjax(serviceReimbursementdetailService.save(serviceReimbursementdetail)); |
| | | 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')") |
| | | //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')") |
| | | @Log(title = "修改申请明细", businessType = BusinessType.UPDATE) |
| | | @PostMapping("/updateRDlList") |
| | | public AjaxResult updateRDlList(@RequestBody List<ServiceReimbursementdetail> serviceReimbursementdetails) |
| | | { |
| | | for (ServiceReimbursementdetail serviceReimbursementdetail:serviceReimbursementdetails) { |
| | | public AjaxResult updateRDlList(@RequestBody List<ServiceReimbursementdetail> serviceReimbursementdetails) { |
| | | for (ServiceReimbursementdetail serviceReimbursementdetail : serviceReimbursementdetails) { |
| | | // 2026-10-15:附件文件名规范二次校验(只校验本次变更的附件,历史附件放行) |
| | | java.util.Set<String> 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); |
| | | //新增或修改报销申请明细分享表 |
| | | ServiceReimbursementdetailShared serviceReimbursementdetailShared = DtoConversionUtils.sourceToTarget(serviceReimbursementdetail, ServiceReimbursementdetailShared.class); |
| | | detailSharedService.saveOrUpdate(serviceReimbursementdetailShared); |
| | | |
| | | } |
| | | return null; |
| | | } |
| | |
| | | * 修改报销申请明细 |
| | | */ |
| | | @ApiOperation("修改报销申请明细") |
| | | //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')") |
| | | //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')") |
| | | @Log(title = "报销申请明细", businessType = BusinessType.UPDATE) |
| | | @PutMapping |
| | | @PostMapping("/reimbursementdetailEdit") |
| | | //@RepeatSubmit |
| | | public AjaxResult edit(@RequestBody ServiceReimbursementdetail serviceReimbursementdetail) |
| | | { |
| | | public AjaxResult edit(@RequestBody ServiceReimbursementdetailVO serviceReimbursementdetailVO) { |
| | | // 2026-10-15:附件文件名规范二次校验(与前端 fileNameCheck 同口径,防止绕过前端)。 |
| | | // 修改场景按业务口径"只校验本次变更的附件":保存前已存在的历史附件名不参与校验,避免卡住老单据。 |
| | | java.util.Set<String> 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')") |
| | | //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:remove')") |
| | | @Log(title = "报销申请明细", businessType = BusinessType.DELETE) |
| | | @DeleteMapping("/{ids}") |
| | | public AjaxResult remove(@PathVariable Long[] ids) |
| | | { |
| | | @GetMapping("/remove/{ids}") |
| | | public AjaxResult remove(@PathVariable Long[] ids) { |
| | | return toAjax(serviceReimbursementdetailService.removeByIds(Arrays.asList(ids))); |
| | | } |
| | | |
| | |
| | | */ |
| | | @ApiOperation("删除报销申请明细并修改金额") |
| | | @Log(title = "报销申请明细", businessType = BusinessType.DELETE) |
| | | @DeleteMapping("/deleteDetail/{id}") |
| | | public AjaxResult deleteDetail(@PathVariable Long id) |
| | | { |
| | | @GetMapping("/deleteDetail/{id}") |
| | | public AjaxResult deleteDetail(@PathVariable Long id) { |
| | | return AjaxResult.success(serviceReimbursementdetailService.deleteDetail(id)); |
| | | } |
| | | |