|
@@ -0,0 +1,275 @@
|
|
|
|
+package cn.iocoder.yudao.module.expense.service.expenseinfo;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
|
|
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
|
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
|
|
|
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
|
|
|
+import cn.iocoder.yudao.module.employee.api.EmployeeApi;
|
|
|
|
+import cn.iocoder.yudao.module.employee.api.dto.EmployeeRespDTO;
|
|
|
|
+import cn.iocoder.yudao.module.employee.enums.ErrorCodeConstants;
|
|
|
|
+import cn.iocoder.yudao.module.expense.controller.admin.expenseinfo.vo.ExpenseInfoPageReqVO;
|
|
|
|
+import cn.iocoder.yudao.module.expense.controller.admin.expenseinfo.vo.ExpenseInfoRespVO;
|
|
|
|
+import cn.iocoder.yudao.module.expense.controller.admin.expenseinfo.vo.ExpenseInfoSaveReqVO;
|
|
|
|
+import cn.iocoder.yudao.module.expense.dal.dataobject.expenseinfo.ExpenseInfoDO;
|
|
|
|
+import cn.iocoder.yudao.module.expense.dal.dataobject.expenseinfo.ExpenseInfoObjDO;
|
|
|
|
+import cn.iocoder.yudao.module.expense.dal.mysql.expenseinfo.ExpenseInfoMapper;
|
|
|
|
+import cn.iocoder.yudao.module.expense.dal.mysql.expenseinfo.ExpenseInfoObjMapper;
|
|
|
|
+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.List;
|
|
|
|
+import java.util.Objects;
|
|
|
|
+
|
|
|
|
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
|
+import static cn.iocoder.yudao.module.expense.enums.ErrorCodeConstants.*;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 报销信息 Service 实现类
|
|
|
|
+ *
|
|
|
|
+ * @author dp
|
|
|
|
+ */
|
|
|
|
+@Service
|
|
|
|
+@Validated
|
|
|
|
+public class ExpenseInfoServiceImpl implements ExpenseInfoService {
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private ExpenseInfoMapper infoMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private ExpenseInfoObjMapper expenseInfoObjMapper;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private EmployeeApi employeeApi;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
+ public Long createInfo(ExpenseInfoSaveReqVO createReqVO) {
|
|
|
|
+ // 获取当前登录用户ID
|
|
|
|
+ Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
|
|
|
+ // 通过用户ID获取登录员工信息
|
|
|
|
+ EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(loginUserId);
|
|
|
|
+ // 获取报销员工ID
|
|
|
|
+ Long employeeId = createReqVO.getEmployeeId();
|
|
|
|
+ // 通过员工ID获取员工详细信息
|
|
|
|
+ EmployeeRespDTO employee = employeeApi.getEmployeeById(employeeId);
|
|
|
|
+ // 校验员工信息是否存在
|
|
|
|
+ if (Objects.isNull(loginEmployee) || Objects.isNull(employee)) {
|
|
|
|
+ throw exception(ErrorCodeConstants.EMPLOYEE_INFO_NOT_EXISTS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理费用明细信息
|
|
|
|
+ List<ExpenseInfoObjDO> oaExpenseObjs = createReqVO.getExpenseInfoObjs();
|
|
|
|
+ for (ExpenseInfoObjDO oaExpenseObj : oaExpenseObjs) {
|
|
|
|
+ // 设置费用明细的创建人
|
|
|
|
+ oaExpenseObj.setCreator(String.valueOf(loginEmployee.getId()));
|
|
|
|
+ oaExpenseObj.setMoney(oaExpenseObj.getMoney().setScale(2, BigDecimal.ROUND_HALF_UP));
|
|
|
|
+ oaExpenseObj.setExpenseObjUuid(IdUtil.fastSimpleUUID());
|
|
|
|
+
|
|
|
|
+ // 校验费用项目是否为空
|
|
|
|
+ if (oaExpenseObj.getExpenseItemId() == null) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_ITEM_BLANK);
|
|
|
|
+ }
|
|
|
|
+ // 校验费用金额是否有效
|
|
|
|
+ if (oaExpenseObj.getMoney() == null || oaExpenseObj.getMoney().compareTo(BigDecimal.ZERO) < 1) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_MONEY_ZERO);
|
|
|
|
+ }
|
|
|
|
+ // 校验开始日期是否为空
|
|
|
|
+ if (StrUtil.isBlank(oaExpenseObj.getStartDate())) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_START_DATE_NULL);
|
|
|
|
+ }
|
|
|
|
+ // 校验结束日期是否为空
|
|
|
|
+ if (StrUtil.isBlank(oaExpenseObj.getEndDate())) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_END_DATE_NULL);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 准备插入费用主表数据
|
|
|
|
+ ExpenseInfoDO info = BeanUtils.toBean(createReqVO, ExpenseInfoDO.class);
|
|
|
|
+ // 获取所有费用信息的总金额
|
|
|
|
+ BigDecimal totalMoney = info.getTotalMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ // 使用流操作累加oaExpenseObjs中所有ExpenseInfoObjDO对象的金额,并与0进行比较
|
|
|
|
+ BigDecimal reduce = oaExpenseObjs.stream()
|
|
|
|
+ .map(ExpenseInfoObjDO::getMoney)
|
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
|
|
|
|
+ .setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ // 比较总金额与累加金额是否一致,如果不一致则抛出异常
|
|
|
|
+ if (totalMoney.compareTo(reduce) != 0) {
|
|
|
|
+ throw exception(EXPENSE_INFO_TOTAL_MONEY_ERROR);
|
|
|
|
+ }
|
|
|
|
+ info.setTotalMoney(info.getTotalMoney().setScale(2, BigDecimal.ROUND_HALF_UP));
|
|
|
|
+ // 生成唯一标识符
|
|
|
|
+ info.setExpenseUuid(IdUtil.fastSimpleUUID());
|
|
|
|
+ // 设置部门ID、岗位ID、用户ID和创建人信息
|
|
|
|
+ info.setDeptId(employee.getDeptId());
|
|
|
|
+ info.setPostId(employee.getPostId());
|
|
|
|
+ info.setStatus("0");
|
|
|
|
+ info.setUserId(loginUserId);
|
|
|
|
+ info.setCreateEmployeeId(loginEmployee.getId());
|
|
|
|
+ info.setCreator(String.valueOf(loginEmployee.getId()));
|
|
|
|
+ // 插入费用主表数据
|
|
|
|
+ infoMapper.insert(info);
|
|
|
|
+
|
|
|
|
+ // 插入费用明细数据
|
|
|
|
+ createExpenseInfoObjList(info.getId(), createReqVO.getExpenseInfoObjs());
|
|
|
|
+
|
|
|
|
+ // 返回费用主表ID
|
|
|
|
+ return info.getId();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
+ public void updateInfo(ExpenseInfoSaveReqVO updateReqVO) {
|
|
|
|
+ // 获取当前登录用户ID
|
|
|
|
+ Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
|
|
|
+ // 通过用户ID获取登录员工信息
|
|
|
|
+ EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(loginUserId);
|
|
|
|
+ // 获取报销员工ID
|
|
|
|
+ Long employeeId = updateReqVO.getEmployeeId();
|
|
|
|
+ // 通过员工ID获取员工详细信息
|
|
|
|
+ EmployeeRespDTO employee = employeeApi.getEmployeeById(employeeId);
|
|
|
|
+ // 校验员工信息是否存在
|
|
|
|
+ if (Objects.isNull(loginEmployee) || Objects.isNull(employee)) {
|
|
|
|
+ throw exception(ErrorCodeConstants.EMPLOYEE_INFO_NOT_EXISTS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理费用明细信息
|
|
|
|
+ List<ExpenseInfoObjDO> oaExpenseObjs = updateReqVO.getExpenseInfoObjs();
|
|
|
|
+ for (ExpenseInfoObjDO oaExpenseObj : oaExpenseObjs) {
|
|
|
|
+ // 设置费用明细的创建人
|
|
|
|
+ oaExpenseObj.setCreator(String.valueOf(loginEmployee.getId()));
|
|
|
|
+ oaExpenseObj.setMoney(oaExpenseObj.getMoney().setScale(2, BigDecimal.ROUND_HALF_UP));
|
|
|
|
+ oaExpenseObj.setExpenseObjUuid(IdUtil.fastSimpleUUID());
|
|
|
|
+
|
|
|
|
+ // 校验费用项目是否为空
|
|
|
|
+ if (oaExpenseObj.getExpenseItemId() == null) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_ITEM_BLANK);
|
|
|
|
+ }
|
|
|
|
+ // 校验费用金额是否有效
|
|
|
|
+ if (oaExpenseObj.getMoney() == null || oaExpenseObj.getMoney().compareTo(BigDecimal.ZERO) < 1) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_MONEY_ZERO);
|
|
|
|
+ }
|
|
|
|
+ // 校验开始日期是否为空
|
|
|
|
+ if (StrUtil.isBlank(oaExpenseObj.getStartDate())) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_START_DATE_NULL);
|
|
|
|
+ }
|
|
|
|
+ // 校验结束日期是否为空
|
|
|
|
+ if (StrUtil.isBlank(oaExpenseObj.getEndDate())) {
|
|
|
|
+ throw exception(EXPENSE_INFO_OBJ_END_DATE_NULL);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 校验存在
|
|
|
|
+ ExpenseInfoDO expenseInfoBefore = validateInfoExists(updateReqVO.getId());
|
|
|
|
+ // 更新
|
|
|
|
+ ExpenseInfoDO updateObj = BeanUtils.toBean(updateReqVO, ExpenseInfoDO.class);
|
|
|
|
+
|
|
|
|
+ // 获取所有费用信息的总金额
|
|
|
|
+ BigDecimal totalMoney = updateObj.getTotalMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ // 使用流操作累加oaExpenseObjs中所有ExpenseInfoObjDO对象的金额,并与0进行比较
|
|
|
|
+ BigDecimal reduce = oaExpenseObjs.stream()
|
|
|
|
+ .map(ExpenseInfoObjDO::getMoney)
|
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
|
|
|
|
+ .setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ // 比较总金额与累加金额是否一致,如果不一致则抛出异常
|
|
|
|
+ if (totalMoney.compareTo(reduce) != 0) {
|
|
|
|
+ throw exception(EXPENSE_INFO_TOTAL_MONEY_ERROR);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 设置部门ID、岗位ID、用户ID和创建人信息
|
|
|
|
+ updateObj.setDeptId(employee.getDeptId());
|
|
|
|
+ updateObj.setPostId(employee.getPostId());
|
|
|
|
+ updateObj.setStatus("0");
|
|
|
|
+
|
|
|
|
+ infoMapper.updateById(updateObj);
|
|
|
|
+
|
|
|
|
+ // 更新子表
|
|
|
|
+ updateExpenseInfoObjList(updateReqVO.getId(), updateReqVO.getExpenseInfoObjs());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
+ public void deleteInfo(Long id) {
|
|
|
|
+ // 校验存在
|
|
|
|
+ validateInfoExists(id);
|
|
|
|
+ // 删除
|
|
|
|
+ infoMapper.deleteById(id);
|
|
|
|
+
|
|
|
|
+ // 删除子表
|
|
|
|
+ deleteExpenseInfoObjByExpenseId(id);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private ExpenseInfoDO validateInfoExists(Long id) {
|
|
|
|
+ ExpenseInfoDO expenseInfoDO = infoMapper.selectById(id);
|
|
|
|
+ if (expenseInfoDO == null) {
|
|
|
|
+ throw exception(INFO_NOT_EXISTS);
|
|
|
|
+ }
|
|
|
|
+ return expenseInfoDO;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public ExpenseInfoDO getInfo(Long id) {
|
|
|
|
+ return infoMapper.selectById(id);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public PageResult<ExpenseInfoRespVO> getInfoPage(ExpenseInfoPageReqVO pageReqVO) {
|
|
|
|
+
|
|
|
|
+ pageReqVO.setPageNo(pageReqVO.getPageNo() - 1);
|
|
|
|
+
|
|
|
|
+ long pageCount = 0;
|
|
|
|
+ if (!Objects.equals(pageReqVO.getPageSize(), PageParam.PAGE_SIZE_NONE)) {
|
|
|
|
+ pageCount = infoMapper.selectPageCount(pageReqVO);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<ExpenseInfoRespVO> pageList = infoMapper.selectPageList(pageReqVO);
|
|
|
|
+
|
|
|
|
+ for (ExpenseInfoRespVO expenseInfoRespVO : pageList) {
|
|
|
|
+ String status = expenseInfoRespVO.getStatus();
|
|
|
|
+ if (Objects.equals(status, "0")) {
|
|
|
|
+ expenseInfoRespVO.setStatusDesc("已完成");
|
|
|
|
+ } else if (Objects.equals(status, "1")) {
|
|
|
|
+ expenseInfoRespVO.setStatusDesc("已作废");
|
|
|
|
+ } else {
|
|
|
|
+ expenseInfoRespVO.setStatusDesc("未知");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String infoSource = expenseInfoRespVO.getInfoSource();
|
|
|
|
+ if (Objects.equals(infoSource, "0")) {
|
|
|
|
+ expenseInfoRespVO.setInfoSourceDesc("流程添加");
|
|
|
|
+ } else if (Objects.equals(infoSource, "1")) {
|
|
|
|
+ expenseInfoRespVO.setInfoSourceDesc("手动添加");
|
|
|
|
+ } else {
|
|
|
|
+ expenseInfoRespVO.setInfoSourceDesc("未知来源");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return new PageResult<>(pageList, pageCount);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ==================== 子表(报销信息子) ====================
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<ExpenseInfoObjDO> getExpenseInfoObjListByExpenseId(Long expenseId) {
|
|
|
|
+ return expenseInfoObjMapper.selectListByExpenseId(expenseId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void createExpenseInfoObjList(Long expenseId, List<ExpenseInfoObjDO> list) {
|
|
|
|
+ list.forEach(o -> o.setExpenseId(expenseId));
|
|
|
|
+ expenseInfoObjMapper.insertBatch(list);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void updateExpenseInfoObjList(Long expenseId, List<ExpenseInfoObjDO> list) {
|
|
|
|
+ deleteExpenseInfoObjByExpenseId(expenseId);
|
|
|
|
+ list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null).setCreateTime(null).setDeleted(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新
|
|
|
|
+ createExpenseInfoObjList(expenseId, list);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void deleteExpenseInfoObjByExpenseId(Long expenseId) {
|
|
|
|
+ expenseInfoObjMapper.deleteByExpenseId(expenseId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|