fix/sku-order-display-db-info

pull/8547/head
Xue YANG 2025-07-04 12:14:03 +02:00
parent 20a6f95a3f
commit 356d21ae6d
3 changed files with 86 additions and 73 deletions

View File

@ -464,40 +464,27 @@ public class InvoiceController {
} }
} }
@PostMapping("/createOrderByExcel") @PostMapping("/createOrderByExcel")
public Result<?> createOrderByExcel(@RequestParam("file") MultipartFile file) { public Result<?> createOrderByExcel(@RequestParam("clientId") String clientId,@RequestParam("file") MultipartFile file) {
boolean isEmployee = securityService.checkIsEmployee(); boolean isEmployee = securityService.checkIsEmployee();
Client client = null;
if (!isEmployee) { if (!isEmployee) {
client = clientService.getCurrentClient(); // check if clientId matches the current client
if (client == null) { Client client = clientService.getCurrentClient();
return Result.error(HttpStatus.SC_NOT_FOUND, "Client not found"); if (client == null || !clientId.equals(client.getId())) {
return Result.error(HttpStatus.SC_NOT_FOUND, "Client not found or not authorized");
} }
} }
//get the excel data //get the excel data
List<Map<String, Object>> skuList = skuService.parseExcelToSkuList(file); Result<?> result = skuService.parseExcelToSkuList(clientId,file);
// if not employee, filter out skus that are not from the client if (!result.isSuccess()) {
if (!isEmployee) { return result;
Iterator<Map<String, Object>> iterator = skuList.iterator();
while (iterator.hasNext()) {
Map<String, Object> sku = iterator.next();
String erpCode = (String) sku.get("erpCode");
if (erpCode == null || erpCode.isEmpty()) {
iterator.remove();
continue;
}
String skuId = skuService.getIdFromErpCode(erpCode);
if (skuId == null) {
iterator.remove();
continue;
}
String skuClientId = clientSkuService.getClientIdFromSkuId(skuId);
if (!client.getId().equals(skuClientId)) {
iterator.remove();
}
}
} }
log.info("SKU list after filtering: {}", skuList); Map<String, Object> resultData = (Map<String, Object>) result.getResult();
return Result.OK(skuList); List<Map<String, Object>> validSkuList = (List<Map<String, Object>>) resultData.get("validSkuList");
List<String> warnings = (List<String>) resultData.get("warnings");
Map<String, Object> response = new HashMap<>();
response.put("validSkuList", validSkuList);
response.put("warnings", warnings);
return Result.OK(response);
} }
@GetMapping(value = "/preShipping/orderTime") @GetMapping(value = "/preShipping/orderTime")

View File

