mirror of https://github.com/jeecgboot/jeecg-boot
feat : client order management via Mabang API
parent
a85c7b6beb
commit
0415ca6b5b
|
@ -1,18 +1,31 @@
|
|||
package org.jeecg.modules.business.controller.admin;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.mail.Authenticator;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.PasswordAuthentication;
|
||||
import javax.mail.Session;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import org.jeecg.modules.business.domain.api.mabang.getorderlist.OrderStatus;
|
||||
import org.jeecg.modules.business.domain.job.ThrottlingExecutorService;
|
||||
import org.jeecg.modules.business.entity.Client;
|
||||
import org.jeecg.modules.business.mapper.PlatformOrderMapper;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderQuantity;
|
||||
import org.jeecg.modules.business.service.*;
|
||||
import org.jeecg.modules.business.vo.*;
|
||||
import org.jeecg.modules.system.service.ISysDepartService;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
|
@ -25,11 +38,10 @@ import org.jeecg.common.system.query.QueryGenerator;
|
|||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.business.entity.PlatformOrderContent;
|
||||
import org.jeecg.modules.business.entity.PlatformOrder;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderPage;
|
||||
import org.jeecg.modules.business.service.IPlatformOrderService;
|
||||
import org.jeecg.modules.business.service.IPlatformOrderContentService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -38,10 +50,13 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||
|
||||
import static org.jeecg.modules.business.vo.PlatformOrderOperation.Action.CANCEL;
|
||||
import static org.jeecg.modules.business.vo.PlatformOrderOperation.Action.SUSPEND;
|
||||
|
||||
/**
|
||||
* @Description: 平台订单表
|
||||
|
@ -54,15 +69,28 @@ import org.jeecg.common.aspect.annotation.AutoLog;
|
|||
@RequestMapping("/business/platformOrder")
|
||||
@Slf4j
|
||||
public class PlatformOrderController {
|
||||
private final IPlatformOrderService platformOrderService;
|
||||
|
||||
@Autowired
|
||||
private IClientService clientService;
|
||||
@Autowired
|
||||
private EmailService emailService;
|
||||
@Autowired
|
||||
private IPlatformOrderService platformOrderService;
|
||||
@Autowired
|
||||
private PlatformOrderMapper platformOrderMapper;
|
||||
@Autowired
|
||||
public PlatformOrderController(IPlatformOrderService platformOrderService) {
|
||||
this.platformOrderService = platformOrderService;
|
||||
}
|
||||
private IPlatformOrderMabangService platformOrderMabangService;
|
||||
@Autowired
|
||||
private IShopService shopService;
|
||||
@Autowired
|
||||
private ISysDepartService sysDepartService;
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
@Autowired
|
||||
private FreeMarkerConfigurer freemarkerConfigurer;
|
||||
|
||||
private static final Integer DEFAULT_NUMBER_OF_THREADS = 2;
|
||||
private static final Integer MABANG_API_RATE_LIMIT_PER_MINUTE = 10;
|
||||
|
||||
/**
|
||||
* Fetchs all orders with erp_status = 1, no logicistic channel and product available
|
||||
|
@ -343,4 +371,121 @@ public class PlatformOrderController {
|
|||
List<PlatformOrderQuantity> res = platformOrderService.monthOrderNumber();
|
||||
return Result.OK(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all orders by shop with erp status 1, 2 and 3
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/ordersByShop")
|
||||
public Result<List<PlatformOrderOption>> ordersByShop(@RequestParam("shopID") String shopID) {
|
||||
List<PlatformOrderOption> res = platformOrderService.ordersByShop(shopID);
|
||||
return Result.OK(res);
|
||||
}
|
||||
|
||||
@PostMapping("/orderManagement")
|
||||
public Result<?> orderManagement(@RequestBody List<PlatformOrderOperation> orderOperations) throws IOException {
|
||||
String companyOrgCode = sysDepartService.queryCodeByDepartName(env.getProperty("company.orgName"));
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
Client client;
|
||||
if(!sysUser.getOrgCode().equals(companyOrgCode)) {
|
||||
client = clientService.getCurrentClient();
|
||||
if (client == null) {
|
||||
return Result.error(500,"Client not found. Please contact administrator.");
|
||||
}
|
||||
String shopId = orderOperations.get(0).getShopId();
|
||||
List<String> shopIds = shopService.listIdByClient(client.getId());
|
||||
if(!shopIds.contains(shopId)) {
|
||||
return Result.error(500,"You are not allowed to perform this operation.");
|
||||
}
|
||||
} else {
|
||||
client = clientService.getByShopId(orderOperations.get(0).getShopId());
|
||||
}
|
||||
|
||||
long suspendCount = 0, cancelCount = 0;
|
||||
List<PlatformOrderOperation> ordersToSuspend = orderOperations.stream()
|
||||
.filter(orderOperation -> orderOperation.getAction().equalsIgnoreCase(SUSPEND.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
List<PlatformOrderOperation> ordersToCancel = orderOperations.stream()
|
||||
.filter(orderOperation -> orderOperation.getAction().equalsIgnoreCase(CANCEL.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
for(PlatformOrderOperation orderOperation : ordersToSuspend) {
|
||||
suspendCount += orderOperation.getOrderIds().split(",").length;
|
||||
}
|
||||
for(PlatformOrderOperation orderOperation : ordersToCancel) {
|
||||
cancelCount += orderOperation.getOrderIds().split(",").length;
|
||||
}
|
||||
log.info("{} Orders to suspend: {}", suspendCount, ordersToSuspend);
|
||||
log.info("{} Orders to cancel: {}", cancelCount, ordersToCancel);
|
||||
|
||||
Responses cancelResponses = new Responses();
|
||||
Responses suspendResponses = new Responses();
|
||||
// Cancel orders
|
||||
ExecutorService cancelExecutorService = ThrottlingExecutorService.createExecutorService(DEFAULT_NUMBER_OF_THREADS,
|
||||
MABANG_API_RATE_LIMIT_PER_MINUTE, TimeUnit.MINUTES);
|
||||
List<CompletableFuture<Responses>> futuresCancel = ordersToCancel.stream()
|
||||
.map(orderOperation -> CompletableFuture.supplyAsync(
|
||||
() -> platformOrderMabangService.cancelOrders(orderOperation),
|
||||
cancelExecutorService)
|
||||
).collect(Collectors.toList());
|
||||
List<Responses>cancelResults = futuresCancel.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||
cancelResults.forEach(res -> {
|
||||
cancelResponses.getSuccesses().addAll(res.getSuccesses());
|
||||
cancelResponses.getFailures().addAll(res.getFailures());
|
||||
});
|
||||
log.info("{}/{} orders cancelled successfully.", cancelResponses.getSuccesses().size(), cancelCount);
|
||||
log.info("Failed to cancel orders: {}", cancelResponses.getFailures());
|
||||
|
||||
|
||||
// Suspend orders
|
||||
ExecutorService suspendExecutorService = ThrottlingExecutorService.createExecutorService(DEFAULT_NUMBER_OF_THREADS,
|
||||
MABANG_API_RATE_LIMIT_PER_MINUTE, TimeUnit.MINUTES);
|
||||
List<CompletableFuture<Responses>> futuresSuspend = ordersToSuspend.stream()
|
||||
.map(orderOperation -> CompletableFuture.supplyAsync(
|
||||
() -> platformOrderMabangService.suspendOrder(orderOperation),
|
||||
suspendExecutorService)
|
||||
).collect(Collectors.toList());
|
||||
List<Responses> suspendResults = futuresSuspend.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||
suspendResults.forEach(res -> {
|
||||
suspendResponses.getSuccesses().addAll(res.getSuccesses());
|
||||
suspendResponses.getFailures().addAll(res.getFailures());
|
||||
});
|
||||
log.info("{}/{} orders suspended successfully.", suspendResponses.getSuccesses().size(), suspendCount);
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("cancelResult", cancelResponses);
|
||||
result.put("suspendResult", suspendResponses);
|
||||
|
||||
// send mail
|
||||
String subject = "[" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "] Orders management report";
|
||||
String destEmail = sysUser.getEmail();
|
||||
Properties prop = emailService.getMailSender();
|
||||
Map<String, Object> templateModel = new HashMap<>();
|
||||
templateModel.put("firstname", client.getFirstName());
|
||||
templateModel.put("lastname", client.getSurname());
|
||||
if(cancelCount > 0)
|
||||
templateModel.put("cancelSuccessCount", cancelResponses.getSuccesses().size() + "/" + cancelCount);
|
||||
if(suspendCount > 0)
|
||||
templateModel.put("suspendSuccessCount", suspendResponses.getSuccesses().size() + "/" + suspendCount);
|
||||
templateModel.put("cancelFailures", cancelResponses.getFailures());
|
||||
templateModel.put("suspendFailures", suspendResponses.getFailures());
|
||||
|
||||
Session session = Session.getInstance(prop, new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(env.getProperty("spring.mail.username"), env.getProperty("spring.mail.password"));
|
||||
}
|
||||
});
|
||||
try {
|
||||
freemarkerConfigurer = emailService.freemarkerClassLoaderConfig();
|
||||
Template freemarkerTemplate = freemarkerConfigurer.getConfiguration()
|
||||
.getTemplate("client/orderManagementNotification.ftl");
|
||||
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel);
|
||||
emailService.sendSimpleMessage(destEmail, subject, htmlBody, session);
|
||||
log.info("Mail sent successfully !");
|
||||
} catch (TemplateException | MessagingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return Result.OK(result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.jeecg.modules.business.domain.api.mabang.dochangeorder;
|
|||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jeecg.modules.business.domain.api.mabang.RequestBody;
|
||||
|
||||
|
@ -10,7 +12,11 @@ import java.util.function.Function;
|
|||
|
||||
public class ChangeOrderRequestBody implements RequestBody {
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private String platformOrderId;
|
||||
private String orderStatus;
|
||||
private String remark;
|
||||
|
||||
private final HashSet<Pair<String, Integer>> oldSkuData;
|
||||
|
||||
|
@ -29,11 +35,13 @@ public class ChangeOrderRequestBody implements RequestBody {
|
|||
}
|
||||
}
|
||||
|
||||
public ChangeOrderRequestBody(String platformOrderId, HashSet<Pair<String, Integer>> oldSkuData,
|
||||
HashSet<Pair<String, Integer>> newSkuData) {
|
||||
public ChangeOrderRequestBody(String platformOrderId, String orderStatus, HashSet<Pair<String, Integer>> oldSkuData,
|
||||
HashSet<Pair<String, Integer>> newSkuData, String remark) {
|
||||
this.platformOrderId = platformOrderId;
|
||||
this.oldSkuData = oldSkuData;
|
||||
this.newSkuData = newSkuData;
|
||||
this.orderStatus = orderStatus;
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,8 +53,10 @@ public class ChangeOrderRequestBody implements RequestBody {
|
|||
public JSONObject parameters() {
|
||||
JSONObject json = new JSONObject();
|
||||
putNonNull(json, "platformOrderId", platformOrderId);
|
||||
putNonNull(json, "orderStatus", orderStatus);
|
||||
putNonNull(json, "remark", remark);
|
||||
JSONArray stockDataArray = new JSONArray();
|
||||
if (!oldSkuData.isEmpty()) {
|
||||
if (oldSkuData != null && !oldSkuData.isEmpty()) {
|
||||
for (Pair<String, Integer> oldSkuDatum : oldSkuData) {
|
||||
JSONObject stockData = new JSONObject();
|
||||
stockData.put("warehouseName", DEFAULT_WAREHOUSE_NAME);
|
||||
|
@ -57,26 +67,20 @@ public class ChangeOrderRequestBody implements RequestBody {
|
|||
}
|
||||
|
||||
}
|
||||
for (Pair<String, Integer> newSkuDatum : newSkuData) {
|
||||
JSONObject stockData = new JSONObject();
|
||||
stockData.put("warehouseName", DEFAULT_WAREHOUSE_NAME);
|
||||
stockData.put("stockSku", newSkuDatum.getKey());
|
||||
stockData.put("quantity", newSkuDatum.getValue());
|
||||
stockData.put("type", OperationType.ADD.code);
|
||||
stockDataArray.add(stockData);
|
||||
if(newSkuData != null) {
|
||||
for (Pair<String, Integer> newSkuDatum : newSkuData) {
|
||||
JSONObject stockData = new JSONObject();
|
||||
stockData.put("warehouseName", DEFAULT_WAREHOUSE_NAME);
|
||||
stockData.put("stockSku", newSkuDatum.getKey());
|
||||
stockData.put("quantity", newSkuDatum.getValue());
|
||||
stockData.put("type", OperationType.ADD.code);
|
||||
stockDataArray.add(stockData);
|
||||
}
|
||||
}
|
||||
json.put("stockData", stockDataArray.toJSONString());
|
||||
putNonNull(json,"stockData", stockDataArray.toJSONString());
|
||||
return json;
|
||||
}
|
||||
|
||||
public String getPlatformOrderId() {
|
||||
return platformOrderId;
|
||||
}
|
||||
|
||||
public void setPlatformOrderId(String platformOrderId) {
|
||||
this.platformOrderId = platformOrderId;
|
||||
}
|
||||
|
||||
private <E> void putNonNull(JSONObject json, String key, E value) {
|
||||
if (value != null) {
|
||||
json.put(key, value);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.modules.business.domain.api.mabang.Request;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* This class contains some key information and necessary procedures
|
||||
* to send a request to mabang "order-do-order-abnormal" API, for example: target URL,
|
||||
* correspondent HTTP method, procedure to generate authorization.
|
||||
* <p>
|
||||
* One can use static method {@code sendRequest} to send request with body,
|
||||
* and then get respective response. Or use instance of this class, see below.
|
||||
* <p>
|
||||
*/
|
||||
@Slf4j
|
||||
public class OrderSuspendRequest extends Request {
|
||||
|
||||
public OrderSuspendRequest(OrderSuspendRequestBody body) {
|
||||
super(body);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public OrderSuspendResponse send() {
|
||||
ResponseEntity<String> res = rawSend();
|
||||
return OrderSuspendResponse.parse(JSON.parseObject(res.getBody()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jeecg.modules.business.domain.api.mabang.RequestBody;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class OrderSuspendRequestBody implements RequestBody {
|
||||
|
||||
private String platformOrderId;
|
||||
private final String abnormal_label_name = "客户要求暂时不处理";
|
||||
private String description;
|
||||
|
||||
public OrderSuspendRequestBody(String platformOrderId, String description) {
|
||||
this.platformOrderId = platformOrderId;
|
||||
this.description = description;
|
||||
}
|
||||
@Override
|
||||
public String api() {
|
||||
return "order-do-order-abnormal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> parameters() {
|
||||
JSONObject json = new JSONObject();
|
||||
putNonNull(json, "platformOrderId", platformOrderId);
|
||||
putNonNull(json, "abnormal_label_name", abnormal_label_name);
|
||||
putNonNull(json, "description", description);
|
||||
return json;
|
||||
}
|
||||
private <E> void putNonNull(JSONObject json, String key, E value) {
|
||||
if (value != null) {
|
||||
json.put(key, value);
|
||||
}
|
||||
}
|
||||
private <E, T> void putNonNull(JSONObject json, String key, E value, Function<E, T> mapper) {
|
||||
if (value != null) {
|
||||
json.put(key, mapper.apply(value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal;
|
||||
|
||||
/**
|
||||
* This class represents error that is returned by target order-do-order-abnormal API
|
||||
* Message will contain error details.
|
||||
*/
|
||||
public class OrderSuspendRequestErrorException extends RuntimeException {
|
||||
public OrderSuspendRequestErrorException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.modules.business.domain.api.mabang.Response;
|
||||
|
||||
/**
|
||||
* Immutable object
|
||||
*/
|
||||
@Slf4j
|
||||
@Getter
|
||||
public class OrderSuspendResponse extends Response {
|
||||
|
||||
OrderSuspendResponse(Code successCode) {
|
||||
super(successCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an instance by parsing json, it only checks validity of code.
|
||||
* if json is not valid, return null
|
||||
*
|
||||
* @param json the json to parse
|
||||
* @return Instance
|
||||
* @throws OrderSuspendRequestErrorException if response code represents error.
|
||||
*/
|
||||
public static OrderSuspendResponse parse(JSONObject json) throws OrderSuspendRequestErrorException {
|
||||
log.debug("Constructing a response by json.");
|
||||
String code = json.getString("code");
|
||||
if (code.equals("200"))
|
||||
return new OrderSuspendResponse(Code.SUCCESS);
|
||||
else
|
||||
return new OrderSuspendResponse(Code.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OrderSuspendResponse{" +
|
||||
", code=" + this.success() +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -126,8 +126,8 @@ public class AddPortraitTubeJob implements Job {
|
|||
HashSet<Pair<String, Integer>> adequateTubes = currentAndAdequateTubes.getRight();
|
||||
// Do nothing if current tubes are the adequate tubes
|
||||
if (!currentTubes.containsAll(adequateTubes) || !adequateTubes.containsAll(currentTubes)) {
|
||||
ChangeOrderRequestBody changeOrderRequestBody = new ChangeOrderRequestBody(mabangOrder.getPlatformOrderId(),
|
||||
currentTubes, adequateTubes);
|
||||
ChangeOrderRequestBody changeOrderRequestBody = new ChangeOrderRequestBody(mabangOrder.getPlatformOrderId(), null,
|
||||
currentTubes, adequateTubes, null);
|
||||
changeOrderRequests.add(changeOrderRequestBody);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,6 @@ public interface ClientMapper extends BaseMapper<Client> {
|
|||
Client getClientFromInvoice(@Param("invoiceNumber") String invoiceNumber);
|
||||
|
||||
void anonymizePersonalData(@Param("period") int directClientAnonymizationPeriod);
|
||||
|
||||
Client getByShopId(@Param("shopId") String shopId);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.jeecg.modules.business.domain.api.mabang.getorderlist.Order;
|
|||
import org.jeecg.modules.business.entity.PlatformOrder;
|
||||
import org.jeecg.modules.business.entity.PlatformOrderShopSync;
|
||||
import org.jeecg.modules.business.vo.OrderKpi;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderOption;
|
||||
import org.jeecg.modules.business.vo.ShippingFeeBillableOrders;
|
||||
import org.jeecg.modules.business.vo.clientPlatformOrder.ClientPlatformOrderPage;
|
||||
import org.jeecg.modules.business.vo.clientPlatformOrder.section.OrderQuantity;
|
||||
|
@ -221,4 +222,6 @@ public interface PlatformOrderMapper extends BaseMapper<PlatformOrder> {
|
|||
Map<String, String> fetchShippingPeriodAndType(@Param("invoiceNumber") String invoiceNumber);
|
||||
|
||||
void anonymizePersonalData(@Param("period") int indirectClientAnonymizationPeriod);
|
||||
|
||||
List<PlatformOrderOption> ordersByShop(@Param("shopID") String shopID);
|
||||
}
|
||||
|
|
|
@ -90,4 +90,10 @@
|
|||
WHERE active = 0
|
||||
AND IF (update_time IS NOT NULL, update_time, create_time) < DATE_SUB(NOW(), INTERVAL #{period} YEAR);
|
||||
</update>
|
||||
<select id="getByShopId" resultType="org.jeecg.modules.business.entity.Client">
|
||||
SELECT c.*
|
||||
FROM client c
|
||||
JOIN shop s ON c.id = s.owner_id
|
||||
WHERE s.id = #{shopId};
|
||||
</select>
|
||||
</mapper>
|
|
@ -891,4 +891,11 @@
|
|||
SET recipient = UUID()
|
||||
WHERE create_time < DATE_SUB(NOW(), INTERVAL #{period} YEAR);
|
||||
</update>
|
||||
|
||||
<select id="ordersByShop" resultType="org.jeecg.modules.business.vo.PlatformOrderOption">
|
||||
SELECT platform_order_id as value, platform_order_number as label, erp_status, IF(erp_status = 1 OR erp_status = 2, false, true) as disabled
|
||||
FROM platform_order
|
||||
WHERE shop_id = #{shopID}
|
||||
AND erp_status IN (1,2,3)
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
@ -287,8 +287,8 @@
|
|||
<select id="listSkus" resultType="org.jeecg.modules.business.entity.Sku">
|
||||
SELECT *
|
||||
FROM sku
|
||||
JOIN client_sku cs ON sku.id = cs.sku_id
|
||||
JOIN client c ON cs.client_id = c.id
|
||||
JOIN client_sku ON sku.id = client_sku.sku_id
|
||||
JOIN client c ON client_sku.client_id = c.id
|
||||
WHERE c.active = 1;
|
||||
</select>
|
||||
<select id="getByErpCode" resultType="org.jeecg.modules.business.entity.Sku">
|
||||
|
|
|
@ -60,4 +60,6 @@ public interface IClientService extends IService<Client> {
|
|||
Client getClientFromInvoice(String invoiceNumber);
|
||||
|
||||
void anonymizePersonalData(int directClientAnonymizationPeriod);
|
||||
|
||||
Client getByShopId(String shopId);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ package org.jeecg.modules.business.service;
|
|||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.business.domain.api.mabang.getorderlist.Order;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderOperation;
|
||||
import org.jeecg.modules.business.vo.Responses;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -10,7 +11,6 @@ import java.util.List;
|
|||
/**
|
||||
* Services related to operations on {@code Order} entity
|
||||
*/
|
||||
@Service
|
||||
public interface IPlatformOrderMabangService extends IService<Order> {
|
||||
/**
|
||||
* Save orders to DB from mabang api.
|
||||
|
@ -29,4 +29,7 @@ public interface IPlatformOrderMabangService extends IService<Order> {
|
|||
*/
|
||||
void updateMergedOrderFromMabang(Order mergedOrder, Collection<String> sourceOrderErpId);
|
||||
|
||||
Responses suspendOrder(PlatformOrderOperation orderOperation);
|
||||
|
||||
Responses cancelOrders(PlatformOrderOperation orderOperation);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.business.controller.UserException;
|
||||
import org.jeecg.modules.business.entity.*;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderOption;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderQuantity;
|
||||
import org.jeecg.modules.business.vo.ShippingFeeBillableOrders;
|
||||
import org.jeecg.modules.business.vo.SkuQuantity;
|
||||
|
@ -245,4 +246,6 @@ public interface IPlatformOrderService extends IService<PlatformOrder> {
|
|||
|
||||
|
||||
void anonymizePersonalData(int indirectClientAnonymizationPeriod);
|
||||
|
||||
List<PlatformOrderOption> ordersByShop(String shopID);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.jeecg.modules.business.service;
|
||||
|
||||
import com.aspose.cells.PdfSaveOptions;
|
||||
import com.aspose.cells.SaveFormat;
|
||||
import com.aspose.cells.Workbook;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
@ -781,9 +782,12 @@ public class PlatformOrderShippingInvoiceService {
|
|||
pdfFilePath = INVOICE_PDF_DIR + "/" + m.group(2) + ".pdf";
|
||||
}
|
||||
// Créé un classeur pour charger le fichier Excel
|
||||
PdfSaveOptions saveOptions = new PdfSaveOptions();
|
||||
saveOptions.setDefaultFont("Arial");
|
||||
saveOptions.setCheckWorkbookDefaultFont(false);
|
||||
Workbook workbook = new Workbook(excelFilePath);
|
||||
// On enregistre le document au format PDF
|
||||
workbook.save(pdfFilePath, SaveFormat.PDF);
|
||||
workbook.save(pdfFilePath, saveOptions);
|
||||
return pdfFilePath;
|
||||
}
|
||||
return "ERROR";
|
||||
|
|
|
@ -166,4 +166,9 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
|
|||
public void anonymizePersonalData(int directClientAnonymizationPeriod) {
|
||||
clientMapper.anonymizePersonalData(directClientAnonymizationPeriod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Client getByShopId(String shopId) {
|
||||
return clientMapper.getByShopId(shopId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,31 @@ package org.jeecg.modules.business.service.impl;
|
|||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeOrderRequest;
|
||||
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeOrderRequestBody;
|
||||
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeOrderResponse;
|
||||
import org.jeecg.modules.business.domain.api.mabang.getorderlist.Order;
|
||||
import org.jeecg.modules.business.domain.api.mabang.getorderlist.OrderItem;
|
||||
import org.jeecg.modules.business.domain.api.mabang.getorderlist.OrderStatus;
|
||||
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.domain.job.ThrottlingExecutorService;
|
||||
import org.jeecg.modules.business.entity.PlatformOrder;
|
||||
import org.jeecg.modules.business.mapper.PlatformOrderMabangMapper;
|
||||
import org.jeecg.modules.business.service.IPlatformOrderMabangService;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderOperation;
|
||||
import org.jeecg.modules.business.vo.Responses;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -30,14 +41,11 @@ import static java.util.stream.Collectors.toList;
|
|||
@Service
|
||||
@Slf4j
|
||||
public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMabangMapper, Order> implements IPlatformOrderMabangService {
|
||||
|
||||
private final PlatformOrderMabangMapper platformOrderMabangMapper;
|
||||
|
||||
@Autowired
|
||||
public PlatformOrderMabangServiceImpl(PlatformOrderMabangMapper platformOrderMabangMapper) {
|
||||
this.platformOrderMabangMapper = platformOrderMabangMapper;
|
||||
}
|
||||
private PlatformOrderMabangMapper platformOrderMabangMapper;
|
||||
|
||||
private static final Integer DEFAULT_NUMBER_OF_THREADS = 2;
|
||||
private static final Integer MABANG_API_RATE_LIMIT_PER_MINUTE = 10;
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveOrderFromMabang(List<Order> orders) {
|
||||
|
@ -193,6 +201,72 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
|||
platformOrderMabangMapper.updateMergedOrderItems(targetID, sourceIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Responses suspendOrder(PlatformOrderOperation orderOperation) {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
List<String> orderIds = Arrays.stream(orderOperation.getOrderIds().split(",")).map(String::trim).collect(toList());
|
||||
// group id is the response from mabang API
|
||||
Responses responses = new Responses();
|
||||
ExecutorService throttlingExecutorService = ThrottlingExecutorService.createExecutorService(DEFAULT_NUMBER_OF_THREADS,
|
||||
MABANG_API_RATE_LIMIT_PER_MINUTE, TimeUnit.MINUTES);
|
||||
|
||||
List<CompletableFuture<Responses>> futures = orderIds.stream()
|
||||
.map(id -> CompletableFuture.supplyAsync(() -> {
|
||||
OrderSuspendRequestBody body = new OrderSuspendRequestBody(id, sysUser.getRealname() + " : " + orderOperation.getReason());
|
||||
OrderSuspendRequest request = new OrderSuspendRequest(body);
|
||||
OrderSuspendResponse response = request.send();
|
||||
Responses r = new Responses();
|
||||
if(response.success())
|
||||
r.addSuccess(id);
|
||||
else
|
||||
r.addFailure(id);
|
||||
return r;
|
||||
}, throttlingExecutorService))
|
||||
.collect(toList());
|
||||
List<Responses> results = futures.stream()
|
||||
.map(CompletableFuture::join)
|
||||
.collect(toList());
|
||||
results.forEach(r -> {
|
||||
responses.getSuccesses().addAll(r.getSuccesses());
|
||||
responses.getFailures().addAll(r.getFailures());
|
||||
});
|
||||
log.info("{}/{} orders suspended successfully.", responses.getSuccesses().size(), orderIds.size());
|
||||
return responses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Responses cancelOrders(PlatformOrderOperation orderOperation) {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
List<String> orderIds = Arrays.stream(orderOperation.getOrderIds().split(",")).map(String::trim).collect(toList());
|
||||
|
||||
Responses responses = new Responses();
|
||||
ExecutorService throttlingExecutorService = ThrottlingExecutorService.createExecutorService(DEFAULT_NUMBER_OF_THREADS,
|
||||
MABANG_API_RATE_LIMIT_PER_MINUTE, TimeUnit.MINUTES);
|
||||
|
||||
List<CompletableFuture<Responses>> futures = orderIds.stream()
|
||||
.map(id -> CompletableFuture.supplyAsync(() -> {
|
||||
ChangeOrderRequestBody body = new ChangeOrderRequestBody(id, "5",null, null, sysUser.getRealname() + " : " + orderOperation.getReason());
|
||||
ChangeOrderRequest request = new ChangeOrderRequest(body);
|
||||
ChangeOrderResponse response = request.send();
|
||||
Responses r = new Responses();
|
||||
if(response.success())
|
||||
r.addSuccess(id);
|
||||
else
|
||||
r.addFailure(id);
|
||||
return r;
|
||||
}, throttlingExecutorService))
|
||||
.collect(toList());
|
||||
List<Responses> results = futures.stream()
|
||||
.map(CompletableFuture::join)
|
||||
.collect(toList());
|
||||
results.forEach(r -> {
|
||||
responses.getSuccesses().addAll(r.getSuccesses());
|
||||
responses.getFailures().addAll(r.getFailures());
|
||||
});
|
||||
log.info("{}/{} orders cancelled successfully.", responses.getSuccesses().size(), orderIds.size());
|
||||
return responses;
|
||||
}
|
||||
|
||||
private void updateExistedOrders(List<Order> orders) {
|
||||
|
||||
}
|
||||
|
|
|
@ -496,4 +496,9 @@ public class PlatformOrderServiceImpl extends ServiceImpl<PlatformOrderMapper, P
|
|||
public void anonymizePersonalData(int indirectClientAnonymizationPeriod) {
|
||||
platformOrderMap.anonymizePersonalData(indirectClientAnonymizationPeriod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PlatformOrderOption> ordersByShop(String shopID) {
|
||||
return platformOrderMap.ordersByShop(shopID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package org.jeecg.modules.business.vo;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PlatformOrderOperation {
|
||||
@JSONField(name = "shopId")
|
||||
private String shopId;
|
||||
@JSONField(name = "orderIds")
|
||||
private String orderIds;
|
||||
@JSONField(name = "action")
|
||||
private String action;
|
||||
@JSONField(name = "reason")
|
||||
private String reason;
|
||||
|
||||
public enum Action {
|
||||
CANCEL("cancel"),
|
||||
SUSPEND("suspend");
|
||||
|
||||
private final String action;
|
||||
|
||||
Action(String value) {
|
||||
this.action = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.jeecg.modules.business.vo;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PlatformOrderOption {
|
||||
/**
|
||||
* PlatformOrder.PlatformOrderNumber
|
||||
*/
|
||||
@JSONField(name = "value")
|
||||
private String value;
|
||||
/**
|
||||
* PlatformOrder.PlatformOrderNumber
|
||||
*/
|
||||
@JSONField(name = "label")
|
||||
private String label;
|
||||
/**
|
||||
* PlatformOrder.ErpStatus
|
||||
*/
|
||||
@JSONField(name = "erp_status")
|
||||
private String erpStatus;
|
||||
/**
|
||||
* PlatformOrder.ErpStatus = 1 or 2 ? false : true
|
||||
*/
|
||||
@JSONField(name = "disabled")
|
||||
private boolean disabled;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package org.jeecg.modules.business.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class Responses {
|
||||
private List<String> successes = new ArrayList<>();
|
||||
private List<String> failures = new ArrayList<>();
|
||||
|
||||
public void addSuccess(String message) {
|
||||
successes.add(message);
|
||||
}
|
||||
public void addFailure(String message) {
|
||||
failures.add(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<#include "../components/header.ftl">
|
||||
<tr>
|
||||
<td style="padding:35px 0;">Cher(e) ${firstname} ${lastname},</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:0 0 35px 0;">Voici un récapitulatif des opérations que vous avez effectuées sur vos commandes :</td>
|
||||
</tr>
|
||||
<#if cancelSuccessCount??>
|
||||
<tr>
|
||||
<td style="padding:0 0 35px 0;">Demandes d'annulations de commande : <b>${cancelSuccessCount}</b> réussie(s)</td>
|
||||
</tr>
|
||||
<#if cancelFailures?size gt 0 >
|
||||
<tr>
|
||||
<td style="padding:0 0 35px 0;">Demandes d'annulations de commande échouées :<br/>
|
||||
<ul>
|
||||
<#list cancelFailures as failure>
|
||||
<li>${failure}</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</#if>
|
||||
</#if>
|
||||
<#if suspendSuccessCount??>
|
||||
<tr>
|
||||
<td style="padding:0 0 35px 0;">Demandes de suspension de commande : <b>${suspendSuccessCount}</b> réussie(s)</td>
|
||||
</tr>
|
||||
<#if suspendFailures?size gt 0 >
|
||||
<tr>
|
||||
<td style="padding:0 0 35px 0;">Demandes de suspension de commande échouées :<br/>
|
||||
<ul>
|
||||
<#list suspendFailures as failure>
|
||||
<li>${failure}</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</#if>
|
||||
</#if>
|
||||
<tr>
|
||||
<td style="padding:0 0 35px 0;">Pour toute information complémentaire nous vous invitons à vous rapprocher de votre conseiller.</td>
|
||||
</tr>
|
||||
<#include "../components/footer.ftl">
|
Loading…
Reference in New Issue