package com.ruoyi.purchase.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
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.exception.base.BaseException;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.other.mapper.TempFileMapper;
|
import com.ruoyi.other.pojo.TempFile;
|
import com.ruoyi.project.system.domain.SysUser;
|
import com.ruoyi.project.system.mapper.SysUserMapper;
|
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
|
import com.ruoyi.purchase.mapper.ProductRecordMapper;
|
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
|
import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
|
import com.ruoyi.purchase.pojo.ProductRecord;
|
import com.ruoyi.purchase.pojo.PurchaseLedger;
|
import com.ruoyi.purchase.pojo.TicketRegistration;
|
import com.ruoyi.purchase.service.IPurchaseLedgerService;
|
import com.ruoyi.sales.mapper.CommonFileMapper;
|
import com.ruoyi.sales.mapper.SalesLedgerMapper;
|
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
|
import com.ruoyi.sales.pojo.CommonFile;
|
import com.ruoyi.sales.pojo.SalesLedger;
|
import com.ruoyi.sales.pojo.SalesLedgerProduct;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.io.FilenameUtils;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
|
import java.io.IOException;
|
import java.math.BigDecimal;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.nio.file.Paths;
|
import java.nio.file.StandardCopyOption;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* 采购台账Service业务层处理
|
*
|
* @author ruoyi
|
* @date 2025-05-09
|
*/
|
@Service
|
@RequiredArgsConstructor
|
@Slf4j
|
public class PurchaseLedgerServiceImpl extends ServiceImpl<PurchaseLedgerMapper, PurchaseLedger> implements IPurchaseLedgerService {
|
|
private final PurchaseLedgerMapper purchaseLedgerMapper;
|
|
private final SalesLedgerMapper salesLedgerMapper;
|
private final SalesLedgerProductMapper salesLedgerProductMapper;
|
|
private final SysUserMapper userMapper;
|
|
private final TempFileMapper tempFileMapper;
|
|
private final CommonFileMapper commonFileMapper;
|
|
private final SupplierManageMapper supplierManageMapper;
|
|
private final ProductMapper productMapper;
|
|
private final ProductModelMapper productModelMapper;
|
|
private final TicketRegistrationMapper ticketRegistrationMapper;
|
|
private final ProductRecordMapper productRecordMapper;
|
|
@Value("${file.upload-dir}")
|
private String uploadDir;
|
|
@Override
|
public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) {
|
LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>();
|
if (StringUtils.isNotBlank(purchaseLedger.getPurchaseContractNumber())) {
|
queryWrapper.like(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber());
|
}
|
return purchaseLedgerMapper.selectList(queryWrapper);
|
}
|
|
@Override
|
public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws IOException {
|
|
SalesLedger salesLedger = salesLedgerMapper.selectById(purchaseLedgerDto.getSalesLedgerId());
|
|
if (salesLedger == null) {
|
throw new BaseException("销售台账不存在");
|
}
|
//录入人
|
SysUser sysUser = userMapper.selectUserById(purchaseLedgerDto.getRecorderId());
|
|
SupplierManage supplierManage = supplierManageMapper.selectById(purchaseLedgerDto.getSupplierId());
|
|
// DTO转Entity
|
PurchaseLedger purchaseLedger = new PurchaseLedger();
|
BeanUtils.copyProperties(purchaseLedgerDto, purchaseLedger);
|
purchaseLedger.setTenantId(salesLedger.getTenantId());
|
purchaseLedger.setSalesContractNo(salesLedger.getSalesContractNo());
|
purchaseLedger.setSupplierName(supplierManage.getSupplierName());
|
purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId());
|
purchaseLedger.setRecorderName(sysUser.getNickName());
|
purchaseLedger.setPhoneNumber(sysUser.getPhonenumber());
|
|
// 3. 新增或更新主表
|
if (purchaseLedger.getId() == null) {
|
purchaseLedgerMapper.insert(purchaseLedger);
|
} else {
|
purchaseLedgerMapper.updateById(purchaseLedger);
|
}
|
|
// 4. 处理子表数据
|
List<SalesLedgerProduct> productList = purchaseLedgerDto.getProductData();
|
if (productList != null && !productList.isEmpty()) {
|
handleSalesLedgerProducts(purchaseLedger.getId(), productList, purchaseLedgerDto.getType());
|
}
|
|
// 5. 迁移临时文件到正式目录
|
if (purchaseLedgerDto.getTempFileIds() != null && !purchaseLedgerDto.getTempFileIds().isEmpty()) {
|
migrateTempFilesToFormal(purchaseLedger.getId(), purchaseLedgerDto.getTempFileIds());
|
}
|
|
return 1;
|
}
|
|
private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) {
|
if (products == null || products.isEmpty()) {
|
throw new BaseException("产品信息不存在");
|
}
|
|
// 提前收集所有需要查询的ID
|
Set<Long> productIds = products.stream()
|
.map(SalesLedgerProduct::getProductId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet());
|
|
Set<Long> modelIds = products.stream()
|
.map(SalesLedgerProduct::getProductModelId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet());
|
|
// 一次性查询产品和型号信息
|
Map<Long, String> productMap = new HashMap<>();
|
if (!productIds.isEmpty()) {
|
List<Product> productList = productMapper.selectBatchIds(productIds);
|
productList.forEach(p -> productMap.put(p.getId(), p.getProductName()));
|
}
|
|
Map<Long, String> modelMap = new HashMap<>();
|
if (!modelIds.isEmpty()) {
|
List<ProductModel> modelList = productModelMapper.selectBatchIds(modelIds);
|
modelList.forEach(m -> modelMap.put(m.getId(), m.getModel()));
|
}
|
|
// 设置字段
|
for (SalesLedgerProduct product : products) {
|
product.setSalesLedgerId(salesLedgerId);
|
|
Long productId = product.getProductId();
|
if (productId != null && productMap.containsKey(productId)) {
|
product.setProductCategory(productMap.get(productId));
|
}
|
|
Long productModelId = product.getProductModelId();
|
if (productModelId != null && modelMap.containsKey(productModelId)) {
|
product.setSpecificationModel(modelMap.get(productModelId));
|
}
|
}
|
|
// 分组处理
|
Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
|
.collect(Collectors.partitioningBy(p -> p.getId() != null));
|
|
List<SalesLedgerProduct> updateList = partitionedProducts.get(true);
|
List<SalesLedgerProduct> insertList = partitionedProducts.get(false);
|
|
// 执行更新操作
|
if (!updateList.isEmpty()) {
|
for (SalesLedgerProduct product : updateList) {
|
product.setType(type);
|
salesLedgerProductMapper.updateById(product);
|
}
|
}
|
// 执行插入操作
|
if (!insertList.isEmpty()) {
|
for (SalesLedgerProduct salesLedgerProduct : insertList) {
|
salesLedgerProduct.setType(type);
|
salesLedgerProductMapper.insert(salesLedgerProduct);
|
}
|
}
|
|
// 计算总含税金额
|
BigDecimal totalTaxInclusiveAmount = products.stream()
|
.map(SalesLedgerProduct::getTaxInclusiveTotalPrice)
|
.filter(Objects::nonNull)
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
// 更新主表的总金额字段
|
if (salesLedgerId != null) {
|
// 直接更新指定ID的记录的contractAmount字段为totalTaxInclusiveAmount
|
purchaseLedgerMapper.updateContractAmountById(salesLedgerId, totalTaxInclusiveAmount);
|
}
|
}
|
|
/**
|
* 将临时文件迁移到正式目录
|
*
|
* @param businessId 业务ID(销售台账ID)
|
* @param tempFileIds 临时文件ID列表
|
* @throws IOException 文件操作异常
|
*/
|
private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException {
|
if (CollectionUtils.isEmpty(tempFileIds)) {
|
return;
|
}
|
|
// 构建正式目录路径(按业务类型和日期分组)
|
String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
|
|
Path formalDirPath = Paths.get(formalDir);
|
|
// 确保正式目录存在(递归创建)
|
if (!Files.exists(formalDirPath)) {
|
Files.createDirectories(formalDirPath);
|
}
|
|
for (String tempFileId : tempFileIds) {
|
// 查询临时文件记录
|
TempFile tempFile = tempFileMapper.selectById(tempFileId);
|
if (tempFile == null) {
|
log.warn("临时文件不存在,跳过处理: {}", tempFileId);
|
continue;
|
}
|
|
// 构建正式文件名(包含业务ID和时间戳,避免冲突)
|
String originalFilename = tempFile.getOriginalName();
|
String fileExtension = FilenameUtils.getExtension(originalFilename);
|
String formalFilename = businessId + "_" +
|
System.currentTimeMillis() + "_" +
|
UUID.randomUUID().toString().substring(0, 8) +
|
(StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
|
|
Path formalFilePath = formalDirPath.resolve(formalFilename);
|
|
try {
|
// 执行文件迁移(使用原子操作确保安全性)
|
Files.move(
|
Paths.get(tempFile.getTempPath()),
|
formalFilePath,
|
StandardCopyOption.REPLACE_EXISTING,
|
StandardCopyOption.ATOMIC_MOVE
|
);
|
log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath);
|
|
// 更新文件记录(关联到业务ID)
|
CommonFile fileRecord = new CommonFile();
|
fileRecord.setCommonId(businessId);
|
fileRecord.setName(originalFilename);
|
fileRecord.setUrl(formalFilePath.toString());
|
fileRecord.setCreateTime(LocalDateTime.now());
|
fileRecord.setType("2");
|
commonFileMapper.insert(fileRecord);
|
|
// 删除临时文件记录
|
tempFileMapper.deleteById(tempFile);
|
|
log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath);
|
} catch (IOException e) {
|
log.error("文件迁移失败: {}", tempFile.getTempPath(), e);
|
// 可选择回滚事务或记录失败文件
|
throw new IOException("文件迁移异常", e);
|
}
|
}
|
}
|
|
@Override
|
public int deletePurchaseLedgerByIds(Long[] ids) {
|
if (ids == null || ids.length == 0) {
|
throw new BaseException("请选中至少一条数据");
|
}
|
// 批量删除关联的采购台账产品
|
LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids)
|
.eq(SalesLedgerProduct::getType, "2");
|
salesLedgerProductMapper.delete(queryWrapper);
|
// 批量删除关联的采购台账的来票登记
|
LambdaQueryWrapper<TicketRegistration> ticketRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
ticketRegistrationLambdaQueryWrapper.in(TicketRegistration::getSalesLedgerId,ids);
|
ticketRegistrationMapper.delete(ticketRegistrationLambdaQueryWrapper);
|
// 批量删除关联的采购台账的来票登记记录
|
LambdaQueryWrapper<ProductRecord> productRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
productRecordLambdaQueryWrapper.in(ProductRecord::getPurchaseLedgerId,ids);
|
productRecordMapper.delete(productRecordLambdaQueryWrapper);
|
// 批量删除采购台账
|
return purchaseLedgerMapper.deleteBatchIds(Arrays.asList(ids));
|
}
|
|
@Override
|
public PurchaseLedgerDto getPurchaseById(PurchaseLedgerDto purchaseLedgerDto) {
|
// 1. 查询主表
|
PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(purchaseLedgerDto.getId());
|
if (purchaseLedger == null) {
|
throw new BaseException("采购台账不存在");
|
}
|
|
// 2. 查询子表
|
LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
|
productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
|
.eq(SalesLedgerProduct::getType, purchaseLedgerDto.getType());
|
List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
|
|
// 3.查询上传文件
|
LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>();
|
salesLedgerFileWrapper.eq(CommonFile::getCommonId, purchaseLedger.getId());
|
List<CommonFile> salesLedgerFiles = commonFileMapper.selectList(salesLedgerFileWrapper);
|
|
// 4. 转换 DTO
|
PurchaseLedgerDto resultDto = new PurchaseLedgerDto();
|
BeanUtils.copyProperties(purchaseLedger, resultDto);
|
if (!products.isEmpty()) {
|
resultDto.setHasChildren(true);
|
resultDto.setProductData(products);
|
resultDto.setSalesLedgerFiles(salesLedgerFiles);
|
}
|
return resultDto;
|
}
|
|
@Override
|
public List getProduct(PurchaseLedgerDto purchaseLedgerDto) {
|
LambdaQueryWrapper<PurchaseLedger> queryWrapper = Wrappers.lambdaQuery();
|
queryWrapper.select(PurchaseLedger::getId, PurchaseLedger::getPurchaseContractNumber);
|
|
// 获取原始查询结果
|
List<Map<String, Object>> result = purchaseLedgerMapper.selectMaps(queryWrapper);
|
|
// 将下划线命名转换为驼峰命名
|
return result.stream().map(map -> map.entrySet().stream()
|
.collect(Collectors.toMap(
|
entry -> underlineToCamel(entry.getKey()),
|
Map.Entry::getValue))
|
).collect(Collectors.toList());
|
}
|
|
@Override
|
public PurchaseLedgerDto getInfo(PurchaseLedgerDto purchaseLedgerDto) {
|
PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(purchaseLedgerDto.getId());
|
if (purchaseLedger == null) {
|
throw new BaseException("采购台账不存在");
|
}
|
// 创建并填充DTO
|
PurchaseLedgerDto resultDto = new PurchaseLedgerDto();
|
resultDto.setSalesContractNoId(purchaseLedger.getSalesLedgerId());
|
resultDto.setSalesContractNo(purchaseLedger.getSalesContractNo());
|
resultDto.setSupplierName(purchaseLedger.getSupplierName());
|
resultDto.setProjectName(purchaseLedger.getProjectName());
|
|
// 查询并设置关联产品
|
LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
|
.eq(SalesLedgerProduct::getType, 2);
|
List<SalesLedgerProduct> productList = salesLedgerProductMapper.selectList(queryWrapper);
|
productList.forEach(product -> {
|
product.setFutureTickets(product.getFutureTickets() != null ? product.getFutureTickets() : product.getQuantity().longValue());
|
product.setFutureTicketsAmount(product.getFutureTicketsAmount() != null ? product.getFutureTicketsAmount() : product.getTaxInclusiveTotalPrice());
|
product.setTicketsNum(null);
|
product.setTicketsAmount(null);
|
});
|
resultDto.setProductData(productList);
|
return resultDto;
|
}
|
|
@Override
|
public List getPurchasesNo() {
|
LambdaQueryWrapper<PurchaseLedger> queryWrapper = Wrappers.lambdaQuery();
|
queryWrapper.select(PurchaseLedger::getId, PurchaseLedger::getPurchaseContractNumber, PurchaseLedger::getSupplierId);
|
|
// 获取原始查询结果
|
List<Map<String, Object>> result = purchaseLedgerMapper.selectMaps(queryWrapper);
|
|
// 将下划线命名转换为驼峰命名
|
return result.stream().map(map -> map.entrySet().stream()
|
.collect(Collectors.toMap(
|
entry -> underlineToCamel(entry.getKey()),
|
Map.Entry::getValue))
|
).collect(Collectors.toList());
|
}
|
|
@Override
|
public PurchaseLedgerDto getPurchaseNoById(Long id) {
|
PurchaseLedgerDto purchaseLedgerDto = new PurchaseLedgerDto();
|
PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
|
BeanUtils.copyProperties(purchaseLedger, purchaseLedgerDto);
|
// TicketRegistration ticketRegistration = ticketRegistrationMapper.selectOne(new LambdaQueryWrapper<TicketRegistration>().eq(TicketRegistration::getPurchaseLedgerId, id));
|
// if (ticketRegistration != null) {
|
// purchaseLedgerDto.setInvoiceNumber(ticketRegistration.getInvoiceNumber());
|
// purchaseLedgerDto.setInvoiceAmount(ticketRegistration.getInvoiceAmount());
|
// purchaseLedgerDto.setTicketRegistrationId(ticketRegistration.getId());
|
// }
|
return purchaseLedgerDto;
|
}
|
|
/**
|
* 下划线命名转驼峰命名
|
*/
|
private String underlineToCamel(String param) {
|
if (param == null || "".equals(param.trim())) {
|
return "";
|
}
|
int len = param.length();
|
StringBuilder sb = new StringBuilder(len);
|
for (int i = 0; i < len; i++) {
|
char c = param.charAt(i);
|
if (c == '_') {
|
if (++i < len) {
|
sb.append(Character.toUpperCase(param.charAt(i)));
|
}
|
} else {
|
sb.append(Character.toLowerCase(c));
|
}
|
}
|
return sb.toString();
|
}
|
}
|