package com.vincent.rsf.server.manager.schedules;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.vincent.rsf.framework.exception.CoolException;
|
import com.vincent.rsf.server.manager.entity.AsnOrderItemLog;
|
import com.vincent.rsf.server.manager.entity.AsnOrderLog;
|
import com.vincent.rsf.server.manager.entity.Matnr;
|
import com.vincent.rsf.server.manager.service.AsnOrderItemLogService;
|
import com.vincent.rsf.server.manager.service.AsnOrderLogService;
|
import com.vincent.rsf.server.manager.service.MatnrService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Component;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.text.SimpleDateFormat;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
/**
|
* ASN 单据压测数据定时生成器。
|
*/
|
@Slf4j
|
@Component
|
public class AsnOrderPressureSchedules {
|
|
private static final DateTimeFormatter ORDER_CODE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
private static final String ORDER_TYPE = "in";
|
private static final String ORDER_WORK_TYPE = "71";
|
private static final Integer TENANT_ID = 1;
|
private static final Long USER_ID = 51L;
|
private static final String MEMO = "ASN_PRESSURE_TEST";
|
private final AtomicBoolean running = new AtomicBoolean(false);
|
|
@Autowired
|
private AsnOrderLogService asnOrderLogService;
|
@Autowired
|
private AsnOrderItemLogService asnOrderItemLogService;
|
@Autowired
|
private MatnrService matnrService;
|
|
@Value("${pressure.asn-order.enabled:false}")
|
private boolean enabled;
|
|
@Value("${pressure.asn-order.order-count-per-run:20}")
|
private int orderCountPerRun;
|
|
@Value("${pressure.asn-order.item-count-per-order:5}")
|
private int itemCountPerOrder;
|
|
@Value("${pressure.asn-order.item-qty:10}")
|
private double itemQty;
|
|
@Scheduled(cron = "${pressure.asn-order.cron:0/10 * * * * ?}")
|
@Transactional(rollbackFor = Exception.class)
|
public void insertPressureOrders() {
|
if (!enabled) {
|
return;
|
}
|
if (!running.compareAndSet(false, true)) {
|
log.warn("ASN压测任务仍在执行中,本轮跳过");
|
return;
|
}
|
try {
|
if (orderCountPerRun <= 0 || itemCountPerOrder <= 0 || itemQty <= 0) {
|
log.warn("ASN压测任务配置无效,跳过执行: orderCountPerRun={}, itemCountPerOrder={}, itemQty={}",
|
orderCountPerRun, itemCountPerOrder, itemQty);
|
return;
|
}
|
|
List<Matnr> matnrs = loadMatnrs();
|
if (matnrs.isEmpty()) {
|
log.warn("ASN压测任务未获取到可用物料,跳过执行");
|
return;
|
}
|
Collections.shuffle(matnrs);
|
|
Date now = new Date();
|
LocalDateTime nowTime = LocalDateTime.now();
|
double totalQty = itemCountPerOrder * itemQty;
|
|
List<AsnOrderLog> orders = new ArrayList<>(orderCountPerRun);
|
for (int i = 0; i < orderCountPerRun; i++) {
|
orders.add(buildOrder(now, nowTime, totalQty, i));
|
}
|
if (!asnOrderLogService.saveBatch(orders, 200)) {
|
throw new CoolException("ASN压测主单插入失败");
|
}
|
|
List<AsnOrderLog> persistedOrders = asnOrderLogService.list(new LambdaQueryWrapper<AsnOrderLog>()
|
.in(AsnOrderLog::getCode, extractOrderCodes(orders)));
|
Map<String, AsnOrderLog> orderMap = new HashMap<>(persistedOrders.size());
|
for (AsnOrderLog order : persistedOrders) {
|
orderMap.put(order.getCode(), order);
|
}
|
|
List<AsnOrderItemLog> items = new ArrayList<>(orderCountPerRun * itemCountPerOrder);
|
for (int orderIndex = 0; orderIndex < orders.size(); orderIndex++) {
|
AsnOrderLog order = orderMap.get(orders.get(orderIndex).getCode());
|
if (order == null) {
|
throw new CoolException("ASN压测主单回查失败");
|
}
|
for (int itemIndex = 0; itemIndex < itemCountPerOrder; itemIndex++) {
|
Matnr matnr = matnrs.get((orderIndex * itemCountPerOrder + itemIndex) % matnrs.size());
|
items.add(buildOrderItem(order, matnr, now, orderIndex, itemIndex));
|
}
|
}
|
if (!asnOrderItemLogService.saveBatch(items, 500)) {
|
throw new CoolException("ASN压测明细插入失败");
|
}
|
|
log.info("ASN压测任务执行完成,本次插入主单 {} 条,明细 {} 条", orders.size(), items.size());
|
} finally {
|
running.set(false);
|
}
|
}
|
|
private List<Matnr> loadMatnrs() {
|
int needCount = Math.min(Math.max(orderCountPerRun * itemCountPerOrder, 200), 2000);
|
return matnrService.list(new LambdaQueryWrapper<Matnr>()
|
.eq(Matnr::getDeleted, 0)
|
.eq(Matnr::getStatus, 1)
|
.select(Matnr::getId, Matnr::getCode, Matnr::getName, Matnr::getFieldsIndex,
|
Matnr::getSpec, Matnr::getModel, Matnr::getUnit, Matnr::getPurUnit,
|
Matnr::getStockUnit, Matnr::getBaseUnit, Matnr::getUseOrgId,
|
Matnr::getUseOrgName, Matnr::getErpClsId)
|
.orderByDesc(Matnr::getId)
|
.last("limit " + needCount));
|
}
|
|
private List<String> extractOrderCodes(List<AsnOrderLog> orders) {
|
List<String> codes = new ArrayList<>(orders.size());
|
for (AsnOrderLog order : orders) {
|
codes.add(order.getCode());
|
}
|
return codes;
|
}
|
|
private AsnOrderLog buildOrder(Date now, LocalDateTime nowTime, double totalQty, int sequence) {
|
String suffix = String.format("%04d", sequence + 1);
|
String code = "erp" + nowTime.format(ORDER_CODE_FORMATTER) + suffix;
|
long serialNo = System.currentTimeMillis() * 1000 + sequence;
|
|
AsnOrderLog order = new AsnOrderLog();
|
order.setCode(code);
|
order.setPoCode(code);
|
order.setPoId(serialNo);
|
order.setType(ORDER_TYPE);
|
order.setWkType(ORDER_WORK_TYPE);
|
order.setAnfme(totalQty);
|
order.setQty(totalQty);
|
order.setRleStatus((short) 0);
|
order.setNtyStatus((short) 0);
|
order.setExceStatus((short) 4);
|
order.setStatus(1);
|
order.setDeleted(0);
|
order.setTenantId(TENANT_ID);
|
order.setCreateBy(USER_ID);
|
order.setCreateTime(now);
|
order.setUpdateBy(USER_ID);
|
order.setUpdateTime(now);
|
order.setMemo(MEMO);
|
return order;
|
}
|
|
private AsnOrderItemLog buildOrderItem(AsnOrderLog order, Matnr matnr, Date now, int orderIndex, int itemIndex) {
|
String stockUnit = StringUtils.firstNonBlank(matnr.getStockUnit(), matnr.getPurUnit(), matnr.getUnit(), matnr.getBaseUnit());
|
String purUnit = StringUtils.firstNonBlank(matnr.getPurUnit(), matnr.getUnit(), matnr.getStockUnit(), matnr.getBaseUnit());
|
String batchCode = "B" + new SimpleDateFormat("yyyyMMddHHmmss").format(now)
|
+ String.format("%02d%02d", orderIndex + 1, itemIndex + 1);
|
String trackCode = "T" + System.currentTimeMillis() + String.format("%02d%02d", orderIndex + 1, itemIndex + 1);
|
|
return new AsnOrderItemLog()
|
.setLogId(order.getId())
|
.setAsnId(order.getAsnId())
|
.setAsnCode(order.getCode())
|
.setPlatItemId("M" + (itemIndex + 1))
|
.setPoCode(order.getPoCode())
|
.setFieldsIndex(matnr.getFieldsIndex())
|
.setMatnrId(matnr.getId())
|
.setMatnrCode(matnr.getCode())
|
.setMaktx(matnr.getName())
|
.setAnfme(itemQty)
|
.setPurQty(itemQty)
|
.setQty(itemQty)
|
.setStockUnit(stockUnit)
|
.setPurUnit(purUnit)
|
.setSplrBatch(batchCode)
|
.setSplrCode("gongys1")
|
.setSplrName("供应商1")
|
.setTrackCode(trackCode)
|
.setBarcode(trackCode)
|
.setNtyStatus((short) 0)
|
.setStatus(1)
|
.setDeleted(0)
|
.setTenantId(TENANT_ID)
|
.setCreateBy(USER_ID)
|
.setCreateTime(now)
|
.setUpdateBy(USER_ID)
|
.setUpdateTime(now)
|
.setMemo(MEMO);
|
}
|
}
|