liyong
6 天以前 255930c3226e8990edc6ad44447893001d3c1add
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -12,23 +12,33 @@
import com.ruoyi.account.pojo.AccountIncome;
import com.ruoyi.account.service.AccountIncomeService;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.sales.dto.MonthlyAmountDto;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.dto.*;
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import com.ruoyi.sales.service.ISalesLedgerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -40,10 +50,13 @@
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -74,6 +87,7 @@
    private final CustomerMapper customerMapper;
    private final SalesLedgerProductMapper salesLedgerProductMapper;
    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
    private final CommonFileMapper commonFileMapper;
@@ -87,7 +101,7 @@
    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
    private final SalesLedgerProductionAccountingMapper  salesLedgerProductionAccountingMapper;
    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
@@ -96,6 +110,7 @@
    private final ProductOrderMapper productOrderMapper;
    private final ProcessRouteMapper processRouteMapper;
    private final ProductProcessRouteMapper productProcessRouteMapper;
    private final ProcessRouteItemMapper processRouteItemMapper;
@@ -122,6 +137,13 @@
    private static final long LOCK_EXPIRE_TIME = 30;  // 锁自动过期时间(秒)
    private final RedisTemplate<String, String> redisTemplate;
    @Autowired
    private ProductModelMapper productModelMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductStructureMapper productStructureMapper;
    @Override
    public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
