package com.ruoyi.sales.service.impl;
|
|
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.approve.pojo.ApproveProcess;
|
import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
|
import com.ruoyi.common.enums.FileNameType;
|
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
|
import com.ruoyi.other.service.impl.TempFileServiceImpl;
|
import com.ruoyi.procurementrecord.utils.StockUtils;
|
import com.ruoyi.sales.dto.SalesLedgerProductDto;
|
import com.ruoyi.sales.dto.ShippingInfoDto;
|
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
|
import com.ruoyi.sales.mapper.ShippingInfoMapper;
|
import com.ruoyi.sales.pojo.SalesLedger;
|
import com.ruoyi.sales.pojo.SalesLedgerProduct;
|
import com.ruoyi.sales.pojo.ShippingInfo;
|
import com.ruoyi.sales.service.ShippingInfoService;
|
import com.ruoyi.sales.mapper.SalesLedgerMapper;
|
import com.ruoyi.stock.mapper.StockInventoryMapper;
|
import com.ruoyi.stock.pojo.StockInventory;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import org.springframework.transaction.annotation.Transactional;
|
import java.math.BigDecimal;
|
import java.util.HashMap;
|
import java.util.Map;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.collections4.CollectionUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.io.IOException;
|
import java.util.Collections;
|
import java.util.List;
|
|
/**
|
* @author :yys
|
* @date : 2025/10/22 9:33
|
*/
|
@Service
|
@Slf4j
|
public class ShippingInfoServiceImpl extends ServiceImpl<ShippingInfoMapper, ShippingInfo> implements ShippingInfoService {
|
|
@Autowired
|
private ShippingInfoMapper shippingInfoMapper;
|
|
@Autowired
|
private TempFileServiceImpl tempFileService;
|
@Autowired
|
private SalesLedgerProductMapper salesLedgerProductMapper;
|
@Autowired
|
private StockUtils stockUtils;
|
@Autowired
|
private CommonFileServiceImpl commonFileService;
|
|
@Autowired
|
private ApproveProcessServiceImpl approveProcessService;
|
|
@Autowired
|
private SalesLedgerMapper salesLedgerMapper;
|
|
@Autowired
|
private StockInventoryMapper stockInventoryMapper;
|
|
@Override
|
public IPage<ShippingInfoDto> listPage(Page page, ShippingInfo req) {
|
IPage<ShippingInfoDto> listPage = shippingInfoMapper.listPage(page, req);
|
listPage.getRecords().forEach(item ->{
|
item.setCommonFileList(commonFileService.getFileListByBusinessId(item.getId(), FileNameType.SHIP.getValue()));
|
});
|
return listPage;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean deductStock(ShippingInfoDto req) throws IOException {
|
ShippingInfo byId = this.getById(req.getId());
|
if (byId == null) {
|
throw new RuntimeException("发货信息不存在");
|
}
|
return deductStockByOrder(byId.getSalesLedgerId(), req);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean deductStockByOrder(Long salesLedgerId, ShippingInfoDto req) throws IOException {
|
if (salesLedgerId == null) {
|
throw new RuntimeException("关联订单不可为空");
|
}
|
|
SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerId);
|
if (salesLedger == null) {
|
throw new RuntimeException("关联订单不存在");
|
}
|
|
// 检查该订单下是否还有未发货的记录
|
List<ShippingInfo> unsentShippings = this.list(new LambdaQueryWrapper<ShippingInfo>()
|
.eq(ShippingInfo::getSalesLedgerId, salesLedgerId)
|
.ne(ShippingInfo::getStatus, "已发货"));
|
|
// 仅在存在未发货记录时执行库存扣减
|
if (CollectionUtils.isNotEmpty(unsentShippings)) {
|
// 获取该订单下所有的产品信息进行汇总扣减
|
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
|
.eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId));
|
|
if (CollectionUtils.isEmpty(products)) {
|
throw new RuntimeException("该订单下无产品信息,无法扣减库存");
|
}
|
|
// 汇总需求并校验库存
|
Map<Long, BigDecimal> modelQtyMap = new HashMap<>();
|
for (SalesLedgerProduct p : products) {
|
if (p.getProductModelId() == null) continue;
|
modelQtyMap.put(p.getProductModelId(), modelQtyMap.getOrDefault(p.getProductModelId(), BigDecimal.ZERO).add(p.getQuantity()));
|
}
|
|
for (Map.Entry<Long, BigDecimal> entry : modelQtyMap.entrySet()) {
|
Long modelId = entry.getKey();
|
BigDecimal totalNeeded = entry.getValue();
|
|
StockInventory stock = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>()
|
.eq(StockInventory::getProductModelId, modelId));
|
|
if (stock == null) {
|
throw new RuntimeException("产品规格ID:" + modelId + " 库存记录不存在");
|
}
|
|
BigDecimal locked = stock.getLockedQuantity() == null ? BigDecimal.ZERO : stock.getLockedQuantity();
|
BigDecimal available = stock.getQualitity().subtract(locked);
|
|
if (totalNeeded.compareTo(available) > 0) {
|
throw new RuntimeException("产品规格ID:" + modelId + " 总计需求 " + totalNeeded + ",可用库存 " + available + ",库存充足校验未通过");
|
}
|
}
|
|
// 执行订单下所有产品的库存扣减
|
for (SalesLedgerProduct p : products) {
|
if (p.getProductModelId() == null) continue;
|
// 使用 businessId = salesLedgerId 或当前 req.getId()
|
stockUtils.substractStock(p.getProductModelId(), p.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), salesLedgerId);
|
}
|
}
|
|
// 更新该订单下所有的发货记录状态为已发货
|
LambdaUpdateWrapper<ShippingInfo> updateWrapper = new LambdaUpdateWrapper<>();
|
updateWrapper.set(ShippingInfo::getStatus, "已发货")
|
.eq(ShippingInfo::getSalesLedgerId, salesLedgerId);
|
|
if (req != null) {
|
if (req.getExpressNumber() != null) updateWrapper.set(ShippingInfo::getExpressNumber, req.getExpressNumber());
|
if (req.getExpressCompany() != null) updateWrapper.set(ShippingInfo::getExpressCompany, req.getExpressCompany());
|
if (req.getShippingCarNumber() != null) updateWrapper.set(ShippingInfo::getShippingCarNumber, req.getShippingCarNumber());
|
if (req.getShippingDate() != null) updateWrapper.set(ShippingInfo::getShippingDate, req.getShippingDate());
|
}
|
this.update(updateWrapper);
|
|
// 更新订单状态为 4-已发货
|
if (!Integer.valueOf(4).equals(salesLedger.getDeliveryStatus())) {
|
salesLedger.setDeliveryStatus(4);
|
salesLedgerMapper.updateById(salesLedger);
|
}
|
|
// 迁移当前记录涉及的文件
|
if (req != null && req.getId() != null && CollectionUtils.isNotEmpty(req.getTempFileIds())) {
|
tempFileService.migrateTempFilesToFormal(req.getId(), req.getTempFileIds(), FileNameType.SHIP.getValue());
|
}
|
|
return true;
|
}
|
|
@Override
|
public boolean delete(List<Long> ids) {
|
List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
|
.in(ShippingInfo::getId, ids));
|
if(CollectionUtils.isEmpty(shippingInfos)) return false;
|
// 删除附件
|
commonFileService.deleteByBusinessIds(ids, FileNameType.SHIP.getValue());
|
// 扣已发货库存
|
for (ShippingInfo shippingInfo : shippingInfos) {
|
if("已发货".equals(shippingInfo.getStatus())) {
|
stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
|
}
|
}
|
// 删除发货审批
|
if(CollectionUtils.isNotEmpty(shippingInfos)){
|
for (ShippingInfo shippingInfo : shippingInfos){
|
ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
|
.like(ApproveProcess::getApproveReason, shippingInfo.getShippingNo()));
|
if(one != null){
|
approveProcessService.delByIds(Collections.singletonList(one.getId()));
|
}
|
}
|
}
|
|
return this.removeBatchByIds(ids);
|
}
|
|
@Override
|
public List<SalesLedgerProductDto> getReturnManagementDtoById(Long shippingId) {
|
return shippingInfoMapper.getReturnManagementDtoById(shippingId );
|
|
}
|
|
@Override
|
public List<ShippingInfo> getShippingInfoByCustomerName(String customerName) {
|
return shippingInfoMapper.getShippingInfoByCustomerName(customerName);
|
}
|
}
|