TASK:mixi;
This commit is contained in:
@@ -7,8 +7,10 @@ import com.mixi.common.utils.CopyUtil;
|
||||
import com.mixi.common.utils.MinioUtil;
|
||||
import com.mixi.mapper.*;
|
||||
import com.mixi.mapper.entity.*;
|
||||
import io.minio.errors.MinioException;
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemFactory;
|
||||
@@ -24,6 +26,8 @@ import org.springframework.web.multipart.commons.CommonsMultipartFile;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
@@ -68,7 +72,7 @@ public class MiTuExportScheduledTask {
|
||||
// getBestSell();
|
||||
// getData();
|
||||
// dailySalesIncentiveStatistics();
|
||||
updateProductStock();
|
||||
// updateProductStock();
|
||||
}
|
||||
|
||||
private void updateProductStock() {
|
||||
@@ -549,51 +553,38 @@ public class MiTuExportScheduledTask {
|
||||
private void exportWeeklySellThrReport(List<TransactionSummary> transactionSummaryList, String filePathName) throws IOException {
|
||||
String currentPath = Paths.get("").toAbsolutePath().toString();
|
||||
File file = new File(currentPath + "/" + filePathName);
|
||||
// 如果文件不存在或者为空,则创建一个新的 Workbook
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("Weekly Sell Through Report");
|
||||
|
||||
// 创建一个新的 Sheet 或获取现有的 Sheet
|
||||
Sheet sheet = workbook.getSheet("Weekly Sell Through Report");
|
||||
if (sheet == null) {
|
||||
sheet = workbook.createSheet("Weekly Sell Through Report");
|
||||
Row headerRow = sheet.createRow(0);
|
||||
String[] headers = {"PLU_CODE", "ToShopDate", "SalesDay", "CATEGORY", "SUB_CAT", "ItemName",
|
||||
"PriceOriginal", "ToRetailQty", "TotalSaleNum", "MAS_count", "MEL_count",
|
||||
"MPC_count", "MPS_count", "MTF_count", "MWP_count", "MYO_count",
|
||||
"LwSalesQty", "RetailOnHand", "SalesRate", "Product Image"};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
headerRow.createCell(i).setCellValue(headers[i]);
|
||||
}
|
||||
|
||||
// 写入标题行
|
||||
Row headerRow = sheet.getRow(0);
|
||||
if (headerRow == null) {
|
||||
headerRow = sheet.createRow(0);
|
||||
}
|
||||
headerRow.createCell(0).setCellValue("PLU_CODE");
|
||||
headerRow.createCell(1).setCellValue("ToShopDate");
|
||||
headerRow.createCell(2).setCellValue("SalesDay");
|
||||
headerRow.createCell(3).setCellValue("CATEGORY");
|
||||
headerRow.createCell(4).setCellValue("SUB_CAT");
|
||||
headerRow.createCell(5).setCellValue("ItemName");
|
||||
headerRow.createCell(6).setCellValue("PriceOriginal");
|
||||
headerRow.createCell(7).setCellValue("ToRetailQty");
|
||||
headerRow.createCell(8).setCellValue("TotalSaleNum");
|
||||
headerRow.createCell(9).setCellValue("MAS_count");
|
||||
headerRow.createCell(10).setCellValue("MEL_count");
|
||||
headerRow.createCell(11).setCellValue("MPC_count");
|
||||
headerRow.createCell(12).setCellValue("MPS_count");
|
||||
headerRow.createCell(13).setCellValue("MTF_count");
|
||||
headerRow.createCell(14).setCellValue("MWP_count");
|
||||
headerRow.createCell(15).setCellValue("MYO_count");
|
||||
headerRow.createCell(16).setCellValue("LwSalesQty");
|
||||
headerRow.createCell(17).setCellValue("RetailOnHand");
|
||||
headerRow.createCell(18).setCellValue("SalesRate");
|
||||
int rowNum = 1;
|
||||
int startRow = rowNum;
|
||||
String previousPluCode = "";
|
||||
String imagePath = "";
|
||||
|
||||
// 写入数据
|
||||
int rowNum = sheet.getLastRowNum() + 1;
|
||||
for (TransactionSummary summary : transactionSummaryList) {
|
||||
Row row = sheet.createRow(rowNum++);
|
||||
|
||||
row.createCell(0).setCellValue(summary.getPLU_CODE());
|
||||
if (summary.getToShopDate() != null) {
|
||||
row.createCell(1).setCellValue(summary.getToShopDate().toString());
|
||||
}else {
|
||||
row.createCell(1).setCellValue("");
|
||||
if (!summary.getPLU_CODE().equals(previousPluCode)) {
|
||||
if (startRow < rowNum) {
|
||||
mergeCells(sheet, startRow, rowNum - 1);
|
||||
linkImageToCell(workbook, sheet, startRow, rowNum - 1, headers.length - 1, imagePath);
|
||||
}
|
||||
startRow = rowNum;
|
||||
previousPluCode = summary.getPLU_CODE();
|
||||
imagePath = getImagePath(summary.getPLU_CODE());
|
||||
}
|
||||
|
||||
Row row = sheet.createRow(rowNum);
|
||||
row.createCell(0).setCellValue(summary.getPLU_CODE());
|
||||
// 填充其他列的数据
|
||||
row.createCell(1).setCellValue(summary.getToShopDate() != null ? summary.getToShopDate().toString() : "");
|
||||
row.createCell(2).setCellValue(summary.getSalesDay());
|
||||
row.createCell(3).setCellValue(summary.getCATEGORY());
|
||||
row.createCell(4).setCellValue(summary.getSUB_CAT());
|
||||
@@ -611,17 +602,24 @@ public class MiTuExportScheduledTask {
|
||||
row.createCell(16).setCellValue(summary.getLwSalesQty());
|
||||
row.createCell(17).setCellValue(summary.getRetailOnHand());
|
||||
row.createCell(18).setCellValue(summary.getSalesRate());
|
||||
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// 将Workbook写入文件
|
||||
// 处理最后一个PLU_CODE的数据
|
||||
if (startRow < rowNum) {
|
||||
mergeCells(sheet, startRow, rowNum - 1);
|
||||
linkImageToCell(workbook, sheet, startRow, rowNum - 1, headers.length - 1, imagePath);
|
||||
}
|
||||
|
||||
|
||||
try (FileOutputStream outputStream = new FileOutputStream(file)) {
|
||||
workbook.write(outputStream);
|
||||
}
|
||||
|
||||
FileItem a = getMultipartFile(file, file.getName());
|
||||
MultipartFile multipartFile = new CommonsMultipartFile(a);
|
||||
minioUtil.upload("mi-tu", "export", multipartFile);
|
||||
|
||||
System.out.println("Excel file has been created successfully!");
|
||||
}
|
||||
|
||||
|
||||
@@ -647,41 +645,39 @@ public class MiTuExportScheduledTask {
|
||||
}
|
||||
}
|
||||
|
||||
private void exportWeeklyHeavyStock(List<WeeklyHeavyStock> weeklyHeavyStockList, String weeklyHeavyStockReportName) {
|
||||
private void exportWeeklyHeavyStock(List<WeeklyHeavyStock> weeklyHeavyStockList, String weeklyHeavyStockReportName) throws IOException {
|
||||
String currentPath = Paths.get("").toAbsolutePath().toString();
|
||||
File file = new File(currentPath + "/" + weeklyHeavyStockReportName);
|
||||
// 创建工作簿
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
// 创建工作表
|
||||
Sheet sheet = workbook.createSheet("Weekly Heavy Stock Report");
|
||||
// 创建标题行
|
||||
Row headerRow = sheet.createRow(0);
|
||||
headerRow.createCell(0).setCellValue("PLU_CODE");
|
||||
headerRow.createCell(1).setCellValue("item_name");
|
||||
headerRow.createCell(2).setCellValue("item_barcode");
|
||||
headerRow.createCell(3).setCellValue("cat");
|
||||
headerRow.createCell(4).setCellValue("sub_cat");
|
||||
headerRow.createCell(5).setCellValue("Col");
|
||||
headerRow.createCell(6).setCellValue("price_sales");
|
||||
headerRow.createCell(7).setCellValue("MAS");
|
||||
headerRow.createCell(8).setCellValue("MEL");
|
||||
headerRow.createCell(9).setCellValue("MPC");
|
||||
headerRow.createCell(10).setCellValue("MPS");
|
||||
headerRow.createCell(11).setCellValue("MTF");
|
||||
headerRow.createCell(12).setCellValue("MWP");
|
||||
headerRow.createCell(13).setCellValue("MYO");
|
||||
headerRow.createCell(14).setCellValue("MHZ");
|
||||
headerRow.createCell(15).setCellValue("MRT");
|
||||
headerRow.createCell(16).setCellValue("MBZ");
|
||||
headerRow.createCell(17).setCellValue("TLT");
|
||||
headerRow.createCell(18).setCellValue("subtotal");
|
||||
headerRow.createCell(19).setCellValue("G.TLT");
|
||||
|
||||
// 写入数据
|
||||
Row headerRow = sheet.createRow(0);
|
||||
String[] headers = {"PLU_CODE", "item_name", "item_barcode", "cat", "sub_cat", "Col", "price_sales",
|
||||
"MAS", "MEL", "MPC", "MPS", "MTF", "MWP", "MYO", "MHZ", "MRT", "MBZ", "TLT",
|
||||
"subtotal", "G.TLT", "Product Image"};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
headerRow.createCell(i).setCellValue(headers[i]);
|
||||
}
|
||||
|
||||
int rowNum = 1;
|
||||
int startRow = rowNum;
|
||||
String previousPluCode = "";
|
||||
String imagePath = "";
|
||||
|
||||
for (WeeklyHeavyStock weeklyHeavyStock : weeklyHeavyStockList) {
|
||||
Row row = sheet.createRow(rowNum++);
|
||||
if (!weeklyHeavyStock.getPLU_CODE().equals(previousPluCode)) {
|
||||
if (startRow < rowNum - 1) {
|
||||
mergeCells(sheet, startRow, rowNum - 1);
|
||||
linkImageToCell(workbook, sheet, startRow, rowNum - 1, headers.length - 1, imagePath);
|
||||
}
|
||||
startRow = rowNum;
|
||||
previousPluCode = weeklyHeavyStock.getPLU_CODE();
|
||||
imagePath = getImagePath(weeklyHeavyStock.getPLU_CODE());
|
||||
}
|
||||
|
||||
Row row = sheet.createRow(rowNum);
|
||||
row.createCell(0).setCellValue(weeklyHeavyStock.getPLU_CODE());
|
||||
// 填充其他列的数据
|
||||
row.createCell(1).setCellValue(weeklyHeavyStock.getItem_name());
|
||||
row.createCell(2).setCellValue(weeklyHeavyStock.getItem_barcode());
|
||||
row.createCell(3).setCellValue(weeklyHeavyStock.getCat());
|
||||
@@ -701,22 +697,26 @@ public class MiTuExportScheduledTask {
|
||||
row.createCell(17).setCellValue(weeklyHeavyStock.getTLT());
|
||||
row.createCell(18).setCellValue(weeklyHeavyStock.getSubtotal());
|
||||
row.createCell(19).setCellValue(weeklyHeavyStock.getG_TLT());
|
||||
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
if (startRow < rowNum - 1 || previousPluCode != null) {
|
||||
mergeCells(sheet, startRow, rowNum - 1);
|
||||
linkImageToCell(workbook, sheet, startRow, rowNum - 1, headers.length - 1, imagePath);
|
||||
}
|
||||
|
||||
// 将工作簿写入文件
|
||||
try (FileOutputStream outputStream = new FileOutputStream(file)) {
|
||||
workbook.write(outputStream);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
FileItem a = getMultipartFile(file, file.getName());
|
||||
MultipartFile multipartFile = new CommonsMultipartFile(a);
|
||||
minioUtil.upload("mi-tu", "export", multipartFile);
|
||||
|
||||
System.out.println("Excel file has been created successfully!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Quarterly Product Grouping Report
|
||||
*/
|
||||
@@ -756,70 +756,116 @@ public class MiTuExportScheduledTask {
|
||||
return String.format("0 0 22 %d %d ?", dayOfMonth, month);
|
||||
}
|
||||
|
||||
private void exportQuarterlyProductGrouping(List<WeeklyHeavyStock> weeklyHeavyStockList, String weeklyHeavyStockReportName) {
|
||||
public void exportQuarterlyProductGrouping(List<WeeklyHeavyStock> weeklyHeavyStockList, String weeklyHeavyStockReportName) throws IOException {
|
||||
String currentPath = Paths.get("").toAbsolutePath().toString();
|
||||
File file = new File(currentPath + "/" + weeklyHeavyStockReportName);
|
||||
// 创建工作簿
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
// 创建工作表
|
||||
Sheet sheet = workbook.createSheet("Quarterly Product Grouping Report");
|
||||
// 创建标题行
|
||||
Row headerRow = sheet.createRow(0);
|
||||
headerRow.createCell(0).setCellValue("PLU_CODE");
|
||||
headerRow.createCell(1).setCellValue("Col");
|
||||
headerRow.createCell(2).setCellValue("Size");
|
||||
headerRow.createCell(3).setCellValue("item_barcode");
|
||||
headerRow.createCell(4).setCellValue("item_name");
|
||||
headerRow.createCell(5).setCellValue("cat");
|
||||
headerRow.createCell(6).setCellValue("sub_cat");
|
||||
headerRow.createCell(7).setCellValue("price_sales");
|
||||
headerRow.createCell(8).setCellValue("MASSOLD");
|
||||
headerRow.createCell(9).setCellValue("MELSOLD");
|
||||
headerRow.createCell(10).setCellValue("MPCSOLD");
|
||||
headerRow.createCell(11).setCellValue("MPSSOLD");
|
||||
headerRow.createCell(12).setCellValue("MTFSOLD");
|
||||
headerRow.createCell(13).setCellValue("MWPSOLD");
|
||||
headerRow.createCell(14).setCellValue("MYOSOLD");
|
||||
headerRow.createCell(15).setCellValue("MAS");
|
||||
headerRow.createCell(16).setCellValue("MEL");
|
||||
headerRow.createCell(17).setCellValue("MPC");
|
||||
headerRow.createCell(18).setCellValue("MPS");
|
||||
headerRow.createCell(19).setCellValue("MTF");
|
||||
headerRow.createCell(20).setCellValue("MWP");
|
||||
headerRow.createCell(21).setCellValue("MYO");
|
||||
headerRow.createCell(22).setCellValue("MHZ");
|
||||
headerRow.createCell(23).setCellValue("MRT");
|
||||
headerRow.createCell(24).setCellValue("MBZ");
|
||||
|
||||
// 写入数据
|
||||
int rowNum = 1;
|
||||
// 创建工作簿和工作表
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("Quarterly Product Grouping Report");
|
||||
|
||||
// 添加报表头
|
||||
Row titleRow = sheet.createRow(0);
|
||||
Cell titleCell = titleRow.createCell(0);
|
||||
titleCell.setCellValue("FW24 STOCK LIST");
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 26)); // 合并标题单元格
|
||||
|
||||
// 添加“Stock on hand - shop”和“Stock on hand - back office”
|
||||
Row stockHeaderRow = sheet.createRow(1);
|
||||
|
||||
Cell stockShopCell = stockHeaderRow.createCell(10);
|
||||
stockShopCell.setCellValue("Stock on hand - shop");
|
||||
sheet.addMergedRegion(new CellRangeAddress(1, 1, 10, 16)); // 适当调整列的范围
|
||||
|
||||
Cell stockOfficeCell = stockHeaderRow.createCell(17);
|
||||
stockOfficeCell.setCellValue("Stock on hand - back office");
|
||||
sheet.addMergedRegion(new CellRangeAddress(1, 1, 17, 19)); // 适当调整列的范围
|
||||
|
||||
// 创建标题行
|
||||
Row headerRow = sheet.createRow(2);
|
||||
String[] headers = {"Image", "Plu Code", "Col", "Size", "Item Code", "Item Name", "Cat", "Sub_Cat", "RSP",
|
||||
"HK Sell-thru", "Shop total Sold", // 新增字段
|
||||
"MAS Sold", "MEL Sold", "MPC Sold", "MPS Sold", "MTF Sold", "MWP Sold", "MYO Sold",
|
||||
"MAS", "MEL", "MPC", "MPS", "MTF", "MWP", "MYO", "MRT", "MBZ", "MHZ"};
|
||||
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
headerRow.createCell(i).setCellValue(headers[i]);
|
||||
}
|
||||
|
||||
// // 自动调整除Image列外的其他列宽度
|
||||
// for (int i = 1; i < headers.length; i++) {
|
||||
// sheet.autoSizeColumn(i);
|
||||
// }
|
||||
|
||||
// 写入数据和插入图片
|
||||
int rowNum = 3; // 数据从第四行开始
|
||||
int startRow = rowNum;
|
||||
String previousPluCode = "";
|
||||
String imagePath = "";
|
||||
|
||||
for (WeeklyHeavyStock weeklyHeavyStock : weeklyHeavyStockList) {
|
||||
Row row = sheet.createRow(rowNum++);
|
||||
row.createCell(0).setCellValue(weeklyHeavyStock.getPLU_CODE());
|
||||
row.createCell(1).setCellValue(weeklyHeavyStock.getCol());
|
||||
row.createCell(2).setCellValue(weeklyHeavyStock.getSize());
|
||||
row.createCell(3).setCellValue(weeklyHeavyStock.getItem_barcode());
|
||||
row.createCell(4).setCellValue(weeklyHeavyStock.getItem_name());
|
||||
row.createCell(5).setCellValue(weeklyHeavyStock.getCat());
|
||||
row.createCell(6).setCellValue(weeklyHeavyStock.getSub_cat());
|
||||
row.createCell(7).setCellValue(weeklyHeavyStock.getPrice_sales());
|
||||
row.createCell(8).setCellValue(weeklyHeavyStock.getMASSOLD());
|
||||
row.createCell(9).setCellValue(weeklyHeavyStock.getMELSOLD());
|
||||
row.createCell(10).setCellValue(weeklyHeavyStock.getMPCSOLD());
|
||||
row.createCell(11).setCellValue(weeklyHeavyStock.getMPSSOLD());
|
||||
row.createCell(12).setCellValue(weeklyHeavyStock.getMTFSOLD());
|
||||
row.createCell(13).setCellValue(weeklyHeavyStock.getMWPSOLD());
|
||||
row.createCell(14).setCellValue(weeklyHeavyStock.getMYOSOLD());
|
||||
row.createCell(15).setCellValue(weeklyHeavyStock.getMAS());
|
||||
row.createCell(16).setCellValue(weeklyHeavyStock.getMEL());
|
||||
row.createCell(17).setCellValue(weeklyHeavyStock.getMPC());
|
||||
row.createCell(18).setCellValue(weeklyHeavyStock.getMPS());
|
||||
row.createCell(19).setCellValue(weeklyHeavyStock.getMTF());
|
||||
row.createCell(20).setCellValue(weeklyHeavyStock.getMWP());
|
||||
row.createCell(21).setCellValue(weeklyHeavyStock.getMYO());
|
||||
row.createCell(22).setCellValue(weeklyHeavyStock.getMHZ());
|
||||
row.createCell(23).setCellValue(weeklyHeavyStock.getMRT());
|
||||
row.createCell(24).setCellValue(weeklyHeavyStock.getMBZ());
|
||||
if (!weeklyHeavyStock.getPLU_CODE().equals(previousPluCode)) {
|
||||
// 新的PLU_CODE,合并之前的单元格,并插入图片
|
||||
if (startRow < rowNum - 1) {
|
||||
mergeCells(sheet, startRow, rowNum - 1);
|
||||
linkImageToCell(workbook, sheet, startRow, rowNum - 1, 0, imagePath); // 插入图片到合并单元格
|
||||
}
|
||||
startRow = rowNum;
|
||||
previousPluCode = weeklyHeavyStock.getPLU_CODE();
|
||||
imagePath = getImagePath(weeklyHeavyStock.getPLU_CODE());
|
||||
}
|
||||
|
||||
// 计算“Shop total Sold”
|
||||
int shopTotalSold = weeklyHeavyStock.getMASSOLD() + weeklyHeavyStock.getMELSOLD() +
|
||||
weeklyHeavyStock.getMPCSOLD() + weeklyHeavyStock.getMPSSOLD() +
|
||||
weeklyHeavyStock.getMTFSOLD() + weeklyHeavyStock.getMWPSOLD() +
|
||||
weeklyHeavyStock.getMYOSOLD();
|
||||
|
||||
// 计算“HK Sell-thru”
|
||||
int stockOnHand = weeklyHeavyStock.getMAS() + weeklyHeavyStock.getMEL() +
|
||||
weeklyHeavyStock.getMPC() + weeklyHeavyStock.getMPS() +
|
||||
weeklyHeavyStock.getMTF() + weeklyHeavyStock.getMWP() +
|
||||
weeklyHeavyStock.getMYO() + weeklyHeavyStock.getMRT() +
|
||||
weeklyHeavyStock.getMBZ() + weeklyHeavyStock.getMHZ();
|
||||
|
||||
String hkSellThru = stockOnHand > 0 ? String.format("%.0f%%", (double) shopTotalSold / stockOnHand * 100) : "0%";
|
||||
|
||||
Row row = sheet.createRow(rowNum);
|
||||
row.createCell(1).setCellValue(weeklyHeavyStock.getPLU_CODE());
|
||||
row.createCell(2).setCellValue(weeklyHeavyStock.getCol());
|
||||
row.createCell(3).setCellValue(weeklyHeavyStock.getSize());
|
||||
row.createCell(4).setCellValue(weeklyHeavyStock.getItem_barcode());
|
||||
row.createCell(5).setCellValue(weeklyHeavyStock.getItem_name());
|
||||
row.createCell(6).setCellValue(weeklyHeavyStock.getCat());
|
||||
row.createCell(7).setCellValue(weeklyHeavyStock.getSub_cat());
|
||||
row.createCell(8).setCellValue(weeklyHeavyStock.getPrice_sales());
|
||||
row.createCell(9).setCellValue(hkSellThru); // 填入计算的HK Sell-thru
|
||||
row.createCell(10).setCellValue(shopTotalSold); // 填入计算的Shop total Sold
|
||||
row.createCell(11).setCellValue(weeklyHeavyStock.getMASSOLD());
|
||||
row.createCell(12).setCellValue(weeklyHeavyStock.getMELSOLD());
|
||||
row.createCell(13).setCellValue(weeklyHeavyStock.getMPCSOLD());
|
||||
row.createCell(14).setCellValue(weeklyHeavyStock.getMPSSOLD());
|
||||
row.createCell(15).setCellValue(weeklyHeavyStock.getMTFSOLD());
|
||||
row.createCell(16).setCellValue(weeklyHeavyStock.getMWPSOLD());
|
||||
row.createCell(17).setCellValue(weeklyHeavyStock.getMYOSOLD());
|
||||
row.createCell(18).setCellValue(weeklyHeavyStock.getMAS());
|
||||
row.createCell(19).setCellValue(weeklyHeavyStock.getMEL());
|
||||
row.createCell(20).setCellValue(weeklyHeavyStock.getMPC());
|
||||
row.createCell(21).setCellValue(weeklyHeavyStock.getMPS());
|
||||
row.createCell(22).setCellValue(weeklyHeavyStock.getMTF());
|
||||
row.createCell(23).setCellValue(weeklyHeavyStock.getMWP());
|
||||
row.createCell(24).setCellValue(weeklyHeavyStock.getMYO());
|
||||
row.createCell(25).setCellValue(weeklyHeavyStock.getMRT());
|
||||
row.createCell(26).setCellValue(weeklyHeavyStock.getMBZ());
|
||||
row.createCell(27).setCellValue(weeklyHeavyStock.getMHZ());
|
||||
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// 确保处理最后一个Plu Code
|
||||
if (startRow < rowNum - 1 || previousPluCode != null) {
|
||||
mergeCells(sheet, startRow, rowNum - 1);
|
||||
linkImageToCell(workbook, sheet, startRow, rowNum - 1, 0, imagePath);
|
||||
}
|
||||
|
||||
// 将工作簿写入文件
|
||||
@@ -828,6 +874,8 @@ public class MiTuExportScheduledTask {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
FileItem a = getMultipartFile(file, file.getName());
|
||||
MultipartFile multipartFile = new CommonsMultipartFile(a);
|
||||
minioUtil.upload("mi-tu", "export", multipartFile);
|
||||
@@ -835,7 +883,66 @@ public class MiTuExportScheduledTask {
|
||||
System.out.println("Excel file has been created successfully!");
|
||||
}
|
||||
|
||||
private void mergeCells(Sheet sheet, int startRow, int endRow) {
|
||||
// 合并单元格
|
||||
if (startRow < endRow) {
|
||||
for (int i = 1; i <= 1; i++) { // 只合并Plu Code列
|
||||
sheet.addMergedRegion(new CellRangeAddress(startRow, endRow, i, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void linkImageToCell(Workbook workbook, Sheet sheet, int startRow, int endRow, int colNum, String imagePath) throws IOException {
|
||||
try (InputStream inputStream = minioUtil.download("mi-tu/26/BOTTOM/PANTS/MKTS27000_0BLK.jpg")) {
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
|
||||
|
||||
CreationHelper helper = workbook.getCreationHelper();
|
||||
Drawing<?> drawing = sheet.createDrawingPatriarch();
|
||||
ClientAnchor anchor = helper.createClientAnchor();
|
||||
|
||||
// 将图片设置为150x150像素的大小,并转换为EMU单位
|
||||
int widthInEMU = 150 * 9525;
|
||||
int heightInEMU = 150 * 9525;
|
||||
|
||||
// 设置图片的插入位置和大小,确保只覆盖Image列
|
||||
anchor.setCol1(colNum); // 设置开始列为Image列
|
||||
anchor.setRow1(startRow); // 设置开始行
|
||||
anchor.setCol2(colNum); // 设置结束列为Image列,不应影响Plu Code列
|
||||
anchor.setRow2(endRow + 1); // 设置结束行
|
||||
|
||||
// 设置图片的宽度和高度
|
||||
anchor.setDx1(0); // 起始点x偏移量
|
||||
anchor.setDy1(0); // 起始点y偏移量
|
||||
anchor.setDx2(widthInEMU); // 结束点x偏移量,使得图片只占用Image列的空间
|
||||
anchor.setDy2(heightInEMU); // 结束点y偏移量
|
||||
|
||||
Picture pict = drawing.createPicture(anchor, pictureIdx);
|
||||
|
||||
// 设置Image列的宽度为150像素
|
||||
sheet.setColumnWidth(colNum, 150 * 35); // 设置列宽,Excel列宽的单位为1/256个字符宽度
|
||||
|
||||
// // 自动调整除Image列外的其他列宽度
|
||||
// for (int i = 1; i < sheet.getRow(2).getLastCellNum(); i++) {
|
||||
// sheet.autoSizeColumn(i);
|
||||
// }
|
||||
|
||||
// 计算行数和每行的高度
|
||||
int totalRows = endRow - startRow + 1;
|
||||
int rowHeight = (150 * 15) / totalRows; // 计算每行的高度,单位为1/20点
|
||||
|
||||
for (int i = startRow; i <= endRow; i++) {
|
||||
sheet.getRow(i).setHeight((short) rowHeight); // 设置每一行的行高
|
||||
}
|
||||
} catch (MinioException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getImagePath(String pluCode) {
|
||||
// 假设图片路径与 PLU_CODE 相关,例如:return "path/to/images/" + pluCode + ".jpg";
|
||||
return "C:\\Users\\10233\\Desktop\\2024 SS\\MKTS27000_0CMY.jpg"; // 示例路径
|
||||
}
|
||||
|
||||
private static List<WeeklyHeavyStock> getQuarterlyProductGroupingList() {
|
||||
List<WeeklyHeavyStock> QuarterlyProductGroupingList = new ArrayList<>();
|
||||
@@ -1538,8 +1645,6 @@ public class MiTuExportScheduledTask {
|
||||
public final static String MITU = "mi-tu";
|
||||
|
||||
public void exportToExcelCustomerPurchaseReport(List<CustomerData> customerDataList, String fileName) throws IOException {
|
||||
File productFile = getProductFile(fileName);
|
||||
|
||||
String currentPath = Paths.get("").toAbsolutePath().toString();
|
||||
File file = new File(currentPath + "/" + fileName);
|
||||
// 如果文件不存在或者为空,则创建一个新的 Workbook
|
||||
@@ -1560,7 +1665,7 @@ public class MiTuExportScheduledTask {
|
||||
// 获取当前年月
|
||||
YearMonth currentYearMonth = YearMonth.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");
|
||||
String[] headers = new String[26]; // 增加一个额外的标题列
|
||||
String[] headers = new String[25];
|
||||
headers[0] = "mbrCode";
|
||||
headers[1] = "mbrName";
|
||||
headers[2] = "mbrMobile";
|
||||
@@ -1579,7 +1684,6 @@ public class MiTuExportScheduledTask {
|
||||
for (int i = 0; i < 11; i++) {
|
||||
headers[13 + i] = currentYearMonth.minusMonths(i + 1).format(formatter);
|
||||
}
|
||||
headers[24] = "productFile"; // 新增的标题列
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = headerRow.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
cell.setCellValue(headers[i]);
|
||||
@@ -1616,26 +1720,7 @@ public class MiTuExportScheduledTask {
|
||||
row.createCell(21).setCellValue(customer.getMonth9());
|
||||
row.createCell(22).setCellValue(customer.getMonth10());
|
||||
row.createCell(23).setCellValue(customer.getMonth11());
|
||||
row.createCell(24).setCellValue(""); // 占位符,用于后续插入图片
|
||||
}
|
||||
|
||||
// 插入图片
|
||||
InputStream inputStream = new FileInputStream(productFile);
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
|
||||
inputStream.close();
|
||||
|
||||
CreationHelper helper = workbook.getCreationHelper();
|
||||
Drawing<?> drawing = sheet.createDrawingPatriarch();
|
||||
|
||||
for (int i = 1; i <= customerDataList.size(); i++) { // 跳过标题行,从第一行开始
|
||||
ClientAnchor anchor = helper.createClientAnchor();
|
||||
anchor.setCol1(24); // 图片插入的列
|
||||
anchor.setRow1(i); // 图片插入的行
|
||||
anchor.setCol2(25); // 图片所占的列数
|
||||
anchor.setRow2(i + 1); // 图片所占的行数
|
||||
|
||||
drawing.createPicture(anchor, pictureIdx);
|
||||
row.createCell(24).setCellValue(customer.getMonth12());
|
||||
}
|
||||
|
||||
// 将Workbook写入文件
|
||||
@@ -1880,6 +1965,7 @@ public class MiTuExportScheduledTask {
|
||||
public Map<String, String> mostFrequentSubCatMap = new HashMap<>();
|
||||
public Map<String, String> mostFrequentCategoryMap = new HashMap<>();
|
||||
public Map<String, Double> avePriceMap = new HashMap<>();
|
||||
public Map<String, Double> priceVarianceMap = new HashMap<>();
|
||||
|
||||
private List<MiTuMember> getMemberType(List<String> memberCodeList) {
|
||||
List<MiTuMember> miTuMemberList = new ArrayList<>();
|
||||
@@ -1897,6 +1983,7 @@ public class MiTuExportScheduledTask {
|
||||
miTuMember.setMostFrequentSubCat(mostFrequentSubCatMap.get(miTuMember.getMbrCode()));
|
||||
miTuMember.setMostFrequentCategory(mostFrequentCategoryMap.get(miTuMember.getMbrCode()));
|
||||
miTuMember.setAvePrice(avePriceMap.get(miTuMember.getMbrCode()));
|
||||
miTuMember.setPriceVariance(priceVarianceMap.get(miTuMember.getMbrCode()));
|
||||
miTuMemberList.add(miTuMember);
|
||||
}
|
||||
// 计算顾客颜色方差的方差
|
||||
@@ -2096,6 +2183,20 @@ public class MiTuExportScheduledTask {
|
||||
avePriceMap.put(memberCode, avePrice);
|
||||
}
|
||||
|
||||
// Step 1: 提取每笔交易的实际付款金额
|
||||
List<Double> paymentList = transactionList.stream()
|
||||
.map(Transaction::getNetAmt)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Step 2: 计算均值
|
||||
double mean = paymentList.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
|
||||
|
||||
// Step 3: 计算标准差
|
||||
double priceVariance = paymentList.stream()
|
||||
.mapToDouble(payment -> Math.pow(payment - mean, 2))
|
||||
.average().orElse(0.0);
|
||||
priceVarianceMap.put(memberCode, priceVariance);
|
||||
|
||||
// 计算颜色的方差
|
||||
double colorMean = (double) totalCount / colorCountMap.size();
|
||||
double colorVarianceSum = 0;
|
||||
|
||||
@@ -15,4 +15,6 @@ import java.util.List;
|
||||
public interface MiTuProductMapper extends CommonMapper<MiTuProduct> {
|
||||
|
||||
List<MiTuProduct> getTop30ScoreByMemberCode(String memberCode);
|
||||
|
||||
List<MiTuProduct> getTopScoreByMemberCode(String memberCode, List<Long> productIdList);
|
||||
}
|
||||
|
||||
@@ -32,4 +32,5 @@ public class MiTuMember implements Serializable {
|
||||
private String mostFrequentSubCat;
|
||||
private String mostFrequentCategory;
|
||||
private double avePrice;
|
||||
private double priceVariance;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public class QueryRecommendPageDTO extends PageQueryBaseVo implements Serializab
|
||||
|
||||
@ApiModelProperty("商品一级标签类型 top dress 等等")
|
||||
private String labelItem;
|
||||
|
||||
private String storeId;
|
||||
private String memberCode;
|
||||
|
||||
}
|
||||
|
||||
@@ -157,71 +157,67 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
|
||||
if (StringUtils.isEmpty(query.getMemberCode())) {
|
||||
query.setMemberCode("100002");
|
||||
}
|
||||
|
||||
// 分页数据
|
||||
QueryWrapper<TProduct> queryWrapper = new QueryWrapper<>();
|
||||
List<Long> productIds = new ArrayList<>();
|
||||
List<Long> productIdsByMemberCode = new ArrayList<>(); // 初始化 productIdsByMemberCode
|
||||
|
||||
if (!StringUtils.isEmpty(query.getMemberCode())) {
|
||||
List<Long> productIdsByMemberCode = miTuExportService.getProductIdsByMiTuMemberCode(query.getMemberCode());
|
||||
// 获取三页商品ID列表
|
||||
productIdsByMemberCode = miTuExportService.getProductIdsByMiTuMemberCode(query.getMemberCode());
|
||||
productIds.addAll(productIdsByMemberCode);
|
||||
if (CollectionUtils.isEmpty(productIds)) {
|
||||
return PageBaseResponse.success(new Page<>());
|
||||
}
|
||||
}
|
||||
if (!StringUtils.isEmpty(query.getLabelItem())) {
|
||||
List<Long> byItemAndType = tProductAttributeService.findByItemAndType(query.getLabelItem(), null);
|
||||
if (CollectionUtils.isEmpty(byItemAndType)) {
|
||||
return PageBaseResponse.success(new Page<>());
|
||||
}
|
||||
if (!StringUtils.isEmpty(query.getMemberCode())) {
|
||||
productIds.retainAll(byItemAndType);
|
||||
}else {
|
||||
productIds.addAll(byItemAndType);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(productIds)) {
|
||||
return PageBaseResponse.success(new Page<>());
|
||||
}
|
||||
queryWrapper.in("id", productIds);
|
||||
//个性化商品筛选
|
||||
List<TCustomBuriedPointRecord> customBuriedPointRecords = tCustomBuriedPointRecordService.getRecommendProduct("BROWSE");
|
||||
// if(CollectionUtils.isEmpty(customBuriedPointRecords)){
|
||||
// return PageBaseResponse.success(new Page<>());
|
||||
// }
|
||||
// List<String> selectProductIds = customBuriedPointRecords.stream().map(v->v.getProductId().toString()).collect(Collectors.toList());
|
||||
// queryWrapper.in("id", selectProductIds);
|
||||
|
||||
//上架
|
||||
// 将商品ID列表作为过滤条件
|
||||
queryWrapper.in("id", productIds);
|
||||
|
||||
// 使用 ORDER BY FIELD 语句按照 productIds 列表顺序排序
|
||||
queryWrapper.last("ORDER BY FIELD(id, " + productIdsByMemberCode.stream().map(String::valueOf).collect(Collectors.joining(",")) + ")");
|
||||
|
||||
// 其他筛选条件(如上架状态)
|
||||
queryWrapper.eq("on_sale_state", 1);
|
||||
queryWrapper.eq("upload_state", 1);
|
||||
// queryWrapper.eq("account_id", UserContext.getUserHolder().getId());
|
||||
queryWrapper.orderByDesc("id");
|
||||
|
||||
// 执行分页查询
|
||||
IPage<TProduct> page = getBaseMapper().selectPage(
|
||||
new Page<>(query.getPage(), query.getSize()), queryWrapper);
|
||||
|
||||
if (CollectionUtils.isEmpty(page.getRecords())) {
|
||||
return PageBaseResponse.success(new Page<>());
|
||||
}
|
||||
|
||||
List<Long> collect = page.getRecords().stream().map(TProduct::getId).collect(Collectors.toList());
|
||||
Map<Long,List<TProductLabel>> productToLabelMap = productLabelService.findByProductIds(collect);
|
||||
Map<Long, List<TProductLabel>> productToLabelMap = productLabelService.findByProductIds(collect);
|
||||
List<Long> labelIds = productToLabelMap.values()
|
||||
.stream()
|
||||
.map(list->list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList()))
|
||||
.map(list -> list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList()))
|
||||
.flatMap(List::stream).collect(Collectors.toList());
|
||||
//标签map
|
||||
Map<Long,TLabel> labelMap = labelService.queryMapByIds(labelIds);
|
||||
|
||||
// 标签映射
|
||||
Map<Long, TLabel> labelMap = labelService.queryMapByIds(labelIds);
|
||||
|
||||
// 将查询结果转换为 VO 对象
|
||||
IPage<AppNewProductVO> convert = page.convert((Function<TProduct, AppNewProductVO>)
|
||||
product ->
|
||||
{
|
||||
product -> {
|
||||
AppNewProductVO result = CopyUtil.copyObject(product, AppNewProductVO.class);
|
||||
result.setId(product.getId().toString());
|
||||
result.setPictureUrl(minioUtil.getPresignedUrl(result.getPictureUrl(), 24 * 60));
|
||||
result.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(product.getId()),ProductLabelVO.class,(o,d) ->{
|
||||
result.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(product.getId()), ProductLabelVO.class, (o, d) -> {
|
||||
d.setId(o.getLabelId().toString());
|
||||
d.setName(labelMap.get(o.getLabelId()).getName());
|
||||
d.setType(labelMap.get(o.getLabelId()).getType());
|
||||
}));
|
||||
return result;
|
||||
});
|
||||
|
||||
return PageBaseResponse.success(convert);
|
||||
}
|
||||
/**
|
||||
@@ -726,16 +722,17 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
|
||||
// 创建推荐对象
|
||||
OutfitRecommendation recommendation = new OutfitRecommendation();
|
||||
|
||||
// 调用ai推荐模型
|
||||
JSONObject jsonObject = pythonService.getAIRecommend(aiRecommendDTO);
|
||||
|
||||
// 检查jsonObject是否为null
|
||||
if (jsonObject == null) {
|
||||
throw new NullPointerException("The response from Python service is null");
|
||||
}
|
||||
// // 调用ai推荐模型
|
||||
// JSONObject jsonObject = pythonService.getAIRecommend(aiRecommendDTO);
|
||||
//
|
||||
// // 检查jsonObject是否为null
|
||||
// if (jsonObject == null) {
|
||||
// throw new NullPointerException("The response from Python service is null");
|
||||
// }
|
||||
|
||||
// 从JSON对象中获取output字段
|
||||
String output = jsonObject.getString("output");
|
||||
// String output = jsonObject.getString("output");
|
||||
String output = "I have a great outfit recommendation for you! Here are the details:\n\n### Recommended Outfit:\n1. **Tailored Navy Blue Blazer**\n - **Description**: A single-breasted design with notched lapels and a slim fit. Features two front flap pockets and a single button closure. Made from a wool blend for a structured yet comfortable feel.\n - \n\n2. **White Silk Blouse**\n - **Description**: A classic collar, button-down front, and long sleeves with buttoned cuffs. Slightly loose fit for a sophisticated and airy look.\n - \n\n3. **High-Waisted Beige Trousers**\n - **Description**: Straight-leg trousers in a light beige color. Clean front with a concealed hook-and-bar closure, side pockets, and a slightly cropped length to show off the ankles.\n - \n\n### Reasons for Recommendation:\n- **Parisian Chic Theme**: Classic and versatile pieces that embody sophistication and elegance.\n- **Navy Blue Blazer**: Adds a touch of structure, perfect for various occasions.\n- **White Silk Blouse**: A timeless staple that pairs well with the blazer.\n- **High-Waisted Beige Trousers**: Neutral base that complements the navy and white, creating a balanced and polished ensemble.\n\nThis combination is ideal for general use and can be dressed up or down depending on the occasion. Enjoy your new look!";
|
||||
|
||||
List<String> urls = extractBracketContents(output);
|
||||
Map<String, String> map = new HashMap<>();
|
||||
|
||||
@@ -470,6 +470,20 @@ public class TProductService extends ServiceImpl<TProductMapper, TProduct> {
|
||||
* @returnN
|
||||
*/
|
||||
public ProductVO detail(String id) {
|
||||
if (id.contains("http:")) {
|
||||
String[] split = id.split("\\.jpg\\?");
|
||||
String s = split[0];
|
||||
String[] split1 = s.split("/");
|
||||
String s1 = split1[split1.length - 1];
|
||||
QueryWrapper<TProduct> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(TProduct::getPictureName, s1);
|
||||
List<TProduct> productList = tProductMapper.selectList(qw);
|
||||
if (!CollectionUtils.isEmpty(productList)) {
|
||||
id = String.valueOf(productList.get(0).getId());
|
||||
}else {
|
||||
throw new BusinessException("Unknown Product.");
|
||||
}
|
||||
}
|
||||
TProduct tProduct = tProductMapper.selectById(id);
|
||||
Assert.notNull(tProduct, "Unknown Product!");
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.mixi.common.config.exception.BusinessException;
|
||||
import com.mixi.common.response.PageBaseResponse;
|
||||
import com.mixi.common.tasks.mituExportEntity.WeeklyHeavyStock;
|
||||
import com.mixi.common.utils.CopyUtil;
|
||||
import com.mixi.common.utils.MinioUtil;
|
||||
import com.mixi.mapper.MiTuExportMapper;
|
||||
@@ -28,10 +29,12 @@ import org.springframework.util.StringUtils;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
//import com.ai.da.common.utils.SendSmsUtil;
|
||||
|
||||
@@ -145,102 +148,257 @@ public class MiTuExportServiceImpl implements MiTuExportService {
|
||||
|
||||
@Override
|
||||
public List<Long> getProductIdsByMiTuMemberCode(String memberCode) {
|
||||
List<MiTuProduct> miTuProductList = miTuProductMapper.getTop30ScoreByMemberCode(memberCode);
|
||||
if (CollectionUtils.isEmpty(miTuProductList)) {
|
||||
// 顾客类型筛选
|
||||
QueryWrapper<MiTuMember> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(MiTuMember::getMbrCode, memberCode);
|
||||
List<MiTuMember> miTuMembers = miTuMemberMapper.selectList(qw);
|
||||
if (CollectionUtils.isEmpty(miTuMembers)) {
|
||||
return new ArrayList<>();
|
||||
}else {
|
||||
// List<Long> result = new ArrayList<>();
|
||||
// int i = 0;
|
||||
// while (result.size() <= 30) {
|
||||
//
|
||||
// }
|
||||
return miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toList());
|
||||
}
|
||||
// QueryWrapper<MiTuMember> qw = new QueryWrapper<>();
|
||||
// qw.lambda().eq(MiTuMember::getMbrCode, memberCode);
|
||||
// List<MiTuMember> miTuMembers = miTuMemberMapper.selectList(qw);
|
||||
// if (CollectionUtils.isEmpty(miTuMembers)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// String mostFrequentColor = miTuMembers.get(0).getMostFrequentColor();
|
||||
// String mostFrequentSize = miTuMembers.get(0).getMostFrequentSize();
|
||||
// String mostFrequentSubCat = miTuMembers.get(0).getMostFrequentSubCat();
|
||||
// List<String> colorList = new ArrayList<>();
|
||||
// if (mostFrequentColor.contains(",")) {
|
||||
// colorList = Arrays.asList(mostFrequentColor.split(","));
|
||||
// }else {
|
||||
// colorList.add(mostFrequentColor);
|
||||
// }
|
||||
|
||||
MiTuMember member = miTuMembers.get(0);
|
||||
// 根据顾客代码获取筛选后的商品ID列表
|
||||
List<Long> productIdList = getProductIdListByMemberType(member);
|
||||
if (CollectionUtils.isEmpty(productIdList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 获取经过打分后的商品列表
|
||||
List<MiTuProduct> scoredProducts = miTuProductMapper.getTopScoreByMemberCode(memberCode, productIdList);
|
||||
if (CollectionUtils.isEmpty(scoredProducts)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 获取顾客的平均购买价格
|
||||
double avgPrice = member.getAvePrice();
|
||||
|
||||
double priceVariance = member.getPriceVariance();
|
||||
|
||||
double priceStdDev = Math.sqrt(priceVariance);
|
||||
|
||||
double lowerBound = avgPrice - 2 * priceStdDev;
|
||||
double upperBound = avgPrice + 2 * priceStdDev;
|
||||
|
||||
|
||||
// // 按照商品价格与平均价格的接近程度进行排序
|
||||
// List<MiTuProduct> sortedProducts = scoredProducts.stream()
|
||||
// .sorted(Comparator.comparingDouble(p -> Math.abs(p.getPriceSales() - avgPrice)))
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// List<String> sizeList = new ArrayList<>();
|
||||
// if (mostFrequentSize.contains(",")) {
|
||||
// sizeList = Arrays.asList(mostFrequentSize.split(","));
|
||||
// }else {
|
||||
// sizeList.add(mostFrequentSize);
|
||||
// }
|
||||
// // 计算总商品数量和6:2的比例
|
||||
// int totalProducts = sortedProducts.size();
|
||||
// int closeToAverageCount = (int) Math.round(totalProducts * 0.75); // 6/8 = 0.75
|
||||
// int notCloseToAverageCount = totalProducts - closeToAverageCount;
|
||||
//
|
||||
// List<String> subCatList = new ArrayList<>();
|
||||
// if (mostFrequentSubCat.contains(",")) {
|
||||
// subCatList = Arrays.asList(mostFrequentSubCat.split(","));
|
||||
// }else {
|
||||
// subCatList.add(mostFrequentSubCat);
|
||||
// }
|
||||
// // 选择最接近均价的75%商品
|
||||
// List<MiTuProduct> closeToAverage = sortedProducts.stream()
|
||||
// .limit(closeToAverageCount)
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// String memberType = miTuMembers.get(0).getMemberType();
|
||||
// switch (memberType) {
|
||||
// case "Type D" : {
|
||||
// // 根据牌子、款式、颜色推荐
|
||||
// QueryWrapper<MiTuProduct> miTuProductQueryWrapper = new QueryWrapper<>();
|
||||
// miTuProductQueryWrapper.lambda().in(MiTuProduct::getColor, colorList);
|
||||
// List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
|
||||
// if (CollectionUtils.isEmpty(miTuProductList)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
|
||||
// if (CollectionUtils.isEmpty(collect)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// return new ArrayList<>(collect);
|
||||
// }
|
||||
// case "Type i" : {
|
||||
// QueryWrapper<MiTuProduct> miTuProductQueryWrapper = new QueryWrapper<>();
|
||||
// miTuProductQueryWrapper.lambda().eq(MiTuProduct::getYear, "TE");
|
||||
// miTuProductQueryWrapper.lambda().eq(MiTuProduct::getSeason, "A");
|
||||
// List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
|
||||
// if (CollectionUtils.isEmpty(miTuProductList)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
|
||||
// if (CollectionUtils.isEmpty(collect)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// return new ArrayList<>(collect);
|
||||
// }
|
||||
// case "Type C" : {
|
||||
//
|
||||
// QueryWrapper<MiTuProduct> miTuProductQueryWrapper = new QueryWrapper<>();
|
||||
// miTuProductQueryWrapper.lambda().eq(MiTuProduct::getSubGroup, "TWIN SET");
|
||||
// List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
|
||||
// if (CollectionUtils.isEmpty(miTuProductList)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
|
||||
// if (CollectionUtils.isEmpty(collect)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// return new ArrayList<>(collect);
|
||||
// }
|
||||
// case "Type S" : {
|
||||
// // Sell through 前20
|
||||
// Map<Long, Integer> productIdNumMap = appProductService.getProductIdListByQueryType(3, null);
|
||||
// List<Long> collect = productIdNumMap.keySet().stream().collect(Collectors.toList());
|
||||
// if (CollectionUtils.isEmpty(collect)) {
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// return collect;
|
||||
// }
|
||||
// default :
|
||||
// throw new BusinessException("Unknown memberType.");
|
||||
// }
|
||||
// // 选择不太接近均价的25%商品
|
||||
// List<MiTuProduct> notCloseToAverage = sortedProducts.stream()
|
||||
// .skip(closeToAverageCount)
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
// 选择靠近均价的商品
|
||||
List<MiTuProduct> closeToAverage = scoredProducts.stream()
|
||||
.filter(p -> p.getPriceSales() >= lowerBound && p.getPriceSales() <= upperBound)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 选择不太靠近均价的商品
|
||||
List<MiTuProduct> notCloseToAverage = scoredProducts.stream()
|
||||
.filter(p -> p.getPriceSales() < lowerBound || p.getPriceSales() > upperBound)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
// 获取重仓商品列表
|
||||
List<String> heavyStockPluCodes = getHeavyStockProduct();
|
||||
QueryWrapper<MiTuProduct> heavyStockQw = new QueryWrapper<>();
|
||||
heavyStockQw.lambda().in(MiTuProduct::getPluCode, heavyStockPluCodes);
|
||||
List<MiTuProduct> heavyStockProducts = miTuProductMapper.selectList(heavyStockQw);
|
||||
|
||||
// 最终推荐的商品列表
|
||||
List<MiTuProduct> recommendedProducts = new ArrayList<>();
|
||||
Set<Long> usedProductIds = new HashSet<>(); // 用来记录已经使用过的商品
|
||||
|
||||
for (int i = 0; i < 3; i++) { // 循环处理3页数据
|
||||
List<MiTuProduct> pageProducts = new ArrayList<>();
|
||||
|
||||
// 1. 按照打分顺序填充,先从靠近均价的商品列表中填充6件商品
|
||||
for (MiTuProduct product : scoredProducts) {
|
||||
if (closeToAverage.contains(product) && pageProducts.size() < 6) {
|
||||
if (!usedProductIds.contains(product.getProductId())) {
|
||||
pageProducts.add(product);
|
||||
usedProductIds.add(product.getProductId());
|
||||
}
|
||||
}
|
||||
// 每页最多6个产品
|
||||
if (pageProducts.size() >= 6) break;
|
||||
}
|
||||
|
||||
for (MiTuProduct product : scoredProducts) {
|
||||
// 2. 从不靠近均价的商品列表中填充2件商品
|
||||
if (notCloseToAverage.contains(product) && pageProducts.size() < 8) {
|
||||
if (!usedProductIds.contains(product.getProductId())) {
|
||||
pageProducts.add(product);
|
||||
usedProductIds.add(product.getProductId());
|
||||
}
|
||||
}
|
||||
|
||||
// 每页最多10个产品
|
||||
if (pageProducts.size() >= 8) break;
|
||||
}
|
||||
|
||||
// 3. 从重仓商品列表中填充2件商品,并确保不重复
|
||||
int heavyStockCount = 0;
|
||||
for (MiTuProduct product : heavyStockProducts) {
|
||||
if (heavyStockCount >= 2) break;
|
||||
if (!usedProductIds.contains(product.getProductId()) && !pageProducts.contains(product)) {
|
||||
pageProducts.add(product);
|
||||
usedProductIds.add(product.getProductId());
|
||||
heavyStockCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 如果重仓商品不够2件,从靠近均价的商品中补充
|
||||
if (heavyStockCount < 2) {
|
||||
for (MiTuProduct product : closeToAverage) {
|
||||
if (heavyStockCount >= 2) break;
|
||||
if (!usedProductIds.contains(product.getProductId())) {
|
||||
pageProducts.add(product);
|
||||
usedProductIds.add(product.getProductId());
|
||||
heavyStockCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将这一页的商品加入最终推荐列表
|
||||
recommendedProducts.addAll(pageProducts);
|
||||
|
||||
// 从已使用列表中移除本页使用的商品
|
||||
closeToAverage.removeAll(pageProducts);
|
||||
notCloseToAverage.removeAll(pageProducts);
|
||||
heavyStockProducts.removeAll(pageProducts);
|
||||
}
|
||||
|
||||
// 确保推荐商品的数量足够,并返回最终的商品ID列表
|
||||
return recommendedProducts.stream()
|
||||
.limit(30) // 确保不超过3页(30件)商品
|
||||
.map(MiTuProduct::getProductId)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// private List<MiTuProduct> pickProducts(List<MiTuProduct> products, int count) {
|
||||
// return products.stream().limit(count).collect(Collectors.toList());
|
||||
// }
|
||||
|
||||
private List<Long> getProductIdListByMemberType(MiTuMember member) {
|
||||
String memberType = member.getMemberType();
|
||||
switch (memberType) {
|
||||
case "Type D" : {
|
||||
// 根据颜色、尺寸、sub_cat、category筛选
|
||||
QueryWrapper<MiTuProduct> miTuProductQueryWrapper = new QueryWrapper<>();
|
||||
miTuProductQueryWrapper.lambda()
|
||||
.like(MiTuProduct::getColor, member.getMostFrequentColor())
|
||||
.or()
|
||||
.like(MiTuProduct::getSize, member.getMostFrequentSize())
|
||||
.or()
|
||||
.like(MiTuProduct::getSubGroup, member.getMostFrequentSubCat())
|
||||
.or()
|
||||
.like(MiTuProduct::getItemGroup, member.getMostFrequentCategory());
|
||||
List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
|
||||
if (CollectionUtils.isEmpty(miTuProductList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>(collect);
|
||||
}
|
||||
case "Type i" : {
|
||||
QueryWrapper<MiTuProduct> miTuProductQueryWrapper = new QueryWrapper<>();
|
||||
miTuProductQueryWrapper.lambda().eq(MiTuProduct::getYear, "TE");
|
||||
miTuProductQueryWrapper.lambda().eq(MiTuProduct::getSeason, "A");
|
||||
List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
|
||||
if (CollectionUtils.isEmpty(miTuProductList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>(collect);
|
||||
}
|
||||
case "Type C" : {
|
||||
|
||||
QueryWrapper<MiTuProduct> miTuProductQueryWrapper = new QueryWrapper<>();
|
||||
miTuProductQueryWrapper.lambda().eq(MiTuProduct::getSubGroup, "TWIN SET");
|
||||
List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
|
||||
if (CollectionUtils.isEmpty(miTuProductList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>(collect);
|
||||
}
|
||||
case "Type S" : {
|
||||
// 卖的最好 前24
|
||||
Map<Long, Integer> productIdNumMap = appProductService.getProductIdListByQueryType(3, null);
|
||||
List<Long> collect = productIdNumMap.keySet().stream().collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return collect;
|
||||
}
|
||||
default :
|
||||
throw new BusinessException("Unknown memberType.");
|
||||
}
|
||||
}
|
||||
|
||||
static final String JDBC_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
|
||||
static final String DB_URL = "jdbc:sqlserver://118.142.0.178:1550;databaseName=Hayman_prod";
|
||||
|
||||
// 数据库凭据
|
||||
static final String USER = "user01";
|
||||
static final String PASS = "haySIS-0522";
|
||||
private List<String> getHeavyStockProduct() {
|
||||
List<String> result = new ArrayList<>();
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
try {
|
||||
Class.forName(JDBC_DRIVER);
|
||||
conn = DriverManager.getConnection(DB_URL, USER, PASS);
|
||||
stmt = conn.createStatement();
|
||||
|
||||
String sql = "SELECT plu_code\n" +
|
||||
"FROM v_MZG003A\n" +
|
||||
"WHERE TTL_QTY >= 30";
|
||||
|
||||
ResultSet rs = stmt.executeQuery(sql);
|
||||
|
||||
while (rs.next()) {
|
||||
String pluCode = rs.getString("plu_code");
|
||||
result.add(pluCode);
|
||||
}
|
||||
rs.close();
|
||||
stmt.close();
|
||||
conn.close();
|
||||
} catch (SQLException | ClassNotFoundException se) {
|
||||
se.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (stmt != null) stmt.close();
|
||||
} catch (SQLException ignored) {}
|
||||
try {
|
||||
if (conn != null) conn.close();
|
||||
} catch (SQLException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.out.println("Query execution completed!");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,4 +82,66 @@
|
||||
ORDER BY score DESC
|
||||
LIMIT 30
|
||||
</select>
|
||||
|
||||
<select id="getTopScoreByMemberCode" resultType="com.mixi.mapper.entity.MiTuProduct">
|
||||
WITH CustomerPreferences AS (
|
||||
SELECT
|
||||
mbr_code,
|
||||
most_frequent_size,
|
||||
most_frequent_color,
|
||||
most_frequent_sub_cat,
|
||||
most_frequent_category,
|
||||
ave_price
|
||||
FROM mi_tu_member
|
||||
WHERE mbr_code = #{memberCode}
|
||||
), ProductScores AS (
|
||||
SELECT
|
||||
p.id,
|
||||
p.plu_code,
|
||||
p.item_code,
|
||||
p.item_name,
|
||||
p.item_barcode,
|
||||
p.unit,
|
||||
p.item_type,
|
||||
p.qty_on_hand,
|
||||
p.qty_on_ord,
|
||||
p.price_sales,
|
||||
p.brand,
|
||||
p.gender,
|
||||
p.year,
|
||||
p.season,
|
||||
p.sample_non,
|
||||
p.item_group,
|
||||
p.sub_group,
|
||||
p.country,
|
||||
p.supplier,
|
||||
p.size,
|
||||
p.color,
|
||||
p.image,
|
||||
p.product_id,
|
||||
cp.most_frequent_size,
|
||||
cp.most_frequent_color,
|
||||
cp.most_frequent_sub_cat,
|
||||
cp.most_frequent_category,
|
||||
cp.ave_price,
|
||||
(0.30 * (cp.most_frequent_size like CONCAT('%', p.size, '%')) +
|
||||
0.25 * (cp.most_frequent_color like CONCAT('%', p.color, '%')) +
|
||||
0.20 * (1 - LEAST(ABS(p.price_sales - cp.ave_price) / cp.ave_price, 1)) +
|
||||
0.15 * (cp.most_frequent_sub_cat like CONCAT('%', p.sub_group, '%')) +
|
||||
0.10 * (cp.most_frequent_category like CONCAT('%', p.item_group, '%'))) AS score
|
||||
FROM mi_tu_product p
|
||||
CROSS JOIN CustomerPreferences cp
|
||||
WHERE p.product_id IN
|
||||
<foreach item="item" index="index" collection="productIdList" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
)
|
||||
SELECT
|
||||
product_id,
|
||||
price_sales,
|
||||
sum(score) as score
|
||||
FROM ProductScores
|
||||
GROUP BY product_id,price_sales
|
||||
ORDER BY score DESC
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user