feat: sku weight update in app and mabang

pull/8040/head
Gauthier LO 2024-12-16 16:05:44 +01:00
parent 74e7df9dda
commit 3a6812c6a3
7 changed files with 135 additions and 60 deletions

View File

@ -1,9 +1,6 @@
package org.jeecg.modules.business.controller.admin; package org.jeecg.modules.business.controller.admin;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -15,6 +12,7 @@ import org.jeecg.modules.business.entity.Sku;
import org.jeecg.modules.business.entity.SkuWeight; import org.jeecg.modules.business.entity.SkuWeight;
import org.jeecg.modules.business.mongoService.SkuMongoService; import org.jeecg.modules.business.mongoService.SkuMongoService;
import org.jeecg.modules.business.service.ISecurityService; import org.jeecg.modules.business.service.ISecurityService;
import org.jeecg.modules.business.service.ISkuListMabangService;
import org.jeecg.modules.business.service.ISkuService; import org.jeecg.modules.business.service.ISkuService;
import org.jeecg.modules.business.service.ISkuWeightService; import org.jeecg.modules.business.service.ISkuWeightService;
@ -24,6 +22,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController; import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.modules.business.vo.Responses;
import org.jeecg.modules.business.vo.SkuWeightParam; import org.jeecg.modules.business.vo.SkuWeightParam;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -45,6 +44,8 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
@RequestMapping("/skuWeight") @RequestMapping("/skuWeight")
@Slf4j @Slf4j
public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightService> { public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightService> {
@Autowired
private ISkuListMabangService skuListMabangService;
@Autowired @Autowired
private ISkuService skuService; private ISkuService skuService;
@Autowired @Autowired
@ -164,7 +165,8 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
} }
/** /**
* Updating weight of multiple SKUs, creates new sku_weight entries with new effective_date and weight. * /!\ Not maintained use updateBatch instead.
* Updating weight of a SKU, creates new sku_weight entry with new effective_date and weight.
* @param param * @param param
* @return * @return
*/ */
@ -188,16 +190,23 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
skuWeightService.save(skuWeight); skuWeightService.save(skuWeight);
return Result.OK("data.invoice.effectiveDate"); return Result.OK("data.invoice.effectiveDate");
} }
/**
* Updating weight of multiple SKUs, creates new sku_weight entries with new effective_date and weight.
* Updates the weight in Mabang.
* Updates the weight in MongoDB.
* @param param
* @return
*/
@Transactional @Transactional
@PostMapping(value = "/updateBatch") @PostMapping(value = "/updateBatch")
public Result<String> updateBatch(@RequestBody SkuWeightParam param) { public Result<?> updateBatch(@RequestBody SkuWeightParam param) {
boolean isEmployee = securityService.checkIsEmployee(); boolean isEmployee = securityService.checkIsEmployee();
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
if(!isEmployee){ if(!isEmployee){
log.info("User {}, tried to access /skuWeight/updateBatch but is not authorized.", sysUser.getUsername()); log.info("User {}, tried to access /skuWeight/updateBatch but is not authorized.", sysUser.getUsername());
return Result.error(403,"Forbidden."); return Result.error(403,"Forbidden.");
} }
List<SkuWeight> skuWeights = new ArrayList<>(); Map<String, SkuWeight> skuWeightsMap = new HashMap<>();
for(String skuId : param.getIds()){ for(String skuId : param.getIds()){
Sku sku = skuService.getById(skuId); Sku sku = skuService.getById(skuId);
if(sku == null){ if(sku == null){
@ -208,10 +217,15 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
skuWeight.setEffectiveDate(param.getEffectiveDate()); skuWeight.setEffectiveDate(param.getEffectiveDate());
skuWeight.setSkuId(skuId); skuWeight.setSkuId(skuId);
skuWeight.setWeight(param.getWeight()); skuWeight.setWeight(param.getWeight());
skuWeights.add(skuWeight); skuWeightsMap.put(sku.getErpCode(), skuWeight);
skuMongoService.upsertSkuWeight(skuWeight);
} }
List<SkuWeight> skuWeights = new ArrayList<>(skuWeightsMap.values());
Responses responses = skuListMabangService.mabangSkuWeightUpdate(skuWeights);
List<SkuWeight> skuWeightSuccesses = new ArrayList<>();
responses.getSuccesses().forEach(skuErpCode -> skuWeightSuccesses.add(skuWeightsMap.get(skuErpCode)));
skuWeightSuccesses.forEach(skuWeight -> skuMongoService.upsertSkuWeight(skuWeight));
skuWeightService.saveBatch(skuWeights); skuWeightService.saveBatch(skuWeights);
return Result.OK("data.invoice.effectiveDate"); return Result.OK(responses);
} }
} }

