From 7b8b2456bb15aa733b8599fce2ada5d9549ba881 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期四, 11 六月 2026 13:21:20 +0800
Subject: [PATCH] 销售台账,工艺路线配置设置是否完成;导出工艺路线
---
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 304 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 298 insertions(+), 6 deletions(-)
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index e209855..7fdb825 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -53,6 +53,7 @@
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.ISalesLedgerProcessRouteService;
+import com.ruoyi.sales.service.ISalesLedgerProcessRouteRecordService;
import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
import com.ruoyi.sales.service.ISalesLedgerProductProcessService;
import com.ruoyi.sales.service.ISalesLedgerService;
@@ -152,6 +153,7 @@
private final ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService;
private final ISalesLedgerProcessRouteService salesLedgerProcessRouteService;
+ private final ISalesLedgerProcessRouteRecordService salesLedgerProcessRouteRecordService;
private final StockInventoryService stockInventoryService;
private final StockInRecordMapper stockInRecordMapper;
@@ -754,21 +756,22 @@
@Override
@Transactional(rollbackFor = Exception.class)
- public void saleProcessBind(SalesLedgerProcessRoute salesLedgerProcessRoute) {
- if (salesLedgerProcessRoute == null) {
+ public void saleProcessBind(SalesLedgerProcessRouteDto salesLedgerProcessRouteDto) {
+ if (salesLedgerProcessRouteDto == null) {
throw new ServiceException("缁戝畾澶辫触,鏁版嵁涓嶈兘涓虹┖");
}
- SalesLedger salesLedger = baseMapper.selectById(salesLedgerProcessRoute.getSalesLedgerId());
+ SalesLedger salesLedger = baseMapper.selectById(salesLedgerProcessRouteDto.getSalesLedgerId());
if (salesLedger == null) {
throw new ServiceException("缁戝畾澶辫触,閿�鍞鍗曚笉瀛樺湪");
}
- ProcessRoute processRoute = processRouteMapper.selectById(salesLedgerProcessRoute.getProcessRouteId());
+ ProcessRoute processRoute = processRouteMapper.selectById(salesLedgerProcessRouteDto.getProcessRouteId());
if (processRoute == null) {
throw new ServiceException("缁戝畾澶辫触,宸ヨ壓璺嚎涓嶅瓨鍦�");
}
// 娓呴櫎宸茬粦瀹氱殑鏁版嵁
salesLedgerProcessRouteService.remove(new LambdaQueryWrapper<SalesLedgerProcessRoute>().eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedger.getId()));
+ salesLedgerProcessRouteRecordService.remove(new LambdaQueryWrapper<SalesLedgerProcessRouteRecord>().eq(SalesLedgerProcessRouteRecord::getSalesLedgerId, salesLedger.getId()));
// 灏嗘暟鎹縼绉诲埌sales_ledger_process_route
List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
@@ -783,6 +786,39 @@
salesLedgerProcessRouteList.add(ledgerProcessRoute);
}
salesLedgerProcessRouteService.saveBatch(salesLedgerProcessRouteList);
+
+ List<SalesLedgerProcessRoute> savedRoutes = salesLedgerProcessRouteService.list(new LambdaQueryWrapper<SalesLedgerProcessRoute>()
+ .eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedger.getId())
+ .eq(SalesLedgerProcessRoute::getProcessRouteId, processRoute.getId()));
+ Map<Long, SalesLedgerProcessRoute> routeMap = savedRoutes.stream()
+ .filter(item -> item.getProcessRouteItemId() != null)
+ .collect(Collectors.toMap(SalesLedgerProcessRoute::getProcessRouteItemId, item -> item, (a, b) -> a));
+
+ Map<Long, SalesLedgerProcessRouteRecord> inputRecordMap = new HashMap<>();
+ if (CollectionUtils.isNotEmpty(salesLedgerProcessRouteDto.getRecordList())) {
+ for (SalesLedgerProcessRouteRecord record : salesLedgerProcessRouteDto.getRecordList()) {
+ if (record != null && record.getProcessRouteItemId() != null) {
+ inputRecordMap.put(record.getProcessRouteItemId(), record);
+ }
+ }
+ }
+
+ List<SalesLedgerProcessRouteRecord> routeRecordList = new ArrayList<>();
+ for (ProcessRouteItem routeItem : routeItems) {
+ SalesLedgerProcessRoute route = routeMap.get(routeItem.getId());
+ if (route == null || route.getId() == null) {
+ continue;
+ }
+ SalesLedgerProcessRouteRecord inputRecord = inputRecordMap.get(routeItem.getId());
+ SalesLedgerProcessRouteRecord record = new SalesLedgerProcessRouteRecord();
+ record.setSalesLedgerId(salesLedger.getId());
+ record.setSalesLedgerProcessRouteId(route.getId());
+ Integer isCompleted = inputRecord != null && inputRecord.getIsCompleted() != null ? inputRecord.getIsCompleted() : 0;
+ record.setIsCompleted(isCompleted);
+ record.setCompletedTime(Objects.equals(isCompleted, 1) ? LocalDateTime.now() : null);
+ routeRecordList.add(record);
+ }
+ salesLedgerProcessRouteRecordService.saveBatch(routeRecordList);
}
/**
@@ -1175,6 +1211,11 @@
public SalesLedgerProcessRouteDto salesProcess(Long salesLedgerId) {
SalesLedgerProcessRouteDto dto = new SalesLedgerProcessRouteDto();
List<SalesLedgerProcessRoute> list = baseMapper.selectSalesProcess(salesLedgerId);
+ List<SalesLedgerProcessRouteRecord> recordList = salesLedgerProcessRouteRecordService.list(
+ new LambdaQueryWrapper<SalesLedgerProcessRouteRecord>()
+ .eq(SalesLedgerProcessRouteRecord::getSalesLedgerId, salesLedgerId)
+ .orderByAsc(SalesLedgerProcessRouteRecord::getId)
+ );
if (CollectionUtils.isNotEmpty(list)) {
Long processRouteId = list.get(0).getProcessRouteId();
ProcessRoute processRoute = processRouteMapper.selectById(processRouteId);
@@ -1201,6 +1242,17 @@
}
}
dto.setList(list);
+ if (CollectionUtils.isNotEmpty(list) && CollectionUtils.isNotEmpty(recordList)) {
+ Map<Long, Long> routeItemIdMap = list.stream()
+ .filter(item -> item.getId() != null && item.getProcessRouteItemId() != null)
+ .collect(Collectors.toMap(SalesLedgerProcessRoute::getId, SalesLedgerProcessRoute::getProcessRouteItemId, (a, b) -> a));
+ recordList.forEach(record -> {
+ if (record != null && record.getSalesLedgerProcessRouteId() != null) {
+ record.setProcessRouteItemId(routeItemIdMap.get(record.getSalesLedgerProcessRouteId()));
+ }
+ });
+ }
+ dto.setRecordList(recordList);
return dto;
}
@@ -3740,7 +3792,8 @@
.or().isNull(SalesLedger::getReviewStatus));
}
- List<SalesLedger> ledgerList = salesLedgerMapper.selectList(page, queryWrapper);
+ IPage<SalesLedger> ledgerPage = salesLedgerMapper.selectPage(page, queryWrapper);
+ List<SalesLedger> ledgerList = ledgerPage.getRecords();
// 2. 鏀堕泦鏁版嵁
List<SalesLedgerExportDto> ledgerExportList = new ArrayList<>();
@@ -3821,6 +3874,245 @@
log.error("瀵煎嚭閿�鍞彴璐﹀け璐�", e);
throw new ServiceException("瀵煎嚭澶辫触锛�" + e.getMessage());
}
+ }
+
+ @Override
+ public void exportProcessRoute(HttpServletResponse response, List<Long> salesLedgerIds, String completedTimeStart, String completedTimeEnd) {
+ try {
+ if (CollectionUtils.isEmpty(salesLedgerIds)) {
+ throw new ServiceException("璇烽�夋嫨瑕佸鍑虹殑閿�鍞彴璐�");
+ }
+ LocalDateTime startTime = parseCompletedTime(completedTimeStart);
+ LocalDateTime endTime = parseCompletedTime(completedTimeEnd);
+ if (startTime == null && endTime == null) {
+ startTime = LocalDate.now().atStartOfDay();
+ endTime = LocalDateTime.now();
+ } else {
+ if (startTime == null) {
+ startTime = LocalDate.now().atStartOfDay();
+ }
+ if (endTime == null) {
+ endTime = LocalDateTime.now();
+ }
+ }
+
+ LambdaQueryWrapper<SalesLedgerProcessRouteRecord> queryWrapper = Wrappers.<SalesLedgerProcessRouteRecord>lambdaQuery()
+ .eq(SalesLedgerProcessRouteRecord::getIsCompleted, 1)
+ .ge(SalesLedgerProcessRouteRecord::getCompletedTime, startTime)
+ .le(SalesLedgerProcessRouteRecord::getCompletedTime, endTime)
+ .orderByAsc(SalesLedgerProcessRouteRecord::getCompletedTime)
+ .orderByAsc(SalesLedgerProcessRouteRecord::getId);
+
+ if (CollectionUtils.isNotEmpty(salesLedgerIds)) {
+ queryWrapper.in(SalesLedgerProcessRouteRecord::getSalesLedgerId, salesLedgerIds);
+ }
+
+ List<SalesLedgerProcessRouteRecord> completedRoutes = salesLedgerProcessRouteRecordService.list(queryWrapper);
+ Map<Long, SalesLedger> salesLedgerMap = Collections.emptyMap();
+ Map<Long, SalesLedgerProcessRoute> routeMap = Collections.emptyMap();
+ Map<Long, ProcessRouteItem> processRouteItemMap = Collections.emptyMap();
+ Map<Long, List<SalesLedgerProduct>> productMap = Collections.emptyMap();
+
+ if (CollectionUtils.isNotEmpty(completedRoutes)) {
+ List<Long> routeSalesLedgerIds = completedRoutes.stream()
+ .map(SalesLedgerProcessRouteRecord::getSalesLedgerId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+ List<Long> salesLedgerProcessRouteIds = completedRoutes.stream()
+ .map(SalesLedgerProcessRouteRecord::getSalesLedgerProcessRouteId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+
+ if (CollectionUtils.isNotEmpty(routeSalesLedgerIds)) {
+ salesLedgerMap = salesLedgerMapper.selectBatchIds(routeSalesLedgerIds).stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toMap(SalesLedger::getId, item -> item, (a, b) -> a));
+ List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+ .in(SalesLedgerProduct::getSalesLedgerId, routeSalesLedgerIds)
+ .eq(SalesLedgerProduct::getType, 1)
+ .orderByAsc(SalesLedgerProduct::getSalesLedgerId)
+ .orderByAsc(SalesLedgerProduct::getId));
+ productMap = products.stream().collect(Collectors.groupingBy(
+ SalesLedgerProduct::getSalesLedgerId,
+ LinkedHashMap::new,
+ Collectors.toList()
+ ));
+ }
+
+ if (CollectionUtils.isNotEmpty(salesLedgerProcessRouteIds)) {
+ routeMap = salesLedgerProcessRouteService.listByIds(salesLedgerProcessRouteIds).stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toMap(SalesLedgerProcessRoute::getId, item -> item, (a, b) -> a));
+ List<Long> processRouteItemIds = routeMap.values().stream()
+ .map(SalesLedgerProcessRoute::getProcessRouteItemId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(processRouteItemIds)) {
+ processRouteItemMap = processRouteItemMapper.selectBatchIds(processRouteItemIds).stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toMap(ProcessRouteItem::getId, item -> item, (a, b) -> a));
+ }
+ }
+ }
+
+ Map<Long, List<SalesLedgerProcessRouteRecord>> routeGroupMap = new LinkedHashMap<>();
+ for (SalesLedgerProcessRouteRecord record : completedRoutes) {
+ SalesLedgerProcessRoute route = routeMap.get(record.getSalesLedgerProcessRouteId());
+ if (route == null || route.getProcessRouteItemId() == null) {
+ continue;
+ }
+ routeGroupMap.computeIfAbsent(route.getProcessRouteItemId(), k -> new ArrayList<>()).add(record);
+ }
+
+ final Map<Long, ProcessRouteItem> finalProcessRouteItemMap = processRouteItemMap;
+ LinkedHashMap<String, List<List<Object>>> sheetMap = new LinkedHashMap<>();
+ List<Long> orderedProcessRouteItemIds = routeGroupMap.keySet().stream()
+ .sorted((left, right) -> compareProcessRouteItem(left, right, finalProcessRouteItemMap))
+ .collect(Collectors.toList());
+
+ for (Long processRouteItemId : orderedProcessRouteItemIds) {
+ ProcessRouteItem processRouteItem = finalProcessRouteItemMap.get(processRouteItemId);
+ String sheetName = buildUniqueSheetName(sheetMap, processRouteItem, processRouteItemId);
+ List<List<Object>> sheetData = new ArrayList<>();
+ sheetData.add(buildProcessRouteHeader());
+
+ for (SalesLedgerProcessRouteRecord route : routeGroupMap.getOrDefault(processRouteItemId, Collections.emptyList())) {
+ SalesLedger salesLedger = salesLedgerMap.get(route.getSalesLedgerId());
+ if (salesLedger == null) {
+ continue;
+ }
+ List<SalesLedgerProduct> products = productMap.getOrDefault(salesLedger.getId(), Collections.emptyList());
+ if (CollectionUtils.isEmpty(products)) {
+ sheetData.add(buildProcessRouteRow(salesLedger, null, route));
+ continue;
+ }
+ for (SalesLedgerProduct product : products) {
+ sheetData.add(buildProcessRouteRow(salesLedger, product, route));
+ }
+ }
+
+ if (sheetData.size() == 1) {
+ sheetData.add(Arrays.asList("", "", "", "", "", "", "", "", ""));
+ }
+ sheetMap.put(sheetName, sheetData);
+ }
+
+ if (sheetMap.isEmpty()) {
+ List<List<Object>> sheetData = new ArrayList<>();
+ sheetData.add(buildProcessRouteHeader());
+ sheetData.add(Arrays.asList("", "", "", "", "", "", ""));
+ sheetMap.put("宸ヨ壓璺嚎", sheetData);
+ }
+
+ com.ruoyi.common.utils.excel.ExcelUtils.exportManySheet(response, "閿�鍞彴璐﹀伐鑹鸿矾绾垮鍑�", sheetMap);
+ } catch (Exception e) {
+ log.error("瀵煎嚭鍞悗鍙拌处宸ヨ壓璺嚎澶辫触", e);
+ throw new ServiceException("瀵煎嚭鍞悗鍙拌处宸ヨ壓璺嚎澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ private LocalDateTime parseCompletedTime(String value) {
+ if (!StringUtils.hasText(value)) {
+ return null;
+ }
+ String text = value.trim();
+ try {
+ return LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+ } catch (Exception ex) {
+ try {
+ return LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+ } catch (Exception ignored) {
+ return LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
+ }
+ }
+ }
+
+ private int compareProcessRouteItem(Long left, Long right, Map<Long, ProcessRouteItem> processRouteItemMap) {
+ ProcessRouteItem leftItem = processRouteItemMap.get(left);
+ ProcessRouteItem rightItem = processRouteItemMap.get(right);
+ int leftSort = leftItem != null && leftItem.getDragSort() != null ? leftItem.getDragSort() : Integer.MAX_VALUE;
+ int rightSort = rightItem != null && rightItem.getDragSort() != null ? rightItem.getDragSort() : Integer.MAX_VALUE;
+ if (leftSort != rightSort) {
+ return Integer.compare(leftSort, rightSort);
+ }
+ String leftName = leftItem != null && StringUtils.hasText(leftItem.getProcessName()) ? leftItem.getProcessName() : "";
+ String rightName = rightItem != null && StringUtils.hasText(rightItem.getProcessName()) ? rightItem.getProcessName() : "";
+ int nameCompare = leftName.compareTo(rightName);
+ if (nameCompare != 0) {
+ return nameCompare;
+ }
+ return Long.compare(left, right);
+ }
+
+ private List<Object> buildProcessRouteHeader() {
+ return Arrays.asList("鏃ユ湡", "璁㈠崟缂栧彿", "瀹㈡埛鍚嶇О", "瑙勬牸", "鏁伴噺", "闈㈢Н", "鏄惁鏄伐绋�");
+ }
+
+ private List<Object> buildProcessRouteRow(SalesLedger salesLedger, SalesLedgerProduct product, SalesLedgerProcessRouteRecord route) {
+ List<Object> row = new ArrayList<>();
+ row.add(salesLedger.getEntryDate() == null ? "" : DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, salesLedger.getEntryDate()));
+ row.add(salesLedger.getSalesContractNo());
+ row.add(salesLedger.getCustomerName());
+ row.add(product == null ? "" : product.getSpecificationModel());
+ row.add(product == null ? "" : product.getQuantity());
+ row.add(product == null ? "" : resolveExportArea(product));
+ row.add("");
+ return row;
+ }
+
+ private BigDecimal resolveExportArea(SalesLedgerProduct product) {
+ if (product == null) {
+ return BigDecimal.ZERO;
+ }
+ if (product.getSettleTotalArea() != null) {
+ return product.getSettleTotalArea();
+ }
+ if (product.getActualTotalArea() != null) {
+ return product.getActualTotalArea();
+ }
+ BigDecimal qty = product.getQuantity() == null ? BigDecimal.ONE : product.getQuantity();
+ if (product.getSettlePieceArea() != null) {
+ return product.getSettlePieceArea().multiply(qty).setScale(2, RoundingMode.HALF_UP);
+ }
+ if (product.getActualPieceArea() != null) {
+ return product.getActualPieceArea().multiply(qty).setScale(2, RoundingMode.HALF_UP);
+ }
+ if (product.getWidth() != null && product.getHeight() != null) {
+ BigDecimal area = product.getWidth().multiply(product.getHeight())
+ .divide(new BigDecimal("1000000"), 2, RoundingMode.HALF_UP);
+ return area.multiply(qty).setScale(2, RoundingMode.HALF_UP);
+ }
+ return BigDecimal.ZERO;
+ }
+
+ private String buildUniqueSheetName(Map<String, List<List<Object>>> sheetMap, ProcessRouteItem processRouteItem, Long processRouteItemId) {
+ String baseName = processRouteItem != null && StringUtils.hasText(processRouteItem.getProcessName())
+ ? processRouteItem.getProcessName()
+ : "宸ュ簭" + processRouteItemId;
+ baseName = sanitizeSheetName(baseName);
+ String sheetName = baseName;
+ int suffix = 2;
+ while (sheetMap.containsKey(sheetName)) {
+ String suffixText = "_" + suffix++;
+ int maxBaseLength = 31 - suffixText.length();
+ String trimmedBase = baseName.length() > maxBaseLength ? baseName.substring(0, maxBaseLength) : baseName;
+ sheetName = trimmedBase + suffixText;
+ }
+ return sheetName;
+ }
+
+ private String sanitizeSheetName(String sheetName) {
+ if (!StringUtils.hasText(sheetName)) {
+ return "宸ヨ壓璺嚎";
+ }
+ String sanitized = sheetName.replaceAll("[\\\\/?*\\[\\]:]", "_").trim();
+ if (sanitized.isEmpty()) {
+ sanitized = "宸ヨ壓璺嚎";
+ }
+ return sanitized.length() > 31 ? sanitized.substring(0, 31) : sanitized;
}
/**
@@ -3927,4 +4219,4 @@
default: return "杩涜涓�";
}
}
-}
\ No newline at end of file
+}
--
Gitblit v1.9.3