fix(lastleg): exclude cancelled dispatches from inbound status
This commit is contained in:
+9
-4
@@ -10,6 +10,12 @@ import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface InboundPlanQueryMapper {
|
||||
String SCHEDULED_DISPATCH = "EXISTS (SELECT 1 FROM ll_dispatch_item di" +
|
||||
" JOIN ll_dispatch_order dispatch ON dispatch.id=di.dispatch_order_id" +
|
||||
" AND dispatch.customer_id=di.customer_id" +
|
||||
" WHERE di.customer_id=p.customer_id AND di.order_id=l.order_id" +
|
||||
" AND dispatch.status<>'CANCELLED')";
|
||||
|
||||
String FROM_AND_FILTER = " FROM ll_inbound_plan_line l" +
|
||||
" JOIN ll_inbound_plan p ON p.id=l.plan_id" +
|
||||
" JOIN ll_order o ON o.id=l.order_id" +
|
||||
@@ -31,8 +37,8 @@ public interface InboundPlanQueryMapper {
|
||||
"<if test='q.fbaWarehouseCode != null and q.fbaWarehouseCode != \"\"'> AND l.fba_warehouse_code LIKE CONCAT('%',#{q.fbaWarehouseCode},'%')</if>" +
|
||||
"<choose><when test='q.appointmentStatus == \"UNAPPOINTED\"'> AND ai.id IS NULL</when>" +
|
||||
"<when test='q.appointmentStatus != null and q.appointmentStatus != \"\"'> AND a.appointment_status=#{q.appointmentStatus}</when></choose>" +
|
||||
"<choose><when test='q.dispatchStatus == \"SCHEDULED\"'> AND EXISTS (SELECT 1 FROM ll_dispatch_item di WHERE <if test='customerId != null and customerId != \"\"'>di.customer_id=#{customerId} AND </if>di.order_id=l.order_id)</when>" +
|
||||
"<when test='q.dispatchStatus == \"UNSCHEDULED\"'> AND NOT EXISTS (SELECT 1 FROM ll_dispatch_item di WHERE <if test='customerId != null and customerId != \"\"'>di.customer_id=#{customerId} AND </if>di.order_id=l.order_id)</when></choose>" +
|
||||
"<choose><when test='q.dispatchStatus == \"SCHEDULED\"'> AND " + SCHEDULED_DISPATCH + "</when>" +
|
||||
"<when test='q.dispatchStatus == \"UNSCHEDULED\"'> AND NOT " + SCHEDULED_DISPATCH + "</when></choose>" +
|
||||
"<if test='q.createdFrom != null'> AND p.created_at >=#{q.createdFrom}</if>" +
|
||||
"<if test='q.createdTo != null'> AND p.created_at <=#{q.createdTo}</if>";
|
||||
|
||||
@@ -52,8 +58,7 @@ public interface InboundPlanQueryMapper {
|
||||
"p.urgent_flag urgent,p.status status,a.appointment_no appointmentNo," +
|
||||
"a.appointment_status appointmentStatus,a.appointment_at appointmentAt," +
|
||||
"a.expected_loading_at expectedLoadingAt," +
|
||||
"CASE WHEN EXISTS (SELECT 1 FROM ll_dispatch_item di WHERE " +
|
||||
"<if test='customerId != null and customerId != \"\"'>di.customer_id=#{customerId} AND </if>di.order_id=l.order_id)" +
|
||||
"CASE WHEN " + SCHEDULED_DISPATCH +
|
||||
" THEN 'SCHEDULED' ELSE 'UNSCHEDULED' END dispatchStatus,p.created_at createdAt,p.version version" +
|
||||
FROM_AND_FILTER + " ORDER BY p.created_at DESC,l.id DESC LIMIT #{limit} OFFSET #{offset}</script>")
|
||||
List<InboundPlanListResponse> rows(@Param("customerId") String customerId,
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package com.baiyue.lastleg.inboundplan.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import com.baiyue.lastleg.inboundplan.dto.InboundPlanListResponse;
|
||||
import com.baiyue.lastleg.inboundplan.dto.InboundPlanRequests;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class InboundPlanDispatchStatusPersistenceTest {
|
||||
private JdbcTemplate db;
|
||||
private InboundPlanQueryMapper mapper;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
var data = new DriverManagerDataSource("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", "");
|
||||
db = new JdbcTemplate(data);
|
||||
db.execute("CREATE TABLE ll_inbound_plan(id BIGINT,plan_no VARCHAR(50),customer_id VARCHAR(20),overseas_warehouse_id BIGINT,assigned_flag BOOLEAN,merge_required BOOLEAN,urgent_flag BOOLEAN,status VARCHAR(30),created_at TIMESTAMP,version INT)");
|
||||
db.execute("CREATE TABLE ll_inbound_plan_line(id BIGINT,plan_id BIGINT,order_id BIGINT,inbound_code VARCHAR(50),destination_warehouse_id VARCHAR(30),destination_warehouse_code VARCHAR(30),destination_warehouse_name VARCHAR(50),fba_warehouse_code VARCHAR(30),required_package_count INT,volume_cbm DECIMAL(18,3),planned_pallet_count INT)");
|
||||
db.execute("CREATE TABLE ll_order(id BIGINT,customer_id VARCHAR(20),lx_code VARCHAR(50),order_type VARCHAR(30),overseas_warehouse_code VARCHAR(30),overseas_warehouse_name VARCHAR(50),customer_name VARCHAR(50))");
|
||||
db.execute("CREATE TABLE ll_inbound_fba_appointment_item(id BIGINT,line_id BIGINT,appointment_id BIGINT)");
|
||||
db.execute("CREATE TABLE ll_inbound_fba_appointment(id BIGINT,customer_id VARCHAR(20),created_at TIMESTAMP,appointment_no VARCHAR(50),appointment_status VARCHAR(30),appointment_at TIMESTAMP,expected_loading_at TIMESTAMP)");
|
||||
db.execute("CREATE TABLE ll_inbound_plan_pallet_allocation(line_id BIGINT,picked_package_count INT)");
|
||||
db.execute("CREATE TABLE ll_order_detail(order_id BIGINT,customer_id VARCHAR(20),gross_weight_kg DECIMAL(18,3),net_weight_kg DECIMAL(18,3))");
|
||||
db.execute("CREATE TABLE ll_inbound_order(id BIGINT,customer_id VARCHAR(20),gross_weight_kg DECIMAL(18,3),net_weight_kg DECIMAL(18,3))");
|
||||
db.execute("CREATE TABLE ll_dispatch_item(id BIGINT,customer_id VARCHAR(20),dispatch_order_id BIGINT,order_id BIGINT)");
|
||||
db.execute("CREATE TABLE ll_dispatch_order(id BIGINT,customer_id VARCHAR(20),status VARCHAR(30))");
|
||||
db.update("INSERT INTO ll_inbound_plan VALUES(1,'LIP-1','A',90,TRUE,FALSE,FALSE,'RECEIVED',CURRENT_TIMESTAMP,0)");
|
||||
db.update("INSERT INTO ll_inbound_plan_line VALUES(2,1,3,'IN-1','91','ABE4','ABE4','ABE4',1,1,1)");
|
||||
db.update("INSERT INTO ll_order VALUES(3,'A','LX-1','FIRST_LEG','LA','洛杉矶仓','客户A')");
|
||||
var config = new MybatisConfiguration();
|
||||
config.addMapper(InboundPlanQueryMapper.class);
|
||||
var factory = new MybatisSqlSessionFactoryBean();
|
||||
factory.setDataSource(data);
|
||||
factory.setConfiguration(config);
|
||||
mapper = new SqlSessionTemplate(factory.getObject()).getMapper(InboundPlanQueryMapper.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void cancelledDispatchRetainsHistoryButDoesNotMarkOrFilterTheInboundAsScheduled() {
|
||||
dispatch(10, "A", "CANCELLED", "A");
|
||||
assertStatus("UNSCHEDULED");
|
||||
assertThat(db.queryForObject("SELECT COUNT(*) FROM ll_dispatch_item", Integer.class)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacementDispatchCountsOnceAndCancellingItRestoresUnscheduled() {
|
||||
dispatch(10, "A", "CANCELLED", "A");
|
||||
dispatch(11, "A", "PENDING_DEPARTURE", "A");
|
||||
dispatch(12, "A", "PICKING", "A");
|
||||
assertStatus("SCHEDULED");
|
||||
db.update("UPDATE ll_dispatch_order SET status='CANCELLED'");
|
||||
assertStatus("UNSCHEDULED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void departedAndCompletedDispatchesRemainScheduled() {
|
||||
dispatch(10, "A", "DEPARTED", "A");
|
||||
assertStatus("SCHEDULED");
|
||||
db.update("UPDATE ll_dispatch_order SET status='COMPLETED'");
|
||||
assertStatus("SCHEDULED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void otherCustomerOrMissingDispatchCannotMarkThisInboundScheduled() {
|
||||
dispatch(10, "B", "PENDING_DEPARTURE", "B");
|
||||
dispatch(11, "B", "PENDING_DEPARTURE", "A");
|
||||
db.update("INSERT INTO ll_dispatch_item VALUES(12,'A',999,3)");
|
||||
assertStatus("UNSCHEDULED");
|
||||
assertThat(mapper.rows("B", query(null), 0, 20)).isEmpty();
|
||||
assertThat(mapper.count("B", query(null))).isZero();
|
||||
}
|
||||
|
||||
private void dispatch(long id, String owner, String status, String itemOwner) {
|
||||
db.update("INSERT INTO ll_dispatch_order VALUES(?,?,?)", id, owner, status);
|
||||
db.update("INSERT INTO ll_dispatch_item VALUES(?,?,?,3)", id, itemOwner, id);
|
||||
}
|
||||
|
||||
private void assertStatus(String status) {
|
||||
for (String customer : new String[]{null, "A"}) {
|
||||
assertThat(mapper.rows(customer, query(null), 0, 20))
|
||||
.extracting(InboundPlanListResponse::dispatchStatus).containsExactly(status);
|
||||
assertThat(mapper.rows(customer, query(status), 0, 20)).hasSize(1);
|
||||
assertThat(mapper.count(customer, query(status))).isEqualTo(1);
|
||||
String opposite = "SCHEDULED".equals(status) ? "UNSCHEDULED" : "SCHEDULED";
|
||||
assertThat(mapper.rows(customer, query(opposite), 0, 20)).isEmpty();
|
||||
assertThat(mapper.count(customer, query(opposite))).isZero();
|
||||
}
|
||||
}
|
||||
|
||||
private static InboundPlanRequests.Query query(String status) {
|
||||
return new InboundPlanRequests.Query(1, 20, null, null, null, null, null, null,
|
||||
null, null, null, status, null, null);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -19,6 +19,8 @@ class InboundPlanQueryMapperContractTest {
|
||||
assertTrue(sql.contains("l.order_id orderId,l.inbound_code inboundCode,o.lx_code lxCode,o.order_type orderType"));
|
||||
assertTrue(sql.contains("p.overseas_warehouse_id overseasWarehouseId"));
|
||||
assertTrue(sql.contains("p.overseas_warehouse_id=#{q.overseasWarehouseId}"));
|
||||
assertTrue(sql.contains("WHERE <if test='customerId != null and customerId != \"\"'>di.customer_id=#{customerId} AND </if>di.order_id=l.order_id"));
|
||||
assertTrue(sql.contains("di.customer_id=p.customer_id AND di.order_id=l.order_id"));
|
||||
assertTrue(sql.contains("dispatch.customer_id=di.customer_id"));
|
||||
assertTrue(sql.contains("dispatch.status<>'CANCELLED'"));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -82,7 +82,8 @@ class InboundPlanPaginationTest {
|
||||
.getMethod("rows", String.class, InboundPlanRequests.Query.class, long.class, long.class)
|
||||
.getAnnotation(org.apache.ibatis.annotations.Select.class).value()) + InboundPlanQueryMapper.FROM_AND_FILTER;
|
||||
assertThat(sql).contains("a2.customer_id=#{customerId}", "ORDER BY a2.created_at DESC,ai2.id DESC LIMIT 1");
|
||||
assertThat(sql).contains("di.customer_id=#{customerId} AND </if>di.order_id=l.order_id");
|
||||
assertThat(sql).contains("di.customer_id=p.customer_id AND di.order_id=l.order_id",
|
||||
"dispatch.customer_id=di.customer_id", "dispatch.status<>'CANCELLED'");
|
||||
assertThat(sql).contains("p.overseas_warehouse_id overseasWarehouseId", "o.overseas_warehouse_code overseasWarehouseCode",
|
||||
"o.overseas_warehouse_name overseasWarehouseName",
|
||||
"p.overseas_warehouse_id=#{q.overseasWarehouseId}");
|
||||
|
||||
Reference in New Issue
Block a user