close #78, close #79; feat : set orders to normal job and change warehouse job

pull/8040/head
Gauthier LO 2024-06-05 14:22:44 +02:00
parent 556820e0e2
commit 58b11bac0b
22 changed files with 873 additions and 3 deletions

View File

@ -24,6 +24,7 @@ public class ChangeOrderRequestBody implements RequestBody {
private final static String DEFAULT_WAREHOUSE_NAME = "SZBA宝安仓";
@Getter
public enum OperationType {
MODIFY(1),
REMOVE(2),

View File

@ -0,0 +1,15 @@
package org.jeecg.modules.business.domain.api.mabang.dochangeorder;
import org.jeecg.modules.business.domain.api.mabang.Request;
public class ChangeWarehouseRequest extends Request {
public ChangeWarehouseRequest(ChangeWarehouseRequestBody body) {
super(body);
}
@Override
public ChangeOrderResponse send() {
String jsonString = rawSend().getBody();
return ChangeOrderResponse.parse(jsonString);
}
}

View File

@ -0,0 +1,75 @@
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.jeecg.modules.business.domain.api.mabang.RequestBody;
import org.jeecg.modules.business.domain.api.mabang.getorderlist.Order;
import org.jeecg.modules.business.domain.api.mabang.getorderlist.OrderItem;
import java.util.function.Function;
import static org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeOrderRequestBody.OperationType;
@Getter
@Setter
public class ChangeWarehouseRequestBody implements RequestBody {
private Order order;
private String platformOrderId;
private String warehouseName;
private String recipient;
private String street1;
private String street2;
public ChangeWarehouseRequestBody(Order order, String warehouseName) {
this.platformOrderId = order.getPlatformOrderId();
this.warehouseName = warehouseName;
this.recipient = order.getRecipient();
this.street1 = order.getAddress();
this.street2 = order.getAddress2();
this.order = order;
}
@Override
public String api() {
return "order-do-change-order";
}
@Override
public JSONObject parameters() {
JSONObject json = new JSONObject();
JSONArray stockDataArray = new JSONArray();
putNonNull(json, "platformOrderId", platformOrderId);
putNonNull(json, "buyerName", recipient);
putNonNull(json, "street1", street1);
putNonNull(json, "street2", street2);
if(order.getOrderItems() != null && !order.getOrderItems().isEmpty()) {
for(OrderItem orderItem : order.getOrderItems()) {
if(!isSkuValidFormat(orderItem.getErpCode()))
continue;
JSONObject stockData = new JSONObject();
stockData.put("type", OperationType.MODIFY.getCode());
stockData.put("stockSku", orderItem.getErpCode());
stockData.put("warehouseName", warehouseName);
stockData.put("erpOrderItemId", orderItem.getErpOrderItemId());
stockDataArray.add(stockData);
}
}
putNonNull(json, "stockData", stockDataArray.toJSONString());
return json;
}
private boolean isSkuValidFormat(String sku) {
return sku != null && !sku.matches("^[0-9]+$");
}
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));
}
}
}

View File

