| | |
| | | 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.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.pojo.Customer; |
| | | import com.ruoyi.basic.pojo.CustomerRegions; |
| | | import com.ruoyi.basic.service.ICustomerRegionsService; |
| | | 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.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.production.mapper.*; |
| | | import com.ruoyi.production.pojo.ProcessRoute; |
| | | import com.ruoyi.production.pojo.ProcessRouteItem; |
| | | import com.ruoyi.production.service.ProductionProductMainService; |
| | | 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.sales.dto.*; |
| | | import com.ruoyi.sales.mapper.*; |
| | | import com.ruoyi.sales.pojo.*; |
| | | 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; |
| | |
| | | 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}") |
| | |
| | | ; |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | private final ICustomerRegionsService customerRegionsService; |
| | | |
| | | @Override |
| | | public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) { |
| | |
| | | // 查询退货信息 |
| | | List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList()); |
| | | List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>(); |
| | | if(CollectionUtils.isNotEmpty(productIds)){ |
| | | if (CollectionUtils.isNotEmpty(productIds)) { |
| | | groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds); |
| | | } |
| | | Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity)); |
| | |
| | | .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); |
| | | } |
| | | } |
| | | |
| | |
| | | return salesLedgerDtoIPage; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saleProcessBind(SalesLedgerProcessRoute salesLedgerProcessRoute) { |
| | | if (salesLedgerProcessRoute == null) { |
| | | throw new ServiceException("绑定失败,数据不能为空"); |
| | | } |
| | | |
| | | 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())); |
| | | |
| | | // 将数据迁移到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); |
| | | } |
| | | |
| | | /** |
| | | * 下划线命名转驼峰命名 |
| | | */ |
| | |
| | | if (!productIds.isEmpty()) { |
| | | salesLedgerProductMapper.deleteBatchIds(productIds); |
| | | } |
| | | |
| | | // 清除产品的加工 |
| | | salesLedgerProductProcessBindService.remove(new LambdaQueryWrapper<SalesLedgerProductProcessBind>().in(SalesLedgerProductProcessBind::getSalesLedgerProductId, productIds)); |
| | | |
| | | LambdaQueryWrapper<InvoiceRegistrationProduct> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.in(InvoiceRegistrationProduct::getSalesLedgerId, idList); |
| | |
| | | for (SalesLedgerProduct product : updateList) { |
| | | product.setType(type.getCode()); |
| | | salesLedgerProductMapper.updateById(product); |
| | | // 清空销售产品绑定的加工 |
| | | salesLedgerProductProcessBindService.updateProductProcessBind(product.getSalesProductProcessList(), product.getId()); |
| | | } |
| | | } |
| | | // 执行插入操作 |
| | |
| | | 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); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | @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; |
| | | } |
| | | |
| | | @Override |
| | | public SalesOrdersDto salesOrders(Long salesLedgerId) { |
| | | if (salesLedgerId == null) { |
| | | throw new ServiceException("打印销售订单失败,销售订单ID不能为空"); |
| | | } |
| | | SalesLedger salesLedger = baseMapper.selectById(salesLedgerId); |
| | | if (salesLedger == null) { |
| | | throw new ServiceException("打印销售订单失败,销售订单不存在"); |
| | | } |
| | | |
| | | SalesOrdersDto dto = new SalesOrdersDto(); |
| | | dto.setSalesContractNo(salesLedger.getSalesContractNo()); |
| | | dto.setCustomerName(salesLedger.getCustomerName()); |
| | | dto.setProjectName(salesLedger.getProjectName()); |
| | | dto.setSalesman(salesLedger.getSalesman()); |
| | | dto.setExecutionDate(salesLedger.getExecutionDate() != null ? salesLedger.getExecutionDate().atStartOfDay() : null); |
| | | dto.setDeliveryDate(salesLedger.getDeliveryDate()); |
| | | dto.setRemakes(salesLedger.getRemarks()); |
| | | dto.setCompanyName("鹤壁天沐钢化玻璃厂"); |
| | | |
| | | // 送货地址 |
| | | if (salesLedger.getCustomerId() != null) { |
| | | Customer customer = customerMapper.selectById(salesLedger.getCustomerId()); |
| | | if (customer != null) { |
| | | StringBuilder address = new StringBuilder(); |
| | | if (customer.getRegionsId() != null) { |
| | | CustomerRegions regions = customerRegionsService.getById(customer.getRegionsId()); |
| | | if (regions != null) { |
| | | address.append(regions.getRegionsName()); |
| | | } |
| | | } |
| | | if (StringUtils.isNotEmpty(customer.getCompanyAddress())) { |
| | | address.append(customer.getCompanyAddress()); |
| | | } |
| | | dto.setCompanyAddress(address.toString()); |
| | | } |
| | | } |
| | | |
| | | // 制单员 |
| | | if (StringUtils.isNotEmpty(salesLedger.getEntryPerson())) { |
| | | try { |
| | | SysUser user = sysUserMapper.selectUserById(Long.parseLong(salesLedger.getEntryPerson())); |
| | | if (user != null) { |
| | | dto.setOrderMaker(user.getNickName()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("获取制单员信息失败: {}", e.getMessage()); |
| | | } |
| | | } |
| | | // 制单日期 (底部) |
| | | dto.setOrderMakerDate(salesLedger.getExecutionDate() != null ? salesLedger.getExecutionDate().atStartOfDay() : null); |
| | | |
| | | // 打印信息 |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | if (loginUser != null && loginUser.getUser() != null) { |
| | | dto.setPrintPeople(loginUser.getUser().getNickName()); |
| | | } |
| | | dto.setPrintTime(LocalDateTime.now()); |
| | | |
| | | // 查询产品列表 |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList( |
| | | new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId)); |
| | | |
| | | if (CollectionUtils.isNotEmpty(products)) { |
| | | SalesLedgerProduct firstProduct = products.get(0); |
| | | dto.setProductName(firstProduct.getProductCategory() != null ? firstProduct.getProductCategory() : ""); |
| | | } |
| | | |
| | | List<SalesOrdersDto.SalesOrderItemDto> itemDtos = new ArrayList<>(); |
| | | BigDecimal subtotalQuantity = BigDecimal.ZERO; |
| | | BigDecimal subtotalArea = BigDecimal.ZERO; |
| | | BigDecimal subtotalAmount = BigDecimal.ZERO; |
| | | |
| | | for (SalesLedgerProduct p : products) { |
| | | SalesOrdersDto.SalesOrderItemDto itemDto = new SalesOrdersDto.SalesOrderItemDto(); |
| | | 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.getSettleTotalArea() != null ? p.getSettleTotalArea() : p.getActualTotalArea(); |
| | | if (area == null && p.getWidth() != null && p.getHeight() != null && p.getQuantity() != null) { |
| | | area = p.getWidth().multiply(p.getHeight()).multiply(p.getQuantity()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP); |
| | | } |
| | | itemDto.setArea(area); |
| | | itemDto.setUnitPrice(p.getTaxInclusiveUnitPrice()); |
| | | itemDto.setAmount(p.getTaxInclusiveTotalPrice()); |
| | | itemDto.setRemark(p.getRemark()); |
| | | itemDto.setProcessRequirement(p.getProcessRequirement()); |
| | | |
| | | subtotalQuantity = subtotalQuantity.add(p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO); |
| | | subtotalArea = subtotalArea.add(area != null ? area : BigDecimal.ZERO); |
| | | subtotalAmount = subtotalAmount.add(p.getTaxInclusiveTotalPrice() != null ? p.getTaxInclusiveTotalPrice() : BigDecimal.ZERO); |
| | | |
| | | itemDtos.add(itemDto); |
| | | } |
| | | dto.setItems(itemDtos); |
| | | dto.setSubtotalQuantity(subtotalQuantity); |
| | | dto.setSubtotalArea(subtotalArea.setScale(2, RoundingMode.HALF_UP)); |
| | | dto.setSubtotalAmount(subtotalAmount); |
| | | |
| | | // 处理其他费用 |
| | | List<Long> productIds = products.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList()); |
| | | BigDecimal otherFeesTotal = BigDecimal.ZERO; |
| | | if (CollectionUtils.isNotEmpty(productIds)) { |
| | | List<SalesLedgerProductProcessBind> binds = salesLedgerProductProcessBindService.list( |
| | | new LambdaQueryWrapper<SalesLedgerProductProcessBind>().in(SalesLedgerProductProcessBind::getSalesLedgerProductId, productIds)); |
| | | |
| | | if (CollectionUtils.isNotEmpty(binds)) { |
| | | Map<Integer, Integer> processQuantityMap = binds.stream() |
| | | .collect(Collectors.groupingBy(SalesLedgerProductProcessBind::getSalesLedgerProductProcessId, |
| | | Collectors.summingInt(b -> b.getQuantity() != null ? b.getQuantity() : 0))); |
| | | |
| | | List<Integer> processIds = new ArrayList<>(processQuantityMap.keySet()); |
| | | List<SalesLedgerProductProcess> processes = salesLedgerProductProcessService.listByIds(processIds); |
| | | |
| | | List<SalesOrdersDto.OtherFeeDto> otherFeeDtos = new ArrayList<>(); |
| | | |
| | | for (SalesLedgerProductProcess proc : processes) { |
| | | SalesOrdersDto.OtherFeeDto feeDto = new SalesOrdersDto.OtherFeeDto(); |
| | | feeDto.setFeeName(proc.getProcessName()); |
| | | feeDto.setUnitPrice(proc.getUnitPrice()); |
| | | Integer qty = processQuantityMap.get(proc.getId()); |
| | | feeDto.setQuantity(new BigDecimal(qty != null ? qty : 0)); |
| | | BigDecimal amount = proc.getUnitPrice() != null ? proc.getUnitPrice().multiply(feeDto.getQuantity()) : BigDecimal.ZERO; |
| | | feeDto.setAmount(amount); |
| | | otherFeeDtos.add(feeDto); |
| | | otherFeesTotal = otherFeesTotal.add(amount); |
| | | } |
| | | dto.setOtherFees(otherFeeDtos); |
| | | } |
| | | } |
| | | |
| | | dto.setTotalQuantity(subtotalQuantity); |
| | | dto.setTotalArea(dto.getSubtotalArea()); |
| | | dto.setTotalAmount(subtotalAmount.add(otherFeesTotal)); |
| | | dto.setTotalAmountDisplay(dto.getTotalAmount().setScale(2, RoundingMode.HALF_UP).toString() + "元"); |
| | | |
| | | return dto; |
| | | } |
| | | |
| | | @Override |
| | | public SalesInvoicesDto salesInvoices(List<Long> salesLedgerIds) { |
| | | if (CollectionUtils.isEmpty(salesLedgerIds)) { |
| | | throw new ServiceException("销售发货单打印失败,销售订单不能为空"); |
| | | } |
| | | |
| | | List<SalesLedger> ledgers = salesLedgerMapper.selectBatchIds(salesLedgerIds); |
| | | if (CollectionUtils.isEmpty(ledgers)) { |
| | | throw new ServiceException("销售发货单打印失败,未找到对应台账记录"); |
| | | } |
| | | |
| | | Long customerId = ledgers.get(0).getCustomerId(); |
| | | for (SalesLedger ledger : ledgers) { |
| | | if (!Objects.equals(customerId, ledger.getCustomerId())) { |
| | | throw new ServiceException("销售发货单合并打印只能是同一个客户"); |
| | | } |
| | | } |
| | | |
| | | SalesInvoicesDto dto = new SalesInvoicesDto(); |
| | | |
| | | Customer customer = customerMapper.selectById(customerId); |
| | | if (customer != null) { |
| | | dto.setCustomerName(customer.getCustomerName()); |
| | | dto.setContactPerson(customer.getContactPerson()); |
| | | dto.setContactPhone(customer.getContactPhone()); |
| | | |
| | | StringBuilder address = new StringBuilder(); |
| | | if (customer.getRegionsId() != null) { |
| | | CustomerRegions regions = customerRegionsService.getById(customer.getRegionsId()); |
| | | if (regions != null) { |
| | | address.append(regions.getRegionsName()); |
| | | } |
| | | } |
| | | if (StringUtils.isNotEmpty(customer.getCompanyAddress())) { |
| | | address.append(customer.getCompanyAddress()); |
| | | } |
| | | dto.setCompanyAddress(address.toString()); |
| | | } |
| | | |
| | | // 发货单号 (XF + 日期 + 序列) |
| | | String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd")); |
| | | String redisKey = "sales:delivery:seq:" + dateStr; |
| | | Long seq = redisTemplate.opsForValue().increment(redisKey); |
| | | if (seq != null && seq == 1) { |
| | | redisTemplate.expire(redisKey, 48, TimeUnit.HOURS); |
| | | } |
| | | dto.setDeliveryNo("XF" + dateStr + String.format("%03d", seq != null ? seq : 1)); |
| | | |
| | | // 对方单号 |
| | | // dto.setExternalOrderNo(ledgers.get(0).getCustomerContractNo()); |
| | | |
| | | // 查询所有产品 |
| | | List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList( |
| | | new LambdaQueryWrapper<SalesLedgerProduct>().in(SalesLedgerProduct::getSalesLedgerId, salesLedgerIds)); |
| | | |
| | | if (CollectionUtils.isNotEmpty(allProducts)) { |
| | | Map<Long, SalesLedger> ledgerMap = ledgers.stream() |
| | | .collect(Collectors.toMap(SalesLedger::getId, Function.identity())); |
| | | |
| | | Map<Long, List<SalesLedgerProduct>> groupedData = new LinkedHashMap<>(); |
| | | for (SalesLedgerProduct p : allProducts) { |
| | | groupedData.computeIfAbsent(p.getSalesLedgerId(), k -> new ArrayList<>()).add(p); |
| | | } |
| | | |
| | | List<SalesInvoicesDto.InvoiceOrderGroupDto> groups = new ArrayList<>(); |
| | | BigDecimal totalQty = BigDecimal.ZERO; |
| | | BigDecimal totalArea = BigDecimal.ZERO; |
| | | |
| | | for (Map.Entry<Long, List<SalesLedgerProduct>> ledgerEntry : groupedData.entrySet()) { |
| | | SalesLedger ledger = ledgerMap.get(ledgerEntry.getKey()); |
| | | String orderNo = ledger != null ? ledger.getSalesContractNo() : ""; |
| | | List<SalesLedgerProduct> products = ledgerEntry.getValue(); |
| | | |
| | | SalesInvoicesDto.InvoiceOrderGroupDto group = new SalesInvoicesDto.InvoiceOrderGroupDto(); |
| | | group.setSalesContractNo(orderNo); |
| | | if (CollectionUtils.isNotEmpty(products)) { |
| | | group.setProductName(products.get(0).getProductCategory()); |
| | | } |
| | | |
| | | List<SalesInvoicesDto.InvoiceItemDto> itemDtos = new ArrayList<>(); |
| | | BigDecimal groupQty = BigDecimal.ZERO; |
| | | BigDecimal groupArea = BigDecimal.ZERO; |
| | | |
| | | for (SalesLedgerProduct p : products) { |
| | | SalesInvoicesDto.InvoiceItemDto item = new SalesInvoicesDto.InvoiceItemDto(); |
| | | item.setFloorCode(p.getFloorCode()); |
| | | item.setWidthHeight((p.getWidth() != null ? p.getWidth().stripTrailingZeros().toPlainString() : "0") + |
| | | " * " + (p.getHeight() != null ? p.getHeight().stripTrailingZeros().toPlainString() : "0")); |
| | | item.setQuantity(p.getQuantity()); |
| | | |
| | | // 面积 |
| | | BigDecimal area = p.getSettleTotalArea() != null ? p.getSettleTotalArea() : p.getActualTotalArea(); |
| | | if (area == null && p.getWidth() != null && p.getHeight() != null && p.getQuantity() != null) { |
| | | area = p.getWidth().multiply(p.getHeight()).multiply(p.getQuantity()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP); |
| | | } |
| | | item.setArea(area); |
| | | item.setRemark(p.getRemark()); |
| | | item.setProcessRequirement(p.getProcessRequirement()); |
| | | |
| | | itemDtos.add(item); |
| | | groupQty = groupQty.add(p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO); |
| | | groupArea = groupArea.add(area != null ? area : BigDecimal.ZERO); |
| | | } |
| | | |
| | | group.setItems(itemDtos); |
| | | group.setGroupTotalQuantity(groupQty); |
| | | group.setGroupTotalArea(groupArea.setScale(2, RoundingMode.HALF_UP)); |
| | | groups.add(group); |
| | | |
| | | totalQty = totalQty.add(groupQty); |
| | | totalArea = totalArea.add(groupArea); |
| | | } |
| | | dto.setGroups(groups); |
| | | dto.setTotalQuantity(totalQty); |
| | | dto.setTotalArea(totalArea.setScale(2, RoundingMode.HALF_UP)); |
| | | } |
| | | |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | if (loginUser != null && loginUser.getUser() != null) { |
| | | dto.setOrderMaker(loginUser.getUser().getNickName()); |
| | | } |
| | | dto.setExecutionDate(LocalDateTime.now()); |
| | | |
| | | return dto; |
| | | } |
| | | |
| | | private int findFirstMissingSequence(List<Integer> sequences) { |
| | | if (sequences.isEmpty()) { |
| | | return 1; |