Merge branch 'dev' into feat/skuOrderClient

pull/8523/head
Gauthier LO 2025-06-10 10:03:22 +02:00 committed by GitHub
commit 0bca3a7608
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 566 additions and 211 deletions

View File

@ -438,6 +438,48 @@ public class SkuController {
page.setTotal(total); page.setTotal(total);
return Result.OK(page); 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") @GetMapping("/listAllSelectableSkuIds")
public Result<?> listAllSelectableSkuIds(@RequestParam(name = "clientId") String clientId, public Result<?> listAllSelectableSkuIds(@RequestParam(name = "clientId") String clientId,
@RequestParam(name = "erpCodes", required = false) String erpCodes, @RequestParam(name = "erpCodes", required = false) String erpCodes,

View File

@ -39,6 +39,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
@ -130,6 +131,12 @@ public class SkuPriceController extends JeecgController<SkuPrice, ISkuPriceServi
return Result.error("相同内容的售价记录已存在,仅日期不同,请勿重复添加。"); return Result.error("相同内容的售价记录已存在,仅日期不同,请勿重复添加。");
} }
if (skuPrice.getPrice() != null) {
skuPrice.setPrice(skuPrice.getPrice().setScale(2, RoundingMode.HALF_UP));
}
if (skuPrice.getDiscountedPrice() != null) {
skuPrice.setDiscountedPrice(skuPrice.getDiscountedPrice().setScale(2, RoundingMode.HALF_UP));
}
skuPrice.setCreateBy(sysUser.getUsername()); skuPrice.setCreateBy(sysUser.getUsername());
skuPrice.setCreateTime(new Date()); skuPrice.setCreateTime(new Date());
skuPriceService.save(skuPrice); skuPriceService.save(skuPrice);
@ -281,16 +288,20 @@ public class SkuPriceController extends JeecgController<SkuPrice, ISkuPriceServi
break; break;
case 1: // Price case 1: // Price
BigDecimal price; BigDecimal price;
if (cell.getCellType() == CellType.NUMERIC) { if (cell.getCellType() == CellType.BLANK) {
price = BigDecimal.valueOf(cell.getNumericCellValue()); price = null;
} else if (cell.getCellType() == CellType.NUMERIC) {
price = BigDecimal.valueOf(cell.getNumericCellValue()).setScale(2, RoundingMode.UP);
} else { } else {
price = new BigDecimal(cell.getStringCellValue().trim()); price = new BigDecimal(cell.getStringCellValue().trim()).setScale(2, RoundingMode.UP);
} }
skuPrice.setPrice(price); skuPrice.setPrice(price);
break; break;
case 2: // Threshold case 2: // Threshold
int threshold; Integer threshold;
if (cell.getCellType() == CellType.NUMERIC) { if (cell.getCellType() == CellType.BLANK) {
threshold = null;
} else if (cell.getCellType() == CellType.NUMERIC) {
threshold = (int) cell.getNumericCellValue(); threshold = (int) cell.getNumericCellValue();
} else { } else {
threshold = Integer.parseInt(cell.getStringCellValue().trim()); threshold = Integer.parseInt(cell.getStringCellValue().trim());
@ -299,10 +310,12 @@ public class SkuPriceController extends JeecgController<SkuPrice, ISkuPriceServi
break; break;
case 3: // Discounted Price case 3: // Discounted Price
BigDecimal discountedPrice; BigDecimal discountedPrice;
if (cell.getCellType() == CellType.NUMERIC) { if (cell.getCellType() == CellType.BLANK) {
discountedPrice = BigDecimal.valueOf(cell.getNumericCellValue()); discountedPrice = null;
} else if (cell.getCellType() == CellType.NUMERIC) {
discountedPrice = BigDecimal.valueOf(cell.getNumericCellValue()).setScale(2, RoundingMode.UP);
} else { } else {
discountedPrice = new BigDecimal(cell.getStringCellValue().trim()); discountedPrice = new BigDecimal(cell.getStringCellValue().trim()).setScale(2, RoundingMode.UP);
} }
skuPrice.setDiscountedPrice(discountedPrice); skuPrice.setDiscountedPrice(discountedPrice);
break; break;

View File

@ -11,8 +11,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator; 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.config.JeecgBaseConfig;
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.entity.SkuWeight;
import org.jeecg.modules.business.model.SkuDocument;
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.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.ResponsesWithMsg;
import org.jeecg.modules.business.vo.SkuWeightPage; import org.jeecg.modules.business.vo.SkuWeightPage;
import org.jeecg.modules.business.vo.SkuWeightParam; 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.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams; import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired; 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.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -72,6 +79,8 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
private SkuMongoService skuMongoService; private SkuMongoService skuMongoService;
@Resource @Resource
private JeecgBaseConfig jeecgBaseConfig; private JeecgBaseConfig jeecgBaseConfig;
@Autowired
private MongoTemplate mongoTemplate;
private static final Integer DEFAULT_NUMBER_OF_THREADS = 1; private static final Integer DEFAULT_NUMBER_OF_THREADS = 1;
private final static Integer NUMBER_OF_SKU_EXCEL_COLUMNS = 3; 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-批量删除") @AutoLog(value = "sku_weight-批量删除")
@ApiOperation(value="sku_weight-批量删除", notes="sku_weight-批量删除") @ApiOperation(value="sku_weight-批量删除", notes="sku_weight-批量删除")
@RequiresPermissions("business:sku_weight:deleteBatch")
@DeleteMapping(value = "/deleteBatch") @DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) { public Result<String> deleteBatch(@RequestBody List<String> ids) {
this.skuWeightService.removeByIds(Arrays.asList(ids.split(","))); LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
return Result.OK("批量删除成功!"); 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) @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException { public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {
log.info("Importing Sku weights from Excel..."); 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; MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap(); 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<>(); List<SkuWeight> skuWeights = new ArrayList<>();
Map<String, SkuWeight> skuWeightMappedByErpCode = new HashMap<>(); Map<String, SkuWeight> skuWeightMappedByErpCode = new HashMap<>();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) { ResponsesWithMsg<String> responses = new ResponsesWithMsg<>();
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();
for (int rowIndex = firstRow + 1; rowIndex <= lastRow; rowIndex++) { 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(); SkuWeight skuWeight = new SkuWeight();
boolean hasError = false; boolean hasError = false;
String erpCode = null; 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); Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
if(hasError) continue; if (hasError) break;
if(cell.getCellType().equals(CellType.BLANK)){
responses.addFailure("Row " + rowIndex + " has empty cell at index " + cellIndex); 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; hasError = true;
continue; break;
} }
try {
switch (cellIndex) { switch (cellIndex) {
case 0: case 0: // ERP Code
String skuCode = cell.getStringCellValue(); String skuCode = cell.getStringCellValue().trim();
Sku sku = skuService.getByErpCode(skuCode); Sku sku = skuService.getByErpCode(skuCode);
if(sku == null){ if (sku == null || sku.getId() == null) {
responses.addFailure("Row " + rowIndex + " SKU not found : " + skuCode); responses.addFailure("Row " + (rowIndex + 1), " 无效ERP编码: " + skuCode);
log.error("Row {} is not a valid SKU", rowIndex + 1);
hasError = true; hasError = true;
continue; break;
} }
erpCode = skuCode; erpCode = skuCode;
skuWeight.setSkuId(sku.getId()); skuWeight.setSkuId(sku.getId());
break; break;
case 1:
case 1: // Weight
int weight; int weight;
if(cell.getCellType().equals(CellType.STRING)) if (cell.getCellType() == CellType.STRING) {
weight = Integer.parseInt(cell.getStringCellValue()); weight = Integer.parseInt(cell.getStringCellValue().trim());
else if(cell.getCellType().equals(CellType.NUMERIC)) } else if (cell.getCellType() == CellType.NUMERIC) {
weight = (int) cell.getNumericCellValue(); weight = (int) cell.getNumericCellValue();
else { } else {
responses.addFailure("Row " + rowIndex + " Weight is not a number - Sku : " + erpCode); responses.addFailure("Row " + (rowIndex + 1),
"无法识别的重量类型");
hasError = true; hasError = true;
continue; throw new IllegalArgumentException("无法识别的重量类型");
} }
skuWeight.setWeight(weight); skuWeight.setWeight(weight);
break; break;
case 2:
String date; case 2: // Date
if(cell.getCellType().equals(CellType.STRING)) String dateStr;
date = cell.getStringCellValue(); if (cell.getCellType() == CellType.STRING) {
else if(cell.getCellType().equals(CellType.NUMERIC)) dateStr = cell.getStringCellValue().trim();
date = formatter.format(cell.getDateCellValue()); } else if (cell.getCellType() == CellType.NUMERIC) {
else { dateStr = formatter.format(cell.getDateCellValue());
responses.addFailure("Row " + rowIndex + " Date is not a date - Sku : " + erpCode); } else {
responses.addFailure("Row " + (rowIndex + 1),
"日期格式错误");
hasError = true; hasError = true;
continue; throw new IllegalArgumentException("日期格式错误");
} }
Date effectiveDate = formatter.parse(date); Date effectiveDate = formatter.parse(dateStr);
skuWeight.setEffectiveDate(effectiveDate); skuWeight.setEffectiveDate(effectiveDate);
break; 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); if (hasError) continue;
mabangResponses.getFailures().forEach(responses::addFailure);
} catch (Exception e) { log.info("Querying sku_weight with sku_id = {}", skuWeight.getSkuId());
e.printStackTrace(); QueryWrapper<SkuWeight> wrapper = new QueryWrapper<>();
String msg = e.getMessage(); wrapper.eq("sku_id", skuWeight.getSkuId());
log.error(msg, e); List<SkuWeight> existingWeight = skuWeightService.list(wrapper);
return Result.error("文件导入失败:" + e.getMessage()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
} finally { 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 { try {
file.getInputStream().close(); ResponsesWithMsg<String> mabangResponses = skuListMabangService.mabangSkuWeightUpdate(skuWeights);
} catch (IOException e) {
e.printStackTrace(); 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. * /!\ 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()); log.info("User {}, tried to access /skuWeight/updateBatch but is not authorized.", sysUser.getUsername());
return Result.error(403,"Forbidden."); return Result.error(403,"Forbidden.");
} }
String userId = ((LoginUser) SecurityUtils.getSubject().getPrincipal()).getId();
Map<String, SkuWeight> skuWeightsMap = new HashMap<>(); 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); Sku sku = skuService.getById(skuId);
if (sku == null) { 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 skuWeight = new SkuWeight();
skuWeight.setCreateBy(sysUser.getUsername()); skuWeight.setCreateBy(sysUser.getUsername());
@ -350,34 +513,40 @@ public class SkuWeightController extends JeecgController<SkuWeight, ISkuWeightSe
} }
// Submit task asynchronously // Submit task asynchronously
List<SkuWeight> skuWeights = new ArrayList<>(skuWeightsMap.values()); 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); ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_NUMBER_OF_THREADS);
executor.submit(() -> { executor.submit(() -> {
try { try {
ResponsesWithMsg<String> responses = skuListMabangService.mabangSkuWeightUpdate(skuWeights); skuListMabangService.mabangSkuWeightUpdate(skuWeights);
List<SkuWeight> skuWeightSuccesses = new ArrayList<>(); log.info("updateBatch call to Mabang submitted successfully");
responses.getSuccesses().forEach((skuErpCode, messages) -> {
skuWeightSuccesses.add(skuWeightsMap.get(skuErpCode));
});
// Update Mongo + save to database
skuWeightSuccesses.forEach(skuWeight -> skuMongoService.upsertSkuWeight(skuWeight));
skuWeightService.saveBatch(skuWeights);
} catch (Exception e) { } 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"); 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);*/
} }
} }

View File

@ -53,12 +53,14 @@ public interface SkuMapper extends BaseMapper<Sku> {
Integer countAllSkus(); Integer countAllSkus();
Integer countAllSkuWeightsWithFilters(@Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex); 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 countAllClientSkus(@Param("clientId") String clientId);
Integer countAllClientSkusWithFilters(@Param("clientId") String clientId, @Param("erpCodes") String erpCodesRegex, @Param("zhNames") String zhNamesRegex, @Param("enNames") String enNamesRegex); 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> 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> 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> 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> 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); List<SkuOrderPage> listSelectableSkuIdsWithFilters(@Param("clientId") String clientId, @Param("erpCodes") String erpCodeList, @Param("zhNames") String zhNameList, @Param("enNames") String enNameList);

View File

@ -136,8 +136,7 @@
<result property="threshold" column="threshold"/> <result property="threshold" column="threshold"/>
<result property="discountedPrice" column="discounted_price"/> <result property="discountedPrice" column="discounted_price"/>
<result property="date" column="price_date"/> <result property="date" column="price_date"/>
<result property="priceRmb" column="price_rmb"/> <result property="currencyId" column="currency_id"/>
<result property="discountedPriceRmb" column="discounted_price_rmb"/>
</resultMap> </resultMap>
<resultMap id="promotionResultMap" type="org.jeecg.modules.business.entity.Promotion"> <resultMap id="promotionResultMap" type="org.jeecg.modules.business.entity.Promotion">

View File

@ -262,6 +262,21 @@
</if> </if>
); );
</select> </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"> <select id="fetchSkuWeightsWithFilters" resultType="org.jeecg.modules.business.vo.SkuOrderPage">
WITH latestSkuWeights AS ( WITH latestSkuWeights AS (
SELECT SELECT
@ -303,6 +318,32 @@
</if> </if>
; ;
</select> </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 id="countAllClientSkusWithFilters" resultType="java.lang.Integer">
SELECT COUNT(*) AS total SELECT COUNT(*) AS total
FROM sku s FROM sku s
@ -421,8 +462,7 @@
AND po.can_send = 1 AND po.can_send = 1
AND poc.erp_status IN ('1','2') AND poc.erp_status IN ('1','2')
GROUP BY sku_id GROUP BY sku_id
), ), rmb_id AS (
rmb_id AS (
SELECT id FROM currency WHERE code = 'RMB' SELECT id FROM currency WHERE code = 'RMB'
) )
SELECT s.id, SELECT s.id,
@ -488,6 +528,8 @@
AND po.can_send = 1 AND po.can_send = 1
AND poc.erp_status IN ('1','2') AND poc.erp_status IN ('1','2')
GROUP BY sku_id GROUP BY sku_id
), rmb_id AS (
SELECT id FROM currency WHERE code = 'RMB'
) )
SELECT s.id, SELECT s.id,
s.erp_code, s.erp_code,
@ -499,27 +541,29 @@
s.available_amount + s.purchasing_amount - IF(qtyInOrdersNotShippedCTE.quantity IS NULL, 0, qtyInOrdersNotShippedCTE.quantity) as stock, s.available_amount + s.purchasing_amount - IF(qtyInOrdersNotShippedCTE.quantity IS NULL, 0, qtyInOrdersNotShippedCTE.quantity) as stock,
s.image_source, s.image_source,
s.service_fee, s.service_fee,
IF(sp.price_rmb IS NULL, sp.price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.price_rmb / sp.price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE original_currency = 'EUR' AND target_currency = 'RMB' WHERE original_currency = 'EUR' AND target_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
)) as sku_price, ), sp.price
) as sku_price,
sp.threshold as discount_moq, sp.threshold as discount_moq,
IF(sp.price_rmb IS NULL, sp.discounted_price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.discounted_price_rmb / sp.discounted_price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE target_currency = 'EUR' AND original_currency = 'RMB' WHERE target_currency = 'EUR' AND original_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
)) as discounted_price, ), sp.discounted_price
) as discounted_price,
s7.quantity as sales_last_week, s7.quantity as sales_last_week,
s28.quantity as sales_four_weeks, s28.quantity as sales_four_weeks,
s42.quantity as sales_six_weeks s42.quantity as sales_six_weeks
@ -549,10 +593,7 @@
s.en_name REGEXP #{enNames} s.en_name REGEXP #{enNames}
</if> </if>
) )
AND ( AND (sp.price IS NOT NULL AND sp.price &lt;&gt; 0)
(sp.price_rmb IS NOT NULL AND sp.price_rmb &lt;&gt; 0)
OR (sp.price IS NOT NULL AND sp.price &lt;&gt; 0)
)
ORDER BY s.erp_code ORDER BY s.erp_code
; ;
</select> </select>
@ -573,6 +614,8 @@
AND po.erp_status IN ('1','2') AND po.erp_status IN ('1','2')
AND poc.erp_status IN ('1','2') AND poc.erp_status IN ('1','2')
GROUP BY sku_id GROUP BY sku_id
), rmb_id AS (
SELECT id FROM currency WHERE code = 'RMB'
) )
SELECT s.id, SELECT s.id,
s.erp_code, s.erp_code,
@ -588,28 +631,30 @@
as stock, as stock,
s.image_source as image_source, s.image_source as image_source,
s.service_fee as service_fee, s.service_fee as service_fee,
IF(sp.price_rmb IS NULL, sp.price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.price_rmb / sp.price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE original_currency = 'EUR' AND target_currency = 'RMB' WHERE original_currency = 'EUR' AND target_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
) ) ,
sp.price
) as sku_price, ) as sku_price,
sp.threshold as discount_moq, sp.threshold as discount_moq,
IF(sp.price_rmb IS NULL, sp.discounted_price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.discounted_price_rmb / sp.discounted_price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE target_currency = 'EUR' AND original_currency = 'RMB' WHERE target_currency = 'EUR' AND original_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
) ),
sp.discounted_price
) as discounted_price, ) as discounted_price,
IFNULL(s7.quantity, 0) as sales_last_week, IFNULL(s7.quantity, 0) as sales_last_week,
IFNULL(s28.quantity, 0) as sales_four_weeks, IFNULL(s28.quantity, 0) as sales_four_weeks,
@ -641,6 +686,8 @@
AND po.erp_status IN ('1','2') AND po.erp_status IN ('1','2')
AND poc.erp_status IN ('1','2') AND poc.erp_status IN ('1','2')
GROUP BY sku_id GROUP BY sku_id
), rmb_id AS (
SELECT id FROM currency WHERE code = 'RMB'
) )
SELECT s.id, SELECT s.id,
s.erp_code, s.erp_code,
@ -656,28 +703,28 @@
as stock, as stock,
s.image_source as image_source, s.image_source as image_source,
s.service_fee as service_fee, s.service_fee as service_fee,
IF(sp.price_rmb IS NULL, sp.price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.price_rmb / sp.price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE original_currency = 'EUR' AND target_currency = 'RMB' WHERE original_currency = 'EUR' AND target_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
) ), sp.price
) as sku_price, ) as sku_price,
sp.threshold as discount_moq, sp.threshold as discount_moq,
IF(sp.price_rmb IS NULL, sp.discounted_price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.discounted_price_rmb / sp.discounted_price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE target_currency = 'EUR' AND original_currency = 'RMB' WHERE target_currency = 'EUR' AND original_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
) ), sp.discounted_price
) as discounted_price, ) as discounted_price,
IFNULL(s7.quantity, 0) as sales_last_week, IFNULL(s7.quantity, 0) as sales_last_week,
IFNULL(s28.quantity, 0) as sales_four_weeks, IFNULL(s28.quantity, 0) as sales_four_weeks,
@ -748,6 +795,9 @@
; ;
</select> </select>
<select id="searchExistingSkuByKeywords" resultType="org.jeecg.modules.business.vo.SkuOrderPage"> <select id="searchExistingSkuByKeywords" resultType="org.jeecg.modules.business.vo.SkuOrderPage">
rmb_id AS (
SELECT id FROM currency WHERE code = 'RMB'
)
SELECT SELECT
s.id, s.id,
s.erp_code, s.erp_code,
@ -757,28 +807,28 @@
s.available_amount, s.available_amount,
s.image_source, s.image_source,
s.service_fee, s.service_fee,
IF(sp.price_rmb IS NULL, sp.price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.price_rmb / sp.price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE original_currency = 'EUR' AND target_currency = 'RMB' WHERE original_currency = 'EUR' AND target_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
) ), sp.price
) as sku_price, ) as sku_price,
sp.threshold as discount_moq, sp.threshold as discount_moq,
IF(sp.price_rmb IS NULL, sp.discounted_price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.discounted_price_rmb / sp.discounted_price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE target_currency = 'EUR' AND original_currency = 'RMB' WHERE target_currency = 'EUR' AND original_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2)
) ), sp.discounted_price
) as discounted_price ) as discounted_price
FROM sku s FROM sku s
LEFT JOIN sku_current_price sp ON s.id = sp.sku_id LEFT JOIN sku_current_price sp ON s.id = sp.sku_id

