mirror of https://github.com/jeecgboot/jeecg-boot
feat: mark orders without phone number as abnormal
parent
03a1f0a667
commit
3775c581e1
|
@ -154,6 +154,11 @@ public class Order {
|
||||||
|
|
||||||
@JSONField(name = "phone1")
|
@JSONField(name = "phone1")
|
||||||
private String phone1;
|
private String phone1;
|
||||||
|
/**
|
||||||
|
* 订单收件人是否有电话号码
|
||||||
|
*/
|
||||||
|
@JSONField(name = "hasPhoneNumber")
|
||||||
|
private String hasPhoneNumber;
|
||||||
|
|
||||||
public void setTrackingNumber(String trackingNumber) {
|
public void setTrackingNumber(String trackingNumber) {
|
||||||
if (trackingNumber != null && trackingNumber.isEmpty()) {
|
if (trackingNumber != null && trackingNumber.isEmpty()) {
|
||||||
|
@ -224,4 +229,7 @@ public class Order {
|
||||||
productAvailable = "1";
|
productAvailable = "1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void resolveHasPhoneNumber() {
|
||||||
|
this.hasPhoneNumber = (this.phone1 != null && !this.phone1.trim().isEmpty()) ? "1" : "0";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
package org.jeecg.modules.business.domain.job;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.getorderlist.Order;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.getorderlist.OrderListRequestBody;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal.OrderSuspendRequest;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal.OrderSuspendRequestBody;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal.OrderSuspendResponse;
|
||||||
|
import org.jeecg.modules.business.entity.PlatformOrder;
|
||||||
|
import org.jeecg.modules.business.service.IPlatformOrderMabangService;
|
||||||
|
import org.jeecg.modules.business.service.IPlatformOrderService;
|
||||||
|
import org.quartz.Job;
|
||||||
|
import org.quartz.JobDataMap;
|
||||||
|
import org.quartz.JobExecutionContext;
|
||||||
|
import org.quartz.JobExecutionException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class SuspendNoPhoneOrdersJob implements Job {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPlatformOrderService platformOrderService;
|
||||||
|
@Autowired
|
||||||
|
private IPlatformOrderMabangService platformOrderMabangService;
|
||||||
|
|
||||||
|
private static final String DEFAULT_COUNTRY = "France";
|
||||||
|
private static final String DEFAULT_LOGISTIC = "义速宝Colissimo专线普货(深圳)";
|
||||||
|
private static final String DEFAULT_ABNORMAL_LABEL_NAME = "法国义达缺电话号码";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||||
|
log.info("[Test] Starting SuspendNoPhoneOrdersJob (Filtering and printing localOrders pending review)");
|
||||||
|
// Default parameters
|
||||||
|
String country = DEFAULT_COUNTRY;
|
||||||
|
String logistic = DEFAULT_LOGISTIC;
|
||||||
|
LocalDateTime endDateTime = LocalDateTime.now();
|
||||||
|
LocalDateTime startDateTime = endDateTime.minusDays(30);
|
||||||
|
// Retrieve parameters from job data map
|
||||||
|
JobDataMap jobDataMap = context.getMergedJobDataMap();
|
||||||
|
String parameter = (String) jobDataMap.get("parameter");
|
||||||
|
try {
|
||||||
|
if (parameter != null && !parameter.isEmpty()) {
|
||||||
|
JSONObject json = JSONObject.fromObject(parameter);
|
||||||
|
if (json.has("country")) {
|
||||||
|
country = json.getString("country");
|
||||||
|
}
|
||||||
|
if (json.has("logistic")) {
|
||||||
|
logistic = json.getString("logistic");
|
||||||
|
}
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||||
|
if (json.has("startDateTime")) {
|
||||||
|
startDateTime = LocalDateTime.parse(json.getString("startDateTime"), formatter);
|
||||||
|
}
|
||||||
|
if (json.has("endDateTime")) {
|
||||||
|
endDateTime = LocalDateTime.parse(json.getString("endDateTime"), formatter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Failed to parse parameters, fallback to default values. Reason: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
if (!endDateTime.isAfter(startDateTime)) {
|
||||||
|
throw new JobExecutionException("endDateTime must be after startDateTime");
|
||||||
|
}
|
||||||
|
log.info("Using parameters - Country: {}, Logistic: {}, Start Date: {}, End Date: {}",
|
||||||
|
country, logistic, startDateTime, endDateTime);
|
||||||
|
// Query localOrders based on the criteria
|
||||||
|
List<PlatformOrder> localOrders = platformOrderService.lambdaQuery()
|
||||||
|
.eq(PlatformOrder::getCountry, country)
|
||||||
|
.eq(PlatformOrder::getLogisticChannelName, logistic)
|
||||||
|
.eq(PlatformOrder::getCanSend, "1")
|
||||||
|
.eq(PlatformOrder::getHasPhoneNumber, "0")
|
||||||
|
.in(PlatformOrder::getErpStatus, Arrays.asList("1", "2"))
|
||||||
|
.between(PlatformOrder::getUpdateTime, startDateTime, endDateTime)
|
||||||
|
.list();
|
||||||
|
log.info("Found {} localOrders matching criteria from {} to {}", localOrders.size(), startDateTime, endDateTime);
|
||||||
|
List<String> platformOrderIds = localOrders.stream()
|
||||||
|
.map(PlatformOrder::getPlatformOrderId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<List<String>> partitionedIds = Lists.partition(platformOrderIds, 10);
|
||||||
|
List<OrderListRequestBody> requests = partitionedIds.stream()
|
||||||
|
.map(list -> new OrderListRequestBody().setPlatformOrderIds(list))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
log.info("Fetching orders from Mabang for {} platformOrderIds", platformOrderIds.size());
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(3);
|
||||||
|
List<Order> mabangOrders = platformOrderMabangService.getOrdersFromMabang(requests, executor);
|
||||||
|
Map<String, Order> mabangOrderMap = mabangOrders.stream()
|
||||||
|
.collect(Collectors.toMap(Order::getPlatformOrderId, Function.identity()));
|
||||||
|
List<String> finalOrdersToSuspend = new ArrayList<>();
|
||||||
|
for (PlatformOrder localOrder : localOrders) {
|
||||||
|
Order mabang = mabangOrderMap.get(localOrder.getPlatformOrderId());
|
||||||
|
if (mabang == null) continue;
|
||||||
|
boolean stillCanSend = "1".equals(mabang.getCanSend());
|
||||||
|
boolean stillValidStatus = Arrays.asList("1", "2").contains(mabang.getStatus());
|
||||||
|
|
||||||
|
if (stillCanSend && stillValidStatus) {
|
||||||
|
log.info("Order {} eligible for suspension: CanSend={}, ERP Status={}",
|
||||||
|
localOrder.getPlatformOrderId(), mabang.getCanSend(), mabang.getStatus());
|
||||||
|
finalOrdersToSuspend.add(localOrder.getPlatformOrderId());
|
||||||
|
} else {
|
||||||
|
log.info("Order {} skipped due to updated Mabang status: CanSend={}, ERP Status={}",
|
||||||
|
localOrder.getPlatformOrderId(), mabang.getCanSend(), mabang.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("Setting orders to abnormal...");
|
||||||
|
List<CompletableFuture<Boolean>> futures = finalOrdersToSuspend.stream()
|
||||||
|
.map(id -> CompletableFuture.supplyAsync(() -> {
|
||||||
|
try {
|
||||||
|
OrderSuspendRequestBody body = new OrderSuspendRequestBody(id, DEFAULT_ABNORMAL_LABEL_NAME, "自动标记:无电话号码转为待审核");
|
||||||
|
OrderSuspendRequest request = new OrderSuspendRequest(body);
|
||||||
|
OrderSuspendResponse response = request.send();
|
||||||
|
boolean success = response.success();
|
||||||
|
if (success) {
|
||||||
|
log.info("Successfully suspended order {} from Mabang", id);
|
||||||
|
} else {
|
||||||
|
log.warn("Failed to suspend order {} from Mabang", id);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Exception while suspending order {}: {}", id, e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, executor)).collect(Collectors.toList());
|
||||||
|
futures.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||||
|
executor.shutdown();
|
||||||
|
log.info("Successfully suspended {} orders", finalOrdersToSuspend.size());
|
||||||
|
log.info("[Test] SuspendNoPhoneOrdersJob completed successfully.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -140,6 +140,13 @@ public class PlatformOrder implements Serializable {
|
||||||
@Excel(name = "订单收件人邮编", width = 15)
|
@Excel(name = "订单收件人邮编", width = 15)
|
||||||
@ApiModelProperty(value = "订单收件人邮编")
|
@ApiModelProperty(value = "订单收件人邮编")
|
||||||
private String postcode;
|
private String postcode;
|
||||||
|
/**
|
||||||
|
* 订单收件人是否有电话号码
|
||||||
|
*/
|
||||||
|
@Excel(name = "订单收件人是否有电话号码", width = 15, dicCode = "yn")
|
||||||
|
@Dict(dicCode = "yn")
|
||||||
|
@ApiModelProperty(value = "订单收件人是否有电话号码")
|
||||||
|
private String hasPhoneNumber;
|
||||||
/**
|
/**
|
||||||
* 物流挂号费
|
* 物流挂号费
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -101,6 +101,11 @@
|
||||||
when #{item.id} then #{item.postcode}
|
when #{item.id} then #{item.postcode}
|
||||||
</foreach>
|
</foreach>
|
||||||
end,
|
end,
|
||||||
|
has_phone_number = case id
|
||||||
|
<foreach collection="orders" separator=" " open="" close="" index="index" item="item">
|
||||||
|
when #{item.id} then #{item.hasPhoneNumber}
|
||||||
|
</foreach>
|
||||||
|
end,
|
||||||
tax_number = case id
|
tax_number = case id
|
||||||
<foreach collection="orders" separator=" " open="" close="" index="index" item="item">
|
<foreach collection="orders" separator=" " open="" close="" index="index" item="item">
|
||||||
when #{item.id} then #{item.taxNumber}
|
when #{item.id} then #{item.taxNumber}
|
||||||
|
@ -167,7 +172,7 @@
|
||||||
update_time, shop_id, logistic_channel_name,
|
update_time, shop_id, logistic_channel_name,
|
||||||
platform_order_id, platform_order_number, erp_order_id,
|
platform_order_id, platform_order_number, erp_order_id,
|
||||||
tracking_number, internal_tracking_number, order_time, shipping_time, recipient,
|
tracking_number, internal_tracking_number, order_time, shipping_time, recipient,
|
||||||
country, city, postcode, tax_number, erp_status, product_available, can_send)
|
country, city, postcode, tax_number, erp_status, product_available, can_send, has_phone_number)
|
||||||
VALUES
|
VALUES
|
||||||
<foreach collection="orders" separator="," open="" close="" item="order" index="index">
|
<foreach collection="orders" separator="," open="" close="" item="order" index="index">
|
||||||
(
|
(
|
||||||
|
@ -192,7 +197,8 @@
|
||||||
#{order.taxNumber},
|
#{order.taxNumber},
|
||||||
#{order.status},
|
#{order.status},
|
||||||
#{order.productAvailable},
|
#{order.productAvailable},
|
||||||
#{order.canSend}
|
#{order.canSend},
|
||||||
|
#{order.hasPhoneNumber}
|
||||||
)
|
)
|
||||||
</foreach>
|
</foreach>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
|
@ -201,6 +201,7 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
||||||
for (Order order : orders) {
|
for (Order order : orders) {
|
||||||
order.resolveStatus();
|
order.resolveStatus();
|
||||||
order.resolveProductAvailability();
|
order.resolveProductAvailability();
|
||||||
|
order.resolveHasPhoneNumber();
|
||||||
order.getOrderItems().forEach(
|
order.getOrderItems().forEach(
|
||||||
item -> {
|
item -> {
|
||||||
item.setPlatformOrderId(order.getId());
|
item.setPlatformOrderId(order.getId());
|
||||||
|
|
Loading…
Reference in New Issue