@ -89,6 +89,16 @@ public class Order {
*/
@JSONField(name = "postCode")
private String postcode;
/**
* 1
*/
@JSONField(name = "street1")
private String address;
/**
* 2
*/
@JSONField(name = "street2")
private String address2;
/**
*
*/
@ -127,6 +137,10 @@ public class Order {
@TableField(exist = false)
private List<OrderItem> orderItems;
@JSONField(name = "orderTypeNew")
@TableField(exist = false)
private OrderTypeNew orderType;
@JSONField(name = "phone1")
private String phone1;

View File

@ -24,6 +24,11 @@ public class OrderItem {
@JSONField(name = "originOrderId")
private String originOrderId;
@JSONField(name="erpOrderItemId")
private String erpOrderItemId;
@JSONField(name = "stockWarehouseName")
private String warehouseName;
/**
* 1 =
* 2 =

View File

@ -0,0 +1,12 @@
package org.jeecg.modules.business.domain.api.mabang.getorderlist;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
@Data
public class OrderTypeLabel {
@JSONField(name = "typeId")
private String typeId;
@JSONField(name = "name")
private String name;
}

View File

@ -0,0 +1,12 @@
package org.jeecg.modules.business.domain.api.mabang.getorderlist;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
@Data
public class OrderTypeNew {
@JSONField(name = "normalLabels")
private OrderTypeLabel[] normalLabels;
@JSONField(name = "abnormalLabels")
private OrderTypeLabel[] abnormalLabels;
}

View File

@ -13,7 +13,7 @@ import java.util.function.Function;
public class OrderSuspendRequestBody implements RequestBody {
private String platformOrderId;
private final String abnormal_label_name = "客户要求暂时不处理";
private String abnormal_label_name = "客户要求暂时不处理";
private String description;
public OrderSuspendRequestBody(String platformOrderId, String description) {

View File

@ -0,0 +1,30 @@
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderNormal;
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 OrderToNormalRequest extends Request {
public OrderToNormalRequest(OrderToNormalRequestBody body) {
super(body);
}
@Override
public OrderToNormalResponse send() {
ResponseEntity<String> res = rawSend();
return OrderToNormalResponse.parse(JSON.parseObject(res.getBody()));
}
}

View File

@ -0,0 +1,41 @@
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderNormal;
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 OrderToNormalRequestBody implements RequestBody {
private String platformOrderId;
public OrderToNormalRequestBody(String platformOrderId) {
this.platformOrderId = platformOrderId;
}
@Override
public String api() {
return "order-do-order-normal";
}
@Override
public Map<String, Object> parameters() {
JSONObject json = new JSONObject();
putNonNull(json, "platformOrderId", platformOrderId);
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));
}
}
}

View File

@ -0,0 +1,11 @@
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderNormal;
/**
* This class represents error that is returned by target order-do-order-abnormal API
* Message will contain error details.
*/
public class OrderToNormalRequestErrorException extends RuntimeException {
public OrderToNormalRequestErrorException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,45 @@
package org.jeecg.modules.business.domain.api.mabang.orderDoOrderNormal;
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 OrderToNormalResponse extends Response {
private final String message;
OrderToNormalResponse(Code successCode, String message) {
super(successCode);
this.message = message;
}
/**
* 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 OrderToNormalRequestErrorException if response code represents error.
*/
public static OrderToNormalResponse parse(JSONObject json) throws OrderToNormalRequestErrorException {
log.debug("Constructing a response by json.");
String code = json.getString("code");
String message = json.getString("message");
if (code.equals("200"))
return new OrderToNormalResponse(Code.SUCCESS, message);
else
return new OrderToNormalResponse(Code.ERROR, message);
}
@Override
public String toString() {
return "OrderToNormalResponse{" +
", code=" + this.success() +
'}';
}
}

View File

@ -0,0 +1,12 @@
package org.jeecg.modules.business.domain.job;
import lombok.Data;
import java.util.List;
@Data
public class ChangeWareHouseParam {
private String shop;
private List<String> skus;
private List<String> countries;
}

View File

@ -0,0 +1,192 @@
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.modules.business.domain.api.mabang.dochangeorder.*;
import org.jeecg.modules.business.domain.api.mabang.getorderlist.*;
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.service.IPlatformOrderService;
import org.jeecg.modules.business.vo.Responses;
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.text.Normalizer;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
@Slf4j
public class ChangeWarehouseJob implements Job {
@Autowired
private IPlatformOrderService platformOrderService;
private static final Integer DEFAULT_NUMBER_OF_DAYS = 5;
private static final Integer DEFAULT_NUMBER_OF_THREADS = 10;
private final String DEFAULT_WAREHOUSE_NAME = "法国巴黎仓库-唯客路";
private final String DEFAULT_ABNORMAL_LABEL_NAME = "AC海外仓非法国比利时不发货";
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
log.info("Executing ChangeWarehouseJob...");
LocalDateTime endDateTime = LocalDateTime.now();
LocalDateTime startDateTime = endDateTime.minusDays(DEFAULT_NUMBER_OF_DAYS);
List<String> allSkus = new ArrayList<>();
List<ChangeWareHouseParam> changeWareHouseParams = 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("data")) {
JSONArray dataJsonArray = jsonObject.getJSONArray("data");
for (int i = 0; i < dataJsonArray.length(); i++) {
JSONObject object = dataJsonArray.getJSONObject(i);
ChangeWareHouseParam param = new ChangeWareHouseParam();
if(!object.isNull("shop")) {
param.setShop(object.getString("shop"));
}
if(!object.isNull("skus")) {
JSONArray skusJsonArray = object.getJSONArray("skus");
List<String> skus = new ArrayList<>();
for(int j = 0; j < skusJsonArray.length(); j++) {
skus.add(skusJsonArray.getString(j));
}
param.setSkus(skus);
allSkus.addAll(skus);
}
if(!object.isNull("countries")) {
List<String> countries = new ArrayList<>();
JSONArray countriesJsonArray = object.getJSONArray("countries");
for (int j = 0; j < countriesJsonArray.length(); j++) {
countries.add(countriesJsonArray.getString(j));
}
param.setCountries(countries);
}
changeWareHouseParams.add(param);
}
}
} 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 !");
}
ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_NUMBER_OF_THREADS);
List<String> platformOrderIds = new ArrayList<>();
List<String> ordersToSetAbnormal = new ArrayList<>();
for(ChangeWareHouseParam param: changeWareHouseParams) {
List<String> poIds = platformOrderService.fetchUninvoicedOrdersWithSkusInCountry(startDateTime, endDateTime, param.getShop(), param.getSkus(), param.getCountries());
List<String> abnormalPoIds = platformOrderService.fetchUninvoicedOrdersWithSkusNotInCountry(startDateTime, endDateTime, param.getShop(), allSkus, param.getCountries());
platformOrderIds.addAll(poIds);
ordersToSetAbnormal.addAll(abnormalPoIds);
}
// fetch orders from mabang
log.info("Fetching orders from mabang...");
List<List<String>> platformOrderIdLists = Lists.partition(platformOrderIds, 10);
List<Order> mabangOrders = new ArrayList<>();
List<OrderListRequestBody> requests = new ArrayList<>();
for (List<String> platformOrderIdList : platformOrderIdLists) {
requests.add(new OrderListRequestBody().setPlatformOrderIds(platformOrderIdList));
}
List<CompletableFuture<Boolean>> completableFutures = 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 while fetching orders from mabang: {}", e.getMessage());
}
return success;
}, executor))
.collect(Collectors.toList());
List<Boolean> fetchResults = completableFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
long fetchSuccessCount = fetchResults.stream().filter(Boolean::booleanValue).count();
log.info("Successfully fetched {} out of {} orders from mabang.", fetchSuccessCount, fetchResults.size());
log.info("Updating recipients info...");
replaceOrdersAccents(mabangOrders);
log.info("Updating warehouse name...");
List<CompletableFuture<Boolean>> futures = mabangOrders.stream()
.map(order -> CompletableFuture.supplyAsync(() -> {
ChangeWarehouseRequestBody body = new ChangeWarehouseRequestBody(order, DEFAULT_WAREHOUSE_NAME);
ChangeWarehouseRequest request = new ChangeWarehouseRequest(body);
ChangeOrderResponse response = request.send();
return response.success();
}, executor))
.collect(Collectors.toList());
List<Boolean> results = futures.stream().map(CompletableFuture::join).collect(Collectors.toList());
long successCount = results.stream().filter(Boolean::booleanValue).count();
log.info("Successfully changed warehouse for {} out of {} orders.", successCount, results.size());
log.info("Setting orders to abnormal...");
Responses responses = new Responses();
List<CompletableFuture<Responses>> abnormalFutures = ordersToSetAbnormal.stream()
.map(id -> CompletableFuture.supplyAsync(() -> {
OrderSuspendRequestBody body = new OrderSuspendRequestBody(id, "");
body.setAbnormal_label_name(DEFAULT_ABNORMAL_LABEL_NAME);
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;
}, executor))
.collect(toList());
List<Responses> abnormalResults = abnormalFutures.stream()
.map(CompletableFuture::join)
.collect(toList());
abnormalResults.forEach(r -> {
responses.getSuccesses().addAll(r.getSuccesses());
responses.getFailures().addAll(r.getFailures());
});
log.info("Successfully set {}/{} orders to abnormal.", responses.getSuccesses().size(), ordersToSetAbnormal.size());
executor.shutdown();
}
public void replaceOrdersAccents(List<Order> orders) {
for(Order order: orders) {
order.setRecipient(stripAccents(order.getRecipient()));
order.setAddress(stripAccents(order.getAddress()));
order.setAddress2(stripAccents(order.getAddress2()));
}
}
public String stripAccents(String input) {
input = Normalizer.normalize(input, Normalizer.Form.NFD);
input = input.replaceAll("[^\\p{ASCII}]", "");
return input;
}
}

