mirror of https://github.com/jeecgboot/jeecg-boot
commit
21f1797d23
|
@ -0,0 +1,15 @@
|
||||||
|
package org.jeecg.modules.business.domain.api.mabang.dochangeorder;
|
||||||
|
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.Request;
|
||||||
|
|
||||||
|
public class RemoveSkuRequest extends Request {
|
||||||
|
public RemoveSkuRequest(RemoveSkuRequestBody body) {
|
||||||
|
super(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChangeOrderResponse send() {
|
||||||
|
String jsonString = rawSend().getBody();
|
||||||
|
return ChangeOrderResponse.parse(jsonString);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.jeecg.modules.business.domain.api.mabang.dochangeorder;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.RequestBody;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RemoveSkuRequestBody implements RequestBody {
|
||||||
|
|
||||||
|
|
||||||
|
private String platformOrderId;
|
||||||
|
private final HashSet<Pair<String, Integer>> virtualSkus;
|
||||||
|
private final static String DEFAULT_WAREHOUSE_NAME = "SZBA宝安仓";
|
||||||
|
|
||||||
|
public RemoveSkuRequestBody(String platformOrderId, HashSet<Pair<String, Integer>> virtualSkus) {
|
||||||
|
this.platformOrderId = platformOrderId;
|
||||||
|
this.virtualSkus = virtualSkus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String api() {
|
||||||
|
return "order-do-change-order";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject parameters() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
putNonNull(json, "platformOrderId", platformOrderId);
|
||||||
|
JSONArray stockDataArray = new JSONArray();
|
||||||
|
if (!virtualSkus.isEmpty()) {
|
||||||
|
for (Pair<String, Integer> virtualSku : virtualSkus) {
|
||||||
|
JSONObject stockData = new JSONObject();
|
||||||
|
stockData.put("warehouseName", DEFAULT_WAREHOUSE_NAME);
|
||||||
|
stockData.put("stockSku", virtualSku.getKey());
|
||||||
|
stockData.put("quantity", virtualSku.getValue());
|
||||||
|
stockData.put("type", 2);
|
||||||
|
stockDataArray.add(stockData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
json.put("stockData", stockDataArray.toJSONString());
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <E> void putNonNull(JSONObject json, String key, E value) {
|
||||||
|
if (value != null) {
|
||||||
|
json.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ public class CreateFulfillmentRequest extends ShopifyRequest {
|
||||||
POST_NL("https://postnl.post/", "PostNL International Mail", "LS[0-9]{9}NL"),
|
POST_NL("https://postnl.post/", "PostNL International Mail", "LS[0-9]{9}NL"),
|
||||||
COLI_COLI("https://www.colicoli.fr/trackings?id=%s", "Coli Coli", "CC[0-9]{14}[A-Z]*"),
|
COLI_COLI("https://www.colicoli.fr/trackings?id=%s", "Coli Coli", "CC[0-9]{14}[A-Z]*"),
|
||||||
LUXEMBOURG_POST("https://www.post.lu/particuliers/colis-courrier/track-and-trace#/search", "Luxembourg Post", "LL[0-9]{9}LU"),
|
LUXEMBOURG_POST("https://www.post.lu/particuliers/colis-courrier/track-and-trace#/search", "Luxembourg Post", "LL[0-9]{9}LU"),
|
||||||
CJ_LOGISTICS("https://www.cjlogistics.com/ko/tool/parcel/tracking", "CJ대한통운", "57575[0-9]{7}"),
|
CJ_LOGISTICS("https://www.cjlogistics.com/ko/tool/parcel/tracking", "CJ대한통운", "57575[0-9]{7}|58476[0-9]{7}"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String trackingUrl;
|
private final String trackingUrl;
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
package org.jeecg.modules.business.domain.job;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.codehaus.jettison.json.JSONArray;
|
||||||
|
import org.codehaus.jettison.json.JSONException;
|
||||||
|
import org.codehaus.jettison.json.JSONObject;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeOrderResponse;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.RemoveSkuRequest;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.RemoveSkuRequestBody;
|
||||||
|
import org.jeecg.modules.business.domain.api.mabang.getorderlist.*;
|
||||||
|
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 java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class RemoveVirtualProductJob implements Job {
|
||||||
|
|
||||||
|
private static final Integer DEFAULT_NUMBER_OF_DAYS = 5;
|
||||||
|
|
||||||
|
private static final Integer DEFAULT_NUMBER_OF_THREADS = 10;
|
||||||
|
private static final String REMOVED_SKU_STATUS = "4";;
|
||||||
|
private Map<String, List<String>> virtualSkusByShop = new HashMap<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPlatformOrderService platformOrderService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||||
|
LocalDateTime endDateTime = LocalDateTime.now();
|
||||||
|
LocalDateTime startDateTime = endDateTime.minusDays(DEFAULT_NUMBER_OF_DAYS);
|
||||||
|
List<String> shops = new ArrayList<>();
|
||||||
|
JobDataMap jobDataMap = context.getMergedJobDataMap();
|
||||||
|
String parameter = ((String) jobDataMap.get("parameter"));
|
||||||
|
if (parameter != null) {
|
||||||
|
try {
|
||||||
|
JSONObject jsonObject = new JSONObject(parameter);
|
||||||
|
if (!jsonObject.isNull("startDateTime")) {
|
||||||
|
String startDateStr = jsonObject.getString("startDateTime");
|
||||||
|
startDateTime = LocalDateTime.parse(startDateStr);
|
||||||
|
}
|
||||||
|
if (!jsonObject.isNull("endDateTime")) {
|
||||||
|
String endDateStr = jsonObject.getString("endDateTime");
|
||||||
|
endDateTime = LocalDateTime.parse(endDateStr);
|
||||||
|
}
|
||||||
|
if (!jsonObject.isNull("virtualSkusByShop")) {
|
||||||
|
JSONArray virtualSkusByShopArray = jsonObject.getJSONArray("virtualSkusByShop");
|
||||||
|
for (int i = 0; i < virtualSkusByShopArray.length(); i++) {
|
||||||
|
JSONObject object = virtualSkusByShopArray.getJSONObject((i));
|
||||||
|
if (!object.isNull("shop")) {
|
||||||
|
String shopCode = object.getString("shop");
|
||||||
|
shops.add(shopCode);
|
||||||
|
if (!object.isNull("virtualSkus")) {
|
||||||
|
JSONArray virtualSkusArray = object.getJSONArray("virtualSkus");
|
||||||
|
List<String> virtualSkus = new ArrayList<>();
|
||||||
|
for (int j = 0; j < virtualSkusArray.length(); j++) {
|
||||||
|
virtualSkus.add(virtualSkusArray.getString(j));
|
||||||
|
}
|
||||||
|
virtualSkusByShop.put(shopCode, virtualSkus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Error while parsing parameter as JSON, falling back to default parameters.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!endDateTime.isAfter(startDateTime)) {
|
||||||
|
throw new RuntimeException("EndDateTime must be strictly greater than StartDateTime !");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> platformOrderIds = platformOrderService.fetchUninvoicedOrdersForShops(startDateTime, endDateTime, shops);
|
||||||
|
List<List<String>> platformOrderIdLists = Lists.partition(platformOrderIds, 10);
|
||||||
|
|
||||||
|
List<OrderListRequestBody> requests = new ArrayList<>();
|
||||||
|
for (List<String> platformOrderIdList : platformOrderIdLists) {
|
||||||
|
requests.add(new OrderListRequestBody().setPlatformOrderIds(platformOrderIdList));
|
||||||
|
}
|
||||||
|
List<Order> mabangOrders = new ArrayList<>();
|
||||||
|
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_NUMBER_OF_THREADS);
|
||||||
|
List<CompletableFuture<Boolean>> futures = requests.stream()
|
||||||
|
.map(request -> CompletableFuture.supplyAsync(() -> {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
OrderListRawStream rawStream = new OrderListRawStream(request);
|
||||||
|
OrderListStream stream = new OrderListStream(rawStream);
|
||||||
|
List<Order> orders = stream.all();
|
||||||
|
mabangOrders.addAll(orders);
|
||||||
|
success = !orders.isEmpty();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error("Error communicating with MabangAPI", e);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}, executor))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<Boolean> results = futures.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||||
|
long nbSuccesses = results.stream().filter(b -> b).count();
|
||||||
|
log.info("{}/{} requests have succeeded.", nbSuccesses, requests.size());
|
||||||
|
log.info("{}/{} mabang orders have been retrieved.", mabangOrders.size(), platformOrderIds.size());
|
||||||
|
|
||||||
|
log.info("Constructing virtual SKU removal requests");
|
||||||
|
List<RemoveSkuRequestBody> removeSkuRequests = new ArrayList<>();
|
||||||
|
Set<String> shopErpCodes = virtualSkusByShop.keySet();
|
||||||
|
for (Order mabangOrder : mabangOrders) {
|
||||||
|
String shopErpCode = mabangOrder.getShopErpCode();
|
||||||
|
if (shopErpCodes.contains(shopErpCode)) {
|
||||||
|
List<String> virtualSkus = virtualSkusByShop.get(shopErpCode);
|
||||||
|
HashSet<Pair<String, Integer>> virtualSkuToRemove = new HashSet<>();
|
||||||
|
for (OrderItem orderItem : mabangOrder.getOrderItems()) {
|
||||||
|
String skuErpCode = orderItem.getErpCode();
|
||||||
|
if (!orderItem.getStatus().equalsIgnoreCase(REMOVED_SKU_STATUS) && virtualSkus.contains(skuErpCode)) {
|
||||||
|
virtualSkuToRemove.add(Pair.of(skuErpCode, orderItem.getQuantity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!virtualSkuToRemove.isEmpty()) {
|
||||||
|
RemoveSkuRequestBody removeSkuRequestBody = new RemoveSkuRequestBody(mabangOrder.getPlatformOrderId(),
|
||||||
|
virtualSkuToRemove);
|
||||||
|
removeSkuRequests.add(removeSkuRequestBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("{} virtual SKU removal requests to be sent to MabangAPI", removeSkuRequests.size());
|
||||||
|
|
||||||
|
List<CompletableFuture<Boolean>> removeSkuFutures = removeSkuRequests.stream()
|
||||||
|
.map(removeSkuRequestBody -> CompletableFuture.supplyAsync(() -> {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
RemoveSkuRequest changeOrderRequest = new RemoveSkuRequest(removeSkuRequestBody);
|
||||||
|
ChangeOrderResponse response = changeOrderRequest.send();
|
||||||
|
success = response.success();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error("Error communicating with MabangAPI", e);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}, executor))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
results = removeSkuFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||||
|
nbSuccesses = results.stream().filter(b -> b).count();
|
||||||
|
log.info("{}/{} virtual SKU removal requests have succeeded.", nbSuccesses, removeSkuRequests.size());
|
||||||
|
}
|
||||||
|
}
|
2
pom.xml
2
pom.xml
|
@ -2,7 +2,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.jeecgframework.boot</groupId>
|
<groupId>org.jeecgframework.boot</groupId>
|
||||||
<artifactId>jeecg-boot-parent</artifactId>
|
<artifactId>jeecg-boot-parent</artifactId>
|
||||||
<version>1.10.0</version>
|
<version>1.11.0</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>WIA APP ${project.version} </name>
|
<name>WIA APP ${project.version} </name>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue