yuan
7 天以前 dd3c0399c9f3c2e70bfd0072cddadcd8d34f18bb
测试类
已添加2个文件
已修改1个文件
372 ■■■■■ 文件已修改
.gitignore 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/ruoyi/approve/service/impl/ApproveProcessIdModifyTest.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/ruoyi/stock/service/impl/StockOutRecordBatchUpdateTest.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -6,7 +6,6 @@
!gradle/wrapper/gradle-wrapper.jar
claude.md
target/
test/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
src/test/java/com/ruoyi/approve/service/impl/ApproveProcessIdModifyTest.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,117 @@
package com.ruoyi.approve.service.impl;
import com.ruoyi.approve.mapper.ApproveNodeMapper;
import com.ruoyi.approve.mapper.ApproveProcessMapper;
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.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class ApproveProcessIdModifyTest {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private ApproveProcessMapper approveProcessMapper;
    @Autowired
    private ApproveNodeMapper approveNodeMapper;
    /**
     * ä¿®æ”¹å®¡æ‰¹æµç¨‹ç¼–号
     */
    @Test
    void testModifyApproveId() {
        Map<String, String> modifyMap = new LinkedHashMap<>();
        modifyMap.put("20260523020", "2026-05-09");
        modifyMap.put("20260523019", "2026-04-29");
        modifyMap.put("20260523018", "2026-04-16");
        modifyMap.put("20260523009", "2026-05-07");
        modifyMap.put("20260523008", "2026-04-11");
        modifyMap.put("20260523007", "2026-04-10");
        modifyMap.put("20260523006", "2026-04-07");
        modifyMap.put("20260523003", "2026-04-07");
        for (Map.Entry<String, String> entry : modifyMap.entrySet()) {
            processOne(entry.getKey(), entry.getValue());
        }
        System.out.println("全部完成!");
    }
    private void processOne(String oldApproveId, String targetDateStr) {
        LocalDate targetDate = LocalDate.parse(targetDateStr);
        String datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String maxId = jdbcTemplate.queryForObject(
                "SELECT MAX(approve_id) FROM approve_process WHERE approve_id LIKE ?",
                String.class, datePrefix + "%");
        long nextSeq = 1;
        if (maxId != null && maxId.length() >= 11) {
            nextSeq = Long.parseLong(maxId.substring(8)) + 1;
        }
        String newApproveId = datePrefix + String.format("%03d", nextSeq);
        System.out.println("旧批号: " + oldApproveId + " -> æ–°æ‰¹å·: " + newApproveId);
        List<Map<String, Object>> processList = jdbcTemplate.queryForList(
                "SELECT * FROM approve_process WHERE approve_id = ?", oldApproveId);
        if (processList.isEmpty()) {
            System.out.println("  âš  æœªæ‰¾åˆ°è®°å½•,跳过");
            return;
        }
        Map<String, Object> process = processList.get(0);
        Timestamp newApproveTime = replaceDate(process.get("approve_time"), targetDate);
        Timestamp newApproveOverTime = replaceDate(process.get("approve_over_time"), targetDate);
        Timestamp newCreateTime = replaceDate(process.get("create_time"), targetDate);
        jdbcTemplate.update(
                "UPDATE approve_process SET approve_id = ?, approve_time = ?, approve_over_time = ?, create_time = ? WHERE approve_id = ?",
                newApproveId, newApproveTime, newApproveOverTime, newCreateTime, oldApproveId);
        System.out.println("  âœ“ approve_process å·²æ›´æ–°");
        List<Map<String, Object>> nodeList = jdbcTemplate.queryForList(
                "SELECT * FROM approve_node WHERE approve_process_id = ?", oldApproveId);
        if (!nodeList.isEmpty()) {
            Map<String, Object> node = nodeList.get(0);
            Timestamp newNodeTime = replaceDate(node.get("approve_node_time"), targetDate);
            Timestamp newNodeCreateTime = replaceDate(node.get("create_time"), targetDate);
            Timestamp newNodeUpdateTime = replaceDate(node.get("update_time"), targetDate);
            jdbcTemplate.update(
                    "UPDATE approve_node SET approve_process_id = ?, approve_node_time = ?, create_time = ?, update_time = ? WHERE approve_process_id = ?",
                    newApproveId, newNodeTime, newNodeCreateTime, newNodeUpdateTime, oldApproveId);
            System.out.println("  âœ“ approve_node å·²æ›´æ–° (" + nodeList.size() + " æ¡)");
        } else {
            System.out.println("  - approve_node æ— è®°å½•");
        }
    }
    private static Timestamp replaceDate(Object dateObj, LocalDate targetDate) {
        if (dateObj == null) return null;
        LocalDateTime ldt;
        if (dateObj instanceof Timestamp ts) {
            ldt = ts.toLocalDateTime();
        } else if (dateObj instanceof LocalDateTime dt) {
            ldt = dt;
        } else {
            return null;
        }
        return Timestamp.valueOf(LocalDateTime.of(targetDate, ldt.toLocalTime()));
    }
}
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;
        }
    }
}