View File

@ -0,0 +1,183 @@
package org.jeecg.modules.business.domain.job;
import com.google.common.collect.Lists;
import freemarker.template.Template;
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.modules.business.domain.api.mabang.getorderlist.*;
import org.jeecg.modules.business.domain.api.mabang.orderDoOrderNormal.OrderToNormalRequest;
import org.jeecg.modules.business.domain.api.mabang.orderDoOrderNormal.OrderToNormalRequestBody;
import org.jeecg.modules.business.domain.api.mabang.orderDoOrderNormal.OrderToNormalResponse;
import org.jeecg.modules.business.entity.PlatformOrder;
import org.jeecg.modules.business.entity.PlatformOrderContent;
import org.jeecg.modules.business.service.EmailService;
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.core.env.Environment;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import java.time.LocalDate;
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 SetOrderToNormalJob implements Job {
@Autowired
private EmailService emailService;
@Autowired
private IPlatformOrderService platformOrderService;
@Autowired
Environment env;
@Autowired
private FreeMarkerConfigurer freemarkerConfigurer;
private static final Integer DEFAULT_NUMBER_OF_THREADS = 10;
private final String WAREHOUSE_NAME = "法国巴黎仓库-唯客路";
private final String ABNORMAL_LABEL_NAME = "自动创建SKU的订单";
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
log.info("Executing SetOrderToNormalJob...");
JobDataMap jobDataMap = context.getMergedJobDataMap();
String parameter = ((String) jobDataMap.get("parameter"));
List<String> skus = new ArrayList<>();
List<String> shops = new ArrayList<>();
if (parameter != null) {
try {
JSONObject jsonObject = new JSONObject(parameter);
if(!jsonObject.isNull("skus")) {
JSONArray skusJsonArray = jsonObject.getJSONArray("skus");
for (int i = 0; i < skusJsonArray.length(); i++) {
skus.add(skusJsonArray.getString(i));
}
}
if(!jsonObject.isNull("shops")) {
JSONArray shopsJsonArray = jsonObject.getJSONArray("shops");
for (int i = 0; i < shopsJsonArray.length(); i++) {
shops.add(shopsJsonArray.getString(i));
}
}
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
List<String> orderIds = platformOrderService.findReadyAbnormalOrders(skus, shops);
List<String> orderIdsWithSkus = platformOrderService.findReadyAbnormalOrdersWithSkus(skus);
List<String> orderReadyWithSkus = orderIds.stream()
.filter(orderIdsWithSkus::contains)
.collect(Collectors.toList());
if(!orderReadyWithSkus.isEmpty()) {
Map<PlatformOrder, List<PlatformOrderContent>> orderContents = platformOrderService.fetchOrderData(orderReadyWithSkus);
// Remove orders that contains sku from "skus" list and have wrong warehouse
for(Map.Entry<PlatformOrder, List<PlatformOrderContent>> entry : orderContents.entrySet()) {
for(PlatformOrderContent content : entry.getValue()) {
if(!content.getWarehouseName().equals(WAREHOUSE_NAME)) {
orderIds.remove(content.getPlatformOrderId());
break;
}
}
}
}
ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_NUMBER_OF_THREADS);
List<String> platform_order_ids = platformOrderService.listByIds(orderIds).stream()
.map(PlatformOrder::getPlatformOrderId)
.collect(Collectors.toList());
List<Order> mabangOrders = new ArrayList<>();
List<List<String>> partitionedPlatformOrderIds = Lists.partition(platform_order_ids, 10);
List<OrderListRequestBody> requests = new ArrayList<>();
for (List<String> platformOrderIdList : partitionedPlatformOrderIds) {
requests.add(new OrderListRequestBody().setPlatformOrderIds(platformOrderIdList));
}
// Fetch orders from mabang
List<CompletableFuture<Boolean>> mabangFutures = requests.stream()
.map(request -> CompletableFuture.supplyAsync(() -> {
boolean success = false;
OrderListRawStream rawStream = new OrderListRawStream(request);
OrderListStream stream = new OrderListStream(rawStream);
List<Order> orders = stream.all();
mabangOrders.addAll(orders);
success = !orders.isEmpty();
return success;
}, executor))
.collect(Collectors.toList());
List<Boolean> fetchResults = mabangFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
long fetchSuccessCount = fetchResults.stream().filter(Boolean::booleanValue).count();
log.info("Successfully fetched {} out of {} orders groups from mabang.", fetchSuccessCount, fetchResults.size());
List<String> poIdsToSetNormal = new ArrayList<>();
if(!mabangOrders.isEmpty()) {
for(Order order : mabangOrders) {
OrderTypeLabel[] labels = order.getOrderType().getAbnormalLabels();
if(labels.length > 1) {
continue;
}
if(labels[0].getName().equals(ABNORMAL_LABEL_NAME)) {
poIdsToSetNormal.add(order.getPlatformOrderId());
}
}
}
List<CompletableFuture<Boolean>> futures = poIdsToSetNormal.stream()
.map(orderId -> CompletableFuture.supplyAsync(() -> {
log.info("Setting order {} to normal", orderId);
OrderToNormalRequestBody requestBody = new OrderToNormalRequestBody(orderId);
OrderToNormalRequest request = new OrderToNormalRequest(requestBody);
OrderToNormalResponse response = request.send();
return response.success();
}, executor))
.collect(Collectors.toList());
List<Boolean> results = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
long successCount = results.stream().filter(Boolean::booleanValue).count();
log.info("Successfully set {}/{} orders to normal", successCount, poIdsToSetNormal.size());
executor.shutdown();
// send list of order ids by mail
if(!poIdsToSetNormal.isEmpty()) {
String subject = "[" + LocalDate.now() + "] Set Orders To Normal Job Report";
String destEmail = env.getProperty("spring.mail.username");
Properties prop = emailService.getMailSender();
Map<String, Object> templateModel = new HashMap<>();
templateModel.put("orderIds", poIdsToSetNormal);
templateModel.put("count", poIdsToSetNormal.size());
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("admin/ordersSetToNormalJobReport.ftl");
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel);
emailService.sendSimpleMessage(destEmail, subject, htmlBody, session);
log.info("Mail sent successfully !");
} catch (Exception e) {
log.error("Error while sending Set Orders To Normal Job report mail !");
e.printStackTrace();
}
}
}
}

