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 jnpf.base.ActionResult;
|
import jnpf.base.BillRuleApi;
|
import jnpf.base.UserInfo;
|
import jnpf.base.service.SuperServiceImpl;
|
import jnpf.exception.DataException;
|
import jnpf.limsEntity.LimsHaocaiChukuEntity;
|
import jnpf.limsEntity.LimsHaocaiChukuShenqingEntity;
|
import jnpf.limsEntity.LimsHaocaiChukuShenqingZixiangEntity;
|
import jnpf.limsEntity.LimsHaocaiChukuZixiangEntity;
|
import jnpf.limsEntity.LimsHaocaiJiechuEntity;
|
import jnpf.limsEntity.LimsHaocaiLogEntity;
|
import jnpf.limsEntity.LimsHaocaiRukuEntity;
|
import jnpf.limsEntity.LimsHaocaiRukuSubmitResult;
|
import jnpf.limsEntity.LimsHaocaiRukuYanshouEntity;
|
import jnpf.limsEntity.LimsHaocaiRukuZixiangEntity;
|
import jnpf.limsEntity.LimsHaocaiXiaohuiShenqingEntity;
|
import jnpf.limsEntity.LimsHaocaiXiaohuiShenqingZixiangEntity;
|
import jnpf.limsEntity.LimsHaocaiYanshouShenqingEntity;
|
import jnpf.limsMapper.LimsHaocaiChukuShenqingMapper;
|
import jnpf.limsMapper.LimsHaocaiChukuShenqingZixiangMapper;
|
import jnpf.limsMapper.LimsHaocaiChukuZixiangMapper;
|
import jnpf.limsMapper.LimsHaocaiJiechuMapper;
|
import jnpf.limsMapper.LimsHaocaiLogMapper;
|
import jnpf.limsMapper.LimsHaocaiRukuMapper;
|
import jnpf.limsMapper.LimsHaocaiRukuYanshouMapper;
|
import jnpf.limsMapper.LimsHaocaiRukuZixiangMapper;
|
import jnpf.limsMapper.LimsHaocaiXiaohuiShenqingMapper;
|
import jnpf.limsMapper.LimsHaocaiXiaohuiShenqingZixiangMapper;
|
import jnpf.limsMapper.LimsHaocaiYanshouShenqingMapper;
|
import jnpf.limsService.LimsHaocaiService;
|
import jnpf.util.RandomUtil;
|
import jnpf.util.StringUtil;
|
import jnpf.util.UserProvider;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* 耗材业务服务实现。子表 lims_haocai_ruku_zixiang 不单设 service,
|
* 经 Mapper 直接读写(平台 ProductServiceImpl 同款模式)。
|
*/
|
@Slf4j
|
@Service
|
public class LimsHaocaiServiceImpl
|
extends SuperServiceImpl<LimsHaocaiRukuMapper, LimsHaocaiRukuEntity>
|
implements LimsHaocaiService {
|
|
/** 条码编码的单据规则 enCode(base_bill_rule,HC_ + YYYYMMDD + 6位流水) */
|
private static final String TIAOMA_BILL_RULE = "haocai_ruku_tiaoma";
|
|
/** 子表初始状态:未出库 */
|
private static final String BIZ_STATUS_WEICHUKU = "weichuku";
|
|
/** 子表状态:已出库 */
|
private static final String BIZ_STATUS_YICHUKU = "yichuku";
|
|
/** 子表状态:已开瓶 */
|
private static final String BIZ_STATUS_YIKAIPING = "yikaiping";
|
|
/** 子表状态:已销毁 */
|
private static final String BIZ_STATUS_YIXIAOHUI = "yixiaohui";
|
|
/** 子表状态:待销毁 */
|
private static final String BIZ_STATUS_DAIXIAOHUI = "daixiaohui";
|
|
/** 申领流程状态:已通过 */
|
private static final int FLOW_STATE_APPROVED = 2;
|
|
/** 借出单状态:已借出 */
|
private static final String JIECHU_STATUS_LENT = "lent";
|
|
/** 借出单状态:已归还 */
|
private static final String JIECHU_STATUS_RETURNED = "returned";
|
|
/** 耗材日志操作类型:入库 */
|
private static final String LOG_ACTION_RUKU = "耗材入库";
|
|
/** 耗材日志操作类型:借出 */
|
private static final String LOG_ACTION_JIECHU = "耗材借出";
|
|
/** 耗材日志操作类型:归还 */
|
private static final String LOG_ACTION_GUIHUAN = "耗材归还";
|
|
/** 耗材日志操作类型:出库 */
|
private static final String LOG_ACTION_CHUKU = "耗材出库";
|
|
/** 耗材日志操作类型:销毁 */
|
private static final String LOG_ACTION_XIAOHUI = "耗材销毁";
|
|
/** 验收状态:已验收 */
|
private static final String YANSHOU_STATUS_YIYANSHOU = "yiyanshou";
|
|
/** 验收状态:不适用 */
|
private static final String YANSHOU_STATUS_NA = "na";
|
|
/** 耗材验收申请状态:待验收 */
|
private static final String YANSHOU_SHENQING_STATUS_DAIYANSHOU = "daiyanshou";
|
|
/** 耗材验收申请状态:验收中 */
|
private static final String YANSHOU_SHENQING_STATUS_YANSHOUZHONG = "yanshouzhong";
|
|
/** 耗材验收申请状态:已验收 */
|
private static final String YANSHOU_SHENQING_STATUS_YIYANSHOU = "yiyanshou";
|
|
@Autowired
|
private BillRuleApi billRuleApi;
|
|
@Autowired
|
private LimsHaocaiRukuZixiangMapper zixiangMapper;
|
|
@Autowired
|
private LimsHaocaiJiechuMapper jiechuMapper;
|
|
@Autowired
|
private LimsHaocaiChukuShenqingMapper chukuShenqingMapper;
|
|
@Autowired
|
private LimsHaocaiChukuShenqingZixiangMapper chukuShenqingZixiangMapper;
|
|
@Autowired
|
private LimsHaocaiChukuZixiangMapper chukuZixiangMapper;
|
|
@Autowired
|
private LimsHaocaiLogMapper haocaiLogMapper;
|
|
@Autowired
|
private LimsHaocaiXiaohuiShenqingMapper xiaohuiShenqingMapper;
|
|
@Autowired
|
private LimsHaocaiXiaohuiShenqingZixiangMapper xiaohuiShenqingZixiangMapper;
|
|
@Autowired
|
private LimsHaocaiYanshouShenqingMapper yanshouShenqingMapper;
|
|
@Autowired
|
private LimsHaocaiRukuYanshouMapper rukuYanshouMapper;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "RUKU_SUBMIT", label = "耗材入库提交", bizType = "HAOCAI",
|
bizCodeExpr = "", bizCodeRequired = false, targetTable = "lims_haocai_ruku",
|
targetIdExpr = "#ruku.id", diff = true, entityClass = LimsHaocaiRukuEntity.class)
|
public LimsHaocaiRukuSubmitResult submitRuku(LimsHaocaiRukuEntity ruku) throws DataException {
|
BigDecimal shuliang = parseShuliang(ruku.getRukuShuliang());
|
BigDecimal rongliang = parseRongliang(ruku.getRongliang());
|
String yanshouZhuangtai = resolveYanshouZhuangtai(ruku);
|
ruku.setYanshouZhuangtai(yanshouZhuangtai);
|
ruku.setBizStatus(BIZ_STATUS_WEICHUKU);
|
if (!this.updateById(ruku)) {
|
throw new DataException("入库单状态更新失败:" + ruku.getId());
|
}
|
if (isYanshouEnabled(ruku)) {
|
updateRukuYanshouRukuId(ruku);
|
}
|
|
boolean yigeTiaoma = "yes".equalsIgnoreCase(trimToEmpty(ruku.getShifouYigeTiaoma()));
|
int completeCount = calculateCompleteTiaomaCount(shuliang, ruku.getRukuShuliang());
|
BigDecimal fractionalQuantity = shuliang.remainder(BigDecimal.ONE);
|
int count = yigeTiaoma ? 1 : completeCount + (fractionalQuantity.signum() > 0 ? 1 : 0);
|
// 一个条码:总量 = 入库数量 × 容量;多个条码:整数部分每条为容量,小数部分按比例生成最后一条。
|
BigDecimal singleTiaomaZongliang = rongliang.multiply(shuliang);
|
|
// 编号 = 批号 + "-" + 序号,序号按本批总条数动态补零(3→1位、20→2位、100→3位),
|
// 数量多大都自适应;批号为空时回退用主表 id,避免编号缺前缀
|
String bianhaoPrefix = trimToEmpty(ruku.getPihao());
|
if (bianhaoPrefix.isEmpty()) {
|
bianhaoPrefix = ruku.getId();
|
}
|
int width = String.valueOf(count).length();
|
List<String> tiaomaBianmaList = new ArrayList<>(count);
|
List<String> bianhaoList = new ArrayList<>(count);
|
for (int i = 1; i <= count; i++) {
|
String tiaomaBianma = nextTiaomaBianma();
|
String bianhao = bianhaoPrefix + "-" + String.format("%0" + width + "d", i);
|
BigDecimal zongliang = yigeTiaoma
|
? singleTiaomaZongliang
|
: (i > completeCount ? rongliang.multiply(fractionalQuantity) : rongliang);
|
tiaomaBianmaList.add(tiaomaBianma);
|
bianhaoList.add(bianhao);
|
LimsHaocaiRukuZixiangEntity zixiang =
|
buildZixiang(ruku, tiaomaBianma, bianhao, toPlainString(zongliang), yanshouZhuangtai);
|
zixiangMapper.insert(zixiang);
|
haocaiLogMapper.insert(buildRukuLog(ruku, zixiang));
|
}
|
|
log.info("耗材入库提交完成:rukuId={}, tiaomaList={}, count={}, rukuShuliang={}",
|
ruku.getId(), tiaomaBianmaList, count, ruku.getRukuShuliang());
|
|
LimsHaocaiRukuSubmitResult result = new LimsHaocaiRukuSubmitResult();
|
result.setTiaomaBianma(tiaomaBianmaList.isEmpty() ? null : tiaomaBianmaList.get(0));
|
result.setTiaomaBianmaList(tiaomaBianmaList);
|
result.setBianhaoList(bianhaoList);
|
result.setCount(count);
|
return result;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "JIECHU_SUBMIT", label = "耗材借出提交", bizType = "HAOCAI",
|
bizCodeExpr = "", bizCodeRequired = false, targetTable = "lims_haocai_jiechu",
|
targetIdExpr = "#jiechu.id", diff = true, entityClass = LimsHaocaiJiechuEntity.class)
|
public void submitJiechu(LimsHaocaiJiechuEntity jiechu) throws DataException {
|
String tiaomaBianma = trimToEmpty(jiechu == null ? null : jiechu.getTiaomaBianma());
|
if (tiaomaBianma.isEmpty()) {
|
throw new DataException("条码编码不能为空");
|
}
|
|
List<LimsHaocaiRukuZixiangEntity> list = listRukuZixiangByTiaomaBianma(tiaomaBianma);
|
if (list == null || list.isEmpty()) {
|
throw new DataException("未找到对应的耗材入库子项:" + tiaomaBianma);
|
}
|
|
LimsHaocaiRukuZixiangEntity zixiang = list.get(0);
|
String bizStatus = trimToEmpty(zixiang.getBizStatus());
|
if (BIZ_STATUS_YICHUKU.equalsIgnoreCase(bizStatus)) {
|
throw new DataException("该耗材已出库,不能重复借出:" + tiaomaBianma);
|
}
|
if (!isBorrowableStatus(bizStatus)) {
|
throw new DataException("该耗材状态不允许借出:" + bizStatus);
|
}
|
|
BigDecimal jiechuShuliang = parseRequiredDecimal(jiechu.getJiechuShuliang(),
|
"借出数量不能为空或格式无效");
|
BigDecimal shengyuliang = parseRequiredDecimal(zixiang.getShengyuliang(),
|
"耗材剩余量无效:" + tiaomaBianma);
|
if (jiechuShuliang.compareTo(BigDecimal.ZERO) <= 0) {
|
throw new DataException("借出数量必须大于0");
|
}
|
if (jiechuShuliang.compareTo(shengyuliang) != 0) {
|
throw new DataException("耗材状态已变化,请刷新后重新提交");
|
}
|
|
LimsHaocaiRukuZixiangEntity update = new LimsHaocaiRukuZixiangEntity();
|
update.setId(zixiang.getId());
|
update.setBizStatus(BIZ_STATUS_YICHUKU);
|
update.setShengyuliang("0");
|
LambdaQueryWrapper<LimsHaocaiRukuZixiangEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiRukuZixiangEntity::getId, zixiang.getId());
|
wrapper.in(LimsHaocaiRukuZixiangEntity::getBizStatus, BIZ_STATUS_WEICHUKU, BIZ_STATUS_YIKAIPING);
|
wrapper.eq(LimsHaocaiRukuZixiangEntity::getShengyuliang, zixiang.getShengyuliang());
|
int updated = zixiangMapper.update(update, wrapper);
|
if (updated <= 0) {
|
throw new DataException("耗材状态已变化,请刷新后重新提交");
|
}
|
|
updateRukuJieyuShuliang(zixiang, false, BIZ_STATUS_YICHUKU);
|
zixiang.setBizStatus(BIZ_STATUS_YICHUKU);
|
zixiang.setShengyuliang("0");
|
haocaiLogMapper.insert(buildJiechuLog(jiechu, zixiang));
|
log.info("耗材借出提交完成:tiaomaBianma={}, zixiangId={}", tiaomaBianma, zixiang.getId());
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "GUIHUAN_SUBMIT", label = "耗材归还提交", bizType = "HAOCAI",
|
bizCodeExpr = "", bizCodeRequired = false, targetTable = "lims_haocai_jiechu",
|
targetIdExpr = "#guihuan.id", diff = true, entityClass = LimsHaocaiJiechuEntity.class)
|
public void submitGuihuan(LimsHaocaiJiechuEntity guihuan) throws DataException {
|
String tiaomaBianma = trimToEmpty(guihuan == null ? null : guihuan.getTiaomaBianma());
|
if (tiaomaBianma.isEmpty()) {
|
throw new DataException("条码编码不能为空");
|
}
|
|
LimsHaocaiJiechuEntity lentRecord = getLentJiechuByTiaomaBianma(tiaomaBianma);
|
if (lentRecord == null) {
|
throw new DataException("未找到已借出的耗材借出记录:" + tiaomaBianma);
|
}
|
|
LimsHaocaiJiechuEntity jiechuUpdate = new LimsHaocaiJiechuEntity();
|
jiechuUpdate.setId(lentRecord.getId());
|
jiechuUpdate.setBizStatus(JIECHU_STATUS_RETURNED);
|
jiechuUpdate.setGuihuanRen(guihuan.getGuihuanRen());
|
jiechuUpdate.setGuihuanRiqi(guihuan.getGuihuanRiqi());
|
jiechuUpdate.setGuihuanRenSign(guihuan.getGuihuanRenSign());
|
LambdaQueryWrapper<LimsHaocaiJiechuEntity> jiechuWrapper = new LambdaQueryWrapper<>();
|
jiechuWrapper.eq(LimsHaocaiJiechuEntity::getId, lentRecord.getId());
|
jiechuWrapper.eq(LimsHaocaiJiechuEntity::getBizStatus, JIECHU_STATUS_LENT);
|
int jiechuUpdated = jiechuMapper.update(jiechuUpdate, jiechuWrapper);
|
if (jiechuUpdated <= 0) {
|
throw new DataException("该耗材借出记录状态已变化,不能重复归还:" + tiaomaBianma);
|
}
|
|
List<LimsHaocaiRukuZixiangEntity> list = listRukuZixiangByTiaomaBianma(tiaomaBianma);
|
if (list == null || list.isEmpty()) {
|
throw new DataException("未找到对应的耗材入库子项:" + tiaomaBianma);
|
}
|
|
LimsHaocaiRukuZixiangEntity zixiang = list.get(0);
|
String restoreShuliang = trimToEmpty(lentRecord.getJiechuShuliang());
|
BigDecimal guihuanShuliang = parseRequiredDecimal(restoreShuliang,
|
"借出记录借出数量无效:" + tiaomaBianma);
|
if (guihuanShuliang.compareTo(BigDecimal.ZERO) <= 0) {
|
throw new DataException("借出记录借出数量必须大于0:" + tiaomaBianma);
|
}
|
BigDecimal zongliang = parseRequiredDecimal(zixiang.getZongliang(),
|
"耗材总量无效:" + tiaomaBianma);
|
if (guihuanShuliang.compareTo(zongliang) > 0) {
|
throw new DataException("归还数量不能大于耗材总量:" + tiaomaBianma);
|
}
|
LimsHaocaiRukuZixiangEntity zixiangUpdate = new LimsHaocaiRukuZixiangEntity();
|
zixiangUpdate.setId(zixiang.getId());
|
String newBizStatus = resolveAvailableBizStatus(guihuanShuliang, zixiang);
|
zixiangUpdate.setBizStatus(newBizStatus);
|
zixiangUpdate.setShengyuliang(toPlainString(guihuanShuliang));
|
LambdaQueryWrapper<LimsHaocaiRukuZixiangEntity> zixiangWrapper = new LambdaQueryWrapper<>();
|
zixiangWrapper.eq(LimsHaocaiRukuZixiangEntity::getId, zixiang.getId());
|
zixiangWrapper.eq(LimsHaocaiRukuZixiangEntity::getBizStatus, BIZ_STATUS_YICHUKU);
|
int zixiangUpdated = zixiangMapper.update(zixiangUpdate, zixiangWrapper);
|
if (zixiangUpdated <= 0) {
|
throw new DataException("该耗材批次状态不允许归还:" + zixiang.getBizStatus());
|
}
|
|
zixiang.setShengyuliang(toPlainString(guihuanShuliang));
|
updateRukuJieyuShuliang(zixiang, guihuanShuliang, true, BIZ_STATUS_YICHUKU);
|
zixiang.setBizStatus(newBizStatus);
|
haocaiLogMapper.insert(buildGuihuanLog(guihuan, lentRecord, zixiang));
|
log.info("耗材归还提交完成:tiaomaBianma={}, jiechuId={}, zixiangId={}",
|
tiaomaBianma, lentRecord.getId(), zixiang.getId());
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "CHUKU_SUBMIT", label = "耗材出库提交", bizType = "HAOCAI",
|
bizCodeExpr = "", bizCodeRequired = false, targetTable = "lims_haocai_chuku",
|
targetIdExpr = "#chuku.id", diff = true, entityClass = LimsHaocaiChukuEntity.class)
|
public void submitChuku(LimsHaocaiChukuEntity chuku) throws DataException {
|
if (chuku == null) {
|
throw new DataException("出库表单数据不能为空");
|
}
|
String chukuId = trimToEmpty(chuku.getId());
|
if (chukuId.isEmpty()) {
|
throw new DataException("出库单主键(f_id)不能为空");
|
}
|
String shenlingDanhao = trimToEmpty(chuku.getShenlingDanhao());
|
if (shenlingDanhao.isEmpty()) {
|
throw new DataException("申领单号不能为空");
|
}
|
List<LimsHaocaiChukuZixiangEntity> chukuZixiangList = listChukuZixiang(chukuId);
|
if (chukuZixiangList == null || chukuZixiangList.isEmpty()) {
|
throw new DataException("出库子项不能为空:" + chukuId);
|
}
|
|
LimsHaocaiChukuShenqingEntity shenqing = getApprovedChukuShenqingByDanhao(shenlingDanhao);
|
if (shenqing == null) {
|
throw new DataException("申领单不存在或未通过:" + shenlingDanhao);
|
}
|
|
int count = 0;
|
for (LimsHaocaiChukuZixiangEntity chukuZixiang : chukuZixiangList) {
|
submitChukuZixiang(chuku, shenqing, chukuZixiang);
|
count++;
|
}
|
|
log.info("耗材出库提交完成:shenlingDanhao={}, count={}", shenlingDanhao, count);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "XIAOHUI_SUBMIT", label = "耗材销毁提交", bizType = "HAOCAI",
|
bizCodeExpr = "#xiaohuiDanhao", bizCodeRequired = false,
|
targetTable = "lims_haocai_ruku_zixiang",
|
targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).firstHaocaiDestroyItem(#xiaohuiDanhao)",
|
diff = true, entityClass = LimsHaocaiRukuZixiangEntity.class)
|
public void submitXiaohui(String xiaohuiDanhao) throws DataException {
|
String danhao = trimToEmpty(xiaohuiDanhao);
|
if (danhao.isEmpty()) {
|
throw new DataException("销毁单号不能为空");
|
}
|
|
LimsHaocaiXiaohuiShenqingEntity shenqing = getXiaohuiShenqingByDanhao(danhao);
|
if (shenqing == null) {
|
throw new DataException("销毁申请不存在:" + danhao);
|
}
|
|
List<LimsHaocaiXiaohuiShenqingZixiangEntity> zixiangList = listXiaohuiZixiang(shenqing.getId());
|
if (zixiangList.isEmpty()) {
|
throw new DataException("销毁申请子项不能为空:" + danhao);
|
}
|
|
int count = 0;
|
for (LimsHaocaiXiaohuiShenqingZixiangEntity xiaohuiZixiang : zixiangList) {
|
String tiaomaBianma = trimToEmpty(xiaohuiZixiang.getTiaomaBianma());
|
if (tiaomaBianma.isEmpty()) {
|
throw new DataException("销毁申请子项条码编码不能为空");
|
}
|
|
LimsHaocaiRukuZixiangEntity rukuZixiang = getUniqueRukuZixiangByTiaomaBianma(tiaomaBianma);
|
if (rukuZixiang == null) {
|
throw new DataException("未找到对应的耗材入库子项:" + tiaomaBianma);
|
}
|
if (BIZ_STATUS_YIXIAOHUI.equalsIgnoreCase(trimToEmpty(rukuZixiang.getBizStatus()))) {
|
throw new DataException("该耗材已销毁,不能重复销毁:" + tiaomaBianma);
|
}
|
|
BigDecimal xiaohuiShuliang = parseRequiredDecimal(rukuZixiang.getShengyuliang(),
|
"耗材剩余量无效:" + tiaomaBianma);
|
if (xiaohuiShuliang.compareTo(BigDecimal.ZERO) < 0) {
|
throw new DataException("耗材剩余量不能小于0:" + tiaomaBianma);
|
}
|
|
LimsHaocaiRukuZixiangEntity rukuZixiangUpdate = new LimsHaocaiRukuZixiangEntity();
|
rukuZixiangUpdate.setId(rukuZixiang.getId());
|
rukuZixiangUpdate.setBizStatus(BIZ_STATUS_YIXIAOHUI);
|
rukuZixiangUpdate.setShengyuliang("0");
|
int updated = zixiangMapper.updateById(rukuZixiangUpdate);
|
if (updated <= 0) {
|
throw new DataException("耗材销毁失败:" + tiaomaBianma);
|
}
|
|
updateRukuJieyuShuliang(rukuZixiang, BIZ_STATUS_YIXIAOHUI);
|
rukuZixiang.setBizStatus(BIZ_STATUS_YIXIAOHUI);
|
rukuZixiang.setShengyuliang("0");
|
haocaiLogMapper.insert(buildXiaohuiLog(shenqing, xiaohuiZixiang, rukuZixiang, xiaohuiShuliang));
|
markXiaohuiZixiangDestroyed(xiaohuiZixiang);
|
count++;
|
}
|
|
log.info("耗材销毁提交完成:xiaohuiDanhao={}, xiaohuiShenqingId={}, count={}",
|
danhao, shenqing.getId(), count);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "UPDATE", label = "耗材批量转待销毁", bizType = "HAOCAI",
|
bizCodeExpr = "#result > 0 ? 'HAOCAI_RUKU_BATCH' : ''", targetTable = "lims_haocai_ruku_zixiang",
|
targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).firstHaocaiRukuItem(#rukuIds)",
|
diff = true, entityClass = LimsHaocaiRukuZixiangEntity.class)
|
public int batchMarkRukuZixiangDaixiaohui(List<String> rukuIds) throws DataException {
|
List<String> ids = normalizeIds(rukuIds);
|
if (ids.isEmpty()) {
|
throw new DataException("入库单主键数组不能为空");
|
}
|
UserInfo userInfo = UserProvider.getUser();
|
String currentUserId = userInfo == null ? "" : trimToEmpty(userInfo.getUserId());
|
if (currentUserId.isEmpty()) {
|
throw new DataException("未获取到当前登录用户");
|
}
|
|
LambdaQueryWrapper<LimsHaocaiRukuZixiangEntity> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.in(LimsHaocaiRukuZixiangEntity::getForeignId, ids);
|
queryWrapper.and(w -> w.isNull(LimsHaocaiRukuZixiangEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiRukuZixiangEntity::getDeleteMark, 1));
|
List<LimsHaocaiRukuZixiangEntity> zixiangList = zixiangMapper.selectList(queryWrapper);
|
|
List<String> zixiangIds = new ArrayList<>();
|
for (LimsHaocaiRukuZixiangEntity zixiang : zixiangList) {
|
BigDecimal shengyuliang = parseOptionalDecimal(zixiang.getShengyuliang());
|
if (shengyuliang != null && shengyuliang.compareTo(BigDecimal.ZERO) > 0) {
|
zixiangIds.add(zixiang.getId());
|
}
|
}
|
if (zixiangIds.isEmpty()) {
|
log.info("耗材入库批量转待销毁无可更新子项:rukuIds={}", ids);
|
return 0;
|
}
|
|
LimsHaocaiRukuZixiangEntity update = new LimsHaocaiRukuZixiangEntity();
|
update.setBizStatus(BIZ_STATUS_DAIXIAOHUI);
|
update.setZhuanxiaohuiRen(currentUserId);
|
LambdaQueryWrapper<LimsHaocaiRukuZixiangEntity> updateWrapper = new LambdaQueryWrapper<>();
|
updateWrapper.in(LimsHaocaiRukuZixiangEntity::getId, zixiangIds);
|
int updated = zixiangMapper.update(update, updateWrapper);
|
updateRukuBizStatus(ids, BIZ_STATUS_DAIXIAOHUI);
|
log.info("耗材入库批量转待销毁完成:rukuIds={}, zixiangCount={}", ids, updated);
|
return updated;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "XIAOHUI_START", label = "耗材销毁申请发起", bizType = "HAOCAI",
|
bizCodeExpr = "#result > 0 ? #flowId : ''", targetTable = "lims_haocai_ruku_zixiang",
|
targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).firstHaocaiDestroyItemByFlow(#flowId, #taskId)",
|
diff = true, entityClass = LimsHaocaiRukuZixiangEntity.class)
|
public int startXiaohuiShenqing(String flowId, String taskId) throws DataException {
|
String flow = trimToEmpty(flowId);
|
String task = trimToEmpty(taskId);
|
if (flow.isEmpty()) {
|
throw new DataException("流程id(flow_id)不能为空");
|
}
|
if (task.isEmpty()) {
|
throw new DataException("流程任务id(task_id)不能为空");
|
}
|
LimsHaocaiXiaohuiShenqingEntity shenqing = getXiaohuiShenqingByFlow(flow, task);
|
if (shenqing == null) {
|
throw new DataException("销毁申请不存在:flow_id=" + flow + ", task_id=" + task);
|
}
|
String id = shenqing.getId();
|
String xiaohuiDanhao = trimToEmpty(shenqing.getXiaohuiDanhao());
|
if (xiaohuiDanhao.isEmpty()) {
|
throw new DataException("销毁单号不能为空:" + id);
|
}
|
|
List<LimsHaocaiXiaohuiShenqingZixiangEntity> xiaohuiZixiangList = listXiaohuiZixiang(id);
|
if (xiaohuiZixiangList == null || xiaohuiZixiangList.isEmpty()) {
|
throw new DataException("销毁申请子项不能为空:" + xiaohuiDanhao);
|
}
|
|
int updated = 0;
|
for (LimsHaocaiXiaohuiShenqingZixiangEntity xiaohuiZixiang : xiaohuiZixiangList) {
|
String tiaomaBianma = trimToEmpty(xiaohuiZixiang.getTiaomaBianma());
|
if (tiaomaBianma.isEmpty()) {
|
throw new DataException("销毁申请子项条码不能为空:" + xiaohuiDanhao);
|
}
|
LimsHaocaiRukuZixiangEntity update = new LimsHaocaiRukuZixiangEntity();
|
update.setBizStatus(BIZ_STATUS_DAIXIAOHUI);
|
update.setXiaohuiDanhao(xiaohuiDanhao);
|
|
LambdaQueryWrapper<LimsHaocaiRukuZixiangEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiRukuZixiangEntity::getTiaomaBianma, tiaomaBianma);
|
wrapper.and(w -> w.isNull(LimsHaocaiRukuZixiangEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiRukuZixiangEntity::getDeleteMark, 1));
|
int rowUpdated = zixiangMapper.update(update, wrapper);
|
if (rowUpdated <= 0) {
|
throw new DataException("未找到对应的耗材入库子项:" + tiaomaBianma);
|
}
|
updated += rowUpdated;
|
}
|
log.info("耗材销毁申请发起完成:xiaohuiShenqingId={}, xiaohuiDanhao={}, zixiangCount={}",
|
id, xiaohuiDanhao, updated);
|
return updated;
|
}
|
|
@Override
|
public List<LimsHaocaiRukuZixiangEntity> listRukuZixiangByTiaomaBianma(String tiaomaBianma) {
|
LambdaQueryWrapper<LimsHaocaiRukuZixiangEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiRukuZixiangEntity::getTiaomaBianma, trimToEmpty(tiaomaBianma));
|
wrapper.and(w -> w.isNull(LimsHaocaiRukuZixiangEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiRukuZixiangEntity::getDeleteMark, 1));
|
wrapper.orderByDesc(LimsHaocaiRukuZixiangEntity::getRukuShijian);
|
wrapper.orderByAsc(LimsHaocaiRukuZixiangEntity::getBianhao);
|
return zixiangMapper.selectList(wrapper);
|
}
|
|
@Override
|
public LimsHaocaiChukuShenqingZixiangEntity getChukuShenqingZixiangForChuku(String shenlingDanhao,
|
String tiaomaBianma) throws DataException {
|
String danhao = trimToEmpty(shenlingDanhao);
|
String tiaoma = trimToEmpty(tiaomaBianma);
|
if (danhao.isEmpty()) {
|
throw new DataException("申领单号不能为空");
|
}
|
if (tiaoma.isEmpty()) {
|
throw new DataException("条码编码不能为空");
|
}
|
|
LimsHaocaiRukuZixiangEntity rukuZixiang = getUniqueRukuZixiangByTiaomaBianma(tiaoma);
|
if (rukuZixiang == null) {
|
throw new DataException("未找到对应的耗材入库子项:" + tiaoma);
|
}
|
if (!isChukuAvailableStatus(rukuZixiang.getBizStatus())) {
|
throw new DataException("该耗材状态不允许出库:" + trimToEmpty(rukuZixiang.getBizStatus()));
|
}
|
BigDecimal shengyuliang = parseRequiredDecimal(rukuZixiang.getShengyuliang(),
|
"耗材剩余量无效:" + tiaoma);
|
if (shengyuliang.compareTo(BigDecimal.ZERO) <= 0) {
|
throw new DataException("该耗材剩余量不足,无法出库:" + tiaoma);
|
}
|
|
LimsHaocaiChukuShenqingEntity shenqing = getApprovedChukuShenqingByDanhao(danhao);
|
if (shenqing == null) {
|
throw new DataException("申领单不存在或未通过:" + danhao);
|
}
|
LimsHaocaiChukuShenqingZixiangEntity chukuZixiang = getChukuShenqingZixiang(shenqing.getId(), tiaoma);
|
if (chukuZixiang == null) {
|
throw new DataException("条码编码不在该申领单子表中:" + tiaoma);
|
}
|
if ("yes".equalsIgnoreCase(trimToEmpty(chukuZixiang.getShifouYichuku()))) {
|
throw new DataException("该申领子项已出库,不能重复出库:" + tiaoma);
|
}
|
chukuZixiang.setYongtu(shenqing.getYongtu());
|
chukuZixiang.setShifouShuangrenChuku(rukuZixiang.getShifouShuangrenChuku());
|
return chukuZixiang;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "YANSHOU_SUBMIT", label = "耗材入库验收提交", bizType = "HAOCAI",
|
bizCodeExpr = "#flowId", bizCodeRequired = false, targetTable = "lims_haocai_yanshou_shenqing",
|
targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).haocaiAcceptanceRequestByFlow(#flowId, #taskId)",
|
diff = true, entityClass = LimsHaocaiYanshouShenqingEntity.class)
|
public void submitRukuYanshou(String flowId, String taskId) throws DataException {
|
String flow = trimToEmpty(flowId);
|
String task = trimToEmpty(taskId);
|
if (flow.isEmpty()) {
|
throw new DataException("流程id(flow_id)不能为空");
|
}
|
if (task.isEmpty()) {
|
throw new DataException("流程任务id(task_id)不能为空");
|
}
|
|
LimsHaocaiRukuYanshouEntity yanshou = getUniqueRukuYanshouByFlow(flow, task);
|
String shenqingId = trimToEmpty(yanshou.getShenqingId());
|
if (shenqingId.isEmpty()) {
|
throw new DataException("耗材入库验收记录未关联验收申请:" + yanshou.getId());
|
}
|
|
LambdaUpdateWrapper<LimsHaocaiYanshouShenqingEntity> update = new LambdaUpdateWrapper<>();
|
update.eq(LimsHaocaiYanshouShenqingEntity::getId, shenqingId)
|
.and(w -> w.isNull(LimsHaocaiYanshouShenqingEntity::getDeleteMark)
|
.or().ne(LimsHaocaiYanshouShenqingEntity::getDeleteMark, 1))
|
.set(LimsHaocaiYanshouShenqingEntity::getYanshouId, yanshou.getId());
|
if (yanshouShenqingMapper.update(null, update) != 1) {
|
throw new DataException("耗材验收申请不存在或已删除:" + shenqingId);
|
}
|
log.info("耗材入库验收提交完成:flowId={}, taskId={}, yanshouId={}, shenqingId={}",
|
flow, task, yanshou.getId(), shenqingId);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "YANSHOU_FINISH", label = "耗材入库验收完成", bizType = "HAOCAI",
|
bizCodeExpr = "#flowId", bizCodeRequired = false, targetTable = "lims_haocai_yanshou_shenqing",
|
targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).haocaiAcceptanceRequestByFlow(#flowId, #taskId)",
|
diff = true, entityClass = LimsHaocaiYanshouShenqingEntity.class)
|
public void finishRukuYanshou(String flowId, String taskId) throws DataException {
|
String flow = trimToEmpty(flowId);
|
String task = trimToEmpty(taskId);
|
if (flow.isEmpty()) {
|
throw new DataException("流程id(flow_id)不能为空");
|
}
|
if (task.isEmpty()) {
|
throw new DataException("流程任务id(task_id)不能为空");
|
}
|
|
LimsHaocaiRukuYanshouEntity yanshou = getUniqueRukuYanshouByFlow(flow, task);
|
String shenqingId = trimToEmpty(yanshou.getShenqingId());
|
if (shenqingId.isEmpty()) {
|
throw new DataException("耗材入库验收记录未关联验收申请:" + yanshou.getId());
|
}
|
|
boolean approved = Integer.valueOf(FLOW_STATE_APPROVED).equals(yanshou.getFlowState());
|
LambdaUpdateWrapper<LimsHaocaiYanshouShenqingEntity> update = new LambdaUpdateWrapper<>();
|
update.eq(LimsHaocaiYanshouShenqingEntity::getId, shenqingId)
|
.and(w -> w.isNull(LimsHaocaiYanshouShenqingEntity::getDeleteMark)
|
.or().ne(LimsHaocaiYanshouShenqingEntity::getDeleteMark, 1));
|
if (approved) {
|
update.set(LimsHaocaiYanshouShenqingEntity::getBizStatus,
|
YANSHOU_SHENQING_STATUS_YIYANSHOU);
|
} else {
|
update.set(LimsHaocaiYanshouShenqingEntity::getBizStatus,
|
YANSHOU_SHENQING_STATUS_DAIYANSHOU)
|
.set(LimsHaocaiYanshouShenqingEntity::getShiyanYuan, null)
|
.set(LimsHaocaiYanshouShenqingEntity::getRenwuLingquShijian, null)
|
.set(LimsHaocaiYanshouShenqingEntity::getYanshouId, null);
|
}
|
if (yanshouShenqingMapper.update(null, update) != 1) {
|
throw new DataException("耗材验收申请不存在或已删除:" + shenqingId);
|
}
|
log.info("耗材入库验收完成处理成功:flowId={}, taskId={}, yanshouId={}, flowState={}, approved={}",
|
flow, task, yanshou.getId(), yanshou.getFlowState(), approved);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "YANSHOU_CLAIM", label = "领取耗材验收申请", bizType = "HAOCAI",
|
bizCodeExpr = "#shenqingId", bizCodeRequired = false, targetTable = "lims_haocai_yanshou_shenqing",
|
targetIdExpr = "#shenqingId", diff = true,
|
entityClass = LimsHaocaiYanshouShenqingEntity.class)
|
public void lingquYanshouShenqing(String shenqingId) throws DataException {
|
String id = trimToEmpty(shenqingId);
|
if (id.isEmpty()) {
|
throw new DataException("耗材验收申请主键(shenqing_id)不能为空");
|
}
|
|
LimsHaocaiYanshouShenqingEntity shenqing = yanshouShenqingMapper.selectById(id);
|
if (shenqing == null || Integer.valueOf(1).equals(shenqing.getDeleteMark())) {
|
throw new DataException("耗材验收申请不存在:" + id);
|
}
|
if (!YANSHOU_SHENQING_STATUS_DAIYANSHOU.equals(shenqing.getBizStatus())) {
|
throw new DataException("耗材验收申请当前状态为【"
|
+ yanshouShenqingStatusLabel(shenqing.getBizStatus()) + "】,仅【待验收】状态可领取");
|
}
|
|
UserInfo userInfo = UserProvider.getUser();
|
if (userInfo == null || trimToEmpty(userInfo.getUserId()).isEmpty()) {
|
throw new DataException("当前登录用户不存在");
|
}
|
LambdaUpdateWrapper<LimsHaocaiYanshouShenqingEntity> update = new LambdaUpdateWrapper<>();
|
update.eq(LimsHaocaiYanshouShenqingEntity::getId, id)
|
.eq(LimsHaocaiYanshouShenqingEntity::getBizStatus, YANSHOU_SHENQING_STATUS_DAIYANSHOU)
|
.and(w -> w.isNull(LimsHaocaiYanshouShenqingEntity::getDeleteMark)
|
.or().ne(LimsHaocaiYanshouShenqingEntity::getDeleteMark, 1))
|
.set(LimsHaocaiYanshouShenqingEntity::getBizStatus, YANSHOU_SHENQING_STATUS_YANSHOUZHONG)
|
.set(LimsHaocaiYanshouShenqingEntity::getShiyanYuan, userInfo.getUserId())
|
.set(LimsHaocaiYanshouShenqingEntity::getRenwuLingquShijian, new Date());
|
if (yanshouShenqingMapper.update(null, update) != 1) {
|
throw new DataException("耗材验收申请状态已变化,请刷新后重新领取");
|
}
|
}
|
|
private LimsHaocaiRukuYanshouEntity getUniqueRukuYanshouByFlow(String flowId, String taskId)
|
throws DataException {
|
LambdaQueryWrapper<LimsHaocaiRukuYanshouEntity> query = new LambdaQueryWrapper<>();
|
query.eq(LimsHaocaiRukuYanshouEntity::getFlowId, flowId)
|
.eq(LimsHaocaiRukuYanshouEntity::getFlowTaskId, taskId)
|
.and(w -> w.isNull(LimsHaocaiRukuYanshouEntity::getDeleteMark)
|
.or().ne(LimsHaocaiRukuYanshouEntity::getDeleteMark, 1));
|
List<LimsHaocaiRukuYanshouEntity> list = rukuYanshouMapper.selectList(query);
|
if (list == null || list.isEmpty()) {
|
throw new DataException("耗材入库验收记录不存在:flow_id=" + flowId + ", task_id=" + taskId);
|
}
|
if (list.size() > 1) {
|
throw new DataException("多个耗材入库验收记录关联同一流程任务:task_id=" + taskId);
|
}
|
return list.get(0);
|
}
|
|
private LimsHaocaiRukuZixiangEntity buildZixiang(LimsHaocaiRukuEntity ruku,
|
String tiaomaBianma, String bianhao,
|
String zongliang, String yanshouZhuangtai) {
|
LimsHaocaiRukuZixiangEntity record = new LimsHaocaiRukuZixiangEntity();
|
record.setId(RandomUtil.uuId());
|
record.setForeignId(ruku.getId());
|
record.setRukuId(ruku.getId());
|
record.setTiaomaBianma(tiaomaBianma);
|
record.setBianhao(bianhao);
|
record.setZongliang(zongliang);
|
record.setShengyuliang(zongliang);
|
record.setBizStatus(BIZ_STATUS_WEICHUKU);
|
record.setYanshouZhuangtai(yanshouZhuangtai);
|
record.setMingcheng(ruku.getHaocaiMingcheng());
|
record.setFenlei(ruku.getHaocaiFenlei());
|
record.setGuige(ruku.getGuige());
|
record.setPihao(ruku.getPihao());
|
record.setDanwei(ruku.getRongliangDanwei());
|
record.setCunfangWeizhi(ruku.getCunfangWeizhi());
|
record.setYouxiaoqi(ruku.getYouxiaoqi());
|
record.setKaipingYouxiaoqi(ruku.getKaipingYouxiaoqi());
|
record.setKaipingYouxiaoqiDanwei(ruku.getKaipingYouxiaoqiDanwei());
|
record.setRukuShijian(ruku.getRukuShijian() != null ? ruku.getRukuShijian() : new Date());
|
record.setRukuRen(ruku.getRukuRen());
|
record.setShenheRen(ruku.getShenheRen());
|
record.setHaocaiId(ruku.getHaocaiId());
|
record.setShifouShuangrenChuku(ruku.getShifouShuangrenChuku());
|
return record;
|
}
|
|
private LimsHaocaiLogEntity buildRukuLog(LimsHaocaiRukuEntity ruku, LimsHaocaiRukuZixiangEntity zixiang) {
|
LimsHaocaiLogEntity record = new LimsHaocaiLogEntity();
|
record.setId(RandomUtil.uuId());
|
record.setFenlei(zixiang.getFenlei());
|
record.setTiaomaBianma(zixiang.getTiaomaBianma());
|
record.setBianhao(zixiang.getBianhao());
|
record.setMingcheng(zixiang.getMingcheng());
|
record.setGuige(zixiang.getGuige());
|
record.setPihao(zixiang.getPihao());
|
record.setChurukuShuliang(zixiang.getZongliang());
|
record.setShengyuShuliang(zixiang.getShengyuliang());
|
record.setDanwei(zixiang.getDanwei());
|
record.setCaozuoRen(zixiang.getRukuRen());
|
record.setFuheRen(zixiang.getShenheRen());
|
record.setCaozuoRiqi(zixiang.getRukuShijian());
|
record.setCaozuoLeixing(LOG_ACTION_RUKU);
|
record.setBeizhu(ruku.getBeizhu());
|
return record;
|
}
|
|
private LimsHaocaiLogEntity buildJiechuLog(LimsHaocaiJiechuEntity jiechu, LimsHaocaiRukuZixiangEntity zixiang) {
|
LimsHaocaiLogEntity record = new LimsHaocaiLogEntity();
|
record.setId(RandomUtil.uuId());
|
record.setFenlei(zixiang.getFenlei());
|
record.setTiaomaBianma(zixiang.getTiaomaBianma());
|
record.setBianhao(zixiang.getBianhao());
|
record.setMingcheng(zixiang.getMingcheng());
|
record.setGuige(zixiang.getGuige());
|
record.setPihao(zixiang.getPihao());
|
record.setChurukuShuliang(jiechu.getJiechuShuliang());
|
record.setShengyuShuliang(zixiang.getShengyuliang());
|
record.setDanwei(firstNotBlank(jiechu.getDanwei(), zixiang.getDanwei()));
|
record.setCaozuoRen(jiechu.getJiechuRen());
|
record.setCaozuoRiqi(jiechu.getJiechuRiqi() != null ? jiechu.getJiechuRiqi() : new Date());
|
record.setCaozuoLeixing(LOG_ACTION_JIECHU);
|
record.setBeizhu(jiechu.getYongtu());
|
return record;
|
}
|
|
private LimsHaocaiLogEntity buildGuihuanLog(LimsHaocaiJiechuEntity guihuan,
|
LimsHaocaiJiechuEntity lentRecord,
|
LimsHaocaiRukuZixiangEntity zixiang) {
|
LimsHaocaiLogEntity record = new LimsHaocaiLogEntity();
|
record.setId(RandomUtil.uuId());
|
record.setFenlei(zixiang.getFenlei());
|
record.setTiaomaBianma(zixiang.getTiaomaBianma());
|
record.setBianhao(zixiang.getBianhao());
|
record.setMingcheng(zixiang.getMingcheng());
|
record.setGuige(zixiang.getGuige());
|
record.setPihao(zixiang.getPihao());
|
record.setChurukuShuliang(lentRecord.getJiechuShuliang());
|
record.setShengyuShuliang(zixiang.getShengyuliang());
|
record.setDanwei(firstNotBlank(lentRecord.getDanwei(), zixiang.getDanwei()));
|
record.setCaozuoRen(firstNotBlank(guihuan.getGuihuanRen(), firstNotBlank(guihuan.getJiechuRen(), lentRecord.getJiechuRen())));
|
record.setCaozuoRiqi(guihuan.getGuihuanRiqi() != null ? guihuan.getGuihuanRiqi() : new Date());
|
record.setCaozuoLeixing(LOG_ACTION_GUIHUAN);
|
record.setBeizhu(firstNotBlank(guihuan.getYongtu(), lentRecord.getYongtu()));
|
return record;
|
}
|
|
private LimsHaocaiLogEntity buildChukuLog(LimsHaocaiChukuEntity chuku,
|
LimsHaocaiChukuZixiangEntity chukuZixiang,
|
LimsHaocaiRukuZixiangEntity rukuZixiang,
|
BigDecimal chukuliang) {
|
LimsHaocaiLogEntity record = new LimsHaocaiLogEntity();
|
record.setId(RandomUtil.uuId());
|
record.setFenlei(rukuZixiang.getFenlei());
|
record.setTiaomaBianma(rukuZixiang.getTiaomaBianma());
|
record.setBianhao(rukuZixiang.getBianhao());
|
record.setMingcheng(rukuZixiang.getMingcheng());
|
record.setGuige(rukuZixiang.getGuige());
|
record.setPihao(rukuZixiang.getPihao());
|
record.setChurukuShuliang(toPlainString(chukuliang));
|
record.setShengyuShuliang(rukuZixiang.getShengyuliang());
|
record.setDanwei(firstNotBlank(chukuZixiang.getDanwei(), rukuZixiang.getDanwei()));
|
record.setCaozuoRen(chuku.getChukuRen());
|
record.setFuheRen(chuku.getFuheRen());
|
record.setCaozuoRiqi(chuku.getChukuRiqi() != null ? chuku.getChukuRiqi() : new Date());
|
record.setCaozuoLeixing(LOG_ACTION_CHUKU);
|
record.setBeizhu(chukuZixiang.getYongtu());
|
return record;
|
}
|
|
private LimsHaocaiLogEntity buildXiaohuiLog(LimsHaocaiXiaohuiShenqingEntity shenqing,
|
LimsHaocaiXiaohuiShenqingZixiangEntity xiaohuiZixiang,
|
LimsHaocaiRukuZixiangEntity rukuZixiang,
|
BigDecimal xiaohuiShuliang) {
|
LimsHaocaiLogEntity record = new LimsHaocaiLogEntity();
|
record.setId(RandomUtil.uuId());
|
record.setFenlei(rukuZixiang.getFenlei());
|
record.setTiaomaBianma(rukuZixiang.getTiaomaBianma());
|
record.setBianhao(rukuZixiang.getBianhao());
|
record.setMingcheng(rukuZixiang.getMingcheng());
|
record.setGuige(rukuZixiang.getGuige());
|
record.setPihao(rukuZixiang.getPihao());
|
record.setChurukuShuliang(toPlainString(xiaohuiShuliang));
|
record.setShengyuShuliang(rukuZixiang.getShengyuliang());
|
record.setDanwei(rukuZixiang.getDanwei());
|
record.setCaozuoRen(shenqing.getShenqingRen());
|
record.setCaozuoRiqi(shenqing.getShenqingRiqi() != null ? shenqing.getShenqingRiqi() : new Date());
|
record.setCaozuoLeixing(LOG_ACTION_XIAOHUI);
|
record.setBeizhu(firstNotBlank(xiaohuiZixiang.getYuanyin(), firstNotBlank(shenqing.getYuanyin(), shenqing.getFangfa())));
|
return record;
|
}
|
|
private LimsHaocaiJiechuEntity getLentJiechuByTiaomaBianma(String tiaomaBianma) {
|
LambdaQueryWrapper<LimsHaocaiJiechuEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiJiechuEntity::getTiaomaBianma, trimToEmpty(tiaomaBianma));
|
wrapper.eq(LimsHaocaiJiechuEntity::getBizStatus, JIECHU_STATUS_LENT);
|
wrapper.and(w -> w.isNull(LimsHaocaiJiechuEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiJiechuEntity::getDeleteMark, 1));
|
wrapper.orderByDesc(LimsHaocaiJiechuEntity::getJiechuRiqi);
|
return jiechuMapper.selectList(wrapper).stream().findFirst().orElse(null);
|
}
|
|
private void submitChukuZixiang(LimsHaocaiChukuEntity chuku,
|
LimsHaocaiChukuShenqingEntity shenqing,
|
LimsHaocaiChukuZixiangEntity chukuZixiang) throws DataException {
|
String tiaomaBianma = trimToEmpty(chukuZixiang == null ? null : chukuZixiang.getTiaomaBianma());
|
if (tiaomaBianma.isEmpty()) {
|
throw new DataException("出库子项条码编码不能为空");
|
}
|
|
BigDecimal chukuliang = parseRequiredDecimal(chukuZixiang.getChukuliang(),
|
"本次出库量不能为空或格式无效:" + tiaomaBianma);
|
if (chukuliang.compareTo(BigDecimal.ZERO) <= 0) {
|
throw new DataException("本次出库量必须大于0:" + tiaomaBianma);
|
}
|
|
LimsHaocaiRukuZixiangEntity rukuZixiang = getUniqueRukuZixiangByTiaomaBianma(tiaomaBianma);
|
if (rukuZixiang == null) {
|
throw new DataException("未找到对应的耗材入库子项:" + tiaomaBianma);
|
}
|
String bizStatus = trimToEmpty(rukuZixiang.getBizStatus());
|
if (!isChukuAvailableStatus(bizStatus)) {
|
throw new DataException("该耗材状态不允许出库:" + bizStatus);
|
}
|
|
BigDecimal shengyuliang = parseRequiredDecimal(rukuZixiang.getShengyuliang(),
|
"耗材剩余量无效:" + tiaomaBianma);
|
if (chukuliang.compareTo(shengyuliang) > 0) {
|
throw new DataException("本次出库量不能大于剩余量:" + tiaomaBianma);
|
}
|
|
LimsHaocaiChukuShenqingZixiangEntity shenqingZixiang =
|
getChukuShenqingZixiang(shenqing.getId(), tiaomaBianma);
|
if (shenqingZixiang == null) {
|
throw new DataException("条码编码不在该申领单子表中:" + tiaomaBianma);
|
}
|
if ("yes".equalsIgnoreCase(trimToEmpty(shenqingZixiang.getShifouYichuku()))) {
|
throw new DataException("该申领子项已出库,不能重复出库:" + tiaomaBianma);
|
}
|
|
BigDecimal newShengyuliang = shengyuliang.subtract(chukuliang);
|
String newBizStatus = newShengyuliang.compareTo(BigDecimal.ZERO) == 0
|
? BIZ_STATUS_YICHUKU
|
: BIZ_STATUS_YIKAIPING;
|
|
LimsHaocaiRukuZixiangEntity rukuZixiangUpdate = new LimsHaocaiRukuZixiangEntity();
|
rukuZixiangUpdate.setId(rukuZixiang.getId());
|
rukuZixiangUpdate.setShengyuliang(toPlainString(newShengyuliang));
|
rukuZixiangUpdate.setBizStatus(newBizStatus);
|
LambdaQueryWrapper<LimsHaocaiRukuZixiangEntity> rukuZixiangWrapper = new LambdaQueryWrapper<>();
|
rukuZixiangWrapper.eq(LimsHaocaiRukuZixiangEntity::getId, rukuZixiang.getId());
|
rukuZixiangWrapper.in(LimsHaocaiRukuZixiangEntity::getBizStatus, BIZ_STATUS_WEICHUKU, BIZ_STATUS_YIKAIPING);
|
rukuZixiangWrapper.eq(LimsHaocaiRukuZixiangEntity::getShengyuliang, rukuZixiang.getShengyuliang());
|
int rukuZixiangUpdated = zixiangMapper.update(rukuZixiangUpdate, rukuZixiangWrapper);
|
if (rukuZixiangUpdated <= 0) {
|
throw new DataException("耗材状态已变化,请刷新后重新提交:" + tiaomaBianma);
|
}
|
|
markChukuShenqingZixiangOut(shenqingZixiang);
|
updateRukuJieyuShuliang(rukuZixiang, chukuliang, false, BIZ_STATUS_YICHUKU);
|
rukuZixiang.setShengyuliang(toPlainString(newShengyuliang));
|
rukuZixiang.setBizStatus(newBizStatus);
|
haocaiLogMapper.insert(buildChukuLog(chuku, chukuZixiang, rukuZixiang, chukuliang));
|
}
|
|
private List<LimsHaocaiXiaohuiShenqingZixiangEntity> listXiaohuiZixiang(String foreignId) {
|
LambdaQueryWrapper<LimsHaocaiXiaohuiShenqingZixiangEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiXiaohuiShenqingZixiangEntity::getForeignId, foreignId);
|
wrapper.and(w -> w.isNull(LimsHaocaiXiaohuiShenqingZixiangEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiXiaohuiShenqingZixiangEntity::getDeleteMark, 1));
|
return xiaohuiShenqingZixiangMapper.selectList(wrapper);
|
}
|
|
private List<LimsHaocaiChukuZixiangEntity> listChukuZixiang(String foreignId) {
|
LambdaQueryWrapper<LimsHaocaiChukuZixiangEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiChukuZixiangEntity::getForeignId, foreignId);
|
wrapper.and(w -> w.isNull(LimsHaocaiChukuZixiangEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiChukuZixiangEntity::getDeleteMark, 1));
|
return chukuZixiangMapper.selectList(wrapper);
|
}
|
|
private void markXiaohuiZixiangDestroyed(LimsHaocaiXiaohuiShenqingZixiangEntity xiaohuiZixiang) throws DataException {
|
LimsHaocaiXiaohuiShenqingZixiangEntity update = new LimsHaocaiXiaohuiShenqingZixiangEntity();
|
update.setId(xiaohuiZixiang.getId());
|
update.setShifouYixiaohui("yes");
|
int updated = xiaohuiShenqingZixiangMapper.updateById(update);
|
if (updated <= 0) {
|
throw new DataException("销毁申请子项状态更新失败:" + xiaohuiZixiang.getTiaomaBianma());
|
}
|
}
|
|
private void markChukuShenqingZixiangOut(LimsHaocaiChukuShenqingZixiangEntity shenqingZixiang) throws DataException {
|
LimsHaocaiChukuShenqingZixiangEntity update = new LimsHaocaiChukuShenqingZixiangEntity();
|
update.setId(shenqingZixiang.getId());
|
update.setShifouYichuku("yes");
|
LambdaQueryWrapper<LimsHaocaiChukuShenqingZixiangEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiChukuShenqingZixiangEntity::getId, shenqingZixiang.getId());
|
wrapper.and(w -> w.isNull(LimsHaocaiChukuShenqingZixiangEntity::getShifouYichuku)
|
.or()
|
.ne(LimsHaocaiChukuShenqingZixiangEntity::getShifouYichuku, "yes"));
|
int updated = chukuShenqingZixiangMapper.update(update, wrapper);
|
if (updated <= 0) {
|
throw new DataException("申领子项已出库,不能重复出库:" + shenqingZixiang.getTiaomaBianma());
|
}
|
}
|
|
private LimsHaocaiXiaohuiShenqingEntity getXiaohuiShenqingByDanhao(String xiaohuiDanhao) {
|
LambdaQueryWrapper<LimsHaocaiXiaohuiShenqingEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiXiaohuiShenqingEntity::getXiaohuiDanhao, trimToEmpty(xiaohuiDanhao));
|
wrapper.and(w -> w.isNull(LimsHaocaiXiaohuiShenqingEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiXiaohuiShenqingEntity::getDeleteMark, 1));
|
return xiaohuiShenqingMapper.selectList(wrapper).stream().findFirst().orElse(null);
|
}
|
|
private LimsHaocaiXiaohuiShenqingEntity getXiaohuiShenqingByFlow(String flowId, String taskId) {
|
LambdaQueryWrapper<LimsHaocaiXiaohuiShenqingEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiXiaohuiShenqingEntity::getFlowId, trimToEmpty(flowId));
|
wrapper.eq(LimsHaocaiXiaohuiShenqingEntity::getFlowTaskId, trimToEmpty(taskId));
|
wrapper.and(w -> w.isNull(LimsHaocaiXiaohuiShenqingEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiXiaohuiShenqingEntity::getDeleteMark, 1));
|
return xiaohuiShenqingMapper.selectList(wrapper).stream().findFirst().orElse(null);
|
}
|
|
private LimsHaocaiChukuShenqingEntity getApprovedChukuShenqingByDanhao(String shenlingDanhao) {
|
LambdaQueryWrapper<LimsHaocaiChukuShenqingEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiChukuShenqingEntity::getShenlingDanhao, trimToEmpty(shenlingDanhao));
|
wrapper.eq(LimsHaocaiChukuShenqingEntity::getFlowState, FLOW_STATE_APPROVED);
|
wrapper.and(w -> w.isNull(LimsHaocaiChukuShenqingEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiChukuShenqingEntity::getDeleteMark, 1));
|
return chukuShenqingMapper.selectList(wrapper).stream().findFirst().orElse(null);
|
}
|
|
private LimsHaocaiChukuShenqingZixiangEntity getChukuShenqingZixiang(String foreignId, String tiaomaBianma) {
|
LambdaQueryWrapper<LimsHaocaiChukuShenqingZixiangEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(LimsHaocaiChukuShenqingZixiangEntity::getForeignId, trimToEmpty(foreignId));
|
wrapper.eq(LimsHaocaiChukuShenqingZixiangEntity::getTiaomaBianma, trimToEmpty(tiaomaBianma));
|
wrapper.and(w -> w.isNull(LimsHaocaiChukuShenqingZixiangEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiChukuShenqingZixiangEntity::getDeleteMark, 1));
|
return chukuShenqingZixiangMapper.selectList(wrapper).stream().findFirst().orElse(null);
|
}
|
|
private LimsHaocaiRukuZixiangEntity getUniqueRukuZixiangByTiaomaBianma(String tiaomaBianma) {
|
List<LimsHaocaiRukuZixiangEntity> list = listRukuZixiangByTiaomaBianma(tiaomaBianma);
|
return list == null || list.isEmpty() ? null : list.get(0);
|
}
|
|
private void updateRukuJieyuShuliang(LimsHaocaiRukuZixiangEntity rukuZixiang,
|
String zeroBizStatus) throws DataException {
|
updateRukuJieyuShuliang(rukuZixiang, false, zeroBizStatus);
|
}
|
|
private void updateRukuJieyuShuliang(LimsHaocaiRukuZixiangEntity rukuZixiang,
|
boolean increase,
|
String zeroBizStatus) throws DataException {
|
BigDecimal changeAmount = parseRequiredDecimal(rukuZixiang.getShengyuliang(),
|
"耗材剩余量无效:" + rukuZixiang.getTiaomaBianma());
|
updateRukuJieyuShuliang(rukuZixiang, changeAmount, increase, zeroBizStatus);
|
}
|
|
private void updateRukuJieyuShuliang(LimsHaocaiRukuZixiangEntity rukuZixiang,
|
BigDecimal changeAmount,
|
boolean increase,
|
String zeroBizStatus) throws DataException {
|
String id = trimToEmpty(rukuZixiang.getRukuId());
|
if (id.isEmpty()) {
|
throw new DataException("耗材入库主表主键不能为空");
|
}
|
LimsHaocaiRukuEntity ruku = this.getById(id);
|
if (ruku == null || Integer.valueOf(1).equals(ruku.getDeleteMark())) {
|
throw new DataException("耗材入库主表不存在:" + id);
|
}
|
BigDecimal jieyuShuliang = parseOptionalDecimal(ruku.getJieyuShuliang());
|
if (jieyuShuliang == null) {
|
jieyuShuliang = parseOptionalDecimal(ruku.getRukuShuliang());
|
}
|
if (jieyuShuliang == null) {
|
throw new DataException("入库主表结余数量无效:" + id);
|
}
|
BigDecimal changeShuliang = calculateJieyuChangeShuliang(ruku, rukuZixiang, changeAmount);
|
BigDecimal newJieyuShuliang = increase
|
? jieyuShuliang.add(changeShuliang)
|
: jieyuShuliang.subtract(changeShuliang);
|
if (newJieyuShuliang.compareTo(BigDecimal.ZERO) < 0) {
|
newJieyuShuliang = BigDecimal.ZERO;
|
}
|
|
LimsHaocaiRukuEntity update = new LimsHaocaiRukuEntity();
|
update.setId(id);
|
update.setJieyuShuliang(toPlainString(newJieyuShuliang));
|
update.setBizStatus(resolveRukuBizStatus(ruku, newJieyuShuliang, zeroBizStatus));
|
this.updateById(update);
|
}
|
|
private void updateRukuBizStatus(List<String> rukuIds, String bizStatus) {
|
if (rukuIds == null || rukuIds.isEmpty()) {
|
return;
|
}
|
LimsHaocaiRukuEntity update = new LimsHaocaiRukuEntity();
|
update.setBizStatus(bizStatus);
|
LambdaQueryWrapper<LimsHaocaiRukuEntity> wrapper = new LambdaQueryWrapper<>();
|
wrapper.in(LimsHaocaiRukuEntity::getId, rukuIds);
|
wrapper.and(w -> w.isNull(LimsHaocaiRukuEntity::getDeleteMark)
|
.or()
|
.ne(LimsHaocaiRukuEntity::getDeleteMark, 1));
|
this.update(update, wrapper);
|
}
|
|
private String resolveRukuBizStatus(LimsHaocaiRukuEntity ruku,
|
BigDecimal jieyuShuliang,
|
String zeroBizStatus) throws DataException {
|
if (jieyuShuliang.compareTo(BigDecimal.ZERO) <= 0) {
|
return zeroBizStatus;
|
}
|
BigDecimal rukuShuliang = parseRequiredDecimal(ruku.getRukuShuliang(),
|
"入库主表入库数量无效:" + ruku.getId());
|
if (jieyuShuliang.compareTo(rukuShuliang) >= 0) {
|
return BIZ_STATUS_WEICHUKU;
|
}
|
return BIZ_STATUS_YIKAIPING;
|
}
|
|
private BigDecimal calculateJieyuChangeShuliang(LimsHaocaiRukuEntity ruku,
|
LimsHaocaiRukuZixiangEntity rukuZixiang) throws DataException {
|
BigDecimal changeAmount = parseRequiredDecimal(rukuZixiang.getShengyuliang(),
|
"耗材剩余量无效:" + rukuZixiang.getTiaomaBianma());
|
return calculateJieyuChangeShuliang(ruku, rukuZixiang, changeAmount);
|
}
|
|
private BigDecimal calculateJieyuChangeShuliang(LimsHaocaiRukuEntity ruku,
|
LimsHaocaiRukuZixiangEntity rukuZixiang,
|
BigDecimal changeAmount) throws DataException {
|
BigDecimal zongliang = parseRequiredDecimal(rukuZixiang.getZongliang(),
|
"耗材总量无效:" + rukuZixiang.getTiaomaBianma());
|
if (zongliang.compareTo(BigDecimal.ZERO) <= 0) {
|
throw new DataException("耗材总量必须大于0:" + rukuZixiang.getTiaomaBianma());
|
}
|
if (changeAmount.compareTo(BigDecimal.ZERO) < 0) {
|
throw new DataException("耗材变化量不能小于0:" + rukuZixiang.getTiaomaBianma());
|
}
|
BigDecimal ratio = changeAmount.divide(zongliang, 8, java.math.RoundingMode.HALF_UP);
|
if ("yes".equalsIgnoreCase(trimToEmpty(ruku.getShifouYigeTiaoma()))) {
|
BigDecimal rukuShuliang = parseRequiredDecimal(ruku.getRukuShuliang(),
|
"入库主表入库数量无效:" + ruku.getId());
|
return ratio.multiply(rukuShuliang).stripTrailingZeros();
|
}
|
return ratio.stripTrailingZeros();
|
}
|
|
private boolean isChukuAvailableStatus(String bizStatus) {
|
String status = trimToEmpty(bizStatus);
|
return BIZ_STATUS_WEICHUKU.equalsIgnoreCase(status)
|
|| BIZ_STATUS_YIKAIPING.equalsIgnoreCase(status);
|
}
|
|
private boolean isBorrowableStatus(String bizStatus) {
|
return isChukuAvailableStatus(bizStatus);
|
}
|
|
private String resolveAvailableBizStatus(BigDecimal shengyuliang,
|
LimsHaocaiRukuZixiangEntity rukuZixiang) throws DataException {
|
BigDecimal zongliang = parseRequiredDecimal(rukuZixiang.getZongliang(),
|
"耗材总量无效:" + rukuZixiang.getTiaomaBianma());
|
if (shengyuliang.compareTo(zongliang) >= 0) {
|
return BIZ_STATUS_WEICHUKU;
|
}
|
return BIZ_STATUS_YIKAIPING;
|
}
|
|
private String resolveYanshouZhuangtai(LimsHaocaiRukuEntity ruku) {
|
return isYanshouEnabled(ruku)
|
? YANSHOU_STATUS_YIYANSHOU
|
: YANSHOU_STATUS_NA;
|
}
|
|
private boolean isYanshouEnabled(LimsHaocaiRukuEntity ruku) {
|
return ruku != null && "yes".equalsIgnoreCase(trimToEmpty(ruku.getShifouQiyongYanshou()));
|
}
|
|
private void updateRukuYanshouRukuId(LimsHaocaiRukuEntity ruku) throws DataException {
|
String yanshouId = trimToEmpty(ruku.getYanshouId());
|
if (yanshouId.isEmpty()) {
|
throw new DataException("启用验收的入库单必须关联验收记录主键(yanshou_id):" + ruku.getId());
|
}
|
|
LambdaUpdateWrapper<LimsHaocaiRukuYanshouEntity> update = new LambdaUpdateWrapper<>();
|
update.eq(LimsHaocaiRukuYanshouEntity::getId, yanshouId)
|
.and(w -> w.isNull(LimsHaocaiRukuYanshouEntity::getDeleteMark)
|
.or().ne(LimsHaocaiRukuYanshouEntity::getDeleteMark, 1))
|
.set(LimsHaocaiRukuYanshouEntity::getRukuId, ruku.getId());
|
if (rukuYanshouMapper.update(null, update) != 1) {
|
throw new DataException("耗材入库验收记录不存在或已删除:" + yanshouId);
|
}
|
}
|
|
private String yanshouShenqingStatusLabel(String status) {
|
String value = trimToEmpty(status);
|
if (YANSHOU_SHENQING_STATUS_DAIYANSHOU.equals(value)) {
|
return "待验收";
|
}
|
if (YANSHOU_SHENQING_STATUS_YANSHOUZHONG.equals(value)) {
|
return "验收中";
|
}
|
return value.isEmpty() ? "未设置" : value;
|
}
|
|
/**
|
* 取条码号。BillRuleApi 配了静态 fallback(L009):system 服务不可用时
|
* 静默返回空 ActionResult 而不抛异常,必须显式校验取号结果,空号立即失败回滚。
|
*/
|
private String nextTiaomaBianma() throws DataException {
|
ActionResult<String> result = billRuleApi.getBillNumber(TIAOMA_BILL_RULE);
|
String tiaoma = result == null ? null : result.getData();
|
if (StringUtil.isEmpty(tiaoma)) {
|
throw new DataException("条码取号失败:单据规则[" + TIAOMA_BILL_RULE + "]不可用,请确认规则已配置且系统服务在线");
|
}
|
return tiaoma;
|
}
|
|
private BigDecimal parseShuliang(String rukuShuliang) throws DataException {
|
try {
|
BigDecimal shuliang = new BigDecimal(trimToEmpty(rukuShuliang));
|
if (shuliang.compareTo(BigDecimal.ZERO) <= 0) {
|
throw new DataException("入库数量必须大于0:" + rukuShuliang);
|
}
|
return shuliang;
|
} catch (NumberFormatException e) {
|
throw new DataException("入库数量无效:" + rukuShuliang);
|
}
|
}
|
|
private int calculateCompleteTiaomaCount(BigDecimal shuliang, String originalQuantity)
|
throws DataException {
|
try {
|
return shuliang.setScale(0, RoundingMode.DOWN).intValueExact();
|
} catch (ArithmeticException e) {
|
throw new DataException("入库数量过大:" + originalQuantity);
|
}
|
}
|
|
private BigDecimal parseRongliang(String rongliang) throws DataException {
|
try {
|
return new BigDecimal(trimToEmpty(rongliang));
|
} catch (NumberFormatException e) {
|
throw new DataException("容量无效:" + rongliang);
|
}
|
}
|
|
private BigDecimal parseRequiredDecimal(String value, String errorMessage) throws DataException {
|
BigDecimal decimal = parseOptionalDecimal(value);
|
if (decimal == null) {
|
throw new DataException(errorMessage);
|
}
|
return decimal;
|
}
|
|
private BigDecimal parseOptionalDecimal(String value) {
|
String text = trimToEmpty(value);
|
if (text.isEmpty()) {
|
return null;
|
}
|
try {
|
return new BigDecimal(text);
|
} catch (NumberFormatException e) {
|
return null;
|
}
|
}
|
|
private List<String> normalizeIds(List<String> ids) {
|
List<String> result = new ArrayList<>();
|
if (ids == null) {
|
return result;
|
}
|
for (String id : ids) {
|
String value = trimToEmpty(id);
|
if (!value.isEmpty() && !result.contains(value)) {
|
result.add(value);
|
}
|
}
|
return result;
|
}
|
|
private String trimToEmpty(String value) {
|
return value == null ? "" : value.trim();
|
}
|
|
private String firstNotBlank(String first, String second) {
|
String value = trimToEmpty(first);
|
return value.isEmpty() ? second : value;
|
}
|
|
private String toPlainString(BigDecimal value) {
|
return value.stripTrailingZeros().toPlainString();
|
}
|
}
|