@ -2,6 +2,7 @@ package org.jeecg.modules.business.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.business.controller.UserException; import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.entity.*; import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.vo.*; import org.jeecg.modules.business.vo.*;
@ -137,5 +138,5 @@ public interface ISkuService extends IService<Sku> {
void setIsSynced(List<String> erpCodes, boolean isSynced); void setIsSynced(List<String> erpCodes, boolean isSynced);
List<Map<String, Object>> parseExcelToSkuList(MultipartFile file); Result<?> parseExcelToSkuList(String clientId, MultipartFile file);
} }

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.business.controller.UserException; import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.entity.*; import org.jeecg.modules.business.entity.*;
@ -717,11 +718,14 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
skuMapper.setIsSynced(erpCodes, isSynced); skuMapper.setIsSynced(erpCodes, isSynced);
} }
public List<Map<String, Object>> parseExcelToSkuList(MultipartFile file) { @Override
List<Map<String, Object>> result = new ArrayList<>(); public Result<?> parseExcelToSkuList(String clientId,MultipartFile file) {
List<Map<String, Object>> validSkuList = new ArrayList<>();
List<String> warnings = new ArrayList<>();
try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) { try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) {
Sheet sheet = workbook.getSheetAt(0); Sheet sheet = workbook.getSheetAt(0);
int headerRowIndex = -1; int headerRowIndex = -1;
int skuCol = -1, qtyCol = -1;
Map<String, Integer> colMap = new HashMap<>(); Map<String, Integer> colMap = new HashMap<>();
// find header row with required columns // find header row with required columns
for (int i = 0; i <= 5; i++) { for (int i = 0; i <= 5; i++) {
@ -731,65 +735,86 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
Cell cell = row.getCell(j); Cell cell = row.getCell(j);
if (cell == null || cell.getCellType() != CellType.STRING) continue; if (cell == null || cell.getCellType() != CellType.STRING) continue;
String val = cell.getStringCellValue().trim().toLowerCase(); String val = cell.getStringCellValue().trim().toLowerCase();
if (val.equals("sku")) colMap.put("erpCode", j); if (val.equals("sku")) skuCol = j;
else if (val.contains("anglais")) colMap.put("enName", j); else if (val.contains("quantité") || val.contains("quantity")) qtyCol = j;
else if (val.contains("chinois")) colMap.put("zhName", j);
else if (val.contains("stock dispo")) colMap.put("stock", j);
else if (val.contains("wia")) colMap.put("purchaseWIA", j);
else if (val.contains("shopify")) colMap.put("shopifyOrder", j);
else if (val.contains("stock") && val.matches(".*\\d{2}/\\d{2}.*")) colMap.put("stockDate", j);
else if (val.contains("quantité") || val.contains("quantity")) colMap.put("quantity", j);
else if (val.contains("ventes 7")) colMap.put("sales7d", j);
else if (val.contains("ventes 28")) colMap.put("sales28d", j);
else if (val.contains("ventes 42")) colMap.put("sales42d", j);
else if (val.contains("price")) colMap.put("skuPrice", j);
} }
if (!colMap.isEmpty()) { if (skuCol != -1 && qtyCol != -1) {
headerRowIndex = i; headerRowIndex = i;
break; break;
} }
} }
if (headerRowIndex == -1 || !colMap.containsKey("erpCode") || !colMap.containsKey("quantity")) { if (headerRowIndex == -1) {
throw new RuntimeException("Missing required columns: SKU and Quantity"); throw new RuntimeException("Missing required columns: SKU and Quantity");
} }
List<String> erpCodes = new ArrayList<>();
Map<String, Integer> skuQuantityMap = new HashMap<>();
// parse data rows // parse data rows
for (int i = headerRowIndex + 1; i <= sheet.getLastRowNum(); i++) { for (int i = headerRowIndex + 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i); Row row = sheet.getRow(i);
if (row == null) continue; if (row == null) continue;
Map<String, Object> sku = new HashMap<>(); Cell skuCell = row.getCell(skuCol);
for (Map.Entry<String, Integer> entry : colMap.entrySet()) { Cell qtyCell = row.getCell(qtyCol);
String key = entry.getKey(); if (skuCell == null || qtyCell == null) continue;
int col = entry.getValue();
Cell cell = row.getCell(col); String erpCode = "";
if (cell == null) continue; if (skuCell.getCellType() == CellType.NUMERIC) {
Object value = null; erpCode = new BigDecimal(skuCell.getNumericCellValue()).toPlainString().trim();
if (cell.getCellType() == CellType.NUMERIC) { } else {
value = key.equals("erpCode") erpCode = skuCell.toString().trim();
? new BigDecimal(cell.getNumericCellValue()).toPlainString().trim()
: cell.getNumericCellValue();
} else {
String str = cell.toString().trim();
if (Arrays.asList("quantity", "sales7d", "sales28d", "sales42d", "skuPrice", "stock", "purchaseWIA", "shopifyOrder", "stockDate").contains(key)) {
try {
value = Double.parseDouble(str);
} catch (NumberFormatException ignored) {}
} else {
value = str;
}
}
sku.put(key, value);
} }
// Only add SKUs with positive quantity and positive price Integer quantity = null;
Object qtyObj = sku.get("quantity"); try {
if (qtyObj instanceof Number && ((Number) qtyObj).doubleValue() > 0) { if (qtyCell.getCellType() == CellType.NUMERIC) {
result.add(sku); quantity = (int) qtyCell.getNumericCellValue();
} else {
quantity = Integer.parseInt(qtyCell.toString().trim());
}
} catch (NumberFormatException ignored) {}
if (!erpCode.isEmpty() && quantity != null && quantity > 0) {
erpCodes.add(erpCode);
skuQuantityMap.put(erpCode, quantity);
} }
} }
log.info("Parsed Excel SKU list: {}", result); if (erpCodes.isEmpty()) {
return Result.error("No valid SKU and quantity found in the Excel file.");
}
//extract SKU details from the database
String erpRegex = String.join("|", erpCodes);
List<SkuOrderPage> skuPages = listSelectableSkuIdsWithFilters(clientId, Collections.singletonList(erpRegex), null, null);
// Check for SKUs not found in DB
Set<String> fetchedErpCodes = skuPages.stream()
.map(SkuOrderPage::getErpCode)
.collect(Collectors.toSet());
erpCodes.stream()
.filter(code -> !fetchedErpCodes.contains(code))
.forEach(code -> warnings.add("SKU " + code + " is invalid: it may not exist, not belong to the client, or have missing/zero price."
));
for (SkuOrderPage sku : skuPages) {
Integer quantity = skuQuantityMap.get(sku.getErpCode());
if (quantity == null) continue;
Map<String, Object> skuData = new HashMap<>();
skuData.put("skuId", sku.getId());
skuData.put("erpCode", sku.getErpCode());
skuData.put("enName", sku.getEnName());
skuData.put("zhName", sku.getZhName());
skuData.put("stock", sku.getStock());
skuData.put("skuPrice", sku.getSkuPrice());
skuData.put("sales7d", sku.getSalesLastWeek());
skuData.put("sales28d", sku.getSalesFourWeeks());
skuData.put("sales42d", sku.getSalesSixWeeks());
skuData.put("quantity", quantity);
validSkuList.add(skuData);
}
log.info("Parsed and fetched SKU details: {}, warnings: {}",validSkuList, warnings.size());
Map<String, Object> responseData = new HashMap<>();
responseData.put("validSkuList", validSkuList);
responseData.put("warnings", warnings);
return Result.OK(responseData);
} catch (Exception e) { } catch (Exception e) {
log.error("Excel parsing failed", e); log.error("Excel parsing failed", e);
throw new RuntimeException("Excel parsing error: " + e.getMessage(), e); throw new RuntimeException("Excel parsing error: " + e.getMessage(), e);
} }
return result;
} }
} }