mirror of https://github.com/jeecgboot/jeecg-boot
commit
47b8740a21
|
@ -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")
|
||||
|
|
|
@ -90,6 +90,9 @@ public class SkuData {
|
|||
public SkuStatus getStatus() {
|
||||
return SkuStatus.fromCode(this.status);
|
||||
}
|
||||
public int getStatusValue() {
|
||||
return this.status;
|
||||
}
|
||||
public String toString() {
|
||||
return "ID : " + this.id +
|
||||
"\nStockSkuId : " + this.stockSkuId +
|
||||
|
|
|
@ -18,7 +18,7 @@ public class SkuListRequestBody implements RequestBody {
|
|||
private String stockSku = null;
|
||||
// 50 skus max
|
||||
private String stockSkuList = null;
|
||||
private DateType datetimeType;
|
||||
private DateType datetimeType = DateType.CREATE;
|
||||
private LocalDateTime startDate;
|
||||
private LocalDateTime endDate;
|
||||
private Integer page = 1;
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
package org.jeecg.modules.business.domain.api.mabang.doSearchSkuListNew;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.modules.business.domain.api.mabang.getorderlist.NetworkDataStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* This class provide stream of order.
|
||||
*/
|
||||
@Slf4j
|
||||
public class SkuUpdateListStream implements NetworkDataStream<SkuData> {
|
||||
|
||||
private final NetworkDataStream<SkuListResponse> rawStream;
|
||||
|
||||
private List<SkuData> skus;
|
||||
|
||||
private int index;
|
||||
|
||||
private boolean began;
|
||||
|
||||
/**
|
||||
* Flag of current data is already empty,
|
||||
* either currentOrders is null or currentIndex arrives at the end.
|
||||
* In both case, we should call next() of the rawStream.
|
||||
*/
|
||||
private boolean empty;
|
||||
|
||||
|
||||
public SkuUpdateListStream(NetworkDataStream<SkuListResponse> rawStream) {
|
||||
this.rawStream = rawStream;
|
||||
skus = null;
|
||||
this.index = 0;
|
||||
this.empty = true;
|
||||
this.began = false;
|
||||
}
|
||||
@Override
|
||||
public List<SkuData> all() {
|
||||
SkuData firstElement = attempt();
|
||||
if (firstElement == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
ArrayList<SkuData> res = new ArrayList<>();
|
||||
if (firstElement.getStatus().equals(SkuStatus.Normal) || firstElement.getStatus().equals(SkuStatus.StoppedSelling)) {
|
||||
res.add(firstElement);
|
||||
}
|
||||
while (hasNext()) {
|
||||
SkuData nextSku = next();
|
||||
if(nextSku.getStatus().equals(SkuStatus.Normal) || firstElement.getStatus().equals(SkuStatus.StoppedSelling)) {
|
||||
res.add(nextSku);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@Override
|
||||
public SkuData attempt() {
|
||||
began = true;
|
||||
log.info("Attempting for the first request");
|
||||
SkuListResponse response = rawStream.attempt();
|
||||
if (response == null) {
|
||||
log.info("No response");
|
||||
return null;
|
||||
}
|
||||
if (response.getData().isEmpty()) {
|
||||
log.info("Response with empty data");
|
||||
return null;
|
||||
}
|
||||
skus = response.getData().toJavaList(SkuData.class);
|
||||
index = 1;
|
||||
log.info("Returned the first element");
|
||||
empty = index >= skus.size();
|
||||
return skus.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
// the first time
|
||||
if (!began) {
|
||||
throw new IllegalStateException("Calling hasNext before begin");
|
||||
}
|
||||
|
||||
// Current data is not yet empty
|
||||
if (index < skus.size()) {
|
||||
log.debug("Current order list is not empty yet");
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Current data is empty */
|
||||
this.empty = true;
|
||||
log.debug("Current order list is already empty,");
|
||||
// and raw stream is empty too.
|
||||
if (!rawStream.hasNext()) {
|
||||
log.debug("and source stream is empty too, hasNext: false");
|
||||
return false;
|
||||
}
|
||||
// but raw stream not empty.
|
||||
else {
|
||||
log.debug("but source stream still has data, hasNext: true");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkuData next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException("Stream is empty!");
|
||||
}
|
||||
if (empty) {
|
||||
skus = this.rawStream.next().getData().toJavaList(SkuData.class);
|
||||
empty = false;
|
||||
index = 0;
|
||||
}
|
||||
log.debug("Return data at {}", index);
|
||||
SkuData res = skus.get(index);
|
||||
index++;
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import org.codehaus.jettison.json.JSONObject;
|
|||
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ArchiveOrderRequest;
|
||||
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ArchiveOrderRequestBody;
|
||||
import org.jeecg.modules.business.domain.api.mabang.dochangeorder.ChangeOrderResponse;
|
||||
import org.jeecg.modules.business.service.IPlatformOrderMabangService;
|
||||
import org.jeecg.modules.business.service.IPlatformOrderService;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDataMap;
|
||||
|
@ -36,6 +37,8 @@ public class ArchiveOrderJob implements Job {
|
|||
|
||||
@Autowired
|
||||
private IPlatformOrderService platformOrderService;
|
||||
@Autowired
|
||||
private IPlatformOrderMabangService platformOrderMabangService;
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||
|
@ -86,7 +89,7 @@ public class ArchiveOrderJob implements Job {
|
|||
platformOrderIds.forEach(s -> archiveOrderRequestBodies.add(new ArchiveOrderRequestBody(s)));
|
||||
|
||||
log.info("{} order archiving requests to be sent to MabangAPI", archiveOrderRequestBodies.size());
|
||||
|
||||
List<String> platformOrderIdsArchived = new ArrayList<>();
|
||||
List<CompletableFuture<Boolean>> changeOrderFutures = archiveOrderRequestBodies.stream()
|
||||
.map(archiveOrderRequestBody -> CompletableFuture.supplyAsync(() -> {
|
||||
boolean success = false;
|
||||
|
@ -94,7 +97,9 @@ public class ArchiveOrderJob implements Job {
|
|||
ArchiveOrderRequest archiveOrderRequest = new ArchiveOrderRequest(archiveOrderRequestBody);
|
||||
ChangeOrderResponse response = archiveOrderRequest.send();
|
||||
success = response.success();
|
||||
} catch (RuntimeException e) {
|
||||
if(success)
|
||||
platformOrderIdsArchived.add(archiveOrderRequestBody.getPlatformOrderId());
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Error communicating with MabangAPI", e);
|
||||
}
|
||||
return success;
|
||||
|
@ -103,5 +108,11 @@ public class ArchiveOrderJob implements Job {
|
|||
List<Boolean> results = changeOrderFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||
long nbSuccesses = results.stream().filter(b -> b).count();
|
||||
log.info("{}/{} order archiving requests have succeeded.", nbSuccesses, archiveOrderRequestBodies.size());
|
||||
|
||||
try {
|
||||
platformOrderMabangService.syncOrdersFromMabang(platformOrderIdsArchived);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
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.doSearchSkuListNew.*;
|
||||
import org.jeecg.modules.business.service.ISkuListMabangService;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Job that retrieves all Sku from Mabang
|
||||
* if the sku is of status 3 (normal) and not in DB, then we insert it in DB
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MabangSkuSyncJob implements Job {
|
||||
|
||||
@Autowired
|
||||
private ISkuListMabangService skuListMabangService;
|
||||
private static final Integer DEFAULT_NUMBER_OF_DAYS = 5;
|
||||
private static final DateType DEFAULT_DATE_TYPE = DateType.UPDATE;
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||
LocalDateTime endDateTime = LocalDateTime.now(ZoneId.of(ZoneId.SHORT_IDS.get("CTT")));
|
||||
LocalDateTime startDateTime = endDateTime.minusDays(DEFAULT_NUMBER_OF_DAYS);
|
||||
List<String> skus = new ArrayList<>();
|
||||
DateType dateType = DEFAULT_DATE_TYPE;
|
||||
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("dateType")) {
|
||||
dateType = DateType.fromCode(jsonObject.getInt("dateType"));
|
||||
}
|
||||
if (!jsonObject.isNull("skus")) {
|
||||
JSONArray array = jsonObject.getJSONArray("skus");
|
||||
for(int i = 0; i < array.length(); i++) {
|
||||
skus.add(array.getString(i));
|
||||
}
|
||||
}
|
||||
} 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 !");
|
||||
}
|
||||
|
||||
try {
|
||||
if(skus.isEmpty()) {
|
||||
log.info("Updating skus by date");
|
||||
while (startDateTime.until(endDateTime, ChronoUnit.HOURS) > 0) {
|
||||
LocalDateTime dayBeforeEndDateTime = endDateTime.minusDays(1);
|
||||
SkuListRequestBody body = SkuListRequestBodys.allSkuOfDateType(dayBeforeEndDateTime, endDateTime, dateType);
|
||||
SkuListRawStream rawStream = new SkuListRawStream(body);
|
||||
SkuUpdateListStream stream = new SkuUpdateListStream(rawStream);
|
||||
// the status is directly filtered in all() method
|
||||
List<SkuData> skusFromMabang = stream.all();
|
||||
log.info("{} skus from {} to {} ({})to be updated.", skusFromMabang.size(),
|
||||
dayBeforeEndDateTime, endDateTime, dateType);
|
||||
|
||||
if (!skusFromMabang.isEmpty()) {
|
||||
// we save the skuDatas in DB
|
||||
skuListMabangService.updateSkusFromMabang(skusFromMabang);
|
||||
}
|
||||
endDateTime = dayBeforeEndDateTime;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.info("Updating skus by erpCode : {}", skus);
|
||||
List<List<String>> skusPartition = Lists.partition(skus, 50);
|
||||
for(List<String> skuPartition : skusPartition) {
|
||||
SkuListRequestBody body = new SkuListRequestBody();
|
||||
body.setStockSkuList(String.join(",", skuPartition));
|
||||
SkuListRawStream rawStream = new SkuListRawStream(body);
|
||||
SkuUpdateListStream stream = new SkuUpdateListStream(rawStream);
|
||||
List<SkuData> skusFromMabang = stream.all();
|
||||
log.info("{} skus to be updated.", skusFromMabang.size());
|
||||
if (!skusFromMabang.isEmpty()) {
|
||||
// we save the skuDatas in DB
|
||||
skuListMabangService.updateSkusFromMabang(skusFromMabang);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SkuListRequestErrorException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,9 +32,19 @@ public class CostTrialCalculation {
|
|||
|
||||
private final BigDecimal additionalCost;
|
||||
|
||||
private final BigDecimal previousUnitPrice;
|
||||
|
||||
private CostTrialCalculation(String countryCode, String logisticsChannelName, String logisticChannelCode, BigDecimal unitPrice, BigDecimal shippingCost,
|
||||
BigDecimal registrationCost, BigDecimal additionalCost, Date effectiveDate) {
|
||||
private final BigDecimal previousShippingCost;
|
||||
|
||||
private final BigDecimal previousRegistrationCost;
|
||||
|
||||
private final BigDecimal previousAdditionalCost;
|
||||
|
||||
|
||||
|
||||
private CostTrialCalculation(String countryCode, String logisticsChannelName, String logisticChannelCode,
|
||||
BigDecimal unitPrice, BigDecimal shippingCost, BigDecimal registrationCost, BigDecimal additionalCost, Date effectiveDate,
|
||||
BigDecimal previousUnitPrice,BigDecimal previousShippingCost, BigDecimal previousRegistrationCost, BigDecimal previousAdditionalCost) {
|
||||
this.countryCode = countryCode;
|
||||
this.logisticsChannelName = logisticsChannelName;
|
||||
this.logisticChannelCode = logisticChannelCode;
|
||||
|
@ -43,15 +53,28 @@ public class CostTrialCalculation {
|
|||
this.registrationCost = registrationCost;
|
||||
this.additionalCost = additionalCost;
|
||||
this.effectiveDate = effectiveDate;
|
||||
this.previousUnitPrice = previousUnitPrice;
|
||||
this.previousShippingCost = previousShippingCost;
|
||||
this.previousRegistrationCost = previousRegistrationCost;
|
||||
this.previousAdditionalCost = previousAdditionalCost;
|
||||
}
|
||||
|
||||
public CostTrialCalculation(LogisticChannelPrice price, int weight, String logisticsChannelName, String code) {
|
||||
public CostTrialCalculation(LogisticChannelPrice price, LogisticChannelPrice previousPrice,int weight, String logisticsChannelName, String code) {
|
||||
this(price.getEffectiveCountry(), logisticsChannelName, code, price.getCalUnitPrice(), price.calculateShippingPrice(BigDecimal.valueOf(weight)),
|
||||
price.getRegistrationFee(), price.getAdditionalCost(), price.getEffectiveDate());
|
||||
price.getRegistrationFee(), price.getAdditionalCost(), price.getEffectiveDate(),
|
||||
previousPrice.getCalUnitPrice(), previousPrice.calculateShippingPrice(BigDecimal.valueOf(weight)), previousPrice.getRegistrationFee(), previousPrice.getAdditionalCost()
|
||||
);
|
||||
}
|
||||
|
||||
@JsonProperty("TotalCost")
|
||||
public double getTotalCost() {
|
||||
return shippingCost.add(registrationCost).add(additionalCost).setScale(2, RoundingMode.CEILING).doubleValue();
|
||||
}
|
||||
|
||||
@JsonProperty("CostDifference")
|
||||
public double getCostDifference() {
|
||||
double previousCost = previousShippingCost.add(previousRegistrationCost).add(previousAdditionalCost).setScale(2, RoundingMode.CEILING).doubleValue();
|
||||
BigDecimal diff = BigDecimal.valueOf((getTotalCost() - previousCost) / previousCost * 100);
|
||||
return diff.setScale(2, RoundingMode.CEILING).doubleValue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,4 +98,12 @@ public class Sku implements Serializable {
|
|||
@Excel(name = "服务费", width = 15)
|
||||
@ApiModelProperty(value = "服务费")
|
||||
private java.math.BigDecimal serviceFee;
|
||||
/**
|
||||
* Status
|
||||
* 1:自动创建;2:待开发;3:正常;4:清仓;5:停止销售"
|
||||
* default : 3
|
||||
*/
|
||||
@Excel(name = "Status", width = 15)
|
||||
@ApiModelProperty(value = "Status")
|
||||
private java.lang.Integer status;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public interface LogisticChannelPriceMapper extends BaseMapper<LogisticChannelPr
|
|||
* @param countryList the country, represented by 2 letters code
|
||||
* @return one propre price
|
||||
*/
|
||||
LogisticChannelPrice findBy(
|
||||
List<LogisticChannelPrice> findBy(
|
||||
@Param("channelName") String channelName,
|
||||
@Param("date") Date shippingTime,
|
||||
@Param("trueWeight") BigDecimal weight,
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
AND effective_date <= #{date}
|
||||
AND active = 1
|
||||
ORDER BY effective_date DESC
|
||||
LIMIT 1 </select>
|
||||
LIMIT 2 </select>
|
||||
|
||||
<select id="findPricesBy" resultType="org.jeecg.modules.business.entity.LogisticChannelPrice">
|
||||
SELECT lcp.id, lcp.create_by, lcp.create_time, lcp.update_by, lcp.update_time,
|
||||
|
|
|
@ -209,6 +209,7 @@
|
|||
LEFT JOIN sales_7 s7 ON s.id = s7.sku_id
|
||||
LEFT JOIN qtyInOrdersNotShipped ON s.id = qtyInOrdersNotShipped.ID
|
||||
WHERE client_sku.client_id = #{clientId}
|
||||
AND s.status = 3
|
||||
ORDER BY ${column} ${order}
|
||||
<if test="size != -1">
|
||||
LIMIT #{offset}, #{size}
|
||||
|
@ -272,6 +273,7 @@
|
|||
LEFT JOIN sales_7 s7 ON s.id = s7.sku_id
|
||||
LEFT JOIN qtyInOrdersNotShippedCTE ON s.id = qtyInOrdersNotShippedCTE.ID
|
||||
WHERE client_sku.client_id = #{clientId}
|
||||
AND s.status = 3
|
||||
AND (
|
||||
<if test="erpCodes != ''">
|
||||
s.erp_code REGEXP #{erpCodes}
|
||||
|
|
|
@ -47,7 +47,7 @@ public interface ILogisticChannelService extends IService<LogisticChannel> {
|
|||
* @param country 2 letters code of the destination country
|
||||
* @return one suitable logistic channel price
|
||||
*/
|
||||
LogisticChannelPrice findLogisticsChannelPrice(String channelName, Date date, int trueWeight, List<String> country);
|
||||
List<LogisticChannelPrice> findLogisticsChannelPrice(String channelName, Date date, int trueWeight, List<String> country);
|
||||
|
||||
|
||||
List<CostTrialCalculation> logisticChannelTrial(int weight, int volume, List<String> countryList);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ public interface ISkuListMabangService extends IService<SkuData> {
|
|||
* @param skuDataList skus to save.
|
||||
*/
|
||||
Map<Sku, String> saveSkuFromMabang(List<SkuData> skuDataList);
|
||||
void updateSkusFromMabang(List<SkuData> skuDataList);
|
||||
|
||||
/**
|
||||
* Save products to DB from mabang api.
|
||||
|
|
|
@ -90,13 +90,16 @@ public class LogisticChannelPriceServiceImpl extends ServiceImpl<LogisticChannel
|
|||
|
||||
String countryCode = countryService.findByEnName(order.getCountry()).getCode();
|
||||
|
||||
LogisticChannelPrice price = logisticChannelPriceMapper.findBy(
|
||||
List<LogisticChannelPrice> priceList = logisticChannelPriceMapper.findBy(
|
||||
logisticChannelName,
|
||||
order.getShippingTime(),
|
||||
weight,
|
||||
Collections.singletonList(countryCode)
|
||||
);
|
||||
|
||||
// find the one with latest effective date
|
||||
LogisticChannelPrice price = priceList.stream()
|
||||
.max(Comparator.comparing(LogisticChannelPrice::getEffectiveDate))
|
||||
.orElse(null);
|
||||
if (price == null) {
|
||||
throw new UserException("Can't find price for channel {}, shipped at {}, weight {}, country {}",
|
||||
logisticChannelName,
|
||||
|
|
|
@ -78,7 +78,7 @@ public class LogisticChannelServiceImpl extends ServiceImpl<LogisticChannelMappe
|
|||
}
|
||||
|
||||
@Override
|
||||
public LogisticChannelPrice findLogisticsChannelPrice(String channelName, Date date, int trueWeight, List<String> countryList) {
|
||||
public List<LogisticChannelPrice> findLogisticsChannelPrice(String channelName, Date date, int trueWeight, List<String> countryList) {
|
||||
return logisticChannelPriceMapper.findBy(channelName, new java.util.Date(), BigDecimal.valueOf(trueWeight), countryList);
|
||||
}
|
||||
|
||||
|
@ -98,9 +98,15 @@ public class LogisticChannelServiceImpl extends ServiceImpl<LogisticChannelMappe
|
|||
} else {
|
||||
trueWeight = weight;
|
||||
}
|
||||
LogisticChannelPrice price = findLogisticsChannelPrice(channelName, new Date(), trueWeight, countryList);
|
||||
List<LogisticChannelPrice> priceList = findLogisticsChannelPrice(channelName, new Date(), trueWeight, countryList);
|
||||
LogisticChannelPrice price = priceList.stream()
|
||||
.max(Comparator.comparing(LogisticChannelPrice::getEffectiveDate))
|
||||
.orElse(null);
|
||||
LogisticChannelPrice previousPrice = priceList.stream()
|
||||
.min(Comparator.comparing(LogisticChannelPrice::getEffectiveDate))
|
||||
.orElse(null);
|
||||
if (price != null) {
|
||||
return new CostTrialCalculation(price, trueWeight, internalName, code);
|
||||
return new CostTrialCalculation(price, previousPrice, trueWeight, internalName, code);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -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.*;
|
||||
|
@ -13,6 +17,7 @@ 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.service.IPlatformOrderService;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderOperation;
|
||||
import org.jeecg.modules.business.vo.Responses;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -23,6 +28,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 +46,10 @@ import static java.util.stream.Collectors.toList;
|
|||
public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMabangMapper, Order> implements IPlatformOrderMabangService {
|
||||
@Autowired
|
||||
private PlatformOrderMabangMapper platformOrderMabangMapper;
|
||||
@Autowired
|
||||
private IPlatformOrderService orderservice;
|
||||
@Autowired
|
||||
private ISysBaseAPI ISysBaseApi;
|
||||
|
||||
private static final Integer DEFAULT_NUMBER_OF_THREADS = 2;
|
||||
private static final Integer MABANG_API_RATE_LIMIT_PER_MINUTE = 10;
|
||||
|
@ -92,6 +102,9 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
|||
) {
|
||||
// If order wasn't invoiced pre-shipping, we can remove and re-insert contents
|
||||
if (orderInDatabase.getShippingInvoiceNumber() == null) {
|
||||
boolean hasInvoiceNumber = orderservice.getById(orderInDatabase.getId()).getShippingInvoiceNumber() != null;
|
||||
if(hasInvoiceNumber)
|
||||
continue;
|
||||
oldOrders.add(retrievedOrder);
|
||||
} else {
|
||||
invoicedShippedOrders.add(retrievedOrder);
|
||||
|
@ -116,11 +129,11 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
|||
/* for new orders, insert them to DB and their children */
|
||||
List<OrderItem> allNewItems = prepareItems(newOrders);
|
||||
try {
|
||||
if (newOrders.size() != 0) {
|
||||
if (!newOrders.isEmpty()) {
|
||||
log.info("{} orders to be inserted/updated.", newOrders.size());
|
||||
platformOrderMabangMapper.insertOrdersFromMabang(newOrders);
|
||||
}
|
||||
if (allNewItems.size() != 0) {
|
||||
if (!allNewItems.isEmpty()) {
|
||||
platformOrderMabangMapper.insertOrderItemsFromMabang(allNewItems);
|
||||
log.info("{} order items to be inserted/updated.", allNewItems.size());
|
||||
}
|
||||
|
@ -131,12 +144,12 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
|||
// for old orders, update themselves and delete and reinsert their content.
|
||||
List<OrderItem> allNewItemsOfOldItems = prepareItems(oldOrders);
|
||||
try {
|
||||
if (oldOrders.size() != 0) {
|
||||
if (!oldOrders.isEmpty()) {
|
||||
log.info("{} orders to be inserted/updated.", oldOrders.size());
|
||||
platformOrderMabangMapper.batchUpdateById(oldOrders);
|
||||
platformOrderMabangMapper.batchDeleteByMainID(oldOrders.stream().map(Order::getId).collect(toList()));
|
||||
}
|
||||
if (ordersFromShippedToCompleted.size() != 0) {
|
||||
if (!ordersFromShippedToCompleted.isEmpty()) {
|
||||
log.info("{} orders to be updated from Shipped to Completed.", ordersFromShippedToCompleted.size());
|
||||
platformOrderMabangMapper.batchUpdateById(ordersFromShippedToCompleted);
|
||||
log.info("Contents of {} orders to be updated from Shipped to Completed.", ordersFromShippedToCompleted.size());
|
||||
|
@ -144,7 +157,7 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
|||
ordersFromShippedToCompleted.stream().map(Order::getId).collect(toList()),
|
||||
OrderStatus.Completed.getCode());
|
||||
}
|
||||
if (invoicedShippedOrders.size() != 0) {
|
||||
if (!invoicedShippedOrders.isEmpty()) {
|
||||
log.info("{} orders to be updated from Pending/Preparing to Shipped.", invoicedShippedOrders.size());
|
||||
platformOrderMabangMapper.batchUpdateById(invoicedShippedOrders);
|
||||
log.info("Contents of {} orders to be updated from Pending/Preparing to Shipped.", invoicedShippedOrders.size());
|
||||
|
@ -152,7 +165,7 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
|||
invoicedShippedOrders.stream().map(Order::getId).collect(toList()),
|
||||
OrderStatus.Shipped.getCode());
|
||||
}
|
||||
if (obsoleteOrders.size() != 0) {
|
||||
if (!obsoleteOrders.isEmpty()) {
|
||||
log.info("{} orders to become obsolete.", obsoleteOrders.size());
|
||||
platformOrderMabangMapper.batchUpdateById(obsoleteOrders);
|
||||
log.info("Contents of {} orders to be updated to Obsolete.", obsoleteOrders.size());
|
||||
|
@ -160,7 +173,7 @@ public class PlatformOrderMabangServiceImpl extends ServiceImpl<PlatformOrderMab
|
|||
obsoleteOrders.stream().map(Order::getId).collect(toList()),
|
||||
OrderStatus.Obsolete.getCode());
|
||||
}
|
||||
if (allNewItemsOfOldItems.size() != 0) {
|
||||
if (!allNewItemsOfOldItems.isEmpty()) {
|
||||
log.info("{} order items to be inserted/updated.", allNewItemsOfOldItems.size());
|
||||
platformOrderMabangMapper.insertOrderItemsFromMabang(allNewItemsOfOldItems);
|
||||
}
|
||||
|
@ -324,4 +337,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,7 +54,10 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
@Autowired
|
||||
Environment env;
|
||||
|
||||
|
||||
// In NameCN field on top of the product name we also get the customer code in the beginning of the string : "XX Description of the product"
|
||||
final Pattern cnNamePattern = Pattern.compile("^([a-zA-Z]{2,5})\\s(.*)$");
|
||||
// In NameEN field on top of the product name we also get the customer code in the beginning of the string : "XX-En name of product"
|
||||
final Pattern enNamePattern = Pattern.compile("^([a-zA-Z]{2,5})-(.*)$");
|
||||
/**
|
||||
* Save skus to DB from mabang api.
|
||||
*
|
||||
|
@ -94,7 +97,7 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
|
||||
/* for new skuDatas, insert them to DB */
|
||||
try {
|
||||
if (newSkuDatas.size() != 0) {
|
||||
if (!newSkuDatas.isEmpty()) {
|
||||
// we need to check if the product associated with the sku exists, for that we are going to parse the Sku erpCode into product code
|
||||
// check if the product code exists in DB, if not we create a new entry in DB and fill all the infos.
|
||||
// then we can finally add the new Sku, product has to be created first if it doesn't exist, since we need to fill productID in Sku table
|
||||
|
@ -160,6 +163,63 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
return newSkusMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateSkusFromMabang(List<SkuData> skuDataList) {
|
||||
if (skuDataList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// we collect all erpCode
|
||||
List<String> allSkuErpCode = skuDataList.stream()
|
||||
.map(SkuData::getErpCode)
|
||||
.collect(toList());
|
||||
// find Skus that already exist in DB
|
||||
List<Sku> existingSkuList = skuListMabangMapper.searchExistence(allSkuErpCode);
|
||||
// We map all existing Skus in DB with erpCode as key
|
||||
Map<String, Sku> existingSkusIDMap = existingSkuList.stream()
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
Sku::getErpCode, Function.identity()
|
||||
)
|
||||
);
|
||||
|
||||
ArrayList<SkuData> existingSkuDatas = new ArrayList<>();
|
||||
for (SkuData retrievedSkuData : skuDataList) {
|
||||
Sku skuInDatabase = existingSkusIDMap.get(retrievedSkuData.getErpCode());
|
||||
// the current SkuData's erpCode is in DB, so we add it to the list of existingSkuDatas
|
||||
if (skuInDatabase != null) {
|
||||
existingSkuDatas.add(retrievedSkuData);
|
||||
}
|
||||
}
|
||||
|
||||
/* for skuDatas to update, update product names and sku status them to DB */
|
||||
try {
|
||||
if (!existingSkuDatas.isEmpty()) {
|
||||
// we need to check if the product associated with the sku exists, for that we are going to parse the Sku erpCode into product code
|
||||
// check if the product code exists in DB, if not we create a new entry in DB and fill all the infos.
|
||||
// then we can finally add the new Sku, product has to be created first if it doesn't exist, since we need to fill productID in Sku table
|
||||
// we can now proceed to create new sku_declare_value associated with the new Sku and also sku_price
|
||||
updateProductFromMabang(existingSkuDatas);
|
||||
log.info("{} skus to be updated.", existingSkuDatas.size());
|
||||
|
||||
//update status of existing skus
|
||||
List<Sku> skusToUpdate = new ArrayList<>();
|
||||
for(SkuData skuData: existingSkuDatas) {
|
||||
Sku s = new Sku();
|
||||
s.setId(existingSkusIDMap.get(skuData.getErpCode()).getId());
|
||||
s.setUpdateBy("mabang api");
|
||||
s.setUpdateTime(new Date());
|
||||
s.setStatus(skuData.getStatusValue());
|
||||
skusToUpdate.add(s);
|
||||
}
|
||||
skuService.updateBatchById(skusToUpdate);
|
||||
log.info("Updated {} skus : {}.", skusToUpdate.size(), existingSkuDatas.stream().map(SkuData::getErpCode).collect(toList()));
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
log.error(e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save products to DB from mabang api.
|
||||
*
|
||||
|
@ -197,6 +257,63 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
}
|
||||
return productsWithInfoMap;
|
||||
}
|
||||
/**
|
||||
* Update products enName and zhName to DB from mabang api.
|
||||
*
|
||||
* @param skuDataList we update the product enName and zhName of the skus
|
||||
*/
|
||||
public void updateProductFromMabang(List<SkuData> skuDataList) {
|
||||
List<String> allProductCodes = parseSkuListToProductCodeList(skuDataList);
|
||||
|
||||
List< Product> existingProduct = skuListMabangMapper.searchProductExistence(allProductCodes);
|
||||
Map<String, Product> existingProductsIDMap = existingProduct.stream()
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
Product::getCode, Function.identity()
|
||||
)
|
||||
);
|
||||
List<SkuData> skuDatasToUpdate = new ArrayList<>();
|
||||
// we ignore the new products and only update the existing ones
|
||||
for(SkuData skuData : skuDataList) {
|
||||
Product productInDB = existingProductsIDMap.get(parseSkuToProduct(skuData.getErpCode()));
|
||||
// the current product code is in DB, so we add it to the list of newProducts
|
||||
if (productInDB != null) {
|
||||
skuDatasToUpdate.add(skuData);
|
||||
}
|
||||
}
|
||||
List<Product> productsToUpdate = new ArrayList<>();
|
||||
for(SkuData skuData: skuDatasToUpdate) {
|
||||
Product p = new Product();
|
||||
p.setId(existingProductsIDMap.get(parseSkuToProduct(skuData.getErpCode())).getId());
|
||||
p.setUpdateBy("mabang api");
|
||||
p.setUpdateTime(new Date());
|
||||
// Removing the customer code from the product CN name
|
||||
if (!skuData.getNameEN().isEmpty()) {
|
||||
Matcher enNameMatcher = enNamePattern.matcher(skuData.getNameEN());
|
||||
if (enNameMatcher.matches() && !enNameMatcher.group(2).isEmpty()) {
|
||||
p.setEnName(enNameMatcher.group(2));
|
||||
}
|
||||
else {
|
||||
p.setEnName(skuData.getNameEN());
|
||||
}
|
||||
}
|
||||
// Removing the customer code from the product CN name
|
||||
if (!skuData.getNameCN().isEmpty()) {
|
||||
Matcher cnNameMatcher = cnNamePattern.matcher(skuData.getNameCN());
|
||||
if (cnNameMatcher.matches() && !cnNameMatcher.group(2).isEmpty()) {
|
||||
p.setZhName(cnNameMatcher.group(2));
|
||||
}
|
||||
else {
|
||||
p.setZhName(skuData.getNameCN());
|
||||
}
|
||||
}
|
||||
productsToUpdate.add(p);
|
||||
}
|
||||
if(!productsToUpdate.isEmpty()) {
|
||||
productService.updateBatchById(productsToUpdate);
|
||||
}
|
||||
log.info("Updated {} products : {}.", productsToUpdate.size(), skuDatasToUpdate.stream().map(SkuData::getErpCode).collect(toList()));
|
||||
}
|
||||
|
||||
public void saveSkuPrices(List<SkuData> newSkus) {
|
||||
List<SkuPrice> l = new ArrayList<>();
|
||||
|
@ -290,8 +407,6 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
final String electroMagSensitiveAttributeId = skuListMabangMapper.searchSensitiveAttributeId("Electro-magnetic");
|
||||
final String electricSensitiveAttributeId = skuListMabangMapper.searchSensitiveAttributeId("Electronic/Electric");
|
||||
final String normalSensitiveAttributeId = skuListMabangMapper.searchSensitiveAttributeId("Normal goods");
|
||||
// In NameCN field on top of the product name we also get the customer code in the beginning of the string : "XX Description of the product"
|
||||
final Pattern cnNamePattern = Pattern.compile("^([a-zA-Z]{2,5})\\s(.*)$");
|
||||
// IN saleRemark sometimes not only the product weight provided, we can get extra information such as service_fee (eg : "15每件服务费0.2")
|
||||
final Pattern saleRemarkPattern = Pattern.compile("^([0-9]*)(.*)$");
|
||||
// we are stocking product codes, so we don't get duplicates which causes error
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue