优化
This commit is contained in:
@@ -12,6 +12,15 @@ public interface InboundOrderMapper extends BaseMapper<InboundOrderEntity> {
|
||||
@Update("""
|
||||
UPDATE fl_inbound_order
|
||||
SET process_status = 'INBOUNDED', measure_review_status = 'APPROVED',
|
||||
actual_gross_weight_kg = (SELECT COALESCE(SUM(item.total_weight_kg), 0)
|
||||
FROM fl_inbound_measurement_item item
|
||||
WHERE item.tenant_id = #{tenantId} AND item.measurement_id = #{measurementId}),
|
||||
actual_volume_cbm = (SELECT COALESCE(SUM(item.total_volume_cbm), 0)
|
||||
FROM fl_inbound_measurement_item item
|
||||
WHERE item.tenant_id = #{tenantId} AND item.measurement_id = #{measurementId}),
|
||||
volume_weight_kg = (SELECT COALESCE(SUM(item.volume_weight_kg), 0)
|
||||
FROM fl_inbound_measurement_item item
|
||||
WHERE item.tenant_id = #{tenantId} AND item.measurement_id = #{measurementId}),
|
||||
inbounded_at = COALESCE(inbounded_at, CURRENT_TIMESTAMP(3)),
|
||||
updated_by = #{operatorId}, version = version + 1
|
||||
WHERE tenant_id = #{tenantId} AND id = #{inboundId} AND deleted = 0
|
||||
@@ -20,7 +29,8 @@ public interface InboundOrderMapper extends BaseMapper<InboundOrderEntity> {
|
||||
""")
|
||||
int approveMeasurement(@Param("tenantId") long tenantId, @Param("inboundId") long inboundId,
|
||||
@Param("operatorId") long operatorId,
|
||||
@Param("expectedVersion") int expectedVersion);
|
||||
@Param("expectedVersion") int expectedVersion,
|
||||
@Param("measurementId") long measurementId);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_inbound_order
|
||||
|
||||
+2
-2
@@ -67,9 +67,9 @@ public class InboundWorkflowRepository {
|
||||
}
|
||||
|
||||
public int transitionReview(long tenantId, long inboundId, long operatorId, int expectedVersion,
|
||||
boolean approved) {
|
||||
boolean approved, long measurementId) {
|
||||
return approved
|
||||
? orders.approveMeasurement(tenantId, inboundId, operatorId, expectedVersion)
|
||||
? orders.approveMeasurement(tenantId, inboundId, operatorId, expectedVersion, measurementId)
|
||||
: orders.rejectMeasurement(tenantId, inboundId, operatorId, expectedVersion);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 测量审核应用服务。客服确认测量数据后将入库单推进到产品主状态 INBOUNDED;
|
||||
@@ -69,8 +70,8 @@ public class MeasurementReviewService {
|
||||
throw new BizException(ResultCode.CONFLICT, "测量批次不是待审核状态");
|
||||
}
|
||||
if (approved) {
|
||||
long confirmed = repository.listMeasurementItems(tenantId, measurement.getId()).stream()
|
||||
.map(com.baiyue.firstleg.entity.InboundMeasurementItemEntity::getPackageCount)
|
||||
var items = repository.listMeasurementItems(tenantId, measurement.getId());
|
||||
long confirmed = items.stream().map(com.baiyue.firstleg.entity.InboundMeasurementItemEntity::getPackageCount)
|
||||
.filter(java.util.Objects::nonNull)
|
||||
.mapToLong(Integer::longValue)
|
||||
.sum();
|
||||
@@ -78,10 +79,18 @@ public class MeasurementReviewService {
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED,
|
||||
"人工确认箱数合计与入库单总箱数不一致,不能审核通过");
|
||||
}
|
||||
BigDecimal weight = items.stream().map(com.baiyue.firstleg.entity.InboundMeasurementItemEntity::getTotalWeightKg)
|
||||
.filter(java.util.Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal volume = items.stream().map(com.baiyue.firstleg.entity.InboundMeasurementItemEntity::getTotalVolumeCbm)
|
||||
.filter(java.util.Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
if (weight.signum() <= 0 || volume.signum() <= 0) {
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED,
|
||||
"审核通过的测量快照必须包含大于零的实重和体积");
|
||||
}
|
||||
}
|
||||
|
||||
if (repository.transitionReview(tenantId, inboundId, operatorId,
|
||||
request.expectedVersion(), approved) != 1) {
|
||||
request.expectedVersion(), approved, request.measurementId()) != 1) {
|
||||
throw concurrentConflict();
|
||||
}
|
||||
String result = approved ? "APPROVED" : "REJECTED";
|
||||
|
||||
+11
-7
@@ -18,6 +18,7 @@ import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -57,20 +58,20 @@ class MeasurementReviewServiceTest {
|
||||
.isEqualTo(ResultCode.NOT_FOUND);
|
||||
|
||||
verify(repository).findOwned(10002L, 10L);
|
||||
verify(repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean());
|
||||
verify(repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("审核通过是测量到计费的唯一正常推进关口")
|
||||
void shouldApproveOnlyPendingSubmittedMeasurement() {
|
||||
Fixture fixture = fixture(false);
|
||||
when(fixture.repository.transitionReview(10001L, 10L, 9L, 3, true)).thenReturn(1);
|
||||
when(fixture.repository.transitionReview(10001L, 10L, 9L, 3, true, 20L)).thenReturn(1);
|
||||
when(fixture.repository.transitionMeasurement(10001L, 10L, 20L, "APPROVED")).thenReturn(1);
|
||||
|
||||
fixture.service.approve(10001L, 9L, "审核员", 10L, "approve-1",
|
||||
new MeasurementReviewRequest(20L, 3, null));
|
||||
|
||||
verify(fixture.repository).transitionReview(10001L, 10L, 9L, 3, true);
|
||||
verify(fixture.repository).transitionReview(10001L, 10L, 9L, 3, true, 20L);
|
||||
verify(fixture.repository).transitionMeasurement(10001L, 10L, 20L, "APPROVED");
|
||||
verify(fixture.repository).insertReview(any());
|
||||
ArgumentCaptor<InboundStatusHistoryEntity> history =
|
||||
@@ -94,7 +95,7 @@ class MeasurementReviewServiceTest {
|
||||
.extracting(error -> ((BizException) error).getResultCode())
|
||||
.isEqualTo(ResultCode.VALIDATION_FAILED);
|
||||
|
||||
verify(fixture.repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean());
|
||||
verify(fixture.repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -106,7 +107,7 @@ class MeasurementReviewServiceTest {
|
||||
.isInstanceOf(BizException.class)
|
||||
.extracting(error -> ((BizException) error).getResultCode())
|
||||
.isEqualTo(ResultCode.VALIDATION_FAILED);
|
||||
verify(fixture.repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean());
|
||||
verify(fixture.repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -120,7 +121,7 @@ class MeasurementReviewServiceTest {
|
||||
new MeasurementReviewRequest(20L, 3, null));
|
||||
|
||||
verify(fixture.repository, never()).findOwned(anyLong(), anyLong());
|
||||
verify(fixture.repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean());
|
||||
verify(fixture.repository, never()).transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -158,7 +159,7 @@ class MeasurementReviewServiceTest {
|
||||
Fixture fixture = fixture(false);
|
||||
AtomicInteger attempts = new AtomicInteger();
|
||||
CountDownLatch bothArrived = new CountDownLatch(2);
|
||||
when(fixture.repository.transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean()))
|
||||
when(fixture.repository.transitionReview(anyLong(), anyLong(), anyLong(), anyInt(), anyBoolean(), anyLong()))
|
||||
.thenAnswer(invocation -> {
|
||||
bothArrived.countDown();
|
||||
bothArrived.await();
|
||||
@@ -199,6 +200,9 @@ class MeasurementReviewServiceTest {
|
||||
measurement.setStatus("SUBMITTED");
|
||||
InboundMeasurementItemEntity item = new InboundMeasurementItemEntity();
|
||||
item.setPackageCount(5);
|
||||
item.setTotalWeightKg(new BigDecimal("54.400"));
|
||||
item.setTotalVolumeCbm(new BigDecimal("0.7480"));
|
||||
item.setVolumeWeightKg(new BigDecimal("124.916"));
|
||||
when(repository.findOwned(10001L, 10L)).thenReturn(order);
|
||||
when(repository.findMeasurement(10001L, 10L, 20L)).thenReturn(measurement);
|
||||
when(repository.listMeasurementItems(10001L, 20L)).thenReturn(List.of(item));
|
||||
|
||||
Reference in New Issue
Block a user