mirror of https://github.com/jeecgboot/jeecg-boot
feat: add constraints and notification for SKU weight updates
parent
4926576b70
commit
a24b7aa032
|
@ -420,6 +420,48 @@ public class SkuController {
|
|||
page.setTotal(total);
|
||||
return Result.OK(page);
|
||||
}
|
||||
|
||||
@GetMapping("/listAllWithFilters")
|
||||
public Result<?> listAllWithFilters(
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "50") Integer pageSize,
|
||||
@RequestParam(name = "column", defaultValue = "erp_code") String column,
|
||||
@RequestParam(name = "order", defaultValue = "ASC") String order,
|
||||
@RequestParam(name = "erpCodes", required = false) String erpCodes,
|
||||
@RequestParam(name = "zhNames", required = false) String zhNames,
|
||||
@RequestParam(name = "enNames", required = false) String enNames,
|
||||
ServletRequest servletRequest) {
|
||||
|
||||
String parsedColumn = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column.replace("_dictText", ""));
|
||||
String parsedOrder = order.toUpperCase();
|
||||
if (!parsedOrder.equals("ASC") && !parsedOrder.equals("DESC")) {
|
||||
return Result.error("Error 400 Bad Request");
|
||||
}
|
||||
|
||||
try {
|
||||
specialFilterContentForDictSql(parsedColumn);
|
||||
} catch (RuntimeException e) {
|
||||
return Result.error("Error 400 Bad Request");
|
||||
}
|
||||
|
||||
List<SkuOrderPage> skuOrdersPage;
|
||||
int total;
|
||||
|
||||
List<String> erpCodeList = erpCodes == null ? null : Arrays.asList(erpCodes.split(","));
|
||||
List<String> zhNameList = zhNames == null ? null : Arrays.asList(zhNames.split(","));
|
||||
List<String> enNameList = enNames == null ? null : Arrays.asList(enNames.split(","));
|
||||
|
||||
// Count and fetch ALL records (not just latest)
|
||||
total = skuService.countAllSkuWeightHistoryWithFilters(erpCodeList, zhNameList, enNameList);
|
||||
skuOrdersPage = skuService.fetchAllSkuWeightsWithFilters(pageNo, pageSize, parsedColumn, parsedOrder, erpCodeList, zhNameList, enNameList);
|
||||
|
||||
IPage<SkuOrderPage> page = new Page<>();
|
||||
page.setRecords(skuOrdersPage);
|
||||
page.setCurrent(pageNo);
|
||||
page.setSize(pageSize);
|
||||
page.setTotal(total);
|
||||
return Result.OK(page);
|
||||
}
|
||||
@GetMapping("/listAllSelectableSkuIds")
|
||||
public Result<?> listAllSelectableSkuIds(@RequestParam(name = "clientId") String clientId,
|
||||
@RequestParam(name = "erpCodes", required = false) String erpCodes,
|
||||
|
|
|
@ -11,8 +11,10 @@ import javax.annotation.Resource;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
|
@ -20,6 +22,7 @@ import org.jeecg.common.system.vo.LoginUser;
|
|||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.modules.business.entity.Sku;
|
||||
import org.jeecg.modules.business.entity.SkuWeight;
|
||||
import org.jeecg.modules.business.model.SkuDocument;
|
||||
import org.jeecg.modules.business.mongoService.SkuMongoService;
|
||||
import org.jeecg.modules.business.service.ISecurityService;
|
||||
import org.jeecg.modules.business.service.ISkuListMabangService;
|
||||
|
@ -35,10 +38,14 @@ import org.jeecg.common.system.base.controller.JeecgController;
|
|||
import org.jeecg.modules.business.vo.ResponsesWithMsg;
|
||||
import org.jeecg.modules.business.vo.SkuWeightPage;
|
||||
import org.jeecg.modules.business.vo.SkuWeightParam;
|
||||
import org.jeecg.modules.message.websocket.WebSocketSender;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -72,6 +79,8 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
|
|||
private SkuMongoService skuMongoService;
|
||||
@Resource
|
||||
private JeecgBaseConfig jeecgBaseConfig;
|
||||
@Autowired
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
private static final Integer DEFAULT_NUMBER_OF_THREADS = 1;
|
||||
private final static Integer NUMBER_OF_SKU_EXCEL_COLUMNS = 3;
|
||||
|
@ -137,11 +146,39 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
|
|||
*/
|
||||
@AutoLog(value = "sku_weight-批量删除")
|
||||
@ApiOperation(value="sku_weight-批量删除", notes="sku_weight-批量删除")
|
||||
@RequiresPermissions("business:sku_weight:deleteBatch")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
this.skuWeightService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.OK("批量删除成功!");
|
||||
public Result<String> deleteBatch(@RequestBody List<String> ids) {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
boolean isEmployee = securityService.checkIsEmployee();
|
||||
if (!isEmployee) {
|
||||
log.info("User {}, tried to access /skuWeight/updateBatch but is not authorized.", sysUser.getUsername());
|
||||
return Result.error(403,"Forbidden.");
|
||||
}
|
||||
List<SkuWeight> weightsToDelete = skuWeightService.listByIds(ids);
|
||||
// delete from mysql
|
||||
skuWeightService.removeByIds(ids);
|
||||
//update the latest SKU weight in MongoDB
|
||||
for (SkuWeight deleted : weightsToDelete) {
|
||||
String skuId = deleted.getSkuId();
|
||||
Date deletedDate = deleted.getEffectiveDate();
|
||||
|
||||
Query query = new Query(Criteria.where("skuId").is(skuId));
|
||||
SkuDocument doc = mongoTemplate.findOne(query, SkuDocument.class);
|
||||
|
||||
boolean isLatestDeleted = doc != null &&
|
||||
doc.getLatestSkuWeight() != null &&
|
||||
deletedDate.equals(doc.getLatestSkuWeight().getEffectiveDate());
|
||||
if (isLatestDeleted) {
|
||||
skuMongoService.deleteSkuWeightBySkuId(skuId);
|
||||
List<SkuWeight> remaining = skuWeightService.list(
|
||||
new QueryWrapper<SkuWeight>().eq("sku_id", skuId).orderByDesc("effective_date"));
|
||||
if (!remaining.isEmpty()) {
|
||||
skuMongoService.upsertSkuWeight(remaining.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("Deleted SKU weights: {}", weightsToDelete);
|
||||
return Result.OK("SKU重量批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -194,104 +231,196 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
|
|||
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
|
||||
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
log.info("Importing Sku weights from Excel...");
|
||||
boolean isEmployee = securityService.checkIsEmployee();
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
if(!isEmployee){
|
||||
log.info("User {}, tried to access /skuWeight/updateBatch but is not authorized.", sysUser.getUsername());
|
||||
return Result.error(403,"Forbidden.");
|
||||
}
|
||||
String userId = ((LoginUser) SecurityUtils.getSubject().getPrincipal()).getId();
|
||||
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
|
||||
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_NUMBER_OF_THREADS);
|
||||
|
||||
for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
|
||||
MultipartFile file = entry.getValue();
|
||||
|
||||
executor.submit(() -> {
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
Workbook workbook = file.getOriginalFilename().endsWith(".xlsx")
|
||||
? new XSSFWorkbook(inputStream)
|
||||
: new HSSFWorkbook(inputStream);
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
int firstRow = sheet.getFirstRowNum();
|
||||
int lastRow = sheet.getLastRowNum();
|
||||
|
||||
ResponsesWithMsg<String> responses = new ResponsesWithMsg<>();
|
||||
List<SkuWeight> skuWeights = new ArrayList<>();
|
||||
Map<String, SkuWeight> skuWeightMappedByErpCode = new HashMap<>();
|
||||
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
|
||||
MultipartFile file = entity.getValue();
|
||||
try (InputStream inputStream = file.getInputStream()){
|
||||
Workbook workbook = new HSSFWorkbook(inputStream);
|
||||
Sheet firstSheet = workbook.getSheetAt(0);
|
||||
int firstRow = firstSheet.getFirstRowNum();
|
||||
int lastRow = firstSheet.getLastRowNum();
|
||||
ResponsesWithMsg<String> responses = new ResponsesWithMsg<>();
|
||||
|
||||
for (int rowIndex = firstRow + 1; rowIndex <= lastRow; rowIndex++) {
|
||||
Row row = firstSheet.getRow(rowIndex);
|
||||
Row row = sheet.getRow(rowIndex);
|
||||
if (row == null) continue;
|
||||
|
||||
SkuWeight skuWeight = new SkuWeight();
|
||||
boolean hasError = false;
|
||||
String erpCode = null;
|
||||
for (int cellIndex = row.getFirstCellNum(); cellIndex < NUMBER_OF_SKU_EXCEL_COLUMNS; cellIndex++) {
|
||||
|
||||
for (int cellIndex = 0; cellIndex < NUMBER_OF_SKU_EXCEL_COLUMNS; cellIndex++) {
|
||||
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
if(hasError) continue;
|
||||
if(cell.getCellType().equals(CellType.BLANK)){
|
||||
responses.addFailure("Row " + rowIndex + " has empty cell at index " + cellIndex);
|
||||
if (hasError) break;
|
||||
|
||||
if (cell.getCellType() == CellType.BLANK) {
|
||||
responses.addFailure("Row " + (rowIndex + 1), " Cell " + cellIndex + " is blank");
|
||||
log.error("Row {} Cell {} is blank", rowIndex + 1, cellIndex);
|
||||
hasError = true;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
switch (cellIndex) {
|
||||
case 0:
|
||||
String skuCode = cell.getStringCellValue();
|
||||
case 0: // ERP Code
|
||||
String skuCode = cell.getStringCellValue().trim();
|
||||
Sku sku = skuService.getByErpCode(skuCode);
|
||||
if(sku == null){
|
||||
responses.addFailure("Row " + rowIndex + " SKU not found : " + skuCode);
|
||||
if (sku == null || sku.getId() == null) {
|
||||
responses.addFailure("Row " + (rowIndex + 1), " 无效ERP编码: " + skuCode);
|
||||
log.error("Row {} is not a valid SKU", rowIndex + 1);
|
||||
hasError = true;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
erpCode = skuCode;
|
||||
skuWeight.setSkuId(sku.getId());
|
||||
break;
|
||||
case 1:
|
||||
|
||||
case 1: // Weight
|
||||
int weight;
|
||||
if(cell.getCellType().equals(CellType.STRING))
|
||||
weight = Integer.parseInt(cell.getStringCellValue());
|
||||
else if(cell.getCellType().equals(CellType.NUMERIC))
|
||||
if (cell.getCellType() == CellType.STRING) {
|
||||
weight = Integer.parseInt(cell.getStringCellValue().trim());
|
||||
} else if (cell.getCellType() == CellType.NUMERIC) {
|
||||
weight = (int) cell.getNumericCellValue();
|
||||
else {
|
||||
responses.addFailure("Row " + rowIndex + " Weight is not a number - Sku : " + erpCode);
|
||||
} else {
|
||||
responses.addFailure("Row " + (rowIndex + 1),
|
||||
"无法识别的重量类型");
|
||||
hasError = true;
|
||||
continue;
|
||||
throw new IllegalArgumentException("无法识别的重量类型");
|
||||
}
|
||||
skuWeight.setWeight(weight);
|
||||
break;
|
||||
case 2:
|
||||
String date;
|
||||
if(cell.getCellType().equals(CellType.STRING))
|
||||
date = cell.getStringCellValue();
|
||||
else if(cell.getCellType().equals(CellType.NUMERIC))
|
||||
date = formatter.format(cell.getDateCellValue());
|
||||
else {
|
||||
responses.addFailure("Row " + rowIndex + " Date is not a date - Sku : " + erpCode);
|
||||
|
||||
case 2: // Date
|
||||
String dateStr;
|
||||
if (cell.getCellType() == CellType.STRING) {
|
||||
dateStr = cell.getStringCellValue().trim();
|
||||
} else if (cell.getCellType() == CellType.NUMERIC) {
|
||||
dateStr = formatter.format(cell.getDateCellValue());
|
||||
} else {
|
||||
responses.addFailure("Row " + (rowIndex + 1),
|
||||
"日期格式错误");
|
||||
hasError = true;
|
||||
continue;
|
||||
throw new IllegalArgumentException("日期格式错误");
|
||||
}
|
||||
Date effectiveDate = formatter.parse(date);
|
||||
Date effectiveDate = formatter.parse(dateStr);
|
||||
skuWeight.setEffectiveDate(effectiveDate);
|
||||
break;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
responses.addFailure("Row " + (rowIndex + 1), " Column " + cellIndex + " error: " + ex.getMessage());
|
||||
hasError = true;
|
||||
}
|
||||
if(hasError) continue;
|
||||
skuWeights.add(skuWeight);
|
||||
assert erpCode != null;
|
||||
skuWeightMappedByErpCode.put(erpCode, skuWeight);
|
||||
}
|
||||
log.info("Import weights for skus: {}", skuWeightMappedByErpCode.keySet());
|
||||
ResponsesWithMsg<String> mabangResponses = skuListMabangService.mabangSkuWeightUpdate(skuWeights);
|
||||
List<SkuWeight> skuWeightSuccesses = new ArrayList<>();
|
||||
mabangResponses.getSuccesses().forEach((skuErpCode, messages) -> {
|
||||
skuWeightSuccesses.add(skuWeightMappedByErpCode.get(skuErpCode));
|
||||
});
|
||||
skuWeightSuccesses.forEach(skuWeight -> skuMongoService.upsertSkuWeight(skuWeight));
|
||||
skuWeightService.saveBatch(skuWeights);
|
||||
|
||||
mabangResponses.getSuccesses().forEach(responses::addSuccess);
|
||||
mabangResponses.getFailures().forEach(responses::addFailure);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
String msg = e.getMessage();
|
||||
log.error(msg, e);
|
||||
return Result.error("文件导入失败:" + e.getMessage());
|
||||
} finally {
|
||||
if (hasError) continue;
|
||||
|
||||
log.info("Querying sku_weight with sku_id = {}", skuWeight.getSkuId());
|
||||
QueryWrapper<SkuWeight> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("sku_id", skuWeight.getSkuId());
|
||||
List<SkuWeight> existingWeight = skuWeightService.list(wrapper);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
String dateStr = sdf.format(skuWeight.getEffectiveDate());
|
||||
|
||||
boolean sameDateExists = existingWeight.stream()
|
||||
.anyMatch(e -> sdf.format(e.getEffectiveDate()).equals(dateStr));
|
||||
if (sameDateExists) {
|
||||
responses.addSuccess("Row " + (rowIndex + 1), " 已存在相同SKU和日期,跳过");
|
||||
log.info("Row {} 已存在相同SKU和日期,跳过", rowIndex + 1);
|
||||
log.info("Row {} has existing weight with same date for SKU {}, skipping",
|
||||
rowIndex + 1, skuWeight.getSkuId());
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean sameContentExists = existingWeight.stream()
|
||||
.anyMatch(e -> e.getWeight() == skuWeight.getWeight());
|
||||
if (sameContentExists) {
|
||||
responses.addSuccess("Row " + (rowIndex + 1), " 内容一致,仅日期不同,跳过");
|
||||
log.info("Row {} has existing weight with same content but different date for SKU {}, skipping",
|
||||
rowIndex + 1, skuWeight.getSkuId());
|
||||
continue;
|
||||
}
|
||||
|
||||
skuWeights.add(skuWeight);
|
||||
skuWeightMappedByErpCode.put(erpCode, skuWeight);
|
||||
responses.addSuccess("Row " + (rowIndex + 1),
|
||||
erpCode + " 成功解析并导入");
|
||||
}
|
||||
if (!skuWeights.isEmpty()) {
|
||||
//step 1: Save to MySQL and MongoDB
|
||||
skuWeightService.saveBatch(skuWeights);
|
||||
skuWeights.forEach(skuWeight -> skuMongoService.upsertSkuWeight(skuWeight));
|
||||
log.info("Database import completed, {} records processed", skuWeights.size());
|
||||
|
||||
//step 2: Notify frontend about the import result
|
||||
JSONObject detailMsg = new JSONObject();
|
||||
detailMsg.put("cmd", "import-result");
|
||||
detailMsg.put("msgTxt", "SKU重量导入数据库完成,正在同步马帮...");
|
||||
|
||||
detailMsg.put("data", new JSONObject() {{
|
||||
put("successes", responses.getSuccesses());
|
||||
put("failures", responses.getFailures());
|
||||
}});
|
||||
|
||||
log.info("import-result 消息体: {}", detailMsg.toJSONString());
|
||||
log.info("import-result message:{} ", detailMsg.toJSONString());
|
||||
WebSocketSender.sendToUser(userId, detailMsg.toJSONString());
|
||||
|
||||
//step 3: Asynchronously call Mabang API
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
file.getInputStream().close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
ResponsesWithMsg<String> mabangResponses = skuListMabangService.mabangSkuWeightUpdate(skuWeights);
|
||||
|
||||
List<SkuWeight> matchedSuccesses = new ArrayList<>();
|
||||
mabangResponses.getSuccesses().forEach((skuErpCode, messages) -> {
|
||||
SkuWeight matched = skuWeightMappedByErpCode.get(skuErpCode);
|
||||
if (matched != null) {
|
||||
matchedSuccesses.add(matched);
|
||||
}
|
||||
});
|
||||
log.info("Mabang synchronization completed - successes: {}, failures: {}",
|
||||
mabangResponses.getSuccesses().size(), mabangResponses.getFailures().size());
|
||||
} catch (Exception ex) {
|
||||
log.error("Mabang synchronization failed", ex);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
log.warn("No valid SKU weights found to import, skipping");
|
||||
JSONObject detailMsg = new JSONObject();
|
||||
detailMsg.put("cmd", "import-result");
|
||||
detailMsg.put("msgTxt", "未发现可导入的 SKU 权重记录");
|
||||
detailMsg.put("data", new JSONObject() {{
|
||||
put("successes", responses.getSuccesses());
|
||||
put("failures", responses.getFailures());
|
||||
}});
|
||||
|
||||
WebSocketSender.sendToUser(userId, detailMsg.toJSONString());
|
||||
}
|
||||
return Result.OK(responses);
|
||||
} catch (Exception e) {
|
||||
log.error("asynchronous import failed", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
return Result.OK("导入任务已提交,请稍后查看结果");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* /!\ Not maintained use updateBatch instead.
|
||||
|
@ -335,11 +464,45 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
|
|||
log.info("User {}, tried to access /skuWeight/updateBatch but is not authorized.", sysUser.getUsername());
|
||||
return Result.error(403,"Forbidden.");
|
||||
}
|
||||
String userId = ((LoginUser) SecurityUtils.getSubject().getPrincipal()).getId();
|
||||
Map<String, SkuWeight> skuWeightsMap = new HashMap<>();
|
||||
for(String skuId : param.getIds()){
|
||||
|
||||
ResponsesWithMsg<String> responses = new ResponsesWithMsg<>();
|
||||
for (String weightId : param.getIds()) {
|
||||
//get SkuWeight by weightId
|
||||
SkuWeight weightRecord = skuWeightService.getById(weightId);
|
||||
if (weightRecord == null) {
|
||||
log.warn("weightId {} invalid, no corresponding SKU weight record found", weightId);
|
||||
responses.addFailure("weightId 无效: " + weightId);
|
||||
continue;
|
||||
}
|
||||
// get SKU by skuId
|
||||
String skuId = weightRecord.getSkuId();
|
||||
Sku sku = skuService.getById(skuId);
|
||||
if (sku == null) {
|
||||
return Result.error(404,"SKU not found : " + skuId);
|
||||
log.warn("SKU not found for weightId: {}", weightId);
|
||||
responses.addFailure("SKU not found for weightId: " + weightId);
|
||||
continue;
|
||||
}
|
||||
//check if there is an existing record with the same sku_id and effective_date
|
||||
QueryWrapper<SkuWeight> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("sku_id", skuId);
|
||||
wrapper.apply("DATE(effective_date) = {0}", new SimpleDateFormat("yyyy-MM-dd").format(param.getEffectiveDate()));
|
||||
if (skuWeightService.count(wrapper) > 0) {
|
||||
log.warn("SKU {} already has a weight record for the same date, skipping", sku.getErpCode());
|
||||
responses.addSuccess(sku.getErpCode() , ": 相同日期的重量记录已存在,跳过");
|
||||
continue;
|
||||
}
|
||||
//check if there is an existing record with the same sku_id and weight but different effective_date
|
||||
wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("sku_id", skuId).eq("weight", param.getWeight());
|
||||
List<SkuWeight> existing = skuWeightService.list(wrapper);
|
||||
boolean sameContentDiffDate = existing.stream()
|
||||
.anyMatch(e -> !e.getEffectiveDate().equals(param.getEffectiveDate()));
|
||||
if (sameContentDiffDate) {
|
||||
log.warn("SKU {} has the same weight but different date, skipping", sku.getErpCode());
|
||||
responses.addSuccess(sku.getErpCode() , ": 日期不同但重量相同,跳过");
|
||||
continue;
|
||||
}
|
||||
SkuWeight skuWeight = new SkuWeight();
|
||||
skuWeight.setCreateBy(sysUser.getUsername());
|
||||
|
@ -350,34 +513,40 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
|
|||
}
|
||||
// Submit task asynchronously
|
||||
List<SkuWeight> skuWeights = new ArrayList<>(skuWeightsMap.values());
|
||||
if (skuWeights.isEmpty()) {
|
||||
log.warn("No valid SKU weights to update, task not submitted");
|
||||
return Result.error("日期或者重量重复,没有有效的数据可更新,任务未提交");
|
||||
}
|
||||
// Update Mongo + save to database
|
||||
skuWeightService.saveBatch(skuWeights);
|
||||
skuWeights.forEach(skuMongoService::upsertSkuWeight);
|
||||
skuWeights.forEach(skuWeight -> {
|
||||
skuMongoService.upsertSkuWeight(skuWeight);
|
||||
String erpCode = skuService.getById(skuWeight.getSkuId()).getErpCode();
|
||||
responses.addSuccess(erpCode, "数据库重量已成功更新");
|
||||
});
|
||||
|
||||
log.info("SKU weights updated successfully, {} records processed", skuWeights.size());
|
||||
// send WebSocket message
|
||||
JSONObject detailMsg = new JSONObject();
|
||||
detailMsg.put("cmd", "update-result");
|
||||
detailMsg.put("msgTxt", "SKU重量已更新到数据库,正在同步马帮...");
|
||||
detailMsg.put("data", new JSONObject() {{
|
||||
put("successes", responses.getSuccesses());
|
||||
put("failures", responses.getFailures());
|
||||
}});
|
||||
log.info("update-result message: {}", detailMsg.toJSONString());
|
||||
WebSocketSender.sendToUser(userId, detailMsg.toJSONString());
|
||||
// Asynchronously call Mabang API to update SKU weights
|
||||
ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_NUMBER_OF_THREADS);
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
ResponsesWithMsg<String> responses = skuListMabangService.mabangSkuWeightUpdate(skuWeights);
|
||||
List<SkuWeight> skuWeightSuccesses = new ArrayList<>();
|
||||
responses.getSuccesses().forEach((skuErpCode, messages) -> {
|
||||
skuWeightSuccesses.add(skuWeightsMap.get(skuErpCode));
|
||||
});
|
||||
// Update Mongo + save to database
|
||||
skuWeightSuccesses.forEach(skuWeight -> skuMongoService.upsertSkuWeight(skuWeight));
|
||||
skuWeightService.saveBatch(skuWeights);
|
||||
skuListMabangService.mabangSkuWeightUpdate(skuWeights);
|
||||
log.info("updateBatch call to Mabang submitted successfully");
|
||||
} catch (Exception e) {
|
||||
log.error("Asynchronous updateBatch processing failed", e);
|
||||
log.error("Asynchronous updateBatch call to Mabang failed", e);
|
||||
}
|
||||
});
|
||||
|
||||
return Result.OK("Batch Edit task has been submitted, please check progress later");
|
||||
///////////////////////////////////////////////////
|
||||
/**
|
||||
List<SkuWeight> skuWeights = new ArrayList<>(skuWeightsMap.values());
|
||||
ResponsesWithMsg<String> responses = skuListMabangService.mabangSkuWeightUpdate(skuWeights);
|
||||
List<SkuWeight> skuWeightSuccesses = new ArrayList<>();
|
||||
responses.getSuccesses().forEach((skuErpCode, messages) -> {
|
||||
skuWeightSuccesses.add(skuWeightsMap.get(skuErpCode));
|
||||
});
|
||||
|
||||
skuWeightSuccesses.forEach(skuWeight -> skuMongoService.upsertSkuWeight(skuWeight));
|
||||
skuWeightService.saveBatch(skuWeights);
|
||||
return Result.OK(responses);*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,12 +53,14 @@ public interface SkuMapper extends BaseMapper<Sku> {
|
|||
|
||||
Integer countAllSkus();
|
||||
Integer countAllSkuWeightsWithFilters(@Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex);
|
||||
Integer countAllSkuWeightHistoryWithFilters(@Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex);
|
||||
Integer countAllClientSkus(@Param("clientId") String clientId);
|
||||
Integer countAllClientSkusWithFilters(@Param("clientId") String clientId, @Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex);
|
||||
|
||||
List<SkuOrderPage> fetchSkuWeights(@Param("offset") Integer offset, @Param("size") Integer pageSize, @Param("column") String column, @Param("order") String order);
|
||||
List<SkuOrderPage> fetchSkusByClient(@Param("clientId") String clientId, @Param("offset") Integer offset, @Param("size") Integer pageSize, @Param("column") String column, @Param("order") String order);
|
||||
List<SkuOrderPage> fetchSkuWeightsWithFilters(@Param("offset") Integer offset, @Param("size") Integer pageSize, @Param("column") String column, @Param("order") String order, @Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex);
|
||||
List<SkuOrderPage> fetchAllSkuWeightsWithFilters(@Param("offset") Integer offset, @Param("size") Integer pageSize, @Param("column") String column, @Param("order") String order, @Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex);
|
||||
List<SkuOrderPage> fetchSkusByClientWithFilters(@Param("clientId") String clientId, @Param("offset") Integer offset, @Param("size") Integer pageSize, @Param("column") String column, @Param("order") String order, @Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex);
|
||||
|
||||
List<SkuOrderPage> listSelectableSkuIdsWithFilters(@Param("clientId") String clientId, @Param("erpCodes") String erpCodeList, @Param("zhNames") String zhNameList, @Param("enNames") String enNameList);
|
||||
|
|
|
@ -260,6 +260,21 @@
|
|||
</if>
|
||||
);
|
||||
</select>
|
||||
<select id="countAllSkuWeightHistoryWithFilters" resultType="java.lang.Integer">
|
||||
SELECT COUNT(*)
|
||||
FROM sku s
|
||||
LEFT JOIN sku_weight sw ON s.id = sw.sku_id
|
||||
WHERE s.status = 3
|
||||
<if test="erpCodes != null and erpCodes != ''">
|
||||
AND s.erp_code REGEXP #{erpCodes}
|
||||
</if>
|
||||
<if test="zhNames != null and zhNames != ''">
|
||||
AND s.zh_name REGEXP #{zhNames}
|
||||
</if>
|
||||
<if test="enNames != null and enNames != ''">
|
||||
AND s.en_name REGEXP #{enNames}
|
||||
</if>
|
||||
</select>
|
||||
<select id="fetchSkuWeightsWithFilters" resultType="org.jeecg.modules.business.vo.SkuOrderPage">
|
||||
WITH latestSkuWeights AS (
|
||||
SELECT
|
||||
|
@ -301,6 +316,32 @@
|
|||
</if>
|
||||
;
|
||||
</select>
|
||||
<select id="fetchAllSkuWeightsWithFilters" resultType="org.jeecg.modules.business.vo.SkuOrderPage">
|
||||
SELECT
|
||||
s.id,
|
||||
sw.id AS weightId,
|
||||
s.erp_code,
|
||||
s.zh_name,
|
||||
s.en_name,
|
||||
sw.effective_date AS weightEffectiveDate,
|
||||
sw.weight
|
||||
FROM sku s
|
||||
LEFT JOIN sku_weight sw ON s.id = sw.sku_id
|
||||
WHERE s.status = 3
|
||||
<if test="erpCodes != null and erpCodes != ''">
|
||||
AND s.erp_code REGEXP #{erpCodes}
|
||||
</if>
|
||||
<if test="zhNames != null and zhNames != ''">
|
||||
AND s.zh_name REGEXP #{zhNames}
|
||||
</if>
|
||||
<if test="enNames != null and enNames != ''">
|
||||
AND s.en_name REGEXP #{enNames}
|
||||
</if>
|
||||
ORDER BY ${column} ${order}, sw.effective_date DESC
|
||||
<if test="size != -1">
|
||||
LIMIT #{offset}, #{size}
|
||||
</if>
|
||||
</select>
|
||||
<select id="countAllClientSkusWithFilters" resultType="java.lang.Integer">
|
||||
SELECT COUNT(*) AS total
|
||||
FROM sku s
|
||||
|
|
|
@ -95,25 +95,4 @@ public class SkuMongoSyncService {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handeSkuWeightModifiedEvent(SkuWeightModifiedEvent event) {
|
||||
log.info("Received a SkuWeightModifiedEvent: {}", event);
|
||||
String id = event.getId();
|
||||
String operation = event.getOperation();
|
||||
|
||||
SkuWeight skuWeight = skuWeightService.getById(id);
|
||||
|
||||
switch (operation) {
|
||||
case "INSERT":
|
||||
case "UPDATE":
|
||||
skuMongoService.upsertSkuWeight(skuWeight);
|
||||
break;
|
||||
case "DELETE":
|
||||
skuMongoService.deleteSkuWeightBySkuId(skuWeight.getSkuId());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,11 @@ public interface ISkuService extends IService<Sku> {
|
|||
List<SkuOrderPage> fetchSkusByClient(String clientId, Integer pageNo, Integer pageSize, String column, String order);
|
||||
|
||||
Integer countAllSkuWeightsWithFilters(List<String> erpCodeList, List<String> zhNameList, List<String> enNameList);
|
||||
|
||||
Integer countAllSkuWeightHistoryWithFilters(List<String> erpCodes, List<String> zhNames, List<String> enNames);
|
||||
|
||||
List<SkuOrderPage> fetchSkuWeightsWithFilters(Integer pageNo, Integer pageSize, String parsedColumn, String parsedOrder, List<String> erpCodes, List<String> zhNames, List<String> enNames);
|
||||
List<SkuOrderPage> fetchAllSkuWeightsWithFilters(Integer pageNo, Integer pageSize, String column, String order, List<String> erpCodes, List<String> zhNames, List<String> enNames);
|
||||
|
||||
Integer countAllClientSkusWithFilters(String clientId, List<String> erpCodeList, List<String> zhNameList, List<String> enNameList);
|
||||
List<SkuOrderPage> fetchSkusByClientWithFilters(String clientId, Integer pageNo, Integer pageSize, String column, String order, List<String> erpCodes, List<String> zhNames, List<String> enNames);
|
||||
|
|
|
@ -15,6 +15,8 @@ import java.util.List;
|
|||
public interface ISkuWeightService extends IService<SkuWeight> {
|
||||
SkuWeight getBySkuId(String skuId);
|
||||
|
||||
List<SkuWeight> findBySkuId(String skuId);
|
||||
|
||||
String searchFirstEmptyWeightSku(List<String> skuIds);
|
||||
|
||||
List<SkuWeight> exportToExcel(List<String> skuIds);
|
||||
|
|
|
@ -732,7 +732,7 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
Date effectiveDateToImport = skuWeightMappedById.get(sku.getId()).getEffectiveDate();
|
||||
if(latestEffectiveDate.after(effectiveDateToImport)) {
|
||||
log.info("Sku {} has a more recent weight in DB. Therefore won't be imported to Mabang", sku.getErpCode());
|
||||
responses.addSuccess(sku.getErpCode());
|
||||
responses.addSuccess(sku.getErpCode(), "跳过:已有更新的重量,未同步到Mabang");
|
||||
continue;
|
||||
}
|
||||
skusToUpdate.add(sku);
|
||||
|
@ -822,10 +822,10 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
SkuChangeResponse response = request.send();
|
||||
|
||||
if(response.success()) {
|
||||
responses.addSuccess(response.getStockSku(), "Mabang");
|
||||
responses.addSuccess(response.getStockSku(), "Mabang 重量更新成功");
|
||||
}
|
||||
else {
|
||||
responses.addFailure(response.getStockSku(), "Mabang");
|
||||
responses.addFailure(response.getStockSku(), "Mabang 重量更新失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error updating weight for sku {} : {}", skuData.getErpCode(), e.getMessage());
|
||||
|
@ -835,8 +835,16 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
// Only push progress if processed enough items (step) or finished all
|
||||
if (currentProcessed % step == 0 || currentProcessed == totalCount) {
|
||||
JSONObject progressMsg = new JSONObject();
|
||||
progressMsg.put("cmd", "user");
|
||||
progressMsg.put("msgTxt", "已处理 " + currentProcessed + " / " + totalCount + " 条 SKU 更新任务");
|
||||
progressMsg.put("cmd", "mabang-result");
|
||||
progressMsg.put("type", "progress");
|
||||
progressMsg.put("msgTxt", "Mabang重量更新中...");
|
||||
|
||||
JSONObject progressData = new JSONObject();
|
||||
progressData.put("progress", (currentProcessed * 100) / totalCount);
|
||||
progressData.put("current", currentProcessed);
|
||||
progressData.put("total", totalCount);
|
||||
|
||||
progressMsg.put("data", progressData);
|
||||
WebSocketSender.sendToUser(userId, progressMsg.toJSONString());
|
||||
}
|
||||
}
|
||||
|
@ -851,17 +859,19 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
|
|||
int failureCount = responses.getFailures().size();
|
||||
|
||||
JSONObject doneMsg = new JSONObject();
|
||||
doneMsg.put("cmd", "user");
|
||||
doneMsg.put("msgTxt", "SKU 重量更新全部完成!");
|
||||
doneMsg.put("cmd", "mabang-result");
|
||||
doneMsg.put("type", "complete");
|
||||
doneMsg.put("msgTxt", "SKU重量在马帮更新全部完成!");
|
||||
doneMsg.put("data", new JSONObject() {{
|
||||
put("total", skuDataList.size());
|
||||
put("success", successCount);
|
||||
put("failure", failureCount);
|
||||
put("progress", 100);
|
||||
put("successes", responses.getSuccesses());
|
||||
put("failures", responses.getFailures());
|
||||
}});
|
||||
|
||||
// Send the final result to frontend via WebSocket
|
||||
WebSocketSender.sendToUser(userId, doneMsg.toJSONString());
|
||||
|
||||
log.info("SKU Weight update completed: total {} items processed, {} succeeded, {} failed", skuDataList.size(), successCount, failureCount);
|
||||
return responses;
|
||||
}
|
||||
|
|
|
@ -453,6 +453,40 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
|
|||
return skuMapper.countAllSkuWeightsWithFilters(erpCodesRegex.toString(), zhNamesRegex.toString(), enNamesRegex.toString());
|
||||
}
|
||||
@Override
|
||||
public Integer countAllSkuWeightHistoryWithFilters(List<String> erpCodes, List<String> zhNames, List<String> enNames) {
|
||||
StringBuilder erpCodesRegex = new StringBuilder(), zhNamesRegex = new StringBuilder(), enNamesRegex = new StringBuilder();
|
||||
|
||||
if (erpCodes != null) {
|
||||
erpCodesRegex.append("^");
|
||||
for (String name : erpCodes) {
|
||||
erpCodesRegex.append("(?=.*").append(name).append(")");
|
||||
}
|
||||
erpCodesRegex.append(".*");
|
||||
}
|
||||
|
||||
if (enNames != null) {
|
||||
enNamesRegex.append("^");
|
||||
for (String name : enNames) {
|
||||
enNamesRegex.append("(?=.*").append(name).append(")");
|
||||
}
|
||||
enNamesRegex.append(".*");
|
||||
}
|
||||
|
||||
if (zhNames != null) {
|
||||
zhNamesRegex.append("^");
|
||||
for (String name : zhNames) {
|
||||
zhNamesRegex.append("(?=.*").append(name).append(")");
|
||||
}
|
||||
zhNamesRegex.append(".*$");
|
||||
}
|
||||
|
||||
return skuMapper.countAllSkuWeightHistoryWithFilters(
|
||||
erpCodesRegex.toString(),
|
||||
zhNamesRegex.toString(),
|
||||
enNamesRegex.toString()
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public List<SkuOrderPage> fetchSkuWeightsWithFilters(Integer pageNo, Integer pageSize, String column, String order, List<String> erpCodes, List<String> zhNames, List<String> enNames) {
|
||||
int offset = (pageNo - 1) * pageSize;
|
||||
StringBuilder erpCodesRegex= new StringBuilder(), zhNamesRegex = new StringBuilder(), enNamesRegex = new StringBuilder();
|
||||
|
@ -480,6 +514,46 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
|
|||
return skuMapper.fetchSkuWeightsWithFilters(offset, pageSize, column, order, erpCodesRegex.toString(), zhNamesRegex.toString(), enNamesRegex.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SkuOrderPage> fetchAllSkuWeightsWithFilters(Integer pageNo, Integer pageSize, String column, String order, List<String> erpCodes, List<String> zhNames, List<String> enNames) {
|
||||
int offset = (pageNo - 1) * pageSize;
|
||||
StringBuilder erpCodesRegex= new StringBuilder(), zhNamesRegex = new StringBuilder(), enNamesRegex = new StringBuilder();
|
||||
if (erpCodes != null) {
|
||||
erpCodesRegex.append("^");
|
||||
for (String name : erpCodes) {
|
||||
erpCodesRegex.append("(?=.*").append(name).append(")");
|
||||
}
|
||||
erpCodesRegex.append(".*");
|
||||
}
|
||||
if (enNames != null) {
|
||||
enNamesRegex.append("^");
|
||||
for (String name : enNames) {
|
||||
enNamesRegex.append("(?=.*").append(name).append(")");
|
||||
}
|
||||
enNamesRegex.append(".*");
|
||||
}
|
||||
if (zhNames != null) {
|
||||
zhNamesRegex.append("^");
|
||||
for (String name : zhNames) {
|
||||
zhNamesRegex.append("(?=.*").append(name).append(")");
|
||||
}
|
||||
zhNamesRegex.append(".*$");
|
||||
}
|
||||
|
||||
return skuMapper.fetchAllSkuWeightsWithFilters(
|
||||
offset,
|
||||
pageSize,
|
||||
column,
|
||||
order,
|
||||
erpCodesRegex.toString(),
|
||||
zhNamesRegex.toString(),
|
||||
enNamesRegex.toString()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Integer countAllClientSkusWithFilters(String clientId, List<String> erpCodes, List<String> zhNames, List<String> enNames) {
|
||||
StringBuilder erpCodesRegex= new StringBuilder(), zhNamesRegex = new StringBuilder(), enNamesRegex = new StringBuilder();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.jeecg.modules.business.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.modules.business.entity.SkuWeight;
|
||||
import org.jeecg.modules.business.mapper.SkuWeightMapper;
|
||||
|
@ -29,6 +30,13 @@ public class SkuWeightServiceImpl extends ServiceImpl<SkuWeightMapper, SkuWeight
|
|||
return skuWeightMapper.getBySkuId(skuId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SkuWeight> findBySkuId(String skuId) {
|
||||
QueryWrapper<SkuWeight> query = new QueryWrapper<>();
|
||||
query.eq("sku_id", skuId);
|
||||
return this.list(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchFirstEmptyWeightSku(List<String> skuIds) {
|
||||
return skuWeightMapper.searchFirstEmptyWeightSku(skuIds);
|
||||
|
|
|
@ -22,6 +22,9 @@ public class SkuOrderPage {
|
|||
*/
|
||||
@ApiModelProperty(value = "主键")
|
||||
private String id;
|
||||
@ApiModelProperty(value = "SKU重量表主键")
|
||||
private String weightId;
|
||||
|
||||
/**
|
||||
* 商品ID
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue