| | |
| | | package com.ruoyi.sales.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | 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.enums.SaleEnum; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.EnumUtil; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | |
| | | 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.production.pojo.ProcessRoute; |
| | | import com.ruoyi.production.pojo.ProcessRouteItem; |
| | | import com.ruoyi.production.service.ProductionProductMainService; |
| | | |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto; |
| | | import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper; |
| | | import com.ruoyi.quality.mapper.QualityInspectMapper; |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | 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.ISalesLedgerProcessRouteService; |
| | | import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService; |
| | | import com.ruoyi.sales.service.ISalesLedgerProductProcessService; |
| | | import com.ruoyi.sales.service.ISalesLedgerService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.jetbrains.annotations.Nullable; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | |
| | | @RequiredArgsConstructor |
| | | @Slf4j |
| | | public class SalesLedgerServiceImpl extends ServiceImpl<SalesLedgerMapper, SalesLedger> implements ISalesLedgerService { |
| | | private final AccountIncomeService accountIncomeService; |
| | | |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | |
| | | private final CustomerMapper customerMapper; |
| | | |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl; |
| | | |
| | | private final CommonFileMapper commonFileMapper; |
| | | |
| | | private final TempFileMapper tempFileMapper; |
| | | |
| | | private final ReceiptPaymentMapper receiptPaymentMapper; |
| | | |
| | | private final InvoiceLedgerMapper invoiceLedgerMapper; |
| | | |
| | | private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper; |
| | | |
| | | private final SalesLedgerWorkMapper salesLedgerWorkMapper; |
| | | |
| | | private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | |
| | | private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; |
| | | |
| | | private final InvoiceRegistrationMapper invoiceRegistrationMapper; |
| | | |
| | | private final ProductOrderMapper productOrderMapper; |
| | | |
| | | private final ProcessRouteMapper processRouteMapper; |
| | | private final ProductProcessRouteMapper productProcessRouteMapper; |
| | | |
| | | private final ProcessRouteItemMapper processRouteItemMapper; |
| | | |
| | | private final ProductProcessRouteItemMapper productProcessRouteItemMapper; |
| | | |
| | | private final ProductWorkOrderMapper productWorkOrderMapper; |
| | | |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | |
| | | private final ProductionProductOutputMapper productionProductOutputMapper; |
| | | |
| | | private final ProductionProductInputMapper productionProductInputMapper; |
| | | |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | |
| | | @Autowired |
| | | private SysDeptMapper sysDeptMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | |
| | | private static final String LOCK_PREFIX = "contract_no_lock:"; |
| | | private static final long LOCK_WAIT_TIMEOUT = 10; // 锁等待超时时间(秒) |
| | | private static final long LOCK_EXPIRE_TIME = 30; // 锁自动过期时间(秒) |
| | | |
| | | private final AccountIncomeService accountIncomeService; |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | private final CustomerMapper customerMapper; |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl; |
| | | private final CommonFileMapper commonFileMapper; |
| | | private final TempFileMapper tempFileMapper; |
| | | private final ReceiptPaymentMapper receiptPaymentMapper; |
| | | private final ShippingInfoServiceImpl shippingInfoServiceImpl; |
| | | private final CommonFileServiceImpl commonFileService; |
| | | private final ShippingInfoMapper shippingInfoMapper; |
| | | private final InvoiceLedgerMapper invoiceLedgerMapper; |
| | | private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper; |
| | | private final SalesLedgerWorkMapper salesLedgerWorkMapper; |
| | | private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; |
| | | private final InvoiceRegistrationMapper invoiceRegistrationMapper; |
| | | private final ProductOrderMapper productOrderMapper; |
| | | private final ProcessRouteMapper processRouteMapper; |
| | | private final ProductProcessRouteMapper productProcessRouteMapper; |
| | | private final ProcessRouteItemMapper processRouteItemMapper; |
| | | private final ProductProcessRouteItemMapper productProcessRouteItemMapper; |
| | | private final ProductWorkOrderMapper productWorkOrderMapper; |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | private final ProductionProductOutputMapper productionProductOutputMapper; |
| | | private final ProductionProductInputMapper productionProductInputMapper; |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | private final RedisTemplate<String, String> redisTemplate; |
| | | |
| | | private final ISalesLedgerProductProcessService salesLedgerProductProcessService; |
| | | |
| | | private final ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService; |
| | | |
| | | private final ISalesLedgerProcessRouteService salesLedgerProcessRouteService; |
| | | |
| | | @Autowired |
| | | private SysDeptMapper sysDeptMapper; |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | @Autowired |
| | | private ProductModelMapper productModelMapper; |
| | | |
| | |
| | | private ProductMapper productMapper; |
| | | @Autowired |
| | | private ProductStructureMapper productStructureMapper; |
| | | @Autowired |
| | | private ProductionProductMainService productionProductMainService; |
| | | @Autowired |
| | | private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper; |
| | | ; |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | @Override |
| | | public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) { |
| | | return salesLedgerMapper.selectSalesLedgerList(salesLedgerDto); |
| | | } |
| | | |
| | | public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type) { |
| | | LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>(); |
| | | productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, relateId); |
| | | productWrapper.eq(SalesLedgerProduct::getType, type.getCode()); |
| | | return salesLedgerProductMapper.selectList(productWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, SaleEnum type) { |
| | | if (CollectionUtils.isEmpty(relateIds)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>(); |
| | | productWrapper.in(SalesLedgerProduct::getId, relateIds); |
| | | productWrapper.eq(SalesLedgerProduct::getType, type.getCode()); |
| | | List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(productWrapper); |
| | | if (type.equals(SaleEnum.PURCHASE)) { |
| | | // 查询退货信息 |
| | | List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList()); |
| | | List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>(); |
| | | if (CollectionUtils.isNotEmpty(productIds)) { |
| | | groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds); |
| | | } |
| | | Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity)); |
| | | salesLedgerProducts.forEach(item -> { |
| | | BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO); |
| | | item.setReturnQuality(returnQuality); |
| | | item.setAvailableQuality(item.getQuantity().subtract(returnQuality)); |
| | | }); |
| | | } |
| | | return salesLedgerProducts; |
| | | } |
| | | |
| | | @Override |
| | |
| | | product.setTempNoInvoiceNum(product.getNoInvoiceNum()); |
| | | product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName()); |
| | | product.setRegisterDate(LocalDateTime.now()); |
| | | // 发货信息 |
| | | ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>() |
| | | .eq(ShippingInfo::getSalesLedgerProductId, product.getId()) |
| | | .orderByDesc(ShippingInfo::getCreateTime) |
| | | .last("limit 1")); |
| | | if (shippingInfo != null) { |
| | | product.setShippingStatus(shippingInfo.getStatus()); |
| | | } |
| | | // 加工明细,先查bind表获取该产品关联的工序及数量 |
| | | List<SalesLedgerProductProcessBind> bindList = salesLedgerProductProcessBindService.list( |
| | | new LambdaQueryWrapper<SalesLedgerProductProcessBind>() |
| | | .eq(SalesLedgerProductProcessBind::getSalesLedgerProductId, product.getId())); |
| | | if (!bindList.isEmpty()) { |
| | | List<Integer> processIds = bindList.stream() |
| | | .map(SalesLedgerProductProcessBind::getSalesLedgerProductProcessId) |
| | | .collect(Collectors.toList()); |
| | | Map<Integer, Integer> processQuantityMap = bindList.stream() |
| | | .collect(Collectors.toMap( |
| | | SalesLedgerProductProcessBind::getSalesLedgerProductProcessId, |
| | | SalesLedgerProductProcessBind::getQuantity, |
| | | (a, b) -> a)); |
| | | List<SalesLedgerProductProcess> processList = salesLedgerProductProcessService.listByIds(processIds); |
| | | processList.forEach(p -> p.setQuantity(processQuantityMap.get(p.getId()))); |
| | | product.setSalesProductProcessList(processList); |
| | | } |
| | | } |
| | | |
| | | // 3.查询上传文件 |
| | |
| | | |
| | | @Override |
| | | public List<MonthlyAmountDto> getAmountHalfYear(Integer type) { |
| | | |
| | | LocalDate now = LocalDate.now(); |
| | | LocalDateTime currentDateTime = LocalDateTime.now(); |
| | | |
| | | // 根据 type 确定查询的时间间隔(天数)和总查询天数 |
| | | int daysPerPeriod; |
| | | int totalDays; |
| | | switch (type) { |
| | | case 1: |
| | | daysPerPeriod = 5; // 每5天查一次 |
| | | totalDays = 30; // 6次 × 5天 = 30天 |
| | | break; |
| | | case 2: |
| | | daysPerPeriod = 15; // 每15天查一次 |
| | | totalDays = 90; // 6次 × 15天 = 90天 |
| | | break; |
| | | case 3: |
| | | daysPerPeriod = 30; // 每30天查一次 |
| | | totalDays = 180; // 6次 × 30天 = 180天 |
| | | break; |
| | | default: |
| | | throw new IllegalArgumentException("Invalid type value: " + type); |
| | | } |
| | | |
| | | List<MonthlyAmountDto> result = new ArrayList<>(); |
| | | |
| | | // 循环6次,每次查询一个时间段的数据 |
| | | for (int i = 0; i < 6; i++) { |
| | | // 计算当前时间段的起始和结束时间 |
| | | LocalDateTime endTime = currentDateTime.minusDays(i * daysPerPeriod); |
| | | LocalDateTime startTime = endTime.minusDays(daysPerPeriod); |
| | | for (int i = 5; i >= 0; i--) { |
| | | YearMonth yearMonth = YearMonth.from(now.minusMonths(i)); |
| | | LocalDateTime startTime = yearMonth.atDay(1).atStartOfDay(); |
| | | LocalDateTime endTime = yearMonth.atEndOfMonth().atTime(23, 59, 59); |
| | | |
| | | // 查询回款金额 |
| | | // 回款金额 |
| | | LambdaQueryWrapper<ReceiptPayment> receiptPaymentQuery = new LambdaQueryWrapper<>(); |
| | | receiptPaymentQuery |
| | | .ge(ReceiptPayment::getCreateTime, startTime) |
| | | .lt(ReceiptPayment::getCreateTime, endTime); |
| | | List<ReceiptPayment> receiptPayments = receiptPaymentMapper.selectList(receiptPaymentQuery); |
| | | .le(ReceiptPayment::getCreateTime, endTime); |
| | | |
| | | // 查询开票金额 |
| | | LambdaQueryWrapper<InvoiceLedger> invoiceLedgerQuery = new LambdaQueryWrapper<>(); |
| | | invoiceLedgerQuery |
| | | .ge(InvoiceLedger::getCreateTime, startTime) |
| | | .lt(InvoiceLedger::getCreateTime, endTime); |
| | | List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(invoiceLedgerQuery); |
| | | List<ReceiptPayment> receiptPayments = |
| | | receiptPaymentMapper.selectList(receiptPaymentQuery); |
| | | |
| | | // 计算回款总额 |
| | | BigDecimal receiptAmount = receiptPayments.stream() |
| | | .map(ReceiptPayment::getReceiptPaymentAmount) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | |
| | | // 计算开票总额 |
| | | // 开票金额 |
| | | LambdaQueryWrapper<InvoiceLedger> invoiceLedgerQuery = new LambdaQueryWrapper<>(); |
| | | invoiceLedgerQuery |
| | | .ge(InvoiceLedger::getCreateTime, startTime) |
| | | .le(InvoiceLedger::getCreateTime, endTime); |
| | | |
| | | List<InvoiceLedger> invoiceLedgers = |
| | | invoiceLedgerMapper.selectList(invoiceLedgerQuery); |
| | | |
| | | BigDecimal invoiceAmount = invoiceLedgers.stream() |
| | | .map(InvoiceLedger::getInvoiceTotal) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | |
| | | // 构造返回的 DTO |
| | | MonthlyAmountDto dto = new MonthlyAmountDto(); |
| | | dto.setMonth(startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " ~ " + |
| | | endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); |
| | | dto.setMonth(yearMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"))); |
| | | dto.setReceiptAmount(receiptAmount); |
| | | dto.setInvoiceAmount(invoiceAmount); |
| | | |
| | | result.add(dto); |
| | | } |
| | | |
| | | // 反转列表,使时间顺序从早到晚 |
| | | Collections.reverse(result); |
| | | return result; |
| | | } |
| | | |
| | |
| | | public IPage<SalesLedger> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto) { |
| | | return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto); |
| | | } |
| | | |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | // // 产品大类数据 |
| | | // List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>().in(Product::getProductName, |
| | | // salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getProductCategory).collect(Collectors.toList()))); |
| | | List<Map<String,Object>> list = productModelMapper.getProductAndModelList(); |
| | | List<Map<String, Object>> list = productModelMapper.getProductAndModelList(); |
| | | // 录入人数据 |
| | | List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName, |
| | | salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).collect(Collectors.toList()))); |
| | | for (SalesLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) { |
| | | SalesLedger salesLedger1 = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>() |
| | | .eq(SalesLedger::getSalesContractNo, salesLedgerImportDto.getSalesContractNo()) |
| | | .last("LIMIT 1")); |
| | | if (salesLedger1 != null) { |
| | | continue; |
| | | } |
| | | SalesLedger salesLedger = new SalesLedger(); |
| | | BeanUtils.copyProperties(salesLedgerImportDto, salesLedger); |
| | | salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate())); |
| | |
| | | throw new RuntimeException("销售单号:" + salesLedgerImportDto.getSalesContractNo() + ",无对应产品数据!"); |
| | | salesLedger.setContractAmount(salesLedgerProductImportDtos.stream() |
| | | .map(SalesLedgerProductImportDto::getTaxInclusiveTotalPrice) |
| | | .reduce(BigDecimal.ZERO,BigDecimal::add)); |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add)); |
| | | salesLedgerMapper.insert(salesLedger); |
| | | |
| | | |
| | |
| | | salesLedgerProduct.setApproveStatus(0); |
| | | salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice()); |
| | | salesLedgerProductMapper.insert(salesLedgerProduct); |
| | | // 添加生产数据 |
| | | salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct); |
| | | } |
| | | } |
| | | |
| | |
| | | return lossProductModelDtos; |
| | | } |
| | | |
| | | |
| | | // 内部类用于存储聚合结果 |
| | | private static class GroupedCustomer { |
| | | private final Long customerId; |
| | | private final String customerName; |
| | | private BigDecimal totalAmount = BigDecimal.ZERO; |
| | | |
| | | public GroupedCustomer(Long customerId, String customerName) { |
| | | this.customerId = customerId; |
| | | this.customerName = customerName; |
| | | } |
| | | |
| | | public void addAmount(BigDecimal amount) { |
| | | if (amount != null) { |
| | | this.totalAmount = this.totalAmount.add(amount); |
| | | @Override |
| | | public IPage<SalesLedgerDto> listSalesLedger(SalesLedgerDto salesLedgerDto, Page page) { |
| | | IPage<SalesLedgerDto> salesLedgerDtoIPage = salesLedgerMapper.listSalesLedgerAndShipped(page, salesLedgerDto); |
| | | for (SalesLedgerDto salesLedger : salesLedgerDtoIPage.getRecords()) { |
| | | LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>(); |
| | | productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId()); |
| | | productWrapper.eq(SalesLedgerProduct::getType, 1); |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper); |
| | | for (SalesLedgerProduct product : products) { |
| | | product.setOriginalNoInvoiceNum(product.getNoInvoiceNum()); |
| | | // 提供临时未开票数,未开票金额供前段计算 |
| | | product.setTempnoInvoiceAmount(product.getNoInvoiceAmount()); |
| | | product.setTempNoInvoiceNum(product.getNoInvoiceNum()); |
| | | product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName()); |
| | | product.setRegisterDate(LocalDateTime.now()); |
| | | // 发货信息 |
| | | ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>() |
| | | .eq(ShippingInfo::getSalesLedgerProductId, product.getId()) |
| | | .orderByDesc(ShippingInfo::getCreateTime) |
| | | .last("limit 1")); |
| | | product.setShippingCarNumber(shippingInfo.getShippingCarNumber()); |
| | | product.setShippingDate(shippingInfo.getShippingDate()); |
| | | if (shippingInfo != null) { |
| | | product.setShippingStatus(shippingInfo.getStatus()); |
| | | } |
| | | } |
| | | // 过滤只保留发货记录 |
| | | products = products.stream().filter(product -> "已发货".equals(product.getShippingStatus())).collect(Collectors.toList()); |
| | | if (!products.isEmpty()) { |
| | | salesLedger.setHasChildren(true); |
| | | salesLedger.setProductData(products); |
| | | } |
| | | } |
| | | |
| | | public Long getCustomerId() { |
| | | return customerId; |
| | | |
| | | return salesLedgerDtoIPage; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saleProcessBind(SalesLedgerProcessRoute salesLedgerProcessRoute) { |
| | | if (salesLedgerProcessRoute == null) { |
| | | throw new ServiceException("绑定失败,数据不能为空"); |
| | | } |
| | | |
| | | public String getCustomerName() { |
| | | return customerName; |
| | | SalesLedger salesLedger = baseMapper.selectById(salesLedgerProcessRoute.getSalesLedgerId()); |
| | | if (salesLedger == null) { |
| | | throw new ServiceException("绑定失败,销售订单不存在"); |
| | | } |
| | | ProcessRoute processRoute = processRouteMapper.selectById(salesLedgerProcessRoute.getProcessRouteId()); |
| | | if (processRoute == null) { |
| | | throw new ServiceException("绑定失败,工艺路线不存在"); |
| | | } |
| | | // 清除已绑定的数据 |
| | | salesLedgerProcessRouteService.remove(new LambdaQueryWrapper<SalesLedgerProcessRoute>().eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedger.getId())); |
| | | |
| | | public BigDecimal getTotalAmount() { |
| | | return totalAmount; |
| | | // 将数据迁移到sales_ledger_process_route |
| | | List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, processRoute.getId())); |
| | | SalesLedgerProcessRoute ledgerProcessRoute; |
| | | List<SalesLedgerProcessRoute> salesLedgerProcessRouteList = new ArrayList<>(); |
| | | for (ProcessRouteItem routeItem : routeItems) { |
| | | ledgerProcessRoute = new SalesLedgerProcessRoute(); |
| | | ledgerProcessRoute.setProcessRouteId(processRoute.getId()); |
| | | ledgerProcessRoute.setSalesLedgerId(salesLedger.getId()); |
| | | ledgerProcessRoute.setProcessRouteItemId(routeItem.getId()); |
| | | ledgerProcessRoute.setDragSort(routeItem.getDragSort()); |
| | | salesLedgerProcessRouteList.add(ledgerProcessRoute); |
| | | } |
| | | salesLedgerProcessRouteService.saveBatch(salesLedgerProcessRouteList); |
| | | } |
| | | |
| | | /** |
| | |
| | | salesLedgerProductMapper.deleteBatchIds(productIds); |
| | | } |
| | | |
| | | // 清除产品的加工 |
| | | salesLedgerProductProcessBindService.remove(new LambdaQueryWrapper<SalesLedgerProductProcessBind>().in(SalesLedgerProductProcessBind::getSalesLedgerProductId, productIds)); |
| | | |
| | | LambdaQueryWrapper<InvoiceRegistrationProduct> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.in(InvoiceRegistrationProduct::getSalesLedgerId, idList); |
| | | List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(wrapper); |
| | |
| | | wrapperTree.in(ReceiptPayment::getInvoiceLedgerId, invoiceLedgerIds); |
| | | receiptPaymentMapper.delete(wrapperTree); |
| | | } |
| | | // 删除发货台账记录 |
| | | List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>() |
| | | .in(ShippingInfo::getSalesLedgerId, idList)); |
| | | if (CollectionUtils.isNotEmpty(shippingInfos)) { |
| | | shippingInfoServiceImpl.delete(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList())); |
| | | } |
| | | // 删除附件表 |
| | | commonFileService.deleteByBusinessIds(idList, FileNameType.SALE.getValue()); |
| | | |
| | | // 删除生产管控数据 |
| | | // 删除生产订单数据 |
| | | LambdaQueryWrapper<SalesLedgerScheduling> in = new LambdaQueryWrapper<SalesLedgerScheduling>() |
| | | .in(SalesLedgerScheduling::getSalesLedgerId, idList); |
| | | salesLedgerSchedulingMapper.delete(in); |
| | | // 删除生产派工数据 |
| | | 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); |
| | | //查询生产报工id |
| | | ArrayList<Long> mainIdList = productionProductMainService.listMain(idList); |
| | | if (CollectionUtils.isNotEmpty(mainIdList)) { |
| | | mainIdList.stream().forEach(mainId -> { |
| | | productionProductMainService.removeProductMain(mainId); |
| | | }); |
| | | } |
| | | // 2. 再删除主表数据 |
| | | return salesLedgerMapper.deleteBatchIds(idList); |
| | | } |
| | |
| | | // 4. 处理子表数据 |
| | | List<SalesLedgerProduct> productList = salesLedgerDto.getProductData(); |
| | | if (productList != null && !productList.isEmpty()) { |
| | | handleSalesLedgerProducts(salesLedger.getId(), productList, salesLedgerDto.getType()); |
| | | handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType())); |
| | | updateMainContractAmount( |
| | | salesLedger.getId(), |
| | | productList, |
| | |
| | | throw new BaseException("文件迁移失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // 文件迁移方法 |
| | | |
| | | /** |
| | | * 将临时文件迁移到正式目录 |
| | |
| | | } |
| | | } |
| | | |
| | | // 文件迁移方法 |
| | | |
| | | private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) { |
| | | @Override |
| | | public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) { |
| | | // 按ID分组,区分新增和更新的记录 |
| | | Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream() |
| | | .peek(p -> p.setSalesLedgerId(salesLedgerId)) |
| | |
| | | // 执行更新操作 |
| | | if (!updateList.isEmpty()) { |
| | | for (SalesLedgerProduct product : updateList) { |
| | | product.setType(type); |
| | | product.setType(type.getCode()); |
| | | salesLedgerProductMapper.updateById(product); |
| | | // 清空销售产品绑定的加工 |
| | | salesLedgerProductProcessBindService.updateProductProcessBind(product.getSalesProductProcessList(), product.getId()); |
| | | } |
| | | } |
| | | // 执行插入操作 |
| | | if (!insertList.isEmpty()) { |
| | | for (SalesLedgerProduct salesLedgerProduct : insertList) { |
| | | salesLedgerProduct.setType(type); |
| | | salesLedgerProduct.setType(type.getCode()); |
| | | salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity()); |
| | | salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice()); |
| | | salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice()); |
| | | salesLedgerProductMapper.insert(salesLedgerProduct); |
| | | // 绑定产品额外加工 |
| | | // 清空销售产品绑定的加工 |
| | | salesLedgerProductProcessBindService.updateProductProcessBind(salesLedgerProduct.getSalesProductProcessList(), salesLedgerProduct.getId()); |
| | | // 添加生产数据 |
| | | salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | if (!redisTemplate.hasKey(lockKey)) { |
| | | if (Boolean.FALSE.equals(redisTemplate.hasKey(lockKey))) { |
| | | throw new RuntimeException("获取合同编号生成锁失败:超时"); |
| | | } |
| | | |
| | | // 2. 查询当天/公司已存在的序列号(与原逻辑一致) |
| | | Long tenantId = SecurityUtils.getLoginUser().getTenantId(); |
| | | if (null != tenantId) { |
| | | //获取公司编号 |
| | | SysDept sysDept = sysDeptMapper.selectDeptById(tenantId.longValue()); |
| | | if (!ObjectUtils.isEmpty(sysDept)) { |
| | | datePart = (StringUtils.isEmpty(sysDept.getDeptNick()) ? "" : sysDept.getDeptNick()) + datePart; |
| | | } |
| | | } |
| | | // Long tenantId = SecurityUtils.getLoginUser().getTenantId(); |
| | | // if (null != tenantId) { |
| | | // //获取公司编号 |
| | | // SysDept sysDept = sysDeptMapper.selectDeptById(tenantId); |
| | | // if (!ObjectUtils.isEmpty(sysDept)) { |
| | | // datePart = (StringUtils.isEmpty(sysDept.getDeptNick()) ? "" : sysDept.getDeptNick()) + datePart; |
| | | // } |
| | | // } |
| | | datePart = "D" + datePart; |
| | | List<Integer> existingSequences = salesLedgerMapper.selectSequencesByDate(datePart); |
| | | int nextSequence = findFirstMissingSequence(existingSequences); |
| | | |
| | |
| | | lockValue |
| | | ); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public SalesLedgerProcessRouteDto salesProcess(Long salesLedgerId) { |
| | | SalesLedgerProcessRouteDto dto = new SalesLedgerProcessRouteDto(); |
| | | List<SalesLedgerProcessRoute> list = baseMapper.selectSalesProcess(salesLedgerId); |
| | | if (CollectionUtils.isNotEmpty(list)) { |
| | | Long processRouteId = list.get(0).getProcessRouteId(); |
| | | ProcessRoute processRoute = processRouteMapper.selectById(processRouteId); |
| | | if (processRoute != null) { |
| | | dto.setRouteId(processRoute.getId()); |
| | | dto.setRouteName(processRoute.getProcessRouteName()); |
| | | } |
| | | } else { |
| | | // 要是list查询为空的话,就查询默认的工艺路线返回 |
| | | ProcessRoute defaultRoute = processRouteMapper.selectOne(new LambdaQueryWrapper<ProcessRoute>().eq(ProcessRoute::getIsDefault, 1).last("limit 1")); |
| | | if (defaultRoute != null) { |
| | | dto.setRouteId(defaultRoute.getId()); |
| | | dto.setRouteName(defaultRoute.getProcessRouteName()); |
| | | List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, defaultRoute.getId()).orderByAsc(ProcessRouteItem::getDragSort)); |
| | | list = routeItems.stream().map(item -> { |
| | | SalesLedgerProcessRoute salesLedgerProcessRoute = new SalesLedgerProcessRoute(); |
| | | salesLedgerProcessRoute.setProcessRouteId(defaultRoute.getId()); |
| | | salesLedgerProcessRoute.setSalesLedgerId(salesLedgerId); |
| | | salesLedgerProcessRoute.setProcessRouteItemId(item.getId()); |
| | | salesLedgerProcessRoute.setProcessName(item.getProcessName()); |
| | | salesLedgerProcessRoute.setDragSort(item.getDragSort()); |
| | | return salesLedgerProcessRoute; |
| | | }).collect(Collectors.toList()); |
| | | } |
| | | } |
| | | dto.setList(list); |
| | | return dto; |
| | | } |
| | | |
| | | @Override |
| | | public SalesProcessCardDto processCard(Long salesLedgerId) { |
| | | if (salesLedgerId == null) { |
| | | throw new ServiceException("流程卡打印失败,打印销售订单不能为空"); |
| | | } |
| | | // 查询销售订单 |
| | | SalesLedger salesLedger = baseMapper.selectById(salesLedgerId); |
| | | if (salesLedger == null) { |
| | | throw new ServiceException("流程卡打印失败,销售订单不存在"); |
| | | } |
| | | |
| | | SalesProcessCardDto dto = new SalesProcessCardDto(); |
| | | dto.setSalesContractNo(salesLedger.getSalesContractNo()); |
| | | dto.setCustomerName(salesLedger.getCustomerName()); |
| | | dto.setDeliveryDate(salesLedger.getDeliveryDate()); |
| | | dto.setRegister(SecurityUtils.getLoginUser().getUser().getNickName()); |
| | | dto.setRegisterDate(LocalDateTime.now()); |
| | | dto.setOrderProcessRequirement(salesLedger.getRemarks()); |
| | | |
| | | // 查询产品列表 |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList( |
| | | new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId)); |
| | | |
| | | BigDecimal totalQuantity = BigDecimal.ZERO; |
| | | BigDecimal totalArea = BigDecimal.ZERO; |
| | | List<SalesProcessCardDto.ProcessCardItemDto> itemDtos = new ArrayList<>(); |
| | | |
| | | for (SalesLedgerProduct p : products) { |
| | | SalesProcessCardDto.ProcessCardItemDto itemDto = new SalesProcessCardDto.ProcessCardItemDto(); |
| | | itemDto.setFloorCode(p.getFloorCode()); |
| | | // 组装产品描述:大类 + (规格) |
| | | String desc = (p.getProductCategory() != null ? p.getProductCategory() : "") + |
| | | (StringUtils.isNotBlank(p.getSpecificationModel()) ? " " + p.getSpecificationModel() : ""); |
| | | itemDto.setProductDescription(desc.trim()); |
| | | itemDto.setWidth(p.getWidth()); |
| | | itemDto.setHeight(p.getHeight()); |
| | | itemDto.setQuantity(p.getQuantity()); |
| | | |
| | | // 面积计算(平米) |
| | | BigDecimal area = p.getActualPieceArea() != null ? p.getActualPieceArea() : p.getSettlePieceArea(); |
| | | if (area == null && p.getWidth() != null && p.getHeight() != null) { |
| | | area = p.getWidth().multiply(p.getHeight()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP); |
| | | } |
| | | itemDto.setArea(area); |
| | | itemDto.setProcessRequirement(p.getProcessRequirement()); |
| | | |
| | | BigDecimal qty = p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO; |
| | | totalQuantity = totalQuantity.add(qty); |
| | | if (area != null) { |
| | | totalArea = totalArea.add(area.multiply(qty)); |
| | | } |
| | | |
| | | itemDtos.add(itemDto); |
| | | } |
| | | dto.setItems(itemDtos); |
| | | dto.setTotalQuantity(totalQuantity); |
| | | dto.setTotalArea(totalArea.setScale(2, RoundingMode.HALF_UP)); |
| | | |
| | | // 工艺路线 |
| | | List<SalesLedgerProcessRoute> salesLedgerProcessRoutes = salesLedgerProcessRouteService.list( |
| | | new LambdaQueryWrapper<SalesLedgerProcessRoute>() |
| | | .eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedgerId) |
| | | .orderByAsc(SalesLedgerProcessRoute::getDragSort)); |
| | | |
| | | List<SalesProcessCardDto.ProcessNodeDto> nodeDtos = new ArrayList<>(); |
| | | |
| | | if (CollectionUtils.isEmpty(salesLedgerProcessRoutes)) { |
| | | // 无自定义路线,取默认路线 |
| | | ProcessRoute defaultRoute = processRouteMapper.selectOne( |
| | | new LambdaQueryWrapper<ProcessRoute>().eq(ProcessRoute::getIsDefault, 1).last("LIMIT 1")); |
| | | if (defaultRoute != null) { |
| | | List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList( |
| | | new LambdaQueryWrapper<ProcessRouteItem>() |
| | | .eq(ProcessRouteItem::getRouteId, defaultRoute.getId()) |
| | | .orderByAsc(ProcessRouteItem::getDragSort)); |
| | | for (ProcessRouteItem i : routeItems) { |
| | | SalesProcessCardDto.ProcessNodeDto node = new SalesProcessCardDto.ProcessNodeDto(); |
| | | node.setProcessRouteItemId(i.getId()); |
| | | node.setProcessRouteItemName(i.getProcessName()); |
| | | node.setDragSort(i.getDragSort()); |
| | | nodeDtos.add(node); |
| | | } |
| | | } |
| | | } else { |
| | | // 使用自定义路线绑定的节点 |
| | | List<Long> itemIds = salesLedgerProcessRoutes.stream() |
| | | .map(SalesLedgerProcessRoute::getProcessRouteItemId) |
| | | .collect(Collectors.toList()); |
| | | List<ProcessRouteItem> rawItems = processRouteItemMapper.selectBatchIds(itemIds); |
| | | Map<Long, ProcessRouteItem> itemMap = rawItems.stream() |
| | | .collect(Collectors.toMap(ProcessRouteItem::getId, i -> i, (a, b) -> a)); |
| | | |
| | | for (SalesLedgerProcessRoute r : salesLedgerProcessRoutes) { |
| | | ProcessRouteItem pi = itemMap.get(r.getProcessRouteItemId()); |
| | | if (pi != null) { |
| | | SalesProcessCardDto.ProcessNodeDto node = new SalesProcessCardDto.ProcessNodeDto(); |
| | | node.setProcessRouteItemId(pi.getId()); |
| | | node.setProcessRouteItemName(pi.getProcessName()); |
| | | node.setDragSort(r.getDragSort() != null ? r.getDragSort() : pi.getDragSort()); |
| | | node.setRemark(r.getRemark()); |
| | | nodeDtos.add(node); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!nodeDtos.isEmpty()) { |
| | | // dragSort 进行升序排序 |
| | | nodeDtos.sort(Comparator.comparing( |
| | | SalesProcessCardDto.ProcessNodeDto::getDragSort, |
| | | Comparator.nullsLast(Comparator.naturalOrder()) |
| | | )); |
| | | // 重新生成排序后的路径名称列表 |
| | | List<String> sortedPathNames = nodeDtos.stream() |
| | | .map(SalesProcessCardDto.ProcessNodeDto::getProcessRouteItemName) |
| | | .collect(Collectors.toList()); |
| | | // 拼接字符串 |
| | | dto.setProcessPathDisplay(String.join(" -> ", sortedPathNames)); |
| | | // 设置顶层节点的工艺路线 |
| | | dto.setRouteNodes(nodeDtos); |
| | | } |
| | | |
| | | return dto; |
| | | } |
| | | |
| | | private int findFirstMissingSequence(List<Integer> sequences) { |
| | |
| | | throw new RuntimeException("动态更新主表金额失败", e); |
| | | } |
| | | } |
| | | |
| | | // 内部类用于存储聚合结果 |
| | | private static class GroupedCustomer { |
| | | private final Long customerId; |
| | | private final String customerName; |
| | | private BigDecimal totalAmount = BigDecimal.ZERO; |
| | | |
| | | public GroupedCustomer(Long customerId, String customerName) { |
| | | this.customerId = customerId; |
| | | this.customerName = customerName; |
| | | } |
| | | |
| | | public void addAmount(BigDecimal amount) { |
| | | if (amount != null) { |
| | | this.totalAmount = this.totalAmount.add(amount); |
| | | } |
| | | } |
| | | |
| | | public Long getCustomerId() { |
| | | return customerId; |
| | | } |
| | | |
| | | public String getCustomerName() { |
| | | return customerName; |
| | | } |
| | | |
| | | public BigDecimal getTotalAmount() { |
| | | return totalAmount; |
| | | } |
| | | } |
| | | } |