package com.ruoyi.purchase.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.basic.mapper.ProductMapper;
|
import com.ruoyi.basic.mapper.ProductModelMapper;
|
import com.ruoyi.basic.mapper.SupplierManageMapper;
|
import com.ruoyi.basic.pojo.Product;
|
import com.ruoyi.basic.pojo.ProductModel;
|
import com.ruoyi.basic.pojo.SupplierManage;
|
import com.ruoyi.common.enums.PurchaseApplicationStatusEnum;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.OrderUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.project.system.domain.SysUser;
|
import com.ruoyi.project.system.mapper.SysUserMapper;
|
import com.ruoyi.purchase.dto.PurchaseApplicationDto;
|
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
|
import com.ruoyi.purchase.mapper.PurchaseApplicationMapper;
|
import com.ruoyi.purchase.mapper.PurchaseApplicationProductMapper;
|
import com.ruoyi.purchase.pojo.PurchaseApplication;
|
import com.ruoyi.purchase.pojo.PurchaseApplicationProduct;
|
import com.ruoyi.purchase.service.IPurchaseLedgerService;
|
import com.ruoyi.purchase.service.PurchaseApplicationService;
|
import com.ruoyi.sales.pojo.SalesLedgerProduct;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.util.Collections;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
|
/**
|
* 采购申请单 Service 业务层处理
|
*/
|
@Service
|
@Slf4j
|
@RequiredArgsConstructor
|
public class PurchaseApplicationServiceImpl extends ServiceImpl<PurchaseApplicationMapper, PurchaseApplication>
|
implements PurchaseApplicationService {
|
|
private static final String APPLICATION_NO_PREFIX = "CGSQ";
|
|
private final PurchaseApplicationMapper purchaseApplicationMapper;
|
private final PurchaseApplicationProductMapper purchaseApplicationProductMapper;
|
private final IPurchaseLedgerService purchaseLedgerService;
|
private final SupplierManageMapper supplierManageMapper;
|
private final SysUserMapper sysUserMapper;
|
private final ProductMapper productMapper;
|
private final ProductModelMapper productModelMapper;
|
|
@Override
|
public List<PurchaseApplication> selectApplicationList(PurchaseApplicationDto purchaseApplicationDto) {
|
LambdaQueryWrapper<PurchaseApplication> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.like(StringUtils.isNotBlank(purchaseApplicationDto.getApplicationNo()),
|
PurchaseApplication::getApplicationNo, purchaseApplicationDto.getApplicationNo())
|
.like(StringUtils.isNotBlank(purchaseApplicationDto.getProjectName()),
|
PurchaseApplication::getProjectName, purchaseApplicationDto.getProjectName())
|
.eq(purchaseApplicationDto.getSupplierId() != null,
|
PurchaseApplication::getSupplierId, purchaseApplicationDto.getSupplierId())
|
.eq(purchaseApplicationDto.getStatus() != null,
|
PurchaseApplication::getStatus, purchaseApplicationDto.getStatus())
|
.ge(StringUtils.isNotBlank(purchaseApplicationDto.getStartDate()),
|
PurchaseApplication::getApplyDate, purchaseApplicationDto.getStartDate())
|
.le(StringUtils.isNotBlank(purchaseApplicationDto.getEndDate()),
|
PurchaseApplication::getApplyDate, purchaseApplicationDto.getEndDate())
|
.orderByDesc(PurchaseApplication::getId);
|
return this.list(queryWrapper);
|
}
|
|
@Override
|
public PurchaseApplicationDto getDetail(Long id) {
|
PurchaseApplication application = this.getById(id);
|
if (application == null) {
|
throw new ServiceException("采购申请不存在");
|
}
|
PurchaseApplicationDto resultDto = new PurchaseApplicationDto();
|
BeanUtils.copyProperties(application, resultDto);
|
resultDto.setProductData(listProducts(id));
|
return resultDto;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long saveApplication(PurchaseApplicationDto purchaseApplicationDto) {
|
PurchaseApplication application = new PurchaseApplication();
|
BeanUtils.copyProperties(purchaseApplicationDto, application);
|
application.setId(null);
|
application.setStatus(PurchaseApplicationStatusEnum.DRAFT.getCode());
|
application.setPurchaseLedgerId(null);
|
application.setConvertTime(null);
|
application.setApplicationNo(OrderUtils.countTodayByCreateTime(
|
purchaseApplicationMapper, APPLICATION_NO_PREFIX, "application_no", LocalDateTime.now()));
|
fillSupplierName(application);
|
fillApplicant(application, purchaseApplicationDto);
|
this.save(application);
|
|
saveProducts(application.getId(), purchaseApplicationDto.getProductData());
|
return application.getId();
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean updateApplication(PurchaseApplicationDto purchaseApplicationDto) {
|
if (purchaseApplicationDto.getId() == null) {
|
throw new ServiceException("采购申请id不能为空");
|
}
|
PurchaseApplication existing = this.getById(purchaseApplicationDto.getId());
|
if (existing == null) {
|
throw new ServiceException("采购申请不存在");
|
}
|
if (!PurchaseApplicationStatusEnum.DRAFT.getCode().equals(existing.getStatus())) {
|
throw new ServiceException("已生成订单的采购申请不允许修改");
|
}
|
|
PurchaseApplication application = new PurchaseApplication();
|
BeanUtils.copyProperties(purchaseApplicationDto, application);
|
// 单号、状态、订单关联由系统维护,不允许前端改动;置空后 MyBatis-Plus 不会更新这些列
|
application.setApplicationNo(null);
|
application.setStatus(null);
|
application.setPurchaseLedgerId(null);
|
application.setConvertTime(null);
|
application.setTenantId(null);
|
application.setCreateUser(null);
|
application.setCreateTime(null);
|
fillSupplierName(application);
|
boolean updated = this.updateById(application);
|
|
if (updated) {
|
purchaseApplicationProductMapper.delete(Wrappers.<PurchaseApplicationProduct>lambdaQuery()
|
.eq(PurchaseApplicationProduct::getPurchaseApplicationId, purchaseApplicationDto.getId()));
|
saveProducts(purchaseApplicationDto.getId(), purchaseApplicationDto.getProductData());
|
}
|
return updated;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean deleteApplications(List<Long> ids) {
|
if (ids == null || ids.isEmpty()) {
|
throw new ServiceException("请选择要删除的采购申请");
|
}
|
List<String> orderedNos = this.listByIds(ids).stream()
|
.filter(application -> !PurchaseApplicationStatusEnum.DRAFT.getCode().equals(application.getStatus()))
|
.map(PurchaseApplication::getApplicationNo)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toList());
|
if (!orderedNos.isEmpty()) {
|
throw new ServiceException("已生成订单的采购申请不允许删除:" + String.join("、", orderedNos));
|
}
|
|
purchaseApplicationProductMapper.delete(Wrappers.<PurchaseApplicationProduct>lambdaQuery()
|
.in(PurchaseApplicationProduct::getPurchaseApplicationId, ids));
|
return this.removeByIds(ids);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long convertToOrder(Long id) {
|
if (id == null) {
|
throw new ServiceException("采购申请id不能为空");
|
}
|
PurchaseApplication application = this.getById(id);
|
if (application == null) {
|
throw new ServiceException("采购申请不存在");
|
}
|
if (application.getSupplierId() == null) {
|
throw new ServiceException("请先选择供应商再转订单");
|
}
|
SupplierManage supplierManage = supplierManageMapper.selectById(application.getSupplierId());
|
if (supplierManage == null) {
|
throw new ServiceException("供应商不存在,请重新选择");
|
}
|
List<PurchaseApplicationProduct> products = listProducts(id);
|
if (products.isEmpty()) {
|
throw new ServiceException("采购申请没有产品明细,无法转订单");
|
}
|
|
// 条件更新抢占草稿状态,避免并发下重复生成订单
|
boolean converted = this.update(Wrappers.<PurchaseApplication>lambdaUpdate()
|
.eq(PurchaseApplication::getId, id)
|
.eq(PurchaseApplication::getStatus, PurchaseApplicationStatusEnum.DRAFT.getCode())
|
.set(PurchaseApplication::getStatus, PurchaseApplicationStatusEnum.ORDER_GENERATED.getCode()));
|
if (!converted) {
|
throw new ServiceException("该采购申请已生成订单,请勿重复转换");
|
}
|
|
PurchaseLedgerDto purchaseLedgerDto = buildPurchaseLedgerDto(application, supplierManage, products);
|
try {
|
// 复用采购台账新增逻辑:生成采购合同号、保存台账与产品明细、提交 OA 采购审批
|
purchaseLedgerService.addOrEditPurchase(purchaseLedgerDto);
|
} catch (Exception e) {
|
log.error("采购申请转订单失败, applicationId={}, applicationNo={}",
|
id, application.getApplicationNo(), e);
|
throw new ServiceException("转订单失败:" + e.getMessage());
|
}
|
|
Long purchaseLedgerId = purchaseLedgerDto.getId();
|
if (purchaseLedgerId == null) {
|
throw new ServiceException("转订单失败:未生成采购订单");
|
}
|
this.update(Wrappers.<PurchaseApplication>lambdaUpdate()
|
.eq(PurchaseApplication::getId, id)
|
.set(PurchaseApplication::getPurchaseLedgerId, purchaseLedgerId)
|
.set(PurchaseApplication::getConvertTime, LocalDateTime.now()));
|
return purchaseLedgerId;
|
}
|
|
private List<PurchaseApplicationProduct> listProducts(Long applicationId) {
|
return purchaseApplicationProductMapper.selectList(Wrappers.<PurchaseApplicationProduct>lambdaQuery()
|
.eq(PurchaseApplicationProduct::getPurchaseApplicationId, applicationId)
|
.orderByAsc(PurchaseApplicationProduct::getId));
|
}
|
|
private void saveProducts(Long applicationId, List<PurchaseApplicationProduct> products) {
|
if (products == null || products.isEmpty()) {
|
return;
|
}
|
fillProductNames(products);
|
for (PurchaseApplicationProduct product : products) {
|
product.setId(null);
|
product.setPurchaseApplicationId(applicationId);
|
product.setTenantId(null);
|
product.setCreateUser(null);
|
product.setCreateTime(null);
|
purchaseApplicationProductMapper.insert(product);
|
}
|
}
|
|
/**
|
* 补全产品大类与规格型号,便于申请单直接展示产品名称
|
*/
|
private void fillProductNames(List<PurchaseApplicationProduct> products) {
|
Set<Long> productIds = products.stream()
|
.map(PurchaseApplicationProduct::getProductId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet());
|
Set<Long> modelIds = products.stream()
|
.map(PurchaseApplicationProduct::getProductModelId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet());
|
|
Map<Long, String> productMap = new HashMap<>();
|
if (!productIds.isEmpty()) {
|
for (Product product : productMapper.selectBatchIds(productIds)) {
|
productMap.put(product.getId(), product.getProductName());
|
}
|
}
|
Map<Long, String> modelMap = new HashMap<>();
|
if (!modelIds.isEmpty()) {
|
for (ProductModel model : productModelMapper.selectBatchIds(modelIds)) {
|
modelMap.put(model.getId(), model.getModel());
|
}
|
}
|
|
for (PurchaseApplicationProduct product : products) {
|
String productName = productMap.get(product.getProductId());
|
if (productName != null) {
|
product.setProductCategory(productName);
|
}
|
String model = modelMap.get(product.getProductModelId());
|
if (model != null) {
|
product.setSpecificationModel(model);
|
}
|
}
|
}
|
|
private void fillSupplierName(PurchaseApplication application) {
|
if (application.getSupplierId() == null) {
|
return;
|
}
|
SupplierManage supplierManage = supplierManageMapper.selectById(application.getSupplierId());
|
if (supplierManage != null) {
|
application.setSupplierName(supplierManage.getSupplierName());
|
}
|
}
|
|
private void fillApplicant(PurchaseApplication application, PurchaseApplicationDto purchaseApplicationDto) {
|
Long applicantId = purchaseApplicationDto.getApplicantId() != null
|
? purchaseApplicationDto.getApplicantId()
|
: SecurityUtils.getUserId();
|
application.setApplicantId(applicantId);
|
|
if (StringUtils.isBlank(purchaseApplicationDto.getApplicantName())) {
|
SysUser applicant = sysUserMapper.selectUserById(applicantId);
|
application.setApplicantName(applicant != null ? applicant.getNickName() : SecurityUtils.getUsername());
|
}
|
if (application.getApplyDate() == null) {
|
application.setApplyDate(LocalDate.now());
|
}
|
}
|
|
/**
|
* 组装采购台账入参:供应商、销售合同、产品明细等;采购合同号由采购台账侧生成
|
*/
|
private PurchaseLedgerDto buildPurchaseLedgerDto(PurchaseApplication application,
|
SupplierManage supplierManage,
|
List<PurchaseApplicationProduct> products) {
|
PurchaseLedgerDto purchaseLedgerDto = new PurchaseLedgerDto();
|
purchaseLedgerDto.setSupplierId(application.getSupplierId());
|
purchaseLedgerDto.setSupplierName(supplierManage.getSupplierName());
|
purchaseLedgerDto.setRecorderId(application.getApplicantId());
|
purchaseLedgerDto.setRecorderName(application.getApplicantName());
|
purchaseLedgerDto.setSalesContractNo(application.getSalesContractNo());
|
purchaseLedgerDto.setSalesLedgerId(application.getSalesLedgerId());
|
purchaseLedgerDto.setProjectName(application.getProjectName());
|
purchaseLedgerDto.setRemarks(application.getRemarks());
|
purchaseLedgerDto.setPaymentMethod(application.getPaymentMethod());
|
purchaseLedgerDto.setContractAmount(application.getContractAmount());
|
LocalDate entryDate = application.getApplyDate() != null ? application.getApplyDate() : LocalDate.now();
|
purchaseLedgerDto.setEntryDate(DateUtils.toDate(entryDate));
|
purchaseLedgerDto.setProductData(products.stream()
|
.map(this::toSalesLedgerProduct)
|
.collect(Collectors.toList()));
|
return purchaseLedgerDto;
|
}
|
|
private SalesLedgerProduct toSalesLedgerProduct(PurchaseApplicationProduct source) {
|
SalesLedgerProduct target = new SalesLedgerProduct();
|
target.setProductId(source.getProductId());
|
target.setProductModelId(source.getProductModelId());
|
target.setProductCategory(source.getProductCategory());
|
target.setSpecificationModel(source.getSpecificationModel());
|
target.setUnit(source.getUnit());
|
target.setQuantity(source.getQuantity());
|
target.setTaxRate(source.getTaxRate());
|
target.setTaxInclusiveUnitPrice(source.getTaxInclusiveUnitPrice());
|
target.setTaxInclusiveTotalPrice(source.getTaxInclusiveTotalPrice());
|
target.setTaxExclusiveTotalPrice(source.getTaxExclusiveTotalPrice());
|
target.setInvoiceType(source.getInvoiceType());
|
target.setIsChecked(source.getIsChecked());
|
return target;
|
}
|
}
|