@@ -315,6 +337,112 @@
        return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
    }
    @Autowired
    private SysUserMapper sysUserMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importData(MultipartFile file) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        try {
            InputStream inputStream = file.getInputStream();
            ExcelUtil<SalesLedgerImportDto> salesLedgerImportDtoExcelUtil = new ExcelUtil<>(SalesLedgerImportDto.class);
            Map<String, List<SalesLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("销售台账数据", "销售产品数据"), inputStream, 0);
            if (CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("销售表格为空!");
            // 业务层合并
            List<SalesLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("销售台账数据");
            if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("销售台账数据为空!");
            List<SalesLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("销售产品数据");
            if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("销售产品数据为空!");
            // 客户数据
            List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().in(Customer::getCustomerName,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).toArray(String[]::new)));
            // 规格型号数据
            List<ProductModel> productModels = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>().in(ProductModel::getModel,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getSpecificationModel).toArray(String[]::new)));
            // 产品大类数据
            List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>().in(Product::getProductName,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getProductCategory).toArray(String[]::new)));
            // 录入人数据
            List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName,
                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).toArray(String[]::new)));
            for (SalesLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) {
                SalesLedger salesLedger = new SalesLedger();
                BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
                // 通过客户名称查询客户ID,客户合同号
                salesLedger.setCustomerId(customers.stream()
                        .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
                        .findFirst()
                        .map(Customer::getId)
                        .orElse(null));
                salesLedger.setCustomerContractNo(customers.stream()
                        .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
                        .findFirst()
                        .map(Customer::getTaxpayerIdentificationNumber)
                        .orElse(null));
                Long aLong = sysUsers.stream()
                        .filter(sysUser -> sysUser.getNickName().equals(salesLedger.getEntryPerson()))
                        .findFirst()
                        .map(SysUser::getUserId)
                        .orElse(null);
                if (aLong == null)
                    throw new RuntimeException("录入人:" + salesLedger.getEntryPerson() + ",无对应用户!");
                salesLedger.setEntryPerson(aLong.toString());
                salesLedgerMapper.insert(salesLedger);
                // 销售产品数据绑定,通过销售单号获取对应销售产品数据
                List<SalesLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream()
                        .filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getSalesContractNo().equals(salesLedger.getSalesContractNo()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(salesLedgerProductImportDtos))
                    throw new RuntimeException("销售单号:" + salesLedgerImportDto.getSalesContractNo() + ",无对应产品数据!");
                for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
                    SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
                    BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
                    salesLedgerProduct.setSalesLedgerId(salesLedger.getId());
                    salesLedgerProduct.setType(1);
                    // 计算不含税总价
                    salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
                    salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                    salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
                    salesLedgerProduct.setProductId(productList.stream()
                            .filter(product -> product.getProductName().equals(salesLedgerProduct.getProductCategory()))
                            .findFirst()
                            .map(Product::getId)
                            .orElse(null));
                    salesLedgerProduct.setProductModelId(productModels.stream()
                            .filter(productModel -> productModel.getModel().equals(salesLedgerProduct.getSpecificationModel()))
                            .findFirst()
                            .map(ProductModel::getId)
                            .orElse(null));
                    salesLedgerProduct.setRegister(loginUser.getNickName());
                    salesLedgerProduct.setRegisterDate(LocalDateTime.now());
                    salesLedgerProduct.setApproveStatus(0);
                    salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
                    salesLedgerProductMapper.insert(salesLedgerProduct);
                }
            }
            return AjaxResult.success("导入成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success("导入失败");
    }
    @Override
    public List<LossProductModelDto> getSalesLedgerWithProductsLoss(Long salesLedgerId) {
        List<LossProductModelDto> lossProductModelDtos = salesLedgerProductMapper.selectProductBomStructure(salesLedgerId);
        return lossProductModelDtos;
    }
    // 内部类用于存储聚合结果
    private static class GroupedCustomer {
        private final Long customerId;
@@ -385,82 +513,8 @@
        List<Long> productIds = products.stream()
                .map(SalesLedgerProduct::getId)
                .collect(Collectors.toList());
        //批量查询productOrder
        List<ProductOrder> productOrders = productOrderMapper.selectList(
                new LambdaQueryWrapper<ProductOrder>()
                        .in(ProductOrder::getProductModelId, productIds)
        );
        if (!org.springframework.util.CollectionUtils.isEmpty(productOrders)) {
            List<Long> orderIds = productOrders.stream()
                    .map(ProductOrder::getId)
                    .collect(Collectors.toList());
            // 批量查询processRouteItems
            List<ProductProcessRouteItem> allRouteItems = productProcessRouteItemMapper.selectList(
                    new LambdaQueryWrapper<ProductProcessRouteItem>()
                            .in(ProductProcessRouteItem::getRouteId, orderIds)
            );
            if (!CollectionUtils.isEmpty(allRouteItems)) {
                // 获取要删除的工序项ID
                List<Long> routeItemIds = allRouteItems.stream()
                        .map(ProductProcessRouteItem::getId)
                        .collect(Collectors.toList());
                // 查询关联的工单ID
                List<ProductWorkOrder> workOrders = productWorkOrderMapper.selectList(
                        new LambdaQueryWrapper<ProductWorkOrder>()
                                .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds)
                );
                if (!CollectionUtils.isEmpty(workOrders)) {
                    List<Long> workOrderIds = workOrders.stream()
                            .map(ProductWorkOrder::getId)
                            .collect(Collectors.toList());
                    // 查询关联的生产主表ID
                    List<ProductionProductMain> productMains = productionProductMainMapper.selectList(
                            new LambdaQueryWrapper<ProductionProductMain>()
                                    .in(ProductionProductMain::getWorkOrderId, workOrderIds)
                    );
                    List<Long> productMainIds = productMains.stream()
                            .map(ProductionProductMain::getId)
                            .collect(Collectors.toList());
                    // 删除产出表、投入表数据
                    if (!CollectionUtils.isEmpty(productMainIds)) {
                        productionProductOutputMapper.deleteByProductMainIds(productMainIds);
                        productionProductInputMapper.deleteByProductMainIds(productMainIds);
                        List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(
                                new LambdaQueryWrapper<QualityInspect>()
                                        .in(QualityInspect::getProductMainId, productMainIds)
                        );
                        qualityInspects.forEach(qualityInspect -> {
                            //inspectState=1 已提交 不能删除
                            if(qualityInspect.getInspectState() == 1){
                                throw new RuntimeException("已提交的检验单不能删除");
                            }
                        });
                        qualityInspectMapper.deleteByProductMainIds(productMainIds);
                    }
                    // 删除生产主表数据
                    productionProductMainMapper.deleteByWorkOrderIds(workOrderIds);
                    // 删除工单数据
                    productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>()
                            .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds));
                }
            }
            // 批量删除processRouteItem
            productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>()
                    .in(ProductProcessRouteItem::getRouteId, orderIds));
            // 批量删除productOrder
            productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>()
                    .in(ProductOrder::getProductModelId, productIds));
        }
        //删除生产数据
        salesLedgerProductServiceImpl.deleteProductionData(productIds);
        // 批量删除产品子表
        if (!productIds.isEmpty()) {
@@ -471,11 +525,11 @@
        wrapper.in(InvoiceRegistrationProduct::getSalesLedgerId, idList);
        List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(wrapper);
        List<Integer> invoiceLedgerIds = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(invoiceRegistrationProducts)){
        if (CollectionUtils.isNotEmpty(invoiceRegistrationProducts)) {
            LambdaQueryWrapper<InvoiceLedger> wrapperOne = new LambdaQueryWrapper<>();
            wrapperOne.in(InvoiceLedger::getInvoiceRegistrationProductId, invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getId).collect(Collectors.toList()));
            List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(wrapperOne);
            if(CollectionUtils.isNotEmpty(invoiceLedgers)){
            if (CollectionUtils.isNotEmpty(invoiceLedgers)) {
                invoiceLedgerIds = invoiceLedgers.stream().map(InvoiceLedger::getId).collect(Collectors.toList());
            }
            invoiceLedgerMapper.delete(wrapperOne);
@@ -485,7 +539,7 @@
        wrapperTwo.in(InvoiceRegistration::getSalesLedgerId, idList);
        invoiceRegistrationMapper.delete(wrapperTwo);
        if(CollectionUtils.isNotEmpty(invoiceLedgerIds)){
        if (CollectionUtils.isNotEmpty(invoiceLedgerIds)) {
            LambdaQueryWrapper<ReceiptPayment> wrapperTree = new LambdaQueryWrapper<>();
            wrapperTree.in(ReceiptPayment::getInvoiceLedgerId, invoiceLedgerIds);
            receiptPaymentMapper.delete(wrapperTree);
@@ -500,7 +554,7 @@
        LambdaQueryWrapper<SalesLedgerWork> workOrderWrapper = new LambdaQueryWrapper<>();
        workOrderWrapper.in(SalesLedgerWork::getSalesLedgerId, idList);
        salesLedgerWorkMapper.delete(workOrderWrapper);
        // 删除生产报工数据
        // 删除生产核算数据
        LambdaQueryWrapper<SalesLedgerProductionAccounting> reportWrapper = new LambdaQueryWrapper<>();
        reportWrapper.in(SalesLedgerProductionAccounting::getSalesLedgerId, idList);
        salesLedgerProductionAccountingMapper.delete(reportWrapper);
@@ -522,39 +576,13 @@
            SalesLedger salesLedger = convertToEntity(salesLedgerDto);
            salesLedger.setCustomerName(customer.getCustomerName());
            salesLedger.setTenantId(customer.getTenantId());
            AccountIncome accountIncome = new AccountIncome();
            accountIncome.setIncomeDate(salesLedger.getEntryDate());
            accountIncome.setIncomeType("0");
            accountIncome.setCustomerName(customer.getCustomerName());
            accountIncome.setIncomeMoney(salesLedger.getContractAmount());
            accountIncome.setIncomeMethod("0");
            accountIncome.setInputTime(new Date());
            accountIncome.setInputUser(salesLedger.getEntryPerson());
            // 3. 新增或更新主表
            if (salesLedger.getId() == null) {
                String contractNo = generateSalesContractNo();
                salesLedger.setSalesContractNo(contractNo);
                salesLedgerMapper.insert(salesLedger);
                accountIncome.setIncomeDescribed("销售合同:" + salesLedger.getSalesContractNo());
                accountIncome.setInvoiceNumber(salesLedger.getSalesContractNo());
                accountIncomeService.save(accountIncome);
            } else {
                salesLedgerMapper.updateById(salesLedger);
                SalesLedger salesLedgerDB = salesLedgerMapper.selectById(salesLedger.getId());
                List<AccountIncome> accountIncomeDBs = accountIncomeService.getByInvoiceNumberList(salesLedger.getSalesContractNo());
                if (!org.springframework.util.CollectionUtils.isEmpty(accountIncomeDBs)) {
                    accountIncomeDBs.forEach(accountIncomeDB -> {
                        accountIncomeDB.setCustomerName(salesLedgerDB.getCustomerName());
                        accountIncomeDB.setIncomeMoney(salesLedgerDB.getContractAmount());
                        accountIncomeDB.setIncomeDescribed("销售合同:" + salesLedgerDB.getSalesContractNo());
                        accountIncomeDB.setInvoiceNumber(salesLedgerDB.getSalesContractNo());
                        accountIncomeDB.setInputTime(new Date());
                        accountIncomeDB.setInputUser(salesLedgerDB.getEntryPerson());
                        accountIncomeService.updateById(accountIncomeDB);
                    });
                }
            }
            // 4. 处理子表数据
@@ -680,63 +708,10 @@
                salesLedgerProduct.setType(type);
                salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProductMapper.insert(salesLedgerProduct);
                ProductOrder productOrder = new ProductOrder();
                productOrder.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
                productOrder.setProductModelId(salesLedgerProduct.getId());
                productOrder.setNpsNo("SC" + String.format("%08d", salesLedgerProduct.getId()));
                productOrderMapper.insert(productOrder);
                ProcessRoute processRoute = processRouteMapper.selectOne(new QueryWrapper<ProcessRoute>().lambda().eq(ProcessRoute::getProductModelId, salesLedgerProduct.getProductModelId()));
                if (processRoute != null) {
                    List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(new QueryWrapper<ProcessRouteItem>().lambda().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
                    // 生成当前日期的前缀:年月日
                    String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                    int dragSort = 1;
                    for (ProcessRouteItem processRouteItem : processRouteItems) {
                        ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
                        productProcessRouteItem.setProductModelId(processRouteItem.getProductModelId());
                        productProcessRouteItem.setProcessId(processRouteItem.getProcessId());
                        productProcessRouteItem.setRouteId(productOrder.getId());
                        productProcessRouteItem.setDragSort(dragSort);
                        int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
                        if (insert > 0) {
                            // 查询今日已存在的最大工单号
                            QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
                            queryWrapper.likeRight("work_order_no", datePrefix)
                                    .orderByDesc("work_order_no")
                                    .last("LIMIT 1");
                            ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectOne(queryWrapper);
                            int sequenceNumber = 1; // 默认序号
                            if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
                                String lastNo = lastWorkOrder.getWorkOrderNo().toString();
                                if (lastNo.startsWith(datePrefix)) {
                                    String seqStr = lastNo.substring(datePrefix.length());
                                    try {
                                        sequenceNumber = Integer.parseInt(seqStr) + 1;
                                    } catch (NumberFormatException e) {
                                        sequenceNumber = 1;
                                    }
                                }
                            }
                            // 生成完整的工单号
                            String workOrderNoStr = String.format("%s%03d", datePrefix, sequenceNumber);
                            ProductWorkOrder productWorkOrder = new ProductWorkOrder();
                            productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
                            productWorkOrder.setProductOrderId(productOrder.getId());
                            productWorkOrder.setPlanQuantity(salesLedgerProduct.getQuantity());
                            productWorkOrder.setWorkOrderNo(workOrderNoStr);
                            productWorkOrder.setStatus(1);
                            productWorkOrderMapper.insert(productWorkOrder);
                        }
                        dragSort++;
                    }
                    productOrder.setRouteId(processRoute.getId());
                    productOrderMapper.updateById(productOrder);
                }
                // 添加生产数据
                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
            }
        }
    }