package com.ruoyi.sales.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.sales.dto.SalesContractDTO; import com.ruoyi.sales.mapper.SalesContractMapper; import com.ruoyi.sales.mapper.SalesContractProductMapper; import com.ruoyi.sales.pojo.SalesContract; import com.ruoyi.sales.pojo.SalesContractProduct; import com.ruoyi.sales.service.ISalesContractService; import com.ruoyi.sales.vo.SalesContractVO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 销售合同 Service 实现 */ @Slf4j @Service public class SalesContractServiceImpl extends ServiceImpl implements ISalesContractService { @Resource private SalesContractProductMapper salesContractProductMapper; @Override public IPage listPage(Page page, SalesContractDTO dto) { LambdaQueryWrapper queryWrapper = buildQueryWrapper(dto); IPage iPage = this.page(page, queryWrapper); IPage voPage = iPage.convert(item -> { return BeanUtil.copyProperties(item, SalesContractVO.class); }); return voPage; } @Override public AjaxResult getDetail(Long id) { SalesContract contract = this.getById(id); if (contract == null) { return AjaxResult.error("合同数据不存在"); } SalesContractVO vo = BeanUtil.copyProperties(contract, SalesContractVO.class); // 获取明细 LambdaQueryWrapper productQuery = new LambdaQueryWrapper<>(); productQuery.eq(SalesContractProduct::getContractId, id); List productList = salesContractProductMapper.selectList(productQuery); vo.setProductList(productList); return AjaxResult.success(vo); } @Override @Transactional(rollbackFor = Exception.class) public AjaxResult addOrUpdate(SalesContractDTO dto) { SalesContract contract = BeanUtil.copyProperties(dto, SalesContract.class); boolean isUpdate = contract.getId() != null; List productList = dto.getProductList(); if (productList == null) { productList = new ArrayList<>(); } // 重新计算各产品的产值,并汇总合同总产值 BigDecimal totalOutputValue = BigDecimal.ZERO; for (SalesContractProduct product : productList) { BigDecimal price = product.getTaxInclusiveUnitPrice() != null ? product.getTaxInclusiveUnitPrice() : BigDecimal.ZERO; BigDecimal shipped = product.getShippedQuantity() != null ? product.getShippedQuantity() : BigDecimal.ZERO; BigDecimal productOutputValue = price.multiply(shipped); product.setOutputValue(productOutputValue); totalOutputValue = totalOutputValue.add(productOutputValue); } contract.setOutputValue(totalOutputValue); if (isUpdate) { this.updateById(contract); // 差量更新逻辑 handleProductListUpdate(contract.getId(), productList); } else { this.save(contract); // 批量插入明细 for (SalesContractProduct product : productList) { product.setContractId(contract.getId()); salesContractProductMapper.insert(product); } } return AjaxResult.success(); } /** * 处理产品明细的差量更新 */ private void handleProductListUpdate(Long contractId, List newList) { // 获取数据库中旧的明细列表 LambdaQueryWrapper productQuery = new LambdaQueryWrapper<>(); productQuery.eq(SalesContractProduct::getContractId, contractId); List oldList = salesContractProductMapper.selectList(productQuery); Map oldMap = oldList.stream() .collect(Collectors.toMap(SalesContractProduct::getId, p -> p)); // 遍历新列表进行插入或更新 for (SalesContractProduct newProduct : newList) { newProduct.setContractId(contractId); if (newProduct.getId() != null && oldMap.containsKey(newProduct.getId())) { // 更新 salesContractProductMapper.updateById(newProduct); oldMap.remove(newProduct.getId()); // 从 Map 中移除,剩下的就是需要删除的 } else { // 新增 newProduct.setId(null); // 防御性处理 salesContractProductMapper.insert(newProduct); } } // 删除在前端列表中不存在的旧记录 if (!oldMap.isEmpty()) { salesContractProductMapper.deleteBatchIds(oldMap.keySet()); } } @Override @Transactional(rollbackFor = Exception.class) public AjaxResult del(List ids) { if (CollectionUtils.isEmpty(ids)) { return AjaxResult.error("参数不能为空"); } // 删除主表 this.removeByIds(ids); // 级联删除子表 LambdaQueryWrapper delQuery = new LambdaQueryWrapper<>(); delQuery.in(SalesContractProduct::getContractId, ids); salesContractProductMapper.delete(delQuery); return AjaxResult.success(); } @Override public List selectList(SalesContractDTO dto) { return this.list(buildQueryWrapper(dto)); } /** * 构建查询条件 */ private LambdaQueryWrapper buildQueryWrapper(SalesContractDTO dto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); if (dto == null) { return queryWrapper; } queryWrapper.like(StringUtils.isNotBlank(dto.getContractNo()), SalesContract::getContractNo, dto.getContractNo()); queryWrapper.like(StringUtils.isNotBlank(dto.getSigningUnit()), SalesContract::getSigningUnit, dto.getSigningUnit()); queryWrapper.eq(StringUtils.isNotBlank(dto.getArchiveStatus()), SalesContract::getArchiveStatus, dto.getArchiveStatus()); queryWrapper.ge(dto.getSignDateStart() != null, SalesContract::getSignDate, dto.getSignDateStart()); queryWrapper.le(dto.getSignDateEnd() != null, SalesContract::getSignDate, dto.getSignDateEnd()); queryWrapper.orderByDesc(SalesContract::getCreateTime); return queryWrapper; } }