diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/expenseapply/ExpenseApplyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/expenseapply/ExpenseApplyController.java index 13c37fea..3766baef 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/expenseapply/ExpenseApplyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/expenseapply/ExpenseApplyController.java @@ -76,9 +76,9 @@ public class ExpenseApplyController { queryWrapper.eq(ExpenseApplyTripDO::getApplyId, expenseApply.getId()); List list = expenseApplyTripService.list(queryWrapper); expenseApply.setExpenseApplyTrips(list); - expenseApplyService.setNickNameField(CollUtil.toList(expenseApply)); - expenseApplyService.setDeptNameField(CollUtil.toList(expenseApply)); } + expenseApplyService.setNickNameField(CollUtil.toList(expenseApply)); + expenseApplyService.setDeptNameField(CollUtil.toList(expenseApply)); taskService.handleApprovalAuthority(CollUtil.toList(expenseApply)); return success(expenseApply); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/expenseclaim/ExpenseClaimController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/expenseclaim/ExpenseClaimController.java new file mode 100644 index 00000000..356b3361 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/expenseclaim/ExpenseClaimController.java @@ -0,0 +1,153 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.expenseclaim; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.bpm.service.expenseclaim.ExpenseClaimService; +import cn.iocoder.yudao.module.bpm.service.expenseclaimdetail.ExpenseClaimDetailService; +import cn.iocoder.yudao.module.bpm.service.expenseclaimtrip.ExpenseClaimTripService; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.*; +import cn.iocoder.yudao.module.bs.convert.expenseclaim.ExpenseClaimConvert; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseapply.ExpenseApplyDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseapplytrip.ExpenseApplyTripDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaim.ExpenseClaimDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail.ExpenseClaimDetailDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimtrip.ExpenseClaimTripDO; +import cn.iocoder.yudao.module.bs.enums.BillTypeEnum; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.context.annotation.Lazy; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - 报销单") +@RestController +@RequestMapping("/bs/expense-claim") +@Validated +public class ExpenseClaimController { + + @Resource + private ExpenseClaimService expenseClaimService; + @Resource + @Lazy // 解决循环依赖 + private BpmTaskService taskService; + @Resource + @Lazy + private ExpenseClaimTripService expenseClaimTripService; + @Resource + @Lazy + private ExpenseClaimDetailService expenseClaimDetailService; + + @PostMapping("/create") + @Operation(summary = "创建报销单") + @PreAuthorize("@ss.hasPermission('bs:expense-claim:create')") + public CommonResult createExpenseClaim(@Valid @RequestBody ExpenseClaimCreateReqVO createReqVO) { + return expenseClaimService.createExpenseClaim(createReqVO); + } + + + @DeleteMapping("/delete") + @Operation(summary = "删除报销单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('bs:expense-claim:delete')") + public CommonResult deleteExpenseClaim(@RequestParam("id") Long id) { + expenseClaimService.deleteExpenseClaim(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得报销单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('bs:expense-claim:query')") + public CommonResult getExpenseClaim(@RequestParam("id") Long id) { + ExpenseClaimDO expenseClaim = expenseClaimService.getExpenseClaim(id); + if (expenseClaim.getBillType().equals(BillTypeEnum.CLBX.getValue())) { + //差旅报销 + //行程单 + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX<>(); + queryWrapper.eq(ExpenseClaimTripDO::getClaimId, expenseClaim.getId()); + List list = expenseClaimTripService.list(queryWrapper); + expenseClaim.setExpenseClaimTrips(list); + //费用单 + List tripIds = list.stream().map(ExpenseClaimTripDO::getId).collect(Collectors.toList()); + LambdaQueryWrapperX tripqueryWrapper = new LambdaQueryWrapperX<>(); + tripqueryWrapper.in(ExpenseClaimDetailDO::getTripId, tripIds); + List detailDOList = expenseClaimDetailService.list(tripqueryWrapper); + Map tripDOMap = list.stream().collect(Collectors.toMap(ExpenseClaimTripDO::getId, eat -> eat)); + for (ExpenseClaimDetailDO detailDO : detailDOList) { + ExpenseClaimTripDO tripDo = tripDOMap.get(detailDO.getTripId()); + if (tripDo.getExpenseClaimDetails() == null) { + tripDo.setExpenseClaimDetails(new ArrayList<>()); + } + tripDo.getExpenseClaimDetails().add(detailDO); + } + } else { + //日常报销 + //费用单 + LambdaQueryWrapperX tripqueryWrapper = new LambdaQueryWrapperX<>(); + tripqueryWrapper.eq(ExpenseClaimDetailDO::getClaimId, expenseClaim.getId()); + List detailDOList = expenseClaimDetailService.list(tripqueryWrapper); + expenseClaim.setExpenseClaimDetails(detailDOList); + } + expenseClaimService.setNickNameField(CollUtil.toList(expenseClaim)); + expenseClaimService.setDeptNameField(CollUtil.toList(expenseClaim)); + taskService.handleApprovalAuthority(CollUtil.toList(expenseClaim)); + return success(expenseClaim); + } + + @GetMapping("/list") + @Operation(summary = "获得报销单列表") + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") + @PreAuthorize("@ss.hasPermission('bs:expense-claim:query')") + public CommonResult> getExpenseClaimList(@RequestParam("ids") Collection ids) { + List list = expenseClaimService.getExpenseClaimList(ids); + return success(ExpenseClaimConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得报销单分页") + @PreAuthorize("@ss.hasPermission('bs:expense-claim:query')") + public CommonResult> getExpenseClaimPage(@Valid ExpenseClaimPageReqVO pageVO) { + PageResult pageResult = expenseClaimService.getExpenseClaimPage(pageVO); + List list = pageResult.getList(); + if (CollUtil.isNotEmpty(list)) { + + + expenseClaimService.setNickNameField(list); + taskService.handleApprovalAuthority(list); + } + return success(pageResult); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出报销单 Excel") + @PreAuthorize("@ss.hasPermission('bs:expense-claim:export')") + @OperateLog(type = EXPORT) + public void exportExpenseClaimExcel(@Valid ExpenseClaimExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = expenseClaimService.getExpenseClaimList(exportReqVO); + // 导出 Excel + List datas = ExpenseClaimConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "报销单.xls", "数据", ExpenseClaimExcelVO.class, datas); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimService.java new file mode 100644 index 00000000..be8cd564 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.bpm.service.expenseclaim; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimCreateReqVO; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimExportReqVO; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimPageReqVO; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimUpdateReqVO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaim.ExpenseClaimDO; +import com.github.yulichang.base.MPJBaseService; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * 报销单 Service 接口 + * + * @author 芋道源码 + */ +public interface ExpenseClaimService extends MPJBaseService { + + /** + * 创建报销单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + CommonResult createExpenseClaim(@Valid ExpenseClaimCreateReqVO createReqVO); + + + + /** + * 删除报销单 + * + * @param id 编号 + */ + void deleteExpenseClaim(Long id); + + /** + * 获得报销单 + * + * @param id 编号 + * @return 报销单 + */ + ExpenseClaimDO getExpenseClaim(Long id); + + /** + * 获得报销单列表 + * + * @param ids 编号 + * @return 报销单列表 + */ + List getExpenseClaimList(Collection ids); + + /** + * 获得报销单分页 + * + * @param pageReqVO 分页查询 + * @return 报销单分页 + */ + PageResult getExpenseClaimPage(ExpenseClaimPageReqVO pageReqVO); + + /** + * 获得报销单列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 报销单列表 + */ + List getExpenseClaimList(ExpenseClaimExportReqVO exportReqVO); + + void setNickNameField(List toList); + + void setDeptNameField(List toList); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimServiceImpl.java new file mode 100644 index 00000000..80817220 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimServiceImpl.java @@ -0,0 +1,184 @@ +package cn.iocoder.yudao.module.bpm.service.expenseclaim; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.bpm.service.expenseclaimdetail.ExpenseClaimDetailService; +import cn.iocoder.yudao.module.bpm.service.expenseclaimtrip.ExpenseClaimTripService; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.*; +import cn.iocoder.yudao.module.bs.convert.expenseclaim.ExpenseClaimConvert; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaim.ExpenseClaimDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail.ExpenseClaimDetailDO; +import cn.iocoder.yudao.module.bs.dal.mysql.expenseclaim.ExpenseClaimMapper; +import cn.iocoder.yudao.module.bs.enums.BillTypeEnum; +import cn.iocoder.yudao.module.bs.enums.ExpenseApplyStatusEnum; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import com.github.yulichang.base.MPJBaseServiceImpl; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; +import static cn.iocoder.yudao.module.bs.enums.ErrorCodeConstants.EXPENSE_CLAIM_NOT_EXISTS; + +/** + * 报销单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Transactional(rollbackFor = Exception.class) +public class ExpenseClaimServiceImpl extends MPJBaseServiceImpl implements ExpenseClaimService { + + @Resource + private ExpenseClaimMapper expenseClaimMapper; + @Resource + private AdminUserApi adminUserApi; + @Resource + @Lazy + private ExpenseClaimTripService expenseClaimTripService; + @Resource + @Lazy + private ExpenseClaimDetailService expenseClaimDetailService; + @Resource + private DeptApi deptApi; + + @Override + public CommonResult createExpenseClaim(ExpenseClaimCreateReqVO createReqVO) { + // 插入 + ExpenseClaimDO expenseClaim = ExpenseClaimConvert.INSTANCE.convert(createReqVO); + CommonResult result = dataValidAndSetFileName(createReqVO, expenseClaim); + if (result.isError()) { + return result; + } + + expenseClaimMapper.insert(expenseClaim); + // 返回 + return CommonResult.success(); + } + + /** + * 新增和更新数据校验 + * + * @param createReqVO + * @param expenseClaim + * @return + */ + private CommonResult dataValidAndSetFileName(ExpenseClaimCreateReqVO createReqVO, ExpenseClaimDO expenseClaim) { + boolean isAdd = createReqVO.getId() == null; + + if (expenseClaim.getBillType().equals(BillTypeEnum.CLBX.getValue())) { + List expenseApplyTrips = createReqVO.getExpenseClaimTrips(); +// if (CollUtil.isEmpty(expenseApplyTrips)) { +// return CommonResult.error("差旅明细不能为空"); +// } +// // 参数校验 +// ValidationUtils.validate(validator, expenseApplyTrips); + BigDecimal amount = BigDecimal.ZERO; + for (ExpenseClaimTripCreateReqVO trip : expenseApplyTrips) { + BigDecimal tripAmount = BigDecimal.ZERO; + List details = trip.getExpenseClaimDetails(); + if (CollUtil.isNotEmpty(details)) { + for (ExpenseClaimDetailCreateReqVO detail : details) { + tripAmount = tripAmount.add(detail.getAmount()); + } + } + trip.setAmount(tripAmount); + amount = amount.add(tripAmount); + } + expenseClaim.setAmount(amount); + } else { + BigDecimal amount = BigDecimal.ZERO; + List details = expenseClaim.getExpenseClaimDetails(); + for (ExpenseClaimDetailDO detail : details) { + amount = amount.add(detail.getAmount()); + } + expenseClaim.setAmount(amount); + } + if (isAdd) { + //新增 + //cqptodo 单号的规则需要重写 + expenseClaim.setClaimNo(RandomUtil.randomString(6)); + } else { + ExpenseClaimDO dbApply = validateExpenseClaimExists(expenseClaim.getId()); + if (!dbApply.getStatus().equals(ExpenseApplyStatusEnum.NOSUBMIT.getValue())) { + //只有未提交才能更新 + return CommonResult.error("只有未提交单据才能更新"); + } + } + LoginUser loginUser = getLoginUser(); + expenseClaim.setUserId(loginUser.getId()); + AdminUserRespDTO user = adminUserApi.getUser(loginUser.getId()); + expenseClaim.setDeptId(user.getDeptId()); + return CommonResult.success(); + } + + @Override + public void deleteExpenseClaim(Long id) { + // 校验存在 + validateExpenseClaimExists(id); + // 删除 + expenseClaimMapper.deleteById(id); + } + + private ExpenseClaimDO validateExpenseClaimExists(Long id) { + ExpenseClaimDO expenseClaimDO = expenseClaimMapper.selectById(id); + if (expenseClaimDO == null) { + throw exception(EXPENSE_CLAIM_NOT_EXISTS); + } + return expenseClaimDO; + } + + @Override + public ExpenseClaimDO getExpenseClaim(Long id) { + return expenseClaimMapper.selectById(id); + } + + @Override + public List getExpenseClaimList(Collection ids) { + return expenseClaimMapper.selectBatchIds(ids); + } + + @Override + public PageResult getExpenseClaimPage(ExpenseClaimPageReqVO pageReqVO) { + return expenseClaimMapper.selectPage(pageReqVO); + } + + @Override + public List getExpenseClaimList(ExpenseClaimExportReqVO exportReqVO) { + return expenseClaimMapper.selectList(exportReqVO); + } + + @Override + public void setNickNameField(List list) { + List userIds = list.stream().map(ExpenseClaimDO::getUserId).distinct().collect(Collectors.toList()); + Map userMap = adminUserApi.getUserList(userIds).stream().collect(Collectors.toMap(AdminUserRespDTO::getId, user -> user.getNickname())); + for (ExpenseClaimDO expenseApply : list) { + expenseApply.setNickname(userMap.get(expenseApply.getUserId())); + } + } + + @Override + public void setDeptNameField(List list) { + List deptIds = list.stream().map(claim -> claim.getCostDeptId()).distinct().collect(Collectors.toList()); + Map deptMap = deptApi.getDeptList(deptIds).stream().collect(Collectors.toMap(DeptRespDTO::getId, dept -> dept.getName())); + for (ExpenseClaimDO expenseApply : list) { + expenseApply.setCostDeptName(deptMap.get(expenseApply.getDeptId())); + } + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimdetail/ExpenseClaimDetailService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimdetail/ExpenseClaimDetailService.java new file mode 100644 index 00000000..bcd4cf21 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimdetail/ExpenseClaimDetailService.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.bpm.service.expenseclaimdetail; + +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail.ExpenseClaimDetailDO; +import com.github.yulichang.base.MPJBaseService; + +/** + * 报销单费用明细 Service 接口 + * + * @author 芋道源码 + */ +public interface ExpenseClaimDetailService extends MPJBaseService { + + + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimdetail/ExpenseClaimDetailServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimdetail/ExpenseClaimDetailServiceImpl.java new file mode 100644 index 00000000..772a77e3 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimdetail/ExpenseClaimDetailServiceImpl.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.bpm.service.expenseclaimdetail; + +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail.ExpenseClaimDetailDO; +import cn.iocoder.yudao.module.bs.dal.mysql.expenseclaimdetail.ExpenseClaimDetailMapper; +import com.github.yulichang.base.MPJBaseServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +/** + * 报销单费用明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ExpenseClaimDetailServiceImpl extends MPJBaseServiceImpl implements ExpenseClaimDetailService { + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimtrip/ExpenseClaimTripService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimtrip/ExpenseClaimTripService.java new file mode 100644 index 00000000..9012676b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimtrip/ExpenseClaimTripService.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.bpm.service.expenseclaimtrip; + +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimtrip.ExpenseClaimTripDO; +import com.github.yulichang.base.MPJBaseService; + +/** + * 报销单行程明细 Service 接口 + * + * @author 芋道源码 + */ +public interface ExpenseClaimTripService extends MPJBaseService { + + + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimtrip/ExpenseClaimTripServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimtrip/ExpenseClaimTripServiceImpl.java new file mode 100644 index 00000000..5d09ed92 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaimtrip/ExpenseClaimTripServiceImpl.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.bpm.service.expenseclaimtrip; + +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimtrip.ExpenseClaimTripDO; +import cn.iocoder.yudao.module.bs.dal.mysql.expenseclaimtrip.ExpenseClaimTripMapper; +import com.github.yulichang.base.MPJBaseServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +/** + * 报销单行程明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ExpenseClaimTripServiceImpl extends MPJBaseServiceImpl implements ExpenseClaimTripService { + +} diff --git a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java index f65fc578..9f3dfd50 100644 --- a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java +++ b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java @@ -17,8 +17,10 @@ import java.util.stream.Collectors; public enum BillTypeEnum { CLSQ("CLSQ", "差旅申请单"), - RCSQ("RCSQ", "日常申请单"); - + RCSQ("RCSQ", "日常申请单"), + CLBX("CLBX", "差旅报销单"), + RCBX("RCBX", "日常报销单"), + ; /** * 类型 diff --git a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java index 6e2694be..5bde1a33 100644 --- a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java +++ b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ErrorCodeConstants.java @@ -14,4 +14,5 @@ public interface ErrorCodeConstants { ErrorCode BUDGET_NOT_EXISTS = new ErrorCode(200400, "预算管理不存在"); ErrorCode FEE_MANAGE_NOT_EXISTS = new ErrorCode(200500, "费用控制不存在"); ErrorCode CUSTOMER_COMPANY_NOT_EXISTS = new ErrorCode(200600, "客户公司不存在"); + ErrorCode EXPENSE_CLAIM_NOT_EXISTS = new ErrorCode(200700, "报销单不存在"); } diff --git a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ExpenseClaimSettleStatusEnum.java b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ExpenseClaimSettleStatusEnum.java new file mode 100644 index 00000000..df004e4d --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/ExpenseClaimSettleStatusEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.bs.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 报销结算状态枚举 + */ +@AllArgsConstructor +@Getter +public enum ExpenseClaimSettleStatusEnum { + + NOSETTLE("0", "未结算"), + WAITSETTLE("1", "待结算"), + FINISH("2", "已结算"), + ; + + + /** + * 类型 + */ + private final String value; + /** + * 类型名 + */ + private final String name; + + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyBaseVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyBaseVO.java index 484b7fd3..388ee877 100644 --- a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyBaseVO.java +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyBaseVO.java @@ -19,22 +19,6 @@ public class ExpenseApplyBaseVO { @NotNull(message = "申请类型不能为空") private String billType; -// @Schema(description = "申请者ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "9227") -// @NotNull(message = "申请者ID不能为空") -// private Long userId; -// -// @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") -// @NotNull(message = "用户昵称不能为空") -// private String nickname; -// -// @Schema(description = "部门ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "32343") -// @NotNull(message = "部门ID不能为空") -// private Long deptId; -// -// @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") -// @NotNull(message = "部门名称不能为空") -// private String deptName; - @Schema(description = "项目名称", example = "芋艿") private String projectName; diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyCreateReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyCreateReqVO.java index e655d295..9d327a81 100644 --- a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyCreateReqVO.java +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseapply/vo/ExpenseApplyCreateReqVO.java @@ -13,7 +13,7 @@ import javax.validation.constraints.AssertTrue; @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ExpenseApplyCreateReqVO extends ExpenseApplyBaseVO { - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14225") + @Schema(description = "id") private Long id; @AssertTrue(message = "状态只能是0或者1提交") public boolean isStatusValid() { diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimBaseVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimBaseVO.java new file mode 100644 index 00000000..9edba093 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimBaseVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.List; + +/** + * 报销单 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class ExpenseClaimBaseVO { + + @Schema(description = "报销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "报销类型不能为空") + private String billType; + + @Schema(description = "报销单号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "报销单号不能为空") + private String claimNo; + + @Schema(description = "申请者ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31597") + @NotNull(message = "申请者ID不能为空") + private Long userId; + + @Schema(description = "部门ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "16015") + @NotNull(message = "部门ID不能为空") + private Long deptId; + + @Schema(description = "项目名称", example = "赵六") + private String projectName; + + @Schema(description = "报销事由", requiredMode = Schema.RequiredMode.REQUIRED, example = "不香") + @NotNull(message = "报销事由不能为空") + private String reason; + + @Schema(description = "报销金额") + private BigDecimal amount; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "状态不能为空") + private String status; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "附件不能为空") + private List files; + + @Schema(description = "流程实例的编号", example = "11882") + private String processInstanceId; + + @Schema(description = "费用归属部门", requiredMode = Schema.RequiredMode.REQUIRED, example = "26990") + @NotNull(message = "费用归属部门不能为空") + private Long costDeptId; + + @Schema(description = "关联发票ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "关联发票ID不能为空") + private String invoiceIds; + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimCreateReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimCreateReqVO.java new file mode 100644 index 00000000..a454ad6a --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimCreateReqVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import cn.iocoder.yudao.module.bs.enums.BillTypeEnum; +import cn.iocoder.yudao.module.bs.enums.ExpenseApplyStatusEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Schema(description = "管理后台 - 报销单创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpenseClaimCreateReqVO extends ExpenseClaimBaseVO { + @Schema(description = "id") + private Long id; + @Schema(description = "报销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "报销类型不能为空") + private String billType; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "报销事由") + @NotNull(message = "报销事由") + private String reason; + @NotNull(message = "申请事由") + private Long costDeptId; + + @NotBlank(message = "状态不能为空") + private String status; + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED) + private List files; + + @Schema(description = "行程明细,仅为差旅报销单的时候需要传", example = "") + private List expenseClaimTrips; + + @Schema(description = "费用明细,仅为日常报销单的时候需要传", example = "") + private List expenseClaimDetails; + + @AssertTrue(message = "差旅报销单的行程明细及其报销明细不能为空") + public boolean isTripsValid() { + if (BillTypeEnum.CLBX.getValue().equals(billType) && CollUtil.isEmpty(expenseClaimTrips)) { + return false; + } + return true; + } + + @AssertTrue(message = "日常报销单的报销明细不能为空") + public boolean isDetailsValid() { + if (BillTypeEnum.RCBX.getValue().equals(billType) && CollUtil.isEmpty(expenseClaimDetails)) { + return false; + } + return true; + } + + @AssertTrue(message = "状态只能是0或者1提交") + public boolean isStatusValid() { + //只能传未提交和待审核 + return getStatus().equals(ExpenseApplyStatusEnum.NOSUBMIT.getValue()) || getStatus().equals(ExpenseApplyStatusEnum.PROCESS.getValue()); + } +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimDetailCreateReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimDetailCreateReqVO.java new file mode 100644 index 00000000..e2b5d57d --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimDetailCreateReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - 报销单创建 Request VO") +@Data +@ToString(callSuper = true) +public class ExpenseClaimDetailCreateReqVO { + @Schema(description = "费用类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "费用类型不能为空") + private String feeType; + + @Schema(description = "金额") + @NotNull(message = "金额不能为空") + private BigDecimal amount; + + @Schema(description = "发票/凭证张数", example = "24048") + @NotNull(message = "发票/凭证张数不能为空") + private Integer invoiceCount; + + @Schema(description = "备注", example = "你说的对") + private String remark; +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimExcelVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimExcelVO.java new file mode 100644 index 00000000..372a3db0 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimExcelVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 报销单 Excel VO + * + * @author 芋道源码 + */ +@Data +public class ExpenseClaimExcelVO { + + @ExcelProperty("id") + private Long id; + + @ExcelProperty("报销类型") + private String billType; + + @ExcelProperty("报销单号") + private String claimNo; + + @ExcelProperty("申请者ID") + private Long userId; + + @ExcelProperty("部门ID") + private Long deptId; + + @ExcelProperty("项目名称") + private String projectName; + + @ExcelProperty("报销事由") + private String reason; + + @ExcelProperty("报销金额") + private BigDecimal amount; + + @ExcelProperty("状态") + private String status; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("附件") + private List files; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @ExcelProperty("流程实例的编号") + private String processInstanceId; + + @ExcelProperty("费用归属部门") + private Long costDeptId; + + @ExcelProperty("关联发票ID") + private String invoiceIds; + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimExportReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimExportReqVO.java new file mode 100644 index 00000000..ffa4fe4d --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimExportReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 报销单 Excel 导出 Request VO,参数和 ExpenseClaimPageReqVO 是一致的") +@Data +public class ExpenseClaimExportReqVO { + + @Schema(description = "报销类型", example = "2") + private String billType; + + @Schema(description = "报销单号") + private String claimNo; + + @Schema(description = "申请者ID", example = "31597") + private Long userId; + + @Schema(description = "部门ID", example = "16015") + private Long deptId; + + @Schema(description = "项目名称", example = "赵六") + private String projectName; + + @Schema(description = "报销事由", example = "不香") + private String reason; + + @Schema(description = "报销金额") + private BigDecimal amount; + + @Schema(description = "状态", example = "2") + private String status; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "附件") + private List files; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "流程实例的编号", example = "11882") + private String processInstanceId; + + @Schema(description = "费用归属部门", example = "26990") + private Long costDeptId; + + @Schema(description = "关联发票ID") + private String invoiceIds; + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimPageReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimPageReqVO.java new file mode 100644 index 00000000..e620c039 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimPageReqVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 报销单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpenseClaimPageReqVO extends PageParam { + + @Schema(description = "报销类型", example = "2") + private String billType; + + @Schema(description = "报销单号") + private String claimNo; + + @Schema(description = "申请者ID", example = "31597") + private Long userId; + + @Schema(description = "部门ID", example = "16015") + private Long deptId; + + @Schema(description = "项目名称", example = "赵六") + private String projectName; + + @Schema(description = "报销事由", example = "不香") + private String reason; + + @Schema(description = "报销金额") + private BigDecimal amount; + + @Schema(description = "状态", example = "2") + private String status; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "附件") + private List files; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "流程实例的编号", example = "11882") + private String processInstanceId; + + @Schema(description = "费用归属部门", example = "26990") + private Long costDeptId; + + @Schema(description = "关联发票ID") + private String invoiceIds; + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimRespVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimRespVO.java new file mode 100644 index 00000000..eb3d2edc --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 报销单 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpenseClaimRespVO extends ExpenseClaimBaseVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14131") + private Long id; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimTripCreateReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimTripCreateReqVO.java new file mode 100644 index 00000000..a9be9710 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimTripCreateReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import cn.iocoder.yudao.module.bs.controller.admin.expenseapplytrip.vo.ExpenseApplyTripCreateReqVO; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +@Schema(description = "管理后台 - 报销单创建 Request VO") +@Data +@ToString(callSuper = true) +public class ExpenseClaimTripCreateReqVO { + @Schema(description = "出发地编码,二级市", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出发地编码,二级市不能为空") + private String departureLocation; + + @Schema(description = "目的地编码,二级市", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "目的地编码,二级市不能为空") + private String destinationLocation; + + @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "开始日期不能为空") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime startTime; + + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "结束日期不能为空") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime endTime; + + @Schema(description = "出差天数") + @NotNull(message = "出差天数不能为空") + private BigDecimal tripDay; + + @Schema(description = "出差类型") + @NotNull(message = "出差类型不能为空") + private String tripType; + + @Schema(description = "出差同行人") + private Set tripPartners; +// + @Schema(description = "预计费用") + private BigDecimal amount; + + @Schema(description = "费用明细", example = "") + private List expenseClaimDetails; +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimUpdateReqVO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimUpdateReqVO.java new file mode 100644 index 00000000..a2607ec9 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/controller/admin/expenseclaim/vo/ExpenseClaimUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 报销单更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpenseClaimUpdateReqVO extends ExpenseClaimBaseVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14131") + @NotNull(message = "id不能为空") + private Long id; + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/convert/expenseclaim/ExpenseClaimConvert.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/convert/expenseclaim/ExpenseClaimConvert.java new file mode 100644 index 00000000..5034aa9e --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/convert/expenseclaim/ExpenseClaimConvert.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.bs.convert.expenseclaim; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimCreateReqVO; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimExcelVO; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimRespVO; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimUpdateReqVO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaim.ExpenseClaimDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 报销单 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ExpenseClaimConvert { + + ExpenseClaimConvert INSTANCE = Mappers.getMapper(ExpenseClaimConvert.class); + + ExpenseClaimDO convert(ExpenseClaimCreateReqVO bean); + + ExpenseClaimDO convert(ExpenseClaimUpdateReqVO bean); + + ExpenseClaimRespVO convert(ExpenseClaimDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaim/ExpenseClaimDO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaim/ExpenseClaimDO.java new file mode 100644 index 00000000..479e549c --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaim/ExpenseClaimDO.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaim; + +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseapplytrip.ExpenseApplyTripDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail.ExpenseClaimDetailDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimtrip.ExpenseClaimTripDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 报销单 DO + * + * @author 芋道源码 + */ +@TableName(value = "bs_expense_claim", autoResultMap = true) +@KeySequence("bs_expense_claim_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ExpenseClaimDO extends TenantBaseDO { + + /** + * id + */ + @TableId + private Long id; + /** + * 报销类型 + */ + private String billType; + /** + * 报销单号 + */ + private String claimNo; + /** + * 申请者ID + */ + private Long userId; + /** + * 部门ID + */ + private Long deptId; + /** + * 项目名称 + */ + private String projectName; + /** + * 报销事由 + */ + private String reason; + /** + * 报销金额 + */ + private BigDecimal amount; + /** + * 状态 + */ + private String status; + /** + * 备注 + */ + private String remark; + /** + * 附件 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List files; + /** + * 流程实例的编号 + */ + private String processInstanceId; + /** + * 费用归属部门 + */ + private Long costDeptId; + /** + * 结算状态 + */ + private String settleStatus; + /** + * 关联发票ID + */ + private String invoiceIds; + + @TableField(exist = false) + private List expenseClaimTrips; + @TableField(exist = false) + private List expenseClaimDetails; + @TableField(exist = false) + private Boolean deleted; + @TableField(exist = false) + private String nickname; + @TableField(exist = false) + private String deptName; + @TableField(exist = false) + private String costDeptName; +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaimdetail/ExpenseClaimDetailDO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaimdetail/ExpenseClaimDetailDO.java new file mode 100644 index 00000000..b209cf9d --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaimdetail/ExpenseClaimDetailDO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail; + +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Set; + +/** + * 报销单费用明细 DO + * + * @author 芋道源码 + */ +@TableName(value = "bs_expense_claim_detail", autoResultMap = true) +@KeySequence("bs_expense_claim_detail_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ExpenseClaimDetailDO extends TenantBaseDO { + + /** + * id + */ + @TableId + private Long id; + /** + * 报销单ID + */ + private Long claimId; + /** + * 费用类型 + */ + private String feeType; + /** + * 金额 + */ + private BigDecimal amount; + /** + * 发票/凭证张数 + */ + private Integer invoiceCount; + /** + * 备注 + */ + private String remark; + /** + * 附件 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List files; + /** + * 关联发票ID + */ + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set invoiceIds; + /** + * 行程ID/仅差旅报销单有用 + */ + private Long tripId; + @TableField(exist = false) + private Boolean deleted; +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaimtrip/ExpenseClaimTripDO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaimtrip/ExpenseClaimTripDO.java new file mode 100644 index 00000000..b8075700 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/expenseclaimtrip/ExpenseClaimTripDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimtrip; + +import cn.iocoder.yudao.framework.common.pojo.ImageVo; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail.ExpenseClaimDetailDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; + +/** + * 报销单行程明细 DO + * + * @author 芋道源码 + */ +@TableName(value = "bs_expense_claim_trip", autoResultMap = true) +@KeySequence("bs_expense_claim_trip_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ExpenseClaimTripDO extends TenantBaseDO { + + /** + * id + */ + @TableId + private Long id; + /** + * 出发地编码,二级市 + */ + private String departureLocation; + /** + * 目的地编码,二级市 + */ + private String destinationLocation; + /** + * 开始日期 + */ + private LocalDateTime startTime; + /** + * 结束日期 + */ + private LocalDateTime endTime; + /** + * 出差天数 + */ + private BigDecimal tripDay; + /** + * 出差类型 + */ + private String tripType; + /** + * 出差同行人 + */ + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set tripPartners; + /** + * 预计费用 + */ + private BigDecimal amount; + /** + * 备注 + */ + private String remark; + /** + * 附件 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List files; + /** + * 报销ID + */ + private Long claimId; + @TableField(exist = false) + private Boolean deleted; + @TableField(exist = false) + private List expenseClaimDetails; +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaim/ExpenseClaimMapper.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaim/ExpenseClaimMapper.java new file mode 100644 index 00000000..e0236ae3 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaim/ExpenseClaimMapper.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.bs.dal.mysql.expenseclaim; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimExportReqVO; +import cn.iocoder.yudao.module.bs.controller.admin.expenseclaim.vo.ExpenseClaimPageReqVO; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaim.ExpenseClaimDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 报销单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ExpenseClaimMapper extends BaseMapperX { + + default PageResult selectPage(ExpenseClaimPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ExpenseClaimDO::getBillType, reqVO.getBillType()) + .eqIfPresent(ExpenseClaimDO::getClaimNo, reqVO.getClaimNo()) + .eqIfPresent(ExpenseClaimDO::getUserId, reqVO.getUserId()) + .eqIfPresent(ExpenseClaimDO::getDeptId, reqVO.getDeptId()) + .likeIfPresent(ExpenseClaimDO::getProjectName, reqVO.getProjectName()) + .eqIfPresent(ExpenseClaimDO::getReason, reqVO.getReason()) + .eqIfPresent(ExpenseClaimDO::getAmount, reqVO.getAmount()) + .eqIfPresent(ExpenseClaimDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ExpenseClaimDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ExpenseClaimDO::getFiles, reqVO.getFiles()) + .betweenIfPresent(ExpenseClaimDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(ExpenseClaimDO::getProcessInstanceId, reqVO.getProcessInstanceId()) + .eqIfPresent(ExpenseClaimDO::getCostDeptId, reqVO.getCostDeptId()) + .eqIfPresent(ExpenseClaimDO::getInvoiceIds, reqVO.getInvoiceIds()) + .orderByDesc(ExpenseClaimDO::getId)); + } + + default List selectList(ExpenseClaimExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(ExpenseClaimDO::getBillType, reqVO.getBillType()) + .eqIfPresent(ExpenseClaimDO::getClaimNo, reqVO.getClaimNo()) + .eqIfPresent(ExpenseClaimDO::getUserId, reqVO.getUserId()) + .eqIfPresent(ExpenseClaimDO::getDeptId, reqVO.getDeptId()) + .likeIfPresent(ExpenseClaimDO::getProjectName, reqVO.getProjectName()) + .eqIfPresent(ExpenseClaimDO::getReason, reqVO.getReason()) + .eqIfPresent(ExpenseClaimDO::getAmount, reqVO.getAmount()) + .eqIfPresent(ExpenseClaimDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ExpenseClaimDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ExpenseClaimDO::getFiles, reqVO.getFiles()) + .betweenIfPresent(ExpenseClaimDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(ExpenseClaimDO::getProcessInstanceId, reqVO.getProcessInstanceId()) + .eqIfPresent(ExpenseClaimDO::getCostDeptId, reqVO.getCostDeptId()) + .eqIfPresent(ExpenseClaimDO::getInvoiceIds, reqVO.getInvoiceIds()) + .orderByDesc(ExpenseClaimDO::getId)); + } + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaimdetail/ExpenseClaimDetailMapper.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaimdetail/ExpenseClaimDetailMapper.java new file mode 100644 index 00000000..4327d69e --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaimdetail/ExpenseClaimDetailMapper.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.bs.dal.mysql.expenseclaimdetail; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimdetail.ExpenseClaimDetailDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 报销单费用明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ExpenseClaimDetailMapper extends BaseMapperX { + + + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaimtrip/ExpenseClaimTripMapper.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaimtrip/ExpenseClaimTripMapper.java new file mode 100644 index 00000000..bc980dec --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/mysql/expenseclaimtrip/ExpenseClaimTripMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.bs.dal.mysql.expenseclaimtrip; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.bs.dal.dataobject.expenseclaimtrip.ExpenseClaimTripDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 报销单行程明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ExpenseClaimTripMapper extends BaseMapperX { + + +} diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaim/ExpenseClaimMapper.xml b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaim/ExpenseClaimMapper.xml new file mode 100644 index 00000000..f67bfeac --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaim/ExpenseClaimMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaimdetail/ExpenseClaimDetailMapper.xml b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaimdetail/ExpenseClaimDetailMapper.xml new file mode 100644 index 00000000..f57483e5 --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaimdetail/ExpenseClaimDetailMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaimtrip/ExpenseClaimTripMapper.xml b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaimtrip/ExpenseClaimTripMapper.xml new file mode 100644 index 00000000..c96beb6d --- /dev/null +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/resources/mapper/expenseclaimtrip/ExpenseClaimTripMapper.xml @@ -0,0 +1,12 @@ + + + + + + +