View File

@ -95,25 +95,4 @@ public class SkuMongoSyncService {
break; 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;
}
}
} }

View File

@ -100,7 +100,11 @@ public interface ISkuService extends IService<Sku> {
List<SkuOrderPage> fetchSkusByClient(String clientId, Integer pageNo, Integer pageSize, String column, String order); 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 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> 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); 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); List<SkuOrderPage> fetchSkusByClientWithFilters(String clientId, Integer pageNo, Integer pageSize, String column, String order, List<String> erpCodes, List<String> zhNames, List<String> enNames);

View File

@ -15,6 +15,8 @@ import java.util.List;
public interface ISkuWeightService extends IService<SkuWeight> { public interface ISkuWeightService extends IService<SkuWeight> {
SkuWeight getBySkuId(String skuId); SkuWeight getBySkuId(String skuId);
List<SkuWeight> findBySkuId(String skuId);
String searchFirstEmptyWeightSku(List<String> skuIds); String searchFirstEmptyWeightSku(List<String> skuIds);
List<SkuWeight> exportToExcel(List<String> skuIds); List<SkuWeight> exportToExcel(List<String> skuIds);

View File

@ -732,7 +732,7 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
Date effectiveDateToImport = skuWeightMappedById.get(sku.getId()).getEffectiveDate(); Date effectiveDateToImport = skuWeightMappedById.get(sku.getId()).getEffectiveDate();
if(latestEffectiveDate.after(effectiveDateToImport)) { if(latestEffectiveDate.after(effectiveDateToImport)) {
log.info("Sku {} has a more recent weight in DB. Therefore won't be imported to Mabang", sku.getErpCode()); 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; continue;
} }
skusToUpdate.add(sku); skusToUpdate.add(sku);
@ -822,10 +822,10 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
SkuChangeResponse response = request.send(); SkuChangeResponse response = request.send();
if(response.success()) { if(response.success()) {
responses.addSuccess(response.getStockSku(), "Mabang"); responses.addSuccess(response.getStockSku(), "Mabang 重量更新成功");
} }
else { else {
responses.addFailure(response.getStockSku(), "Mabang"); responses.addFailure(response.getStockSku(), "Mabang 重量更新失败");
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Error updating weight for sku {} : {}", skuData.getErpCode(), e.getMessage()); 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 // Only push progress if processed enough items (step) or finished all
if (currentProcessed % step == 0 || currentProcessed == totalCount) { if (currentProcessed % step == 0 || currentProcessed == totalCount) {
JSONObject progressMsg = new JSONObject(); JSONObject progressMsg = new JSONObject();
progressMsg.put("cmd", "user"); progressMsg.put("cmd", "mabang-result");
progressMsg.put("msgTxt", "已处理 " + currentProcessed + " / " + totalCount + " 条 SKU 更新任务"); 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()); WebSocketSender.sendToUser(userId, progressMsg.toJSONString());
} }
} }
@ -851,17 +859,19 @@ public class SkuListMabangServiceImpl extends ServiceImpl<SkuListMabangMapper, S
int failureCount = responses.getFailures().size(); int failureCount = responses.getFailures().size();
JSONObject doneMsg = new JSONObject(); JSONObject doneMsg = new JSONObject();
doneMsg.put("cmd", "user"); doneMsg.put("cmd", "mabang-result");
doneMsg.put("msgTxt", "SKU 重量更新全部完成!"); doneMsg.put("type", "complete");
doneMsg.put("msgTxt", "SKU重量在马帮更新全部完成");
doneMsg.put("data", new JSONObject() {{ doneMsg.put("data", new JSONObject() {{
put("total", skuDataList.size()); put("total", skuDataList.size());
put("success", successCount); put("success", successCount);
put("failure", failureCount); 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()); WebSocketSender.sendToUser(userId, doneMsg.toJSONString());
log.info("SKU Weight update completed: total {} items processed, {} succeeded, {} failed", skuDataList.size(), successCount, failureCount); log.info("SKU Weight update completed: total {} items processed, {} succeeded, {} failed", skuDataList.size(), successCount, failureCount);
return responses; return responses;
} }

View File

@ -453,6 +453,40 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
return skuMapper.countAllSkuWeightsWithFilters(erpCodesRegex.toString(), zhNamesRegex.toString(), enNamesRegex.toString()); return skuMapper.countAllSkuWeightsWithFilters(erpCodesRegex.toString(), zhNamesRegex.toString(), enNamesRegex.toString());
} }
@Override @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) { 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; int offset = (pageNo - 1) * pageSize;
StringBuilder erpCodesRegex= new StringBuilder(), zhNamesRegex = new StringBuilder(), enNamesRegex = new StringBuilder(); 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()); 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 @Override
public Integer countAllClientSkusWithFilters(String clientId, List<String> erpCodes, List<String> zhNames, List<String> enNames) { public Integer countAllClientSkusWithFilters(String clientId, List<String> erpCodes, List<String> zhNames, List<String> enNames) {
StringBuilder erpCodesRegex= new StringBuilder(), zhNamesRegex = new StringBuilder(), enNamesRegex = new StringBuilder(); StringBuilder erpCodesRegex= new StringBuilder(), zhNamesRegex = new StringBuilder(), enNamesRegex = new StringBuilder();

View File

@ -1,5 +1,6 @@
package org.jeecg.modules.business.service.impl; package org.jeecg.modules.business.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.business.entity.SkuWeight; import org.jeecg.modules.business.entity.SkuWeight;
import org.jeecg.modules.business.mapper.SkuWeightMapper; import org.jeecg.modules.business.mapper.SkuWeightMapper;
@ -29,6 +30,13 @@ public class SkuWeightServiceImpl extends ServiceImpl<SkuWeightMapper, SkuWeight
return skuWeightMapper.getBySkuId(skuId); 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 @Override
public String searchFirstEmptyWeightSku(List<String> skuIds) { public String searchFirstEmptyWeightSku(List<String> skuIds) {
return skuWeightMapper.searchFirstEmptyWeightSku(skuIds); return skuWeightMapper.searchFirstEmptyWeightSku(skuIds);

View File

@ -22,6 +22,9 @@ public class SkuOrderPage {
*/ */
@ApiModelProperty(value = "主键") @ApiModelProperty(value = "主键")
private String id; private String id;
@ApiModelProperty(value = "SKU重量表主键")
private String weightId;
/** /**
* ID * ID
*/ */