From 10b88a7ff17caf92f3d4e8a550c1085a70c2517a Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 28 五月 2026 17:43:26 +0800
Subject: [PATCH] Merge dev_New_pro into dev_山西_晋和园_pro

---
 src/test/java/com/ruoyi/stock/service/impl/StockOutRecordBatchUpdateTest.java |  254 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 254 insertions(+), 0 deletions(-)

diff --git a/src/test/java/com/ruoyi/stock/service/impl/StockOutRecordBatchUpdateTest.java b/src/test/java/com/ruoyi/stock/service/impl/StockOutRecordBatchUpdateTest.java
new file mode 100644
index 0000000..352818d
--- /dev/null
+++ b/src/test/java/com/ruoyi/stock/service/impl/StockOutRecordBatchUpdateTest.java
@@ -0,0 +1,254 @@
+package com.ruoyi.stock.service.impl;
+
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionOrderPickMapper;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionOrderPick;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.pojo.SalesLedger;
+import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
+import com.ruoyi.stock.pojo.StockOutRecord;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@SpringBootTest
+public class StockOutRecordBatchUpdateTest {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Autowired
+    private StockOutRecordMapper stockOutRecordMapper;
+
+    @Autowired
+    private PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
+
+    @Autowired
+    private ShippingInfoMapper shippingInfoMapper;
+
+    @Autowired
+    private SalesLedgerMapper salesLedgerMapper;
+
+    @Autowired
+    private ProductionOrderPickMapper productionOrderPickMapper;
+
+    @Autowired
+    private ProductionOrderMapper productionOrderMapper;
+
+    /**
+     * 鏇存柊鍑哄簱鍗曟椂闂�
+     */
+    @Test
+    void testUpdateStockOutRecords() {
+        List<StockOutRecord> allRecords = stockOutRecordMapper.selectList(null);
+        System.out.println("鎬昏褰曟暟: " + allRecords.size());
+
+        List<RecordWithDate> recordWithDates = new ArrayList<>();
+
+        for (StockOutRecord record : allRecords) {
+            String type = record.getRecordType();
+            if (type == null) continue;
+
+            switch (type) {
+                case "1":
+                case "10":
+                    recordWithDates.add(resolveType1or10(record, type));
+                    break;
+                case "3":
+                    System.out.println("绫诲瀷3锛堢敓浜ф姤宸�-鍑哄簱锛夐鐣欏垎鏀紝褰撳墠鏃犳暟鎹紝璺宠繃");
+                    break;
+                case "8":
+                    System.out.println("绫诲瀷8锛堥攢鍞�-鍑哄簱锛夐鐣欏垎鏀紝褰撳墠鏃犳暟鎹紝璺宠繃");
+                    break;
+                case "9":
+                    recordWithDates.add(resolveType9(record));
+                    break;
+                case "13":
+                    recordWithDates.add(resolveType13(record));
+                    break;
+                case "14":
+                    recordWithDates.add(resolveType14or15(record));
+                    break;
+                case "15":
+                    recordWithDates.add(resolveType14or15(record));
+                    break;
+                default:
+                    System.out.println("鏈煡绫诲瀷 " + type + "锛岃烦杩� ID=" + record.getId());
+            }
+        }
+
+        Map<LocalDate, List<RecordWithDate>> byDate = recordWithDates.stream()
+                .collect(Collectors.groupingBy(
+                        rwd -> rwd.dateTime.toLocalDate(),
+                        LinkedHashMap::new,
+                        Collectors.toList()
+                ));
+
+        int totalUpdated = 0;
+        for (Map.Entry<LocalDate, List<RecordWithDate>> dateEntry : byDate.entrySet()) {
+            LocalDate date = dateEntry.getKey();
+            List<RecordWithDate> records = dateEntry.getValue();
+            records.sort(Comparator.comparing(rwd -> rwd.dateTime));
+
+            assignRandomTimes(records, date);
+
+            records.sort(Comparator.comparing(rwd -> rwd.dateTime));
+
+            int seq = 1;
+            for (RecordWithDate rwd : records) {
+                StockOutRecord record = rwd.record;
+                String type = record.getRecordType();
+                String batchNo = "CK" + date.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + String.format("%03d", seq++);
+                LocalDateTime createTime = rwd.dateTime;
+
+                jdbcTemplate.update(
+                        "UPDATE stock_out_record SET outbound_batches = ?, create_time = ?, update_time = ? WHERE id = ?",
+                        batchNo, createTime, createTime, record.getId());
+
+                System.out.println("ID=" + record.getId()
+                        + " type=" + type
+                        + " batch=" + batchNo
+                        + " time=" + createTime);
+                totalUpdated++;
+            }
+        }
+
+        System.out.println("鍏ㄩ儴瀹屾垚锛佸叡鏇存柊 " + totalUpdated + " 鏉¤褰�");
+    }
+
+    private void assignRandomTimes(List<RecordWithDate> records, LocalDate date) {
+        List<RecordWithDate> individual = new ArrayList<>();
+        Map<Long, List<RecordWithDate>> grouped = new LinkedHashMap<>();
+
+        for (RecordWithDate rwd : records) {
+            String type = rwd.record.getRecordType();
+            if (!"1".equals(type) && !"9".equals(type) && !"10".equals(type)
+                    && !"13".equals(type) && !"14".equals(type) && !"15".equals(type)) {
+                continue;
+            }
+            if (("14".equals(type) || "15".equals(type)) && rwd.record.getRecordId() != null) {
+                grouped.computeIfAbsent(rwd.record.getRecordId(), k -> new ArrayList<>()).add(rwd);
+            } else {
+                individual.add(rwd);
+            }
+        }
+
+        List<TimeSlot> slots = new ArrayList<>();
+        for (RecordWithDate rwd : individual) {
+            slots.add(new TimeSlot(rwd.record.getId(), List.of(rwd)));
+        }
+        for (Map.Entry<Long, List<RecordWithDate>> entry : grouped.entrySet()) {
+            long minId = entry.getValue().stream()
+                    .mapToLong(rwd -> rwd.record.getId())
+                    .min().orElse(0);
+            slots.add(new TimeSlot(minId, entry.getValue()));
+        }
+
+        if (slots.isEmpty()) return;
+
+        slots.sort(Comparator.comparingLong(s -> s.sortKey));
+
+        int totalMinutes = 480;
+        for (int i = 0; i < slots.size(); i++) {
+            int offsetMinutes = (int) ((long) i * totalMinutes / slots.size());
+            int jitter = (int) (Math.random() * 6 - 3);
+            offsetMinutes = Math.max(0, Math.min(479, offsetMinutes + jitter));
+
+            LocalTime time;
+            if (offsetMinutes < 240) {
+                time = LocalTime.of(8, 0).plusMinutes(offsetMinutes);
+            } else {
+                time = LocalTime.of(14, 0).plusMinutes(offsetMinutes - 240);
+            }
+            LocalDateTime dt = LocalDateTime.of(date, time);
+            for (RecordWithDate rwd : slots.get(i).members) {
+                rwd.dateTime = dt;
+            }
+        }
+    }
+
+    private static class TimeSlot {
+        final long sortKey;
+        final List<RecordWithDate> members;
+
+        TimeSlot(long sortKey, List<RecordWithDate> members) {
+            this.sortKey = sortKey;
+            this.members = members;
+        }
+    }
+
+    private RecordWithDate resolveType1or10(StockOutRecord record, String type) {
+        LocalDate date = record.getCreateTime() != null
+                ? record.getCreateTime().toLocalDate()
+                : LocalDate.now();
+        return new RecordWithDate(record, LocalDateTime.of(date, LocalTime.of(8, 0)));
+    }
+
+    private RecordWithDate resolveType9(StockOutRecord record) {
+        Long recordId = record.getRecordId();
+        if (recordId != null) {
+            PurchaseReturnOrders pro = purchaseReturnOrdersMapper.selectById(recordId);
+            if (pro != null && pro.getPreparedAt() != null) {
+                return new RecordWithDate(record, LocalDateTime.of(pro.getPreparedAt(), LocalTime.of(8, 0)));
+            }
+        }
+        return fallbackDateTime(record);
+    }
+
+    private RecordWithDate resolveType13(StockOutRecord record) {
+        Long recordId = record.getRecordId();
+        if (recordId != null) {
+            ShippingInfo shippingInfo = shippingInfoMapper.selectById(recordId);
+            if (shippingInfo != null && shippingInfo.getSalesLedgerId() != null) {
+                SalesLedger salesLedger = salesLedgerMapper.selectById(shippingInfo.getSalesLedgerId());
+                if (salesLedger != null && salesLedger.getDeliveryDate() != null) {
+                    return new RecordWithDate(record, LocalDateTime.of(salesLedger.getDeliveryDate(), LocalTime.of(8, 0)));
+                }
+            }
+        }
+        return fallbackDateTime(record);
+    }
+
+    private RecordWithDate resolveType14or15(StockOutRecord record) {
+        Long recordId = record.getRecordId();
+        if (recordId != null) {
+            ProductionOrderPick pick = productionOrderPickMapper.selectById(recordId);
+            if (pick != null && pick.getProductionOrderId() != null) {
+                ProductionOrder order = productionOrderMapper.selectById(pick.getProductionOrderId());
+                if (order != null && order.getStartTime() != null) {
+                    return new RecordWithDate(record, LocalDateTime.of(order.getStartTime().toLocalDate(), LocalTime.of(8, 0)));
+                }
+            }
+        }
+        return fallbackDateTime(record);
+    }
+
+    private RecordWithDate fallbackDateTime(StockOutRecord record) {
+        return record.getCreateTime() != null
+                ? new RecordWithDate(record, record.getCreateTime())
+                : new RecordWithDate(record, LocalDateTime.now());
+    }
+
+    private static class RecordWithDate {
+        final StockOutRecord record;
+        LocalDateTime dateTime;
+
+        RecordWithDate(StockOutRecord record, LocalDateTime dateTime) {
+            this.record = record;
+            this.dateTime = dateTime;
+        }
+    }
+}

--
Gitblit v1.9.3