Merge pull request #95 from LQYBill/feat/orderManagementTriggerSync

Feat/order management trigger sync
pull/8040/head
Qiuyi LI 2024-07-04 15:32:29 +02:00 committed by GitHub
commit 7a773aa3dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 113 additions and 56 deletions

View File

@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.codehaus.jettison.json.JSONException;
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeOrderResponse;
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeWarehouseRequest;
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeWarehouseRequestBody;
@ -385,7 +386,7 @@ public class PlatformOrderController {
}
@PostMapping("/orderManagement")
public Result<?> orderManagement(@RequestBody List<PlatformOrderOperation> orderOperations) throws IOException {
public Result<?> orderManagement(@RequestBody List<PlatformOrderOperation> orderOperations) throws IOException, JSONException {
boolean isEmployee = securityService.checkIsEmployee();
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
Client client;
@ -469,6 +470,9 @@ public class PlatformOrderController {
}
List<Order> mabangOrders = platformOrderMabangService.getOrdersFromMabang(requests, executor);
for(Order mabangOrder : mabangOrders) {
if(mabangOrder.getTrackingNumber() == null) {
continue;
}
if(!mabangOrder.getTrackingNumber().isEmpty()) {
ordersWithTrackingNumber.add(mabangOrder);
}
@ -511,14 +515,17 @@ public class PlatformOrderController {
templateModel.put("lastname", client.getSurname());
if(cancelCount > 0) {
templateModel.put("cancelSuccessCount", cancelResponses.getSuccesses().size() + "/" + cancelCount);
templateModel.put("cancelSuccesses", cancelResponses.getSuccesses());
templateModel.put("cancelFailures", cancelResponses.getFailures());
}
if(suspendCount > 0) {
templateModel.put("suspendSuccessCount", suspendResponses.getSuccesses().size() + "/" + suspendCount);
templateModel.put("suspendSuccesses", suspendResponses.getSuccesses());
templateModel.put("suspendFailures", suspendResponses.getFailures());
}
if(editCount > 0) {
templateModel.put("editSuccessCount", editResponses.getSuccesses().size() + "/" + editCount);
templateModel.put("editSuccesses", editResponses.getSuccesses());
templateModel.put("editFailures", editResponses.getFailures());
}
@ -539,6 +546,13 @@ public class PlatformOrderController {
throw new RuntimeException(e);
}
// sync orders from Mabang
List<String> poIdsSuccesses = new ArrayList<>();
poIdsSuccesses.addAll(cancelResponses.getSuccesses());
poIdsSuccesses.addAll(suspendResponses.getSuccesses());
poIdsSuccesses.addAll(editResponses.getSuccesses());
platformOrderMabangService.syncOrdersFromMabang(poIdsSuccesses);
return Result.OK(result);
}
@GetMapping("/recipientInfo")

View File

@ -1,13 +1,11 @@
package org.jeecg.modules.business.domain.job;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.jeecg.common.api.dto.message.TemplateMessageDTO;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.modules.business.domain.api.mabang.getorderlist.*;
import org.jeecg.modules.business.service.IPlatformOrderMabangService;
import org.jetbrains.annotations.NotNull;
import org.quartz.Job;
@ -17,10 +15,6 @@ import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
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 MabangOrderSyncJob implements Job {
@ -29,7 +23,6 @@ public class MabangOrderSyncJob implements Job {
private IPlatformOrderMabangService platformOrderMabangService;
@Autowired
private ISysBaseAPI ISysBaseApi;
private static final Integer DEFAULT_NUMBER_OF_THREADS = 10;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap jobDataMap = context.getMergedJobDataMap();
@ -54,53 +47,32 @@ public class MabangOrderSyncJob implements Job {
throw new RuntimeException("PlatformOrder ID list can't be empty !");
}
log.info("Syncing following orders {}", platformOrderIds);
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());
int syncedOrderNumber = mabangOrders.size();
List<String> syncedOrderIds = mabangOrders.stream().map(Order::getPlatformOrderId).collect(Collectors.toList());
log.info("{}/{} mabang orders have been retrieved.", syncedOrderNumber, platformOrderIds.size());
log.info("{} orders to be updated.", syncedOrderNumber);
platformOrderMabangService.saveOrderFromMabang(mabangOrders);
Map<String, String> param = new HashMap<>();
param.put("requested_order_number", String.valueOf(platformOrderIds.size()));
param.put("synced_order_number", String.valueOf(syncedOrderNumber));
param.put("requested_order_ids", getHtmlListFromStringList(platformOrderIds));
List<String> failedToSyncOrderIds = new ArrayList<>();
for (String platformOrderId : platformOrderIds) {
if (!syncedOrderIds.contains(platformOrderId)) {
failedToSyncOrderIds.add(platformOrderId);
try {
JSONObject res = platformOrderMabangService.syncOrdersFromMabang(platformOrderIds);
String syncedOrderNumber = String.valueOf(res.getInt("synced_order_number"));
List<String> syncedOrderIds = new ArrayList<>();
JSONArray syncedOrderIdsArray = res.getJSONArray("synced_order_ids");
for (int i = 0; i < syncedOrderIdsArray.length(); i++) {
syncedOrderIds.add(syncedOrderIdsArray.getString(i));
}
Map<String, String> param = new HashMap<>();
param.put("requested_order_number", String.valueOf(platformOrderIds.size()));
param.put("synced_order_number", syncedOrderNumber);
param.put("requested_order_ids", getHtmlListFromStringList(platformOrderIds));
List<String> failedToSyncOrderIds = new ArrayList<>();
for (String platformOrderId : platformOrderIds) {
if (!syncedOrderIds.contains(platformOrderId)) {
failedToSyncOrderIds.add(platformOrderId);
}
}
param.put("failed_to_sync_order_ids", getHtmlListFromStringList(failedToSyncOrderIds));
TemplateMessageDTO message = new TemplateMessageDTO("admin", username == null ? "admin" : username, "马帮订单同步任务", param, "mabang_order_sync_job_result");
ISysBaseApi.sendTemplateAnnouncement(message);
log.info("Order sync job recap message sent");
} catch (JSONException e) {
throw new RuntimeException(e);
}
param.put("failed_to_sync_order_ids", getHtmlListFromStringList(failedToSyncOrderIds));
TemplateMessageDTO message = new TemplateMessageDTO("admin", username == null ? "admin" : username, "马帮订单同步任务", param, "mabang_order_sync_job_result");
ISysBaseApi.sendTemplateAnnouncement(message);
log.info("Order sync job recap message sent");
}
@NotNull

View File

@ -1,6 +1,8 @@
package org.jeecg.modules.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.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.vo.PlatformOrderOperation;
@ -40,4 +42,6 @@ public interface IPlatformOrderMabangService extends IService<Order> {
void clearLogisticChannel(List<Order> orders, ExecutorService executor);
String stripAccents(String input);
JSONObject syncOrdersFromMabang(List<String> platformOrderIds) throws JSONException;
}

View File

@ -1,8 +1,12 @@
package org.jeecg.modules.business.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.*;
import org.jeecg.modules.business.domain.api.mabang.getorderlist.*;
@ -23,6 +27,7 @@ import java.text.Normalizer;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -40,6 +45,8 @@ import static java.util.stream.Collectors.toList;
public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMabangMapper, Order> implements IPlatformOrderMabangService {
@Autowired
private PlatformOrderMabangMapper platformOrderMabangMapper;
@Autowired
private ISysBaseAPI ISysBaseApi;
private static final Integer DEFAULT_NUMBER_OF_THREADS = 2;
private static final Integer MABANG_API_RATE_LIMIT_PER_MINUTE = 10;
@ -324,4 +331,46 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
input = input.replaceAll("[^\\p{ASCII}]", "");
return input;
}
@Transactional
@Override
public JSONObject syncOrdersFromMabang(List<String> platformOrderIds) throws JSONException {
log.info("Syncing following orders {}", platformOrderIds);
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(10);
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());
int syncedOrderNumber = mabangOrders.size();
List<String> syncedOrderIds = mabangOrders.stream().map(Order::getPlatformOrderId).collect(Collectors.toList());
log.info("{}/{} mabang orders have been retrieved.", syncedOrderNumber, platformOrderIds.size());
log.info("{} orders to be updated.", syncedOrderNumber);
saveOrderFromMabang(mabangOrders);
JSONObject res = new JSONObject();
res.put("synced_order_number", syncedOrderNumber);
res.put("synced_order_ids", syncedOrderIds);
return res;
}
}

View File

@ -7,7 +7,13 @@
</tr>
<#if cancelSuccessCount??>
<tr>
<td style="padding:0 0 35px 0;">Demandes d'annulations de commande : <b>${cancelSuccessCount}</b> réussie(s)</td>
<td style="padding:0 0 35px 0;">Demandes d'annulations de commande : <b>${cancelSuccessCount}</b> réussie(s) :
<ul>
<#list cancelSuccesses as success>
<li>${success}</li>
</#list>
</ul>
</td>
</tr>
<#if cancelFailures?size gt 0 >
<tr>
@ -23,7 +29,13 @@
</#if>
<#if suspendSuccessCount??>
<tr>
<td style="padding:0 0 35px 0;">Demandes de suspension de commande : <b>${suspendSuccessCount}</b> réussie(s)</td>
<td style="padding:0 0 35px 0;">Demandes de suspension de commande : <b>${suspendSuccessCount}</b> réussie(s) :
<ul>
<#list suspendSuccesses as success>
<li>${success}</li>
</#list>
</ul>
</td>
</tr>
<#if suspendFailures?size gt 0 >
<tr>
@ -39,7 +51,13 @@
</#if>
<#if editSuccessCount??>
<tr>
<td style="padding:0 0 35px 0;">Demandes de modification d'informations de commande : <b>${editSuccessCount}</b> réussie(s)</td>
<td style="padding:0 0 35px 0;">Demandes de modification d'informations de commande : <b>${editSuccessCount}</b> réussie(s) :
<ul>
<#list editSuccesses as success>
<li>${success}</li>
</#list>
</ul>
</td>
</tr>
<#if editFailures?size gt 0 >
<tr>