View File

@ -75,7 +75,7 @@ public class SkuData {
@JSONField(name="height") @JSONField(name="height")
private String height; private String height;
@JSONField(name="weight") @JSONField(name="weight")
private Double weight; private Integer weight;
/** /**
* saleRemark contains the weight * saleRemark contains the weight
*/ */

View File

@ -18,15 +18,16 @@ import org.springframework.http.ResponseEntity;
*/ */
@Slf4j @Slf4j
public class SkuChangeRequest extends Request { public class SkuChangeRequest extends Request {
private final SkuChangeRequestBody body;
public SkuChangeRequest(SkuChangeRequestBody body) { public SkuChangeRequest(SkuChangeRequestBody body) {
super(body); super(body);
this.body = body;
} }
@Override @Override
public SkuChangeResponse send() { public SkuChangeResponse send() {
ResponseEntity<String> res = rawSend(); ResponseEntity<String> res = rawSend();
return SkuChangeResponse.parse(JSON.parseObject(res.getBody())); return SkuChangeResponse.parse(JSON.parseObject(res.getBody()), body.getStockSku());
} }
} }

View File

@ -19,21 +19,12 @@ public class SkuChangeRequestBody implements RequestBody {
private String nameEn; private String nameEn;
private Integer status; private Integer status;
private BigDecimal salePrice; private BigDecimal salePrice;
private BigDecimal declareValue;
private String declareName; private String declareName;
private String declareEname; private String declareEname;
private String warehouse; private String warehouse;
private String remark; private String remark;
private Integer hasBattery; private Integer weight;
private Integer magnetic;
private Integer powder;
private Integer isPaste;
private Integer noLiquidCosmetic;
private Integer isFlammable;
private Integer isKnife;
private Integer isGift; private Integer isGift;
private String supplier;
private String supplierLink;
@Override @Override
public String api() { public String api() {
@ -48,32 +39,11 @@ public class SkuChangeRequestBody implements RequestBody {
putNonNull(json, "nameEN", nameEn); putNonNull(json, "nameEN", nameEn);
putNonNull(json, "status", status); putNonNull(json, "status", status);
putNonNull(json, "salePrice", salePrice); putNonNull(json, "salePrice", salePrice);
putNonNull(json, "declareValue", declareValue);
putNonNull(json, "declareName", declareName); putNonNull(json, "declareName", declareName);
putNonNull(json, "declareEname", declareEname); putNonNull(json, "declareEname", declareEname);
JSONArray warehouseData = new JSONArray(); putNonNull(json, "weight", weight);
JSONObject warehouse = new JSONObject();
warehouse.put("name", this.warehouse);
warehouseData.add(warehouse);
json.put("warehouseData", warehouseData.toJSONString());
putNonNull(json, "weight", remark);
putNonNull(json, "saleRemark", remark); putNonNull(json, "saleRemark", remark);
putNonNull(json, "hasBattery", hasBattery);
putNonNull(json, "magnetic", magnetic);
putNonNull(json, "powder", powder);
putNonNull(json, "ispaste", isPaste);
putNonNull(json, "noLiquidCosmetic", noLiquidCosmetic);
putNonNull(json, "is_flammable", isFlammable);
putNonNull(json, "is_knife", isKnife);
putNonNull(json, "isGift", isGift); putNonNull(json, "isGift", isGift);
putNonNull(json, "autoCreateSupplier", 1);
JSONArray supplierData = new JSONArray();
JSONObject supplier = new JSONObject();
supplier.put("name", this.supplier);
supplier.put("productLinkAddress", this.supplierLink);
supplier.put("flag", 1);
supplierData.add(supplier);
json.put("suppliersData", supplierData.toJSONString());
return json; return json;
} }
@ -82,21 +52,11 @@ public class SkuChangeRequestBody implements RequestBody {
this.nameCn = data.getNameCN(); this.nameCn = data.getNameCN();
this.nameEn = data.getNameEN(); this.nameEn = data.getNameEN();
this.salePrice = data.getSalePrice(); this.salePrice = data.getSalePrice();
this.declareValue = data.getDeclareValue();
this.declareName = data.getDeclareNameZh(); this.declareName = data.getDeclareNameZh();
this.declareEname = data.getDeclareNameEn(); this.declareEname = data.getDeclareNameEn();
this.warehouse = data.getWarehouse();
this.remark = data.getSaleRemark(); this.remark = data.getSaleRemark();
this.hasBattery = data.getHasBattery(); this.weight = data.getWeight();
this.magnetic = data.getMagnetic();
this.powder = data.getPowder();
this.isPaste = data.getIsPaste();
this.noLiquidCosmetic = data.getNoLiquidCosmetic();
this.isFlammable = data.getIsFlammable();
this.isKnife = data.getIsKnife();
this.isGift = data.getIsGift(); this.isGift = data.getIsGift();
this.supplier = data.getSupplier();
this.supplierLink = data.getSupplierLink();
} }
private <E> void putNonNull(JSONObject json, String key, E value) { private <E> void putNonNull(JSONObject json, String key, E value) {

View File

@ -35,7 +35,7 @@ public class SkuChangeResponse extends Response {
* @return Instance * @return Instance
* @throws SkuChangeRequestErrorException if response code represents error. * @throws SkuChangeRequestErrorException if response code represents error.
*/ */
public static SkuChangeResponse parse(JSONObject json) throws SkuChangeRequestErrorException { public static SkuChangeResponse parse(JSONObject json, String erpCode) throws SkuChangeRequestErrorException {
log.debug("Constructing a response by json."); log.debug("Constructing a response by json.");
String code = json.getString("code"); String code = json.getString("code");
if (code.equals(Code.ERROR.value)) if (code.equals(Code.ERROR.value))
@ -43,21 +43,20 @@ public class SkuChangeResponse extends Response {
JSONObject data = json.getJSONObject("data"); JSONObject data = json.getJSONObject("data");
String stockId = data.getString("stockId"); String stockId = data.getString("stockId");
String stockSku = data.getString("stockSku");
if(data != null) { if(data != null) {
log.info("Constructed response: data contained {}", data); log.info("Constructed response: data contained {}", data);
} }
else { else {
log.info("Data is null"); log.info("Data is null");
} }
return new SkuChangeResponse(Code.SUCCESS, data, stockId, stockSku); return new SkuChangeResponse(Code.SUCCESS, data, stockId, erpCode);
} }
@Override @Override
public String toString() { public String toString() {
return "SkuListResponse{" + return "SkuChangeResponse{" +
", data=" + data + ", data=" + data +
'}'; '}';
} }

View File

@ -3,6 +3,7 @@ package org.jeecg.modules.business.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.business.domain.api.mabang.doSearchSkuListNew.SkuData; import org.jeecg.modules.business.domain.api.mabang.doSearchSkuListNew.SkuData;
import org.jeecg.modules.business.entity.Sku; import org.jeecg.modules.business.entity.Sku;
import org.jeecg.modules.business.entity.SkuWeight;
import org.jeecg.modules.business.vo.Responses; import org.jeecg.modules.business.vo.Responses;
import org.jeecg.modules.business.vo.SkuOrderPage; import org.jeecg.modules.business.vo.SkuOrderPage;
@ -38,4 +39,6 @@ public interface ISkuListMabangService extends IService<SkuData> {
void updateSkuId(); void updateSkuId();
void mabangSkuStockUpdate(List<String> erpCodes); void mabangSkuStockUpdate(List<String> erpCodes);
Responses mabangSkuWeightUpdate(List<SkuWeight> skuWeights);
} }

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.business.service.impl; package org.jeecg.modules.business.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import freemarker.template.Template; import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.SpringContextUtils; import org.jeecg.common.util.SpringContextUtils;
@ -9,10 +10,14 @@ import org.jeecg.modules.business.domain.api.mabang.doSearchSkuListNew.*;
import org.jeecg.modules.business.domain.api.mabang.stockDoAddStock.SkuAddRequest; import org.jeecg.modules.business.domain.api.mabang.stockDoAddStock.SkuAddRequest;
import org.jeecg.modules.business.domain.api.mabang.stockDoAddStock.SkuAddRequestBody; import org.jeecg.modules.business.domain.api.mabang.stockDoAddStock.SkuAddRequestBody;
import org.jeecg.modules.business.domain.api.mabang.stockDoAddStock.SkuAddResponse; import org.jeecg.modules.business.domain.api.mabang.stockDoAddStock.SkuAddResponse;
import org.jeecg.modules.business.domain.api.mabang.stockDoChangeStock.SkuChangeRequest;
import org.jeecg.modules.business.domain.api.mabang.stockDoChangeStock.SkuChangeRequestBody;
import org.jeecg.modules.business.domain.api.mabang.stockDoChangeStock.SkuChangeResponse;
import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockData; import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockData;
import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockRawStream; import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockRawStream;
import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockRequestBody; import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockRequestBody;
import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockStream; import org.jeecg.modules.business.domain.api.mabang.stockGetStockQuantity.SkuStockStream;
import org.jeecg.modules.business.domain.job.ThrottlingExecutorService;
import org.jeecg.modules.business.entity.*; import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.mapper.SkuListMabangMapper; import org.jeecg.modules.business.mapper.SkuListMabangMapper;
import org.jeecg.modules.business.mongoService.SkuMongoService; import org.jeecg.modules.business.mongoService.SkuMongoService;
@ -36,6 +41,7 @@ import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -73,6 +79,7 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
Environment env; Environment env;
private static final Integer DEFAULT_NUMBER_OF_THREADS = 10; private static final Integer DEFAULT_NUMBER_OF_THREADS = 10;
private static final Integer MABANG_API_RATE_LIMIT_PER_MINUTE = 10;
private final static String DEFAULT_WAREHOUSE_NAME = "SZBA宝安仓"; private final static String DEFAULT_WAREHOUSE_NAME = "SZBA宝安仓";
@ -626,4 +633,95 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
skuMongoService.updateStock(sku); skuMongoService.updateStock(sku);
} }
} }
@Override
public Responses mabangSkuWeightUpdate(List<SkuWeight> skuWeights) {
Responses responses = new Responses();
List<String> failures = new ArrayList<>();
List<Sku> skus = skuService.listByIds(skuWeights.stream()
.map(SkuWeight::getSkuId).collect(toList()));
Map<String, String> remarkMappedByErpCode = new HashMap<>();
List<List<String>> skusPartition = Lists.partition(skus.stream().map(Sku::getErpCode).collect(toList()), 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()) {
continue;
}
skusFromMabang.stream()
.filter(skuData -> skuData.getSaleRemark() != null)
.forEach(skuData -> {
String erpCode = skuData.getErpCode();
String remark = skuData.getSaleRemark();
remarkMappedByErpCode.put(erpCode, remark);
});
}
List<SkuData> skuDataList = skuWeights.stream()
.map(skuWeight -> {
Sku sku = skus.stream()
.filter(s -> s.getId().equals(skuWeight.getSkuId()))
.findFirst()
.orElse(null);
if(null == sku) {
log.error("Sku not found : {}", skuWeight.getSkuId());
failures.add(skuWeight.getSkuId());
return null;
}
SkuData skuData = new SkuData();
skuData.setErpCode(sku.getErpCode());
if(remarkMappedByErpCode.containsKey(sku.getErpCode())) {
StringBuilder remark = new StringBuilder();
remark.append(skuWeight.getWeight());
Matcher saleRemarkMatcher = saleRemarkPattern.matcher(remarkMappedByErpCode.get(sku.getErpCode()));
if(saleRemarkMatcher.matches() && !saleRemarkMatcher.group(2).isEmpty()) {
log.info("Sku {} has remark from Mabang : {}", sku.getErpCode(), saleRemarkMatcher.group(2));
String saleRemarkNotWeight = saleRemarkMatcher.group(2);
remark.append(saleRemarkNotWeight);
}
skuData.setSaleRemark(remark.toString());
}
else {
skuData.setSaleRemark(String.valueOf(skuWeight.getWeight()));
}
skuData.setWeight(skuWeight.getWeight());
return skuData;
})
.filter(Objects::nonNull)
.collect(toList());
ExecutorService executor = ThrottlingExecutorService.createExecutorService(DEFAULT_NUMBER_OF_THREADS, MABANG_API_RATE_LIMIT_PER_MINUTE, TimeUnit.MINUTES);
List<CompletableFuture<SkuChangeResponse>> futures = skuDataList.stream()
.map(skuData -> CompletableFuture.supplyAsync(() -> {
try {
SkuChangeRequestBody body = new SkuChangeRequestBody(skuData);
SkuChangeRequest request = new SkuChangeRequest(body);
return request.send();
} catch (Exception e) {
log.error("Error updating weight for sku {} : {}", skuData.getErpCode(), e.getMessage());
return new SkuChangeResponse(Response.Code.ERROR, null, null, skuData.getErpCode());
}
}, executor))
.collect(toList());
List<SkuChangeResponse> results = futures.stream().map(CompletableFuture::join).collect(toList());
long successCount = results.stream().filter(SkuChangeResponse::success).count();
log.info("{}/{} skus updated successfully.", successCount, skuDataList.size());
List<String> successes = results.stream()
.filter(SkuChangeResponse::success)
.map(SkuChangeResponse::getStockSku)
.collect(toList());
failures.addAll(results.stream()
.filter(response -> !response.success())
.map(SkuChangeResponse::getStockSku)
.collect(toList()));
responses.setSuccesses(successes);
responses.setFailures(failures);
return responses;
}
} }