package jnpf.limsService.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import jnpf.audit.sdk.annotation.AuditLog;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import jnpf.base.UserInfo;
|
import jnpf.exception.DataException;
|
import jnpf.limsEntity.LimsWendingxingChurukuEntity;
|
import jnpf.limsEntity.LimsWendingxingChurukuSubmitParam;
|
import jnpf.limsEntity.LimsWendingxingChurukuZixiangEntity;
|
import jnpf.limsMapper.LimsWendingxingChurukuMapper;
|
import jnpf.limsMapper.LimsWendingxingChurukuZixiangMapper;
|
import jnpf.limsService.LimsWendingxingChurukuService;
|
import jnpf.util.RandomUtil;
|
import jnpf.util.UserProvider;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
|
import java.math.BigDecimal;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Locale;
|
import java.util.Map;
|
|
@Service
|
public class LimsWendingxingChurukuServiceImpl implements LimsWendingxingChurukuService {
|
|
private static final String LEIXING_RUKU = "ruku";
|
private static final String LEIXING_CHUKU = "chuku";
|
private static final String ZERO = "0";
|
|
@Autowired
|
private LimsWendingxingChurukuMapper churukuMapper;
|
|
@Autowired
|
private LimsWendingxingChurukuZixiangMapper zixiangMapper;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "CREATE", label = "稳定性出入库提交", bizType = "WENDINGXING",
|
bizCodeExpr = "#result['f_id']", targetTable = "lims_wendingxing_churuku",
|
targetIdExpr = "#result != null ? #result['f_id'] : null", diff = true,
|
entityClass = LimsWendingxingChurukuEntity.class)
|
public Map<String, Object> submit(LimsWendingxingChurukuSubmitParam param) {
|
validateParam(param);
|
UserInfo userInfo = UserProvider.getUser();
|
if (userInfo == null || !StringUtils.hasText(userInfo.getUserId())) {
|
throw new DataException("当前未登录");
|
}
|
|
Date now = new Date();
|
String churukuId = RandomUtil.uuId();
|
LimsWendingxingChurukuEntity churuku = buildChuruku(param, churukuId, userInfo, now);
|
if (churukuMapper.insert(churuku) != 1) {
|
throw new DataException("稳定性出入库主表保存失败");
|
}
|
|
Map<String, BigDecimal> balanceCache = new HashMap<>();
|
for (int i = 0; i < param.getZixiang().size(); i++) {
|
LimsWendingxingChurukuZixiangEntity zixiang = param.getZixiang().get(i);
|
saveZixiang(zixiang, i, churukuId, param.getBeizhu(), userInfo, now, balanceCache);
|
}
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
result.put("f_id", churukuId);
|
result.put("zixiang_count", param.getZixiang().size());
|
return result;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "BALANCE_SYNC", label = "同步稳定性出入库结存", bizType = "WENDINGXING",
|
bizCodeExpr = "#result > 0 ? #flowId : ''", targetTable = "lims_wendingxing_churuku_zixiang",
|
targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).firstWendingxingChurukuItemByFlow(#flowId, #flowTaskId)",
|
diff = true, entityClass = LimsWendingxingChurukuZixiangEntity.class)
|
public int recalculateByFlow(String flowId, String flowTaskId) {
|
LimsWendingxingChurukuEntity churuku = getChurukuByFlow(flowId, flowTaskId);
|
|
LambdaQueryWrapper<LimsWendingxingChurukuZixiangEntity> currentQuery = new LambdaQueryWrapper<>();
|
currentQuery.eq(LimsWendingxingChurukuZixiangEntity::getForeignId, churuku.getId())
|
.and(wrapper -> wrapper.isNull(LimsWendingxingChurukuZixiangEntity::getDeleteMark)
|
.or().ne(LimsWendingxingChurukuZixiangEntity::getDeleteMark, 1))
|
.orderByAsc(LimsWendingxingChurukuZixiangEntity::getCreatorTime)
|
.orderByAsc(LimsWendingxingChurukuZixiangEntity::getId);
|
List<LimsWendingxingChurukuZixiangEntity> currentRows = zixiangMapper.selectList(currentQuery);
|
if (currentRows.isEmpty()) {
|
throw new DataException("未找到对应的稳定性出入库子项数据");
|
}
|
|
Map<String, BigDecimal> balanceCache = new HashMap<>();
|
for (int i = 0; i < currentRows.size(); i++) {
|
recalculateZixiang(currentRows.get(i), i, churuku.getId(), balanceCache);
|
}
|
return currentRows.size();
|
}
|
|
private LimsWendingxingChurukuEntity getChurukuByFlow(String flowId, String flowTaskId) {
|
LambdaQueryWrapper<LimsWendingxingChurukuEntity> query = new LambdaQueryWrapper<>();
|
query.eq(LimsWendingxingChurukuEntity::getFlowId, flowId)
|
.eq(LimsWendingxingChurukuEntity::getFlowTaskId, flowTaskId)
|
.and(wrapper -> wrapper.isNull(LimsWendingxingChurukuEntity::getDeleteMark)
|
.or().ne(LimsWendingxingChurukuEntity::getDeleteMark, 1));
|
LimsWendingxingChurukuEntity churuku = churukuMapper.selectOne(query);
|
if (churuku == null) {
|
throw new DataException("未找到对应的稳定性出入库数据");
|
}
|
return churuku;
|
}
|
|
private void recalculateZixiang(LimsWendingxingChurukuZixiangEntity row, int index,
|
String currentForeignId, Map<String, BigDecimal> balanceCache) {
|
String zhouqiId = trim(row.getJihuaZhouqiId());
|
if (!StringUtils.hasText(zhouqiId)) {
|
throw new DataException("第" + (index + 1) + "条子项的计划周期ID(jihua_zhouqi_id)不能为空");
|
}
|
String leixing = trim(row.getChurukuLeixing()).toLowerCase(Locale.ROOT);
|
if (!LEIXING_RUKU.equals(leixing) && !LEIXING_CHUKU.equals(leixing)) {
|
throw new DataException("第" + (index + 1) + "条子项的出入库类型必须为ruku或chuku");
|
}
|
BigDecimal shuliang = parseQuantity(row.getChurukuShuliang(), index, "出入库数量");
|
if (shuliang.signum() < 0) {
|
throw new DataException("第" + (index + 1) + "条子项的出入库数量不能小于0");
|
}
|
|
BigDecimal previousBalance = balanceCache.get(zhouqiId);
|
if (previousBalance == null) {
|
previousBalance = getLatestBalance(zhouqiId, currentForeignId);
|
}
|
BigDecimal currentBalance = LEIXING_RUKU.equals(leixing)
|
? previousBalance.add(shuliang) : previousBalance.subtract(shuliang);
|
if (currentBalance.signum() < 0) {
|
throw new DataException("第" + (index + 1) + "条子项出库后结存量小于0,当前结存量为"
|
+ format(previousBalance) + ",出库数量为" + format(shuliang));
|
}
|
|
String shouruliang = LEIXING_RUKU.equals(leixing) ? format(shuliang) : ZERO;
|
String fachuliang = LEIXING_CHUKU.equals(leixing) ? format(shuliang) : ZERO;
|
LambdaUpdateWrapper<LimsWendingxingChurukuZixiangEntity> update = new LambdaUpdateWrapper<>();
|
update.eq(LimsWendingxingChurukuZixiangEntity::getId, row.getId())
|
.eq(LimsWendingxingChurukuZixiangEntity::getForeignId, currentForeignId)
|
.set(LimsWendingxingChurukuZixiangEntity::getShouruliang, shouruliang)
|
.set(LimsWendingxingChurukuZixiangEntity::getFachuliang, fachuliang)
|
.set(LimsWendingxingChurukuZixiangEntity::getJiecunliang, format(currentBalance));
|
if (zixiangMapper.update(null, update) != 1) {
|
throw new DataException("第" + (index + 1) + "条稳定性出入库子项更新失败");
|
}
|
balanceCache.put(zhouqiId, currentBalance);
|
}
|
|
private LimsWendingxingChurukuEntity buildChuruku(LimsWendingxingChurukuSubmitParam param,
|
String churukuId, UserInfo userInfo, Date now) {
|
LimsWendingxingChurukuEntity entity = new LimsWendingxingChurukuEntity();
|
entity.setId(churukuId);
|
entity.setShenqingRen(param.getShenqingRen());
|
entity.setShenqingRiqi(param.getShenqingRiqi());
|
entity.setBeizhu(param.getBeizhu());
|
entity.setBizSign(param.getBizSign());
|
entity.setTenantId("0");
|
entity.setCreatorUserId(userInfo.getUserId());
|
entity.setCreatorTime(now);
|
return entity;
|
}
|
|
private void saveZixiang(LimsWendingxingChurukuZixiangEntity entity, int index,
|
String churukuId, String beizhu, UserInfo userInfo, Date now,
|
Map<String, BigDecimal> balanceCache) {
|
if (entity == null) {
|
throw new DataException("第" + (index + 1) + "条子项不能为空");
|
}
|
String zhouqiId = trim(entity.getJihuaZhouqiId());
|
if (!StringUtils.hasText(zhouqiId)) {
|
throw new DataException("第" + (index + 1) + "条子项的计划周期ID(jihua_zhouqi_id)不能为空");
|
}
|
String leixing = trim(entity.getChurukuLeixing()).toLowerCase(Locale.ROOT);
|
if (!LEIXING_RUKU.equals(leixing) && !LEIXING_CHUKU.equals(leixing)) {
|
throw new DataException("第" + (index + 1) + "条子项的出入库类型必须为ruku或chuku");
|
}
|
BigDecimal shuliang = parseQuantity(entity.getChurukuShuliang(), index, "出入库数量");
|
if (shuliang.signum() < 0) {
|
throw new DataException("第" + (index + 1) + "条子项的出入库数量不能小于0");
|
}
|
|
BigDecimal previousBalance = balanceCache.get(zhouqiId);
|
if (previousBalance == null) {
|
previousBalance = getLatestBalance(zhouqiId);
|
}
|
BigDecimal currentBalance = LEIXING_RUKU.equals(leixing)
|
? previousBalance.add(shuliang) : previousBalance.subtract(shuliang);
|
if (currentBalance.signum() < 0) {
|
throw new DataException("第" + (index + 1) + "条子项出库后结存量小于0,当前结存量为"
|
+ format(previousBalance) + ",出库数量为" + format(shuliang));
|
}
|
|
entity.setId(RandomUtil.uuId());
|
entity.setJihuaZhouqiId(zhouqiId);
|
entity.setChurukuLeixing(leixing);
|
entity.setChurukuShuliang(format(shuliang));
|
entity.setShouruliang(LEIXING_RUKU.equals(leixing) ? format(shuliang) : ZERO);
|
entity.setFachuliang(LEIXING_CHUKU.equals(leixing) ? format(shuliang) : ZERO);
|
entity.setJiecunliang(format(currentBalance));
|
entity.setForeignId(churukuId);
|
entity.setBeizhu(beizhu);
|
entity.setTenantId(userInfo.getTenantId());
|
entity.setCreatorUserId(userInfo.getUserId());
|
entity.setCreatorTime(now);
|
if (zixiangMapper.insert(entity) != 1) {
|
throw new DataException("第" + (index + 1) + "条稳定性出入库子项保存失败");
|
}
|
balanceCache.put(zhouqiId, currentBalance);
|
}
|
|
private BigDecimal getLatestBalance(String zhouqiId) {
|
return getLatestBalance(zhouqiId, null);
|
}
|
|
private BigDecimal getLatestBalance(String zhouqiId, String excludedForeignId) {
|
LambdaQueryWrapper<LimsWendingxingChurukuZixiangEntity> query = new LambdaQueryWrapper<>();
|
query.eq(LimsWendingxingChurukuZixiangEntity::getJihuaZhouqiId, zhouqiId)
|
.and(wrapper -> wrapper.isNull(LimsWendingxingChurukuZixiangEntity::getDeleteMark)
|
.or().ne(LimsWendingxingChurukuZixiangEntity::getDeleteMark, 1));
|
if (StringUtils.hasText(excludedForeignId)) {
|
query.ne(LimsWendingxingChurukuZixiangEntity::getForeignId, excludedForeignId);
|
}
|
query.orderByDesc(LimsWendingxingChurukuZixiangEntity::getCreatorTime)
|
.orderByDesc(LimsWendingxingChurukuZixiangEntity::getId);
|
List<LimsWendingxingChurukuZixiangEntity> rows = zixiangMapper
|
.selectPage(new Page<>(1, 1, false), query)
|
.getRecords();
|
if (rows.isEmpty()) {
|
return BigDecimal.ZERO;
|
}
|
LimsWendingxingChurukuZixiangEntity row = rows.get(0);
|
return parseBalance(row.getJiecunliang(), zhouqiId);
|
}
|
|
private BigDecimal parseBalance(String value, String zhouqiId) {
|
if (!StringUtils.hasText(value)) {
|
return BigDecimal.ZERO;
|
}
|
try {
|
return new BigDecimal(value.trim());
|
} catch (NumberFormatException e) {
|
throw new DataException("计划周期" + zhouqiId + "的最新结存量格式不正确:" + value);
|
}
|
}
|
|
private BigDecimal parseQuantity(String value, int index, String fieldName) {
|
if (!StringUtils.hasText(value)) {
|
throw new DataException("第" + (index + 1) + "条子项的" + fieldName + "(churuku_shuliang)不能为空");
|
}
|
try {
|
return new BigDecimal(value.trim());
|
} catch (NumberFormatException e) {
|
throw new DataException("第" + (index + 1) + "条子项的" + fieldName + "格式不正确:" + value);
|
}
|
}
|
|
private void validateParam(LimsWendingxingChurukuSubmitParam param) {
|
if (param == null) {
|
throw new DataException("提交数据不能为空");
|
}
|
if (param.getZixiang() == null || param.getZixiang().isEmpty()) {
|
throw new DataException("出入库子项(zixiang)不能为空");
|
}
|
}
|
|
private String trim(String value) {
|
return value == null ? "" : value.trim();
|
}
|
|
private String format(BigDecimal value) {
|
return value.stripTrailingZeros().toPlainString();
|
}
|
}
|