View File

@ -139,6 +139,12 @@ public class PlatformOrderContent implements Serializable {
@Excel(name = "商品多属性", width = 15)
@ApiModelProperty(value = "商品多属性")
private java.lang.String customizationData;
/**
*
*/
@Excel(name = "Warehouse name", width = 15)
@ApiModelProperty(value = "添加的商品仓库")
private String warehouseName;
@Override
public boolean equals(Object o) {

View File

@ -224,4 +224,11 @@ public interface PlatformOrderMapper extends BaseMapper<PlatformOrder> {
void anonymizePersonalData(@Param("period") int indirectClientAnonymizationPeriod);
List<PlatformOrderOption> ordersByShop(@Param("shopID") String shopID);
List<String> fetchUninvoicedOrdersWithSkusInCountry(@Param("startDate") LocalDateTime startDateTime, @Param("endDate") LocalDateTime endDateTime, @Param("shop") String shop, @Param("skus") List<String> skus, @Param("countries") List<String> countries);
List<String> fetchUninvoicedOrdersWithSkusNotInCountry(@Param("startDate") LocalDateTime startDateTime, @Param("endDate") LocalDateTime endDateTime, @Param("shop") String shop, @Param("skus") List<String> skus, @Param("countries") List<String> countries);
List<String> findReadyAbnormalOrders(@Param("skus") List<String> skus, @Param("shops") List<String> shops);
List<String> findReadyAbnormalOrdersWithSkus(@Param("skus") List<String> skus);
}

View File

@ -195,14 +195,14 @@
INSERT INTO platform_order_content(
id, create_by, create_time,
update_by, update_time, platform_order_id,
sku_id, quantity, erp_status, product_available, customization_data)
sku_id, quantity, erp_status, product_available, customization_data, warehouse_name)
VALUES
<foreach collection="items" separator="," open="" close="" item="item" index="index">
(
UUID(), 'Mabang API', NOW(),
'Mabang API', NOW(), #{item.platformOrderId},
skuErpToId(#{item.erpCode}), #{item.quantity}, #{item.erpStatus},
#{item.productAvailable}, #{item.specifics})
#{item.productAvailable}, #{item.specifics}, #{item.warehouseName})
</foreach>
</insert>

View File

@ -898,4 +898,170 @@
WHERE shop_id = #{shopID}
AND erp_status IN (1,2,3)
</select>
<select id="fetchUninvoicedOrdersWithSkusInCountry" resultType="java.lang.String">
SELECT po.platform_order_id
FROM platform_order po
JOIN shop ON po.shop_id = shop.id
JOIN country c ON po.country = c.name_en
JOIN platform_order_content poc ON po.id = poc.platform_order_id
JOIN sku s ON poc.sku_id = s.id
WHERE po.erp_status IN (1,2)
AND po.can_send = 2
AND c.code IN
<foreach
collection="countries"
separator=","
open="("
close=")"
index="index"
item="country"
>
#{country}
</foreach>
AND shop.erp_code = #{shop}
AND s.erp_code IN
<foreach
collection="skus"
separator=","
open="("
close=")"
index="index"
item="sku"
>
#{sku}
</foreach>
AND order_time &gt;= #{startDate}
AND order_time &lt;= #{endDate}
AND shipping_invoice_number IS NULL;
</select>
<select id="fetchUninvoicedOrdersWithSkusNotInCountry" resultType="java.lang.String">
SELECT po.platform_order_id
FROM platform_order po
JOIN shop ON po.shop_id = shop.id
JOIN country c ON po.country = c.name_en
JOIN platform_order_content poc ON po.id = poc.platform_order_id
JOIN sku s ON poc.sku_id = s.id
WHERE po.erp_status IN (1,2)
AND po.can_send = 2
AND c.code NOT IN
<foreach
collection="countries"
separator=","
open="("
close=")"
index="index"
item="country"
>
#{country}
</foreach>
AND shop.erp_code = #{shop}
AND s.erp_code IN
<foreach
collection="skus"
separator=","
open="("
close=")"
index="index"
item="sku"
>
#{sku}
</foreach>
AND order_time &gt;= #{startDate}
AND order_time &lt;= #{endDate}
AND shipping_invoice_number IS NULL;
</select>
<select id="findReadyAbnormalOrders" resultType="java.lang.String">
WITH skusInAbnormalOrders AS (
SELECT poc.sku_id , poc.platform_order_id, poc.erp_status
FROM platform_order po
JOIN platform_order_content poc ON po.id = poc.platform_order_id
JOIN shop s ON po.shop_id = s.id
WHERE can_send = 2
AND po.erp_status IN (1,2)
AND po.order_time &gt;= NOW() - INTERVAL 5 DAY
AND s.erp_code IN
<foreach
collection="shops"
separator=","
open="("
close=")"
index="index"
item="shop">
#{shop}
</foreach>
),
orders_with_bad_sku AS (
SELECT DISTINCT
CASE
WHEN s.id IS NULL AND sao.erp_status &lt;&gt; 5 THEN sao.platform_order_id
END as order_id
FROM skusInAbnormalOrders sao
LEFT JOIN sku s ON sao.sku_id = s.id
),
ac_orders AS (
SELECT DISTINCT poc.platform_order_id as id
FROM platform_order_content poc
JOIN sku s ON poc.sku_id = s.id
JOIN platform_order po ON poc.platform_order_id = po.id
WHERE po.can_send IN (1,2)
AND po.can_send = 2
AND po.order_time &gt;= NOW() - INTERVAL 5 DAY
AND s.erp_code IN
<foreach
collection="skus"
separator=","
open="("
close=")"
index="index"
item="sku">
#{sku}
</foreach>
AND poc.erp_status &lt;&gt; 5
AND poc.warehouse_name != '法国巴黎仓库-唯客路'
),
orders_ready AS (
SELECT po.id as id
FROM platform_order po
JOIN shop s ON po.shop_id = s.id
LEFT JOIN orders_with_bad_sku owbs ON po.id = owbs.order_id
WHERE owbs.order_id IS NULL
AND po.erp_status IN (1,2)
AND po.can_send = 2
AND po.order_time &gt;= NOW() - INTERVAL 5 DAY
AND s.erp_code IN
<foreach
collection="shops"
separator=","
open="("
close=")"
index="index"
item="shop">
#{shop}
</foreach>
)
SELECT ors.id
FROM orders_ready ors
WHERE ors.id NOT IN (SELECT * FROM ac_orders);
</select>
<select id="findReadyAbnormalOrdersWithSkus" resultType="java.lang.String">
SELECT DISTINCT poc.platform_order_id
FROM platform_order_content poc
JOIN sku s ON poc.sku_id = s.id
JOIN platform_order po ON poc.platform_order_id = po.id
WHERE po.can_send IN (1,2)
AND po.can_send = 2
AND po.order_time &gt;= NOW() - INTERVAL 5 DAY
AND s.erp_code IN
<foreach
collection="skus"
separator=","
open="("
close=")"
index="index"
item="sku">
#{sku}
</foreach>
AND poc.erp_status &lt;&gt; 5
AND poc.warehouse_name = '法国巴黎仓库-唯客路';
</select>
</mapper>

View File

@ -248,4 +248,11 @@ public interface IPlatformOrderService extends IService<PlatformOrder> {
void anonymizePersonalData(int indirectClientAnonymizationPeriod);
List<PlatformOrderOption> ordersByShop(String shopID);
List<String> fetchUninvoicedOrdersWithSkusInCountry(LocalDateTime startDateTime, LocalDateTime endDateTime, String shop, List<String> skus, List<String> countries);
List<String> fetchUninvoicedOrdersWithSkusNotInCountry(LocalDateTime startDateTime, LocalDateTime endDateTime, String shop, List<String> skus, List<String> countries);
List<String> findReadyAbnormalOrders(List<String> skus, List<String> shops);
List<String> findReadyAbnormalOrdersWithSkus(List<String> skus);
}

View File

@ -501,4 +501,23 @@ public class PlatformOrderServiceImpl extends ServiceImpl<PlatformOrderMapper, P
public List<PlatformOrderOption> ordersByShop(String shopID) {
return platformOrderMap.ordersByShop(shopID);
}
@Override
public List<String> fetchUninvoicedOrdersWithSkusInCountry(LocalDateTime startDateTime, LocalDateTime endDateTime, String shop, List<String> skus, List<String> countries) {
return platformOrderMap.fetchUninvoicedOrdersWithSkusInCountry(startDateTime, endDateTime, shop, skus, countries);
}
@Override
public List<String> fetchUninvoicedOrdersWithSkusNotInCountry(LocalDateTime startDateTime, LocalDateTime endDateTime, String shop, List<String> skus, List<String> countries) {
return platformOrderMap.fetchUninvoicedOrdersWithSkusNotInCountry(startDateTime, endDateTime, shop, skus, countries);
}
@Override
public List<String> findReadyAbnormalOrders(List<String> skus, List<String> shops) {
return platformOrderMap.findReadyAbnormalOrders(skus, shops);
}
@Override
public List<String> findReadyAbnormalOrdersWithSkus(List<String> skus) {
return platformOrderMap.findReadyAbnormalOrdersWithSkus(skus);
}
}

View File

@ -0,0 +1,17 @@
<#include "../components/header.ftl">
<tr>
<td style="padding:35px 0;">Cher Collègue</td>
</tr>
<tr>
<td style="padding:0 0 35px 0;">Voici la liste des commandes dont le status a été mis à jour à "Normal" :</td>
</tr>
<tr>
<td style="padding:10px 0;">Nombre de commandes :<b> ${count}</b><br/>
<ul>
<#list orderIds as orderId>
<li>${orderId}</li>
</#list>
</ul>
</td>
</tr>
<#include "../components/footer.ftl">