fix: 显式生成出库单聚合主键
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package cn.code.nl.module.wms.service.iostorinv;
|
package cn.code.nl.module.wms.service.iostorinv;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.code.nl.framework.common.pojo.CommonResult;
|
import cn.code.nl.framework.common.pojo.CommonResult;
|
||||||
import cn.code.nl.module.base.api.codegen.CodeGenApi;
|
import cn.code.nl.module.base.api.codegen.CodeGenApi;
|
||||||
import cn.code.nl.module.base.api.codegen.dto.CodeGenerateReqDTO;
|
import cn.code.nl.module.base.api.codegen.dto.CodeGenerateReqDTO;
|
||||||
@@ -65,6 +66,7 @@ public class IostorInvServiceImpl implements IostorInvService {
|
|||||||
.map(IostorInvCreateReqVO.Detail::getPlanQty)
|
.map(IostorInvCreateReqVO.Detail::getPlanQty)
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
IostorInvDO iostorInv = new IostorInvDO();
|
IostorInvDO iostorInv = new IostorInvDO();
|
||||||
|
iostorInv.setIostorinvId(IdUtil.fastSimpleUUID());
|
||||||
iostorInv.setBillCode(codeResult.getData());
|
iostorInv.setBillCode(codeResult.getData());
|
||||||
iostorInv.setIoType("OUT");
|
iostorInv.setIoType("OUT");
|
||||||
iostorInv.setBillType(reqVO.getBillType());
|
iostorInv.setBillType(reqVO.getBillType());
|
||||||
@@ -79,6 +81,7 @@ public class IostorInvServiceImpl implements IostorInvService {
|
|||||||
for (int index = 0; index < reqVO.getDetails().size(); index++) {
|
for (int index = 0; index < reqVO.getDetails().size(); index++) {
|
||||||
IostorInvCreateReqVO.Detail detail = reqVO.getDetails().get(index);
|
IostorInvCreateReqVO.Detail detail = reqVO.getDetails().get(index);
|
||||||
IostorinvDtlDO detailDO = new IostorinvDtlDO();
|
IostorinvDtlDO detailDO = new IostorinvDtlDO();
|
||||||
|
detailDO.setIostorinvdtlId(IdUtil.fastSimpleUUID());
|
||||||
detailDO.setIostorinvId(iostorInv.getIostorinvId());
|
detailDO.setIostorinvId(iostorInv.getIostorinvId());
|
||||||
detailDO.setSeqNo(index + 1);
|
detailDO.setSeqNo(index + 1);
|
||||||
detailDO.setMaterialCode(detail.getMaterialCode());
|
detailDO.setMaterialCode(detail.getMaterialCode());
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import cn.code.nl.framework.common.pojo.CommonResult;
|
|||||||
import cn.code.nl.module.base.api.codegen.CodeGenApi;
|
import cn.code.nl.module.base.api.codegen.CodeGenApi;
|
||||||
import cn.code.nl.module.base.api.codegen.dto.CodeGenerateReqDTO;
|
import cn.code.nl.module.base.api.codegen.dto.CodeGenerateReqDTO;
|
||||||
import cn.code.nl.module.wms.controller.admin.iostorinv.vo.IostorInvCreateReqVO;
|
import cn.code.nl.module.wms.controller.admin.iostorinv.vo.IostorInvCreateReqVO;
|
||||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
|
||||||
import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator;
|
|
||||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
@@ -31,7 +29,9 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
@SpringJUnitConfig
|
@SpringJUnitConfig
|
||||||
@@ -56,10 +56,13 @@ class IostorInvServiceLocalSpringTest {
|
|||||||
String id = iostorInvService.createOutbound(buildRequest());
|
String id = iostorInvService.createOutbound(buildRequest());
|
||||||
|
|
||||||
assertNotNull(id);
|
assertNotNull(id);
|
||||||
|
assertFalse(id.isBlank());
|
||||||
jdbcTemplate.queryForObject("SELECT * FROM wms_iostorinv WHERE iostorinv_id = ?", (rs, rowNum) -> {
|
jdbcTemplate.queryForObject("SELECT * FROM wms_iostorinv WHERE iostorinv_id = ?", (rs, rowNum) -> {
|
||||||
assertEquals("OUT-TEST-0001", rs.getString("bill_code"));
|
assertEquals("OUT-TEST-0001", rs.getString("bill_code"));
|
||||||
assertEquals("OUT", rs.getString("io_type"));
|
assertEquals("OUT", rs.getString("io_type"));
|
||||||
assertEquals("销售出库", rs.getString("bill_type"));
|
assertEquals("销售出库", rs.getString("bill_type"));
|
||||||
|
assertEquals(LocalDateTime.of(2026, 7, 22, 0, 0),
|
||||||
|
rs.getTimestamp("biz_date").toLocalDateTime());
|
||||||
assertEquals("STOR-01", rs.getString("stor_id"));
|
assertEquals("STOR-01", rs.getString("stor_id"));
|
||||||
assertEquals("生成", rs.getString("bill_status"));
|
assertEquals("生成", rs.getString("bill_status"));
|
||||||
assertEquals("主表备注", rs.getString("remark"));
|
assertEquals("主表备注", rs.getString("remark"));
|
||||||
@@ -70,19 +73,27 @@ class IostorInvServiceLocalSpringTest {
|
|||||||
|
|
||||||
List<DetailRow> details = jdbcTemplate.query(
|
List<DetailRow> details = jdbcTemplate.query(
|
||||||
"SELECT * FROM wms_iostorinvdtl WHERE iostorinv_id = ? ORDER BY seq_no",
|
"SELECT * FROM wms_iostorinvdtl WHERE iostorinv_id = ? ORDER BY seq_no",
|
||||||
(rs, rowNum) -> new DetailRow(rs.getInt("seq_no"), rs.getString("material_code"),
|
(rs, rowNum) -> new DetailRow(rs.getString("iostorinvdtl_id"), rs.getString("iostorinv_id"),
|
||||||
|
rs.getInt("seq_no"), rs.getString("material_code"),
|
||||||
rs.getString("material_id"), rs.getString("pcsn"), rs.getBigDecimal("plan_qty"),
|
rs.getString("material_id"), rs.getString("pcsn"), rs.getBigDecimal("plan_qty"),
|
||||||
rs.getBigDecimal("assign_qty"), rs.getBigDecimal("unassign_qty"),
|
rs.getBigDecimal("assign_qty"), rs.getBigDecimal("unassign_qty"),
|
||||||
rs.getString("qty_unit_id"), rs.getString("qty_unit_name"),
|
rs.getString("qty_unit_id"), rs.getString("qty_unit_name"),
|
||||||
rs.getString("source_bill_code"), rs.getString("source_bill_type"),
|
rs.getString("source_bill_code"), rs.getString("source_bill_type"),
|
||||||
rs.getString("source_billdtl_id"), rs.getString("remark")), id);
|
rs.getString("source_billdtl_id"), rs.getString("remark")), id);
|
||||||
assertEquals(List.of(
|
assertEquals(2, details.size());
|
||||||
new DetailRow(1, "MAT-01", "MID-01", "PCSN-01", new BigDecimal("12.500"),
|
assertNotNull(details.get(0).detailId());
|
||||||
BigDecimal.ZERO.setScale(3), new BigDecimal("12.500"), "KG", "千克",
|
assertNotNull(details.get(1).detailId());
|
||||||
"SRC-01", "ORDER", "SRC-DTL-01", "明细一"),
|
assertFalse(details.get(0).detailId().isBlank());
|
||||||
new DetailRow(2, "MAT-02", "MID-02", "PCSN-02", new BigDecimal("7.250"),
|
assertFalse(details.get(1).detailId().isBlank());
|
||||||
BigDecimal.ZERO.setScale(3), new BigDecimal("7.250"), "KG", "千克",
|
assertNotEquals(details.get(0).detailId(), details.get(1).detailId());
|
||||||
"SRC-02", "ORDER", "SRC-DTL-02", "明细二")), details);
|
assertEquals(id, details.get(0).headerId());
|
||||||
|
assertEquals(id, details.get(1).headerId());
|
||||||
|
assertEquals(new DetailRow(details.get(0).detailId(), id, 1, "MAT-01", "MID-01", "PCSN-01",
|
||||||
|
new BigDecimal("12.500"), BigDecimal.ZERO.setScale(3), new BigDecimal("12.500"),
|
||||||
|
"KG", "千克", "SRC-01", "ORDER", "SRC-DTL-01", "明细一"), details.get(0));
|
||||||
|
assertEquals(new DetailRow(details.get(1).detailId(), id, 2, "MAT-02", "MID-02", "PCSN-02",
|
||||||
|
new BigDecimal("7.250"), BigDecimal.ZERO.setScale(3), new BigDecimal("7.250"),
|
||||||
|
"KG", "千克", "SRC-02", "ORDER", "SRC-DTL-02", "明细二"), details.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -97,6 +108,17 @@ class IostorInvServiceLocalSpringTest {
|
|||||||
assertEquals(0, jdbcTemplate.queryForObject("SELECT COUNT(*) FROM wms_iostorinvdtl", Integer.class));
|
assertEquals(0, jdbcTemplate.queryForObject("SELECT COUNT(*) FROM wms_iostorinvdtl", Integer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRollbackHeaderAndFirstDetailWhenSecondDetailInsertFails() {
|
||||||
|
IostorInvCreateReqVO request = buildRequest();
|
||||||
|
request.getDetails().get(1).setSourceBillCode(null);
|
||||||
|
|
||||||
|
assertThrows(RuntimeException.class, () -> iostorInvService.createOutbound(request));
|
||||||
|
|
||||||
|
assertEquals(0, jdbcTemplate.queryForObject("SELECT COUNT(*) FROM wms_iostorinv", Integer.class));
|
||||||
|
assertEquals(0, jdbcTemplate.queryForObject("SELECT COUNT(*) FROM wms_iostorinvdtl", Integer.class));
|
||||||
|
}
|
||||||
|
|
||||||
private IostorInvCreateReqVO buildRequest() {
|
private IostorInvCreateReqVO buildRequest() {
|
||||||
IostorInvCreateReqVO request = new IostorInvCreateReqVO();
|
IostorInvCreateReqVO request = new IostorInvCreateReqVO();
|
||||||
request.setBillType("销售出库");
|
request.setBillType("销售出库");
|
||||||
@@ -123,7 +145,8 @@ class IostorInvServiceLocalSpringTest {
|
|||||||
return detail;
|
return detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record DetailRow(Integer seqNo, String materialCode, String materialId, String pcsn,
|
private record DetailRow(String detailId, String headerId, Integer seqNo, String materialCode,
|
||||||
|
String materialId, String pcsn,
|
||||||
BigDecimal planQty, BigDecimal assignQty, BigDecimal unassignQty,
|
BigDecimal planQty, BigDecimal assignQty, BigDecimal unassignQty,
|
||||||
String qtyUnitId, String qtyUnitName, String sourceBillCode,
|
String qtyUnitId, String qtyUnitName, String sourceBillCode,
|
||||||
String sourceBillType, String sourceBilldtlId, String remark) {
|
String sourceBillType, String sourceBilldtlId, String remark) {
|
||||||
@@ -144,9 +167,6 @@ class IostorInvServiceLocalSpringTest {
|
|||||||
SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
|
SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
|
||||||
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
|
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
|
||||||
factory.setDataSource(dataSource);
|
factory.setDataSource(dataSource);
|
||||||
GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
|
|
||||||
dbConfig.setKeyGenerators(List.of(new H2KeyGenerator()));
|
|
||||||
factory.setGlobalConfig(new GlobalConfig().setDbConfig(dbConfig));
|
|
||||||
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
|
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
|
||||||
configuration.setMapUnderscoreToCamelCase(true);
|
configuration.setMapUnderscoreToCamelCase(true);
|
||||||
factory.setConfiguration(configuration);
|
factory.setConfiguration(configuration);
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
DROP TABLE IF EXISTS wms_iostorinvdtl;
|
DROP TABLE IF EXISTS wms_iostorinvdtl;
|
||||||
DROP TABLE IF EXISTS wms_iostorinv;
|
DROP TABLE IF EXISTS wms_iostorinv;
|
||||||
DROP SEQUENCE IF EXISTS wms_iostorinvdtl_seq;
|
|
||||||
DROP SEQUENCE IF EXISTS wms_iostorinv_seq;
|
|
||||||
|
|
||||||
CREATE SEQUENCE wms_iostorinv_seq START WITH 1;
|
|
||||||
CREATE SEQUENCE wms_iostorinvdtl_seq START WITH 1;
|
|
||||||
|
|
||||||
CREATE TABLE wms_iostorinv (
|
CREATE TABLE wms_iostorinv (
|
||||||
iostorinv_id VARCHAR(64) PRIMARY KEY,
|
iostorinv_id VARCHAR(64) PRIMARY KEY,
|
||||||
bill_code VARCHAR(64), io_type VARCHAR(32), bill_type VARCHAR(64), biz_date TIMESTAMP,
|
bill_code VARCHAR(64), io_type VARCHAR(32), bill_type VARCHAR(64), biz_date TIMESTAMP,
|
||||||
@@ -22,7 +16,7 @@ CREATE TABLE wms_iostorinvdtl (
|
|||||||
iostorinvdtl_id VARCHAR(64) PRIMARY KEY, iostorinv_id VARCHAR(64), seq_no INT,
|
iostorinvdtl_id VARCHAR(64) PRIMARY KEY, iostorinv_id VARCHAR(64), seq_no INT,
|
||||||
pcsn VARCHAR(128), bill_status VARCHAR(32), qty_unit_id VARCHAR(64), qty_unit_name VARCHAR(64),
|
pcsn VARCHAR(128), bill_status VARCHAR(32), qty_unit_id VARCHAR(64), qty_unit_name VARCHAR(64),
|
||||||
plan_qty DECIMAL(18, 3), real_qty DECIMAL(18, 3), source_billdtl_id VARCHAR(64),
|
plan_qty DECIMAL(18, 3), real_qty DECIMAL(18, 3), source_billdtl_id VARCHAR(64),
|
||||||
source_bill_type VARCHAR(64), source_bill_code VARCHAR(64), source_bill_table VARCHAR(128),
|
source_bill_type VARCHAR(64), source_bill_code VARCHAR(64) NOT NULL, source_bill_table VARCHAR(128),
|
||||||
remark VARCHAR(255), assign_qty DECIMAL(18, 3), unassign_qty DECIMAL(18, 3),
|
remark VARCHAR(255), assign_qty DECIMAL(18, 3), unassign_qty DECIMAL(18, 3),
|
||||||
material_code VARCHAR(64), source_load_port VARCHAR(64), callback_strategy VARCHAR(255),
|
material_code VARCHAR(64), source_load_port VARCHAR(64), callback_strategy VARCHAR(255),
|
||||||
material_id VARCHAR(64), create_time TIMESTAMP, update_time TIMESTAMP,
|
material_id VARCHAR(64), create_time TIMESTAMP, update_time TIMESTAMP,
|
||||||
|
|||||||
Reference in New Issue
Block a user