feat: purchase order result logs

pull/8040/head
Gauthier LO 2024-12-17 14:15:22 +01:00
parent 018332c29f
commit aab90a0e2c
6 changed files with 214 additions and 26 deletions

View File

@ -574,16 +574,17 @@ public class PurchaseOrderController {
@GetMapping(value = "/createMabangPurchaseOrder")
public Result<?> createMabangPurchaseOrder(@RequestParam("invoiceNumbers") List<String> invoiceNumbers) {
log.info("Creating purchase order to Mabang for invoices : {} ", invoiceNumbers);
Map<String, Responses> responsesMappedByInvoiceNumber = new HashMap<>();
ExecutorService throttlingExecutorService = ThrottlingExecutorService.createExecutorService(DEFAULT_NUMBER_OF_THREADS,
MABANG_API_RATE_LIMIT_PER_MINUTE, TimeUnit.MINUTES);
// providersHistory lists the providers that have already been processed, if the current provider is in the list and has been processed within the last 10 seconds, the thread will sleep for 10 seconds
AtomicReference<Map<String, LocalDateTime>> providersHistory = new AtomicReference<>(new HashMap<>());
List<CompletableFuture<String>> future = invoiceNumbers.stream()
List<CompletableFuture<Boolean>> future = invoiceNumbers.stream()
.map(invoiceNumber -> CompletableFuture.supplyAsync(() -> {
log.info("Invoice number : {}", invoiceNumber);
List<SkuQuantity> skuQuantities = purchaseOrderService.getSkuQuantityByInvoiceNumber(invoiceNumber);
if(skuQuantities.isEmpty()) {
return null;
return false;
}
Map<String, Integer> skuQuantityMap = skuQuantities.stream()
.collect(Collectors.toMap(SkuQuantity::getErpCode, SkuQuantity::getQuantity));
@ -592,30 +593,32 @@ public class PurchaseOrderController {
.filter(entry -> entry.getValue() > 0)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
InvoiceMetaData metaData = purchaseOrderService.getMetaDataFromInvoiceNumbers(invoiceNumber);
List<String> errors = providerMabangService.addPurchaseOrderToMabang(skuQtyNotEmptyMap, metaData, providersHistory);
return errors.isEmpty() ? invoiceNumber : errors.toString();
Responses results = providerMabangService.addPurchaseOrderToMabang(skuQtyNotEmptyMap, metaData, providersHistory);
if(responsesMappedByInvoiceNumber.get(invoiceNumber) != null) {
responsesMappedByInvoiceNumber.get(invoiceNumber).getFailures().addAll(results.getFailures());
responsesMappedByInvoiceNumber.get(invoiceNumber).getSuccesses().addAll(results.getSuccesses());
} else {
responsesMappedByInvoiceNumber.put(invoiceNumber, results);
}
return results.getFailures().isEmpty();
},throttlingExecutorService))
.collect(Collectors.toList());
List<String> results = future.stream().map(CompletableFuture::join).collect(Collectors.toList());
long nbSuccesses = results.stream().filter(Invoice::isInvoiceNumber).count();
List<Boolean> results = future.stream().map(CompletableFuture::join).collect(Collectors.toList());
long nbSuccesses = results.stream().filter(Boolean::booleanValue).count();
log.info("{}/{} purchase order requests have succeeded.", nbSuccesses, invoiceNumbers.size());
Map<String, List<String>> data = new HashMap<>();
List<String> failedInvoices = new ArrayList<>();
List<String> successInvoices = new ArrayList<>();
results.forEach(result -> {
if(isInvoiceNumber(result)) {
successInvoices.add(result);
} else {
failedInvoices.add(result);
List<String> groupIdsToDelete = new ArrayList<>();
for(Map.Entry<String, Responses> entry : responsesMappedByInvoiceNumber.entrySet()) {
if(!entry.getValue().getFailures().isEmpty()) {
groupIdsToDelete.addAll(entry.getValue().getSuccesses());
}
});
data.put("fail", failedInvoices);
data.put("success", successInvoices);
return Result.OK(data);
}
if(!groupIdsToDelete.isEmpty()) {
log.info("Deleting purchase orders that have been incompletely created in Mabang : {}", groupIdsToDelete);
Responses groupIdsDeleteResult = providerMabangService.deletePurchaseOrderFromMabang(groupIdsToDelete);
responsesMappedByInvoiceNumber.put("groupIdDelete", groupIdsDeleteResult);
}
return Result.OK(responsesMappedByInvoiceNumber);
}
}

View File

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

View File

@ -0,0 +1,94 @@
package org.jeecg.modules.business.domain.api.mabang.purDoChangePurchase;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.modules.business.domain.api.mabang.RequestBody;
import java.util.List;
import java.util.function.Function;
public class ChangePurchaseOrderRequestBody implements RequestBody {
private final String employeeName;
private final String groupId;
private final String actionType;
private final String scrapOrder;
public ChangePurchaseOrderRequestBody(String employeeName, String groupId, String actionType, String scrapOrder) {
this.employeeName = employeeName;
this.groupId = groupId;
this.actionType = actionType;
this.scrapOrder = scrapOrder;
}
@Override
public String api() {
return "pur-do-change-purchase";
}
@Override
public JSONObject parameters() {
JSONObject json = new JSONObject();
putNonNull(json, "employeeName", employeeName);
putNonNull(json, "groupId", groupId);
putNonNull(json, "actionType", actionType);
putNonNull(json, "scrapOrder", scrapOrder);
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));
}
}
/**
* :
* 1;
* 2;
* 3;
* 4;
* 5
* 6
*/
public static enum ActionType {
MARK_COMPLETE("1"),
CANCEL("2"),
CHANGE_BASIC_INFO("3"),
CHANGE_PRODUCT_INFO("4"),
ADD_PRODUCT("5"),
CHANGE_EXPAND_PROPERTY("6");
private final String value;
ActionType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
/**
* 1. 2. 2
*/
public static enum ScrapOrder {
ALL("1"),
PART("2");
private final String value;
ScrapOrder(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}

View File

@ -0,0 +1,34 @@
package org.jeecg.modules.business.domain.api.mabang.purDoChangePurchase;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import org.jeecg.modules.business.domain.api.mabang.Response;
@Getter
public class ChangePurchaseOrderResponse extends Response {
private final String message;
private ChangePurchaseOrderResponse(Code status, String message) {
super(status);
this.message = message;
}
public static ChangePurchaseOrderResponse parse(String json) {
JSONObject jsonObject = JSON.parseObject(json);
String code = jsonObject.getString("code");
String message = jsonObject.getString("message");
if (code.equals("200")) {
return new ChangePurchaseOrderResponse(Code.SUCCESS, message);
} else {
return new ChangePurchaseOrderResponse(Code.ERROR, message);
}
}
@Override
public String toString() {
return "AddPurchaseOrderResponse{" +
"message='" + message + '\'' +
'}';
}
}

View File

@ -3,6 +3,7 @@ package org.jeecg.modules.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.business.domain.api.mabang.purDoGetProvider.ProviderData;
import org.jeecg.modules.business.vo.InvoiceMetaData;
import org.jeecg.modules.business.vo.Responses;
import java.time.LocalDateTime;
import java.util.List;
@ -17,5 +18,7 @@ public interface IProviderMabangService extends IService<ProviderData> {
*/
void saveProviderFromMabang(List<ProviderData> providerDataList);
List<String> addPurchaseOrderToMabang(Map<String, Integer> skuQuantities, InvoiceMetaData metaData, AtomicReference<Map<String, LocalDateTime>> providersHistory);
Responses addPurchaseOrderToMabang(Map<String, Integer> skuQuantities, InvoiceMetaData metaData, AtomicReference<Map<String, LocalDateTime>> providersHistory);
Responses deletePurchaseOrderFromMabang(List<String> groupIds);
}

View File

@ -9,6 +9,9 @@ import org.jeecg.modules.business.domain.api.mabang.purDoAddPurchase.AddPurchase
import org.jeecg.modules.business.domain.api.mabang.purDoAddPurchase.AddPurchaseOrderRequestBody;
import org.jeecg.modules.business.domain.api.mabang.purDoAddPurchase.AddPurchaseOrderResponse;
import org.jeecg.modules.business.domain.api.mabang.purDoAddPurchase.SkuStockData;
import org.jeecg.modules.business.domain.api.mabang.purDoChangePurchase.ChangePurchaseOrderRequest;
import org.jeecg.modules.business.domain.api.mabang.purDoChangePurchase.ChangePurchaseOrderRequestBody;
import org.jeecg.modules.business.domain.api.mabang.purDoChangePurchase.ChangePurchaseOrderResponse;
import org.jeecg.modules.business.domain.api.mabang.purDoGetProvider.ProviderData;
import org.jeecg.modules.business.domain.job.ThrottlingExecutorService;
import org.jeecg.modules.business.entity.Provider;
@ -18,6 +21,7 @@ import org.jeecg.modules.business.service.IProviderService;
import org.jeecg.modules.business.service.IPurchaseOrderService;
import org.jeecg.modules.business.service.ISkuService;
import org.jeecg.modules.business.vo.InvoiceMetaData;
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;
@ -33,6 +37,9 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import static org.jeecg.modules.business.domain.api.mabang.purDoChangePurchase.ChangePurchaseOrderRequestBody.ActionType.CANCEL;
import static org.jeecg.modules.business.domain.api.mabang.purDoChangePurchase.ChangePurchaseOrderRequestBody.ScrapOrder.ALL;
/**
* @Description: provider
* @Author: jeecg-boot
@ -76,9 +83,10 @@ public class ProviderMabangServiceImpl extends ServiceImpl<ProviderMabangMapper,
*/
@Transactional
@Override
public List<String> addPurchaseOrderToMabang(Map<String, Integer> skuQuantities, InvoiceMetaData metaData, AtomicReference<Map<String, LocalDateTime>> providersHistory) {
public Responses addPurchaseOrderToMabang(Map<String, Integer> skuQuantities, InvoiceMetaData metaData, AtomicReference<Map<String, LocalDateTime>> providersHistory) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String mabangUsername = sysUser.getMabangUsername();
Responses responses = new Responses();
String content = metaData.getFilename();
List<String> stockSkuList = new ArrayList<>();
String stockSkus;
@ -115,7 +123,8 @@ public class ProviderMabangServiceImpl extends ServiceImpl<ProviderMabangMapper,
}
if(skuDataList.isEmpty()) {
log.error("Couldn't get SKU data from Mabang API for invoice : {}", metaData.getInvoiceCode());
return Collections.singletonList("Couldn't get SKU data from Mabang API for invoice : " + metaData.getInvoiceCode());
responses.addFailure("Couldn't get SKU data from Mabang API for invoice : " + metaData.getInvoiceCode());
return responses;
}
for(SkuData skuData : skuDataList) {
@ -178,6 +187,7 @@ public class ProviderMabangServiceImpl extends ServiceImpl<ProviderMabangMapper,
return false;
}
groupIds.add(response.getGroupId());
responses.addSuccess(response.getGroupId());
providersHistory.get().put(providerName, LocalDateTime.now());
return true;
}, throttlingExecutorService))
@ -190,8 +200,37 @@ public class ProviderMabangServiceImpl extends ServiceImpl<ProviderMabangMapper,
if(nbSuccesses == stockProviderMap.size()) {
purchaseOrderService.updatePurchaseOrderStatus(metaData.getInvoiceCode(), true);
purchaseOrderService.updatePurchaseOrderGroupIds(metaData.getInvoiceCode(), groupIds);
return Collections.emptyList();
}
return errors;
responses.setFailures(errors);
return responses;
}
@Override
public Responses deletePurchaseOrderFromMabang(List<String> groupIds) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String mabangUsername = sysUser.getMabangUsername();
Responses groupIdsDeleteResult = new Responses();
log.info("Deleting purchase orders from Mabang : {}", groupIds);
// delete purchase order from Mabang via group_id
ExecutorService throttlingExecutorService = ThrottlingExecutorService.createExecutorService(DEFAULT_NUMBER_OF_THREADS,
MABANG_API_RATE_LIMIT_PER_MINUTE, TimeUnit.MINUTES);
List<CompletableFuture<Boolean>> changeOrderFutures = groupIds.stream()
.map(groupId -> CompletableFuture.supplyAsync(() -> {
ChangePurchaseOrderRequestBody body = new ChangePurchaseOrderRequestBody(mabangUsername, groupId, CANCEL.getValue(), ALL.getValue());
ChangePurchaseOrderRequest request = new ChangePurchaseOrderRequest(body);
ChangePurchaseOrderResponse response = request.send();
if(!response.success()) {
log.error("Failed to delete purchase order from Mabang. GroupId : {} - Reason : {}", groupId, response.getMessage());
groupIdsDeleteResult.addFailure(groupId);
} else {
groupIdsDeleteResult.addSuccess(groupId);
}
return response.success();
}, throttlingExecutorService))
.collect(Collectors.toList());
List<Boolean> results = changeOrderFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
long nbSuccesses = results.stream().filter(b -> b).count();
log.info("{}/{} purchase orders deleted successfully from Mabang. GroupIds : {}", nbSuccesses, groupIds.size(), groupIds);
return groupIdsDeleteResult;
}
}