diff --git a/pom.xml b/pom.xml
index b1025d1..5182e6e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -216,6 +216,12 @@
1.4
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.13
+
+
diff --git a/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java b/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java
index 3faea5c..5712d7b 100644
--- a/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java
+++ b/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java
@@ -6,6 +6,7 @@ import com.mixi.common.utils.CopyUtil;
import com.mixi.common.utils.MinioUtil;
import com.mixi.mapper.*;
import com.mixi.mapper.entity.*;
+import org.apache.commons.compress.utils.IOUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.commons.fileupload.FileItem;
@@ -56,7 +57,7 @@ public class MiTuExportScheduledTask {
private MiTuProductSellNumMapper miTuProductSellNumMapper;
@PostConstruct
public void executeWeeklyHeavyStockReport() {
-// customerPurchaseReport();
+ customerPurchaseReport();
// NewJoinVIPReport();
// weeklySellThrReport();
// WeeklyHeavyStockReport();
@@ -341,6 +342,24 @@ public class MiTuExportScheduledTask {
miTuExportMapper.insert(miTuExport);
System.out.println("接口执行完成!");
}
+ }else {
+ MiTuExport miTuExport = createMiTuExport("Customer purchase report", "month");
+ try {
+ List transactionData = retrieveTransactionData();
+ List userMembers = transactionData.stream().map(TransactionData::getUserMember).collect(Collectors.toList());
+ List customerData = retrieveCustomerData(userMembers);
+ updateCustomerDataWithTransactionData(customerData, transactionData);
+ String filePath = miTuExport.getExportName()+".xlsx";
+ exportToExcelCustomerPurchaseReport(customerData, filePath);
+ miTuExport.setUrl("mi-tu/export/" + filePath);
+ miTuExport.setStatus(1);
+ } catch (Exception e) {
+ miTuExport.setStatus(0);
+ e.printStackTrace();
+ } finally {
+ miTuExportMapper.insert(miTuExport);
+ System.out.println("接口执行完成!");
+ }
}
}
@@ -1510,6 +1529,8 @@ public class MiTuExportScheduledTask {
public final static String MITU = "mi-tu";
public void exportToExcelCustomerPurchaseReport(List customerDataList, String fileName) throws IOException {
+ File productFile = getProductFile(fileName);
+
String currentPath = Paths.get("").toAbsolutePath().toString();
File file = new File(currentPath + "/" + fileName);
// 如果文件不存在或者为空,则创建一个新的 Workbook
@@ -1530,7 +1551,7 @@ public class MiTuExportScheduledTask {
// 获取当前年月
YearMonth currentYearMonth = YearMonth.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");
- String[] headers = new String[25];
+ String[] headers = new String[26]; // 增加一个额外的标题列
headers[0] = "mbrCode";
headers[1] = "mbrName";
headers[2] = "mbrMobile";
@@ -1549,6 +1570,7 @@ 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]);
@@ -1585,7 +1607,26 @@ 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(customer.getMonth12());
+ 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);
}
// 将Workbook写入文件
@@ -1599,6 +1640,11 @@ public class MiTuExportScheduledTask {
System.out.println("Excel file has been created successfully!");
}
+ private File getProductFile(String fileName) {
+ File file = new File("C:\\Users\\10233\\Desktop\\2024 SS NEW\\MKTS27000_0BLK.jpg");
+ return file;
+ }
+
private static FileItem getMultipartFile(File file, String fieldName) {
// 使用 DiskFileItemFactory 创建一个 FileItemFactory
FileItemFactory factory = new DiskFileItemFactory(16, null);
@@ -1821,6 +1867,10 @@ public class MiTuExportScheduledTask {
public Map varianceMap = new HashMap<>();
public Map mostFrequentColorMap = new HashMap<>();
+ public Map mostFrequentSizeMap = new HashMap<>();
+ public Map mostFrequentSubCatMap = new HashMap<>();
+ public Map avePriceMap = new HashMap<>();
+
private List getMemberType(List memberCodeList) {
List miTuMemberList = new ArrayList<>();
for (String memberCode : memberCodeList) {
@@ -1832,6 +1882,10 @@ public class MiTuExportScheduledTask {
MiTuMember miTuMember = CopyUtil.copyObject(member, MiTuMember.class);
miTuMember.setMbrCode(memberCode);
miTuMember.setMemberType(memberType);
+ miTuMember.setMostFrequentColor(mostFrequentColorMap.get(miTuMember.getMbrCode()));
+ miTuMember.setMostFrequentSize(mostFrequentSizeMap.get(miTuMember.getMbrCode()));
+ miTuMember.setMostFrequentSubCat(mostFrequentSubCatMap.get(miTuMember.getMbrCode()));
+ miTuMember.setAvePrice(avePriceMap.get(miTuMember.getMbrCode()));
miTuMemberList.add(miTuMember);
}
// 计算顾客颜色方差的方差
@@ -1841,7 +1895,6 @@ public class MiTuExportScheduledTask {
if (miTuMember.getMemberType() == null) {
if (varianceMap.get(miTuMember.getMbrCode()) < overallVariance) {
miTuMember.setMemberType("Type D");
- miTuMember.setMostFrequentColor(mostFrequentColorMap.get(miTuMember.getMbrCode()));
}else {
miTuMember.setMemberType("Type S");
}
@@ -1972,6 +2025,10 @@ public class MiTuExportScheduledTask {
transaction.setSeason(rs.getString("SEASON"));
transaction.setColor(rs.getString("COLOR"));
transaction.setSubCat(rs.getString("SUB_CAT"));
+// transaction.setCategory(rs.getString("CATEGORY"));
+ transaction.setSize(rs.getString("SIZE"));
+ transaction.setNetAmt(rs.getDouble("net_amt"));
+
transactionList.add(transaction);
}
@@ -1990,54 +2047,120 @@ public class MiTuExportScheduledTask {
private String analysis(List transactionList, String memberCode) {
int discountNum = 0;
int currentSeasonNum = 0;
- int leadingNum = 0;
Map colorCountMap = new HashMap<>();
+ Map sizeCountMap = new HashMap<>();
+ Map subCatCountMap = new HashMap<>();
int totalCount = transactionList.size();
+ double totalPrice = 0;
- // 统计每种颜色的出现次数
+ // 统计每种颜色和尺寸的出现次数
for (Transaction transaction : transactionList) {
String color = transaction.getColor();
colorCountMap.put(color, colorCountMap.getOrDefault(color, 0) + 1);
+
+ totalPrice += transaction.getNetAmt();
+
+ String size = transaction.getSize();
+ sizeCountMap.put(size, sizeCountMap.getOrDefault(size, 0) + 1);
+
+ String subCat = transaction.getSubCat();
+ subCatCountMap.put(subCat, subCatCountMap.getOrDefault(size, 0) + 1);
}
- // 计算每种颜色的出现频率
- double mean = (double) totalCount / colorCountMap.size();
- double varianceSum = 0;
- String mostFrequentColor = null;
- int maxCount = 0;
+ if (totalCount > 0) {
+ double avePrice = totalPrice / totalCount;
+ avePriceMap.put(memberCode, avePrice);
+ }
+
+ // 计算颜色的方差
+ double colorMean = (double) totalCount / colorCountMap.size();
+ double colorVarianceSum = 0;
+ int maxColorCount = 0;
for (Map.Entry entry : colorCountMap.entrySet()) {
int count = entry.getValue();
- varianceSum += Math.pow(count - mean, 2);
- if (count > maxCount) {
- maxCount = count;
- mostFrequentColor = entry.getKey();
+ colorVarianceSum += Math.pow(count - colorMean, 2);
+ if (count > maxColorCount) {
+ maxColorCount = count;
+ }
+ }
+ double colorVariance = colorVarianceSum / colorCountMap.size();
+
+ // 计算尺寸的方差
+ double sizeMean = (double) totalCount / sizeCountMap.size();
+ double sizeVarianceSum = 0;
+ int maxSizeCount = 0;
+ for (Map.Entry entry : sizeCountMap.entrySet()) {
+ int count = entry.getValue();
+ sizeVarianceSum += Math.pow(count - sizeMean, 2);
+ if (count > maxSizeCount) {
+ maxSizeCount = count;
+ }
+ }
+ double sizeVariance = sizeVarianceSum / sizeCountMap.size();
+
+ // 计算SUBCAT的方差
+ double subCatMean = (double) totalCount / sizeCountMap.size();
+ double subCatVarianceSum = 0;
+ int maxSubCatCount = 0;
+ for (Map.Entry entry : sizeCountMap.entrySet()) {
+ int count = entry.getValue();
+ subCatVarianceSum += Math.pow(count - subCatMean, 2);
+ if (count > maxSubCatCount) {
+ maxSubCatCount = count;
+ }
+ }
+ double subCatVariance = subCatVarianceSum / subCatCountMap.size();
+
+ // 获取出现次数最多的颜色
+ int finalMaxColorCount = maxColorCount;
+ List mostFrequentColors = colorCountMap.entrySet().stream()
+ .filter(entry -> entry.getValue() == finalMaxColorCount)
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+ String mostFrequentColor = String.join(",", mostFrequentColors);
+
+ // 获取出现次数最多的尺寸
+ int finalMaxSizeCount = maxSizeCount;
+ List mostFrequentSizes = sizeCountMap.entrySet().stream()
+ .filter(entry -> entry.getValue() == finalMaxSizeCount)
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+ String size = String.join(",", mostFrequentSizes);
+
+ // 获取出现次数最多的SubCat
+ int finalMaxSubCatCount = maxSizeCount;
+ List mostFrequentSubCats = sizeCountMap.entrySet().stream()
+ .filter(entry -> entry.getValue() == finalMaxSubCatCount)
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+ String subCat = String.join(",", mostFrequentSubCats);
+
+ // 统计折扣和当季商品数量
+ for (Transaction transaction : transactionList) {
+ if ((transaction.getDiscountPer() != null && transaction.getDiscountPer() >= 20.0) || transaction.getSubCat().equals("TWIN SET")) {
+ discountNum++;
+ }
+ if (transaction.getYear().equals("TE") && transaction.getSeason().equals("A")) {
+ currentSeasonNum++;
}
}
- // 计算方差
- double variance = varianceSum / colorCountMap.size();
- for (Transaction transaction : transactionList) {
- if ((transaction.getDiscountPer() != null && transaction.getDiscountPer() >= 20.0) || transaction.getSubCat().equals("TWIN SET")) {
- discountNum ++;
- }
- if (transaction.getYear().equals("TE") && transaction.getSeason().equals("A")) {
- currentSeasonNum ++;
- }
- }
if (discountNum >= transactionList.size() * 0.5) {
return "Type C";
}
if (currentSeasonNum >= transactionList.size() * 0.7) {
return "Type i";
}
+
+ double variance = (colorVariance + sizeVariance + subCatVariance) / 3;
varianceMap.put(memberCode, variance);
+// varianceMap.put(memberCode, sizeVariance);
mostFrequentColorMap.put(memberCode, mostFrequentColor);
+ mostFrequentSizeMap.put(memberCode, size);
+ mostFrequentSubCatMap.put(memberCode, subCat);
+
return null;
-// if (variance <= 0.2) {
-// return "Type D";
-// }
-// return "Type S";
}
private List getMemberCode() {
diff --git a/src/main/java/com/mixi/common/utils/NasUtil.java b/src/main/java/com/mixi/common/utils/NasUtil.java
new file mode 100644
index 0000000..baf69c1
--- /dev/null
+++ b/src/main/java/com/mixi/common/utils/NasUtil.java
@@ -0,0 +1,132 @@
+package com.mixi.common.utils;
+
+import org.apache.commons.compress.utils.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.TrustStrategy;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Base64;
+
+public class NasUtil {
+
+ private static final String NAS_URL = "https://haymanrccnas.synology.me:7106/volume1/PIC/DP9070.bmp";
+ private static final String USERNAME = "your_username";
+ private static final String PASSWORD = "your_password";
+
+ public static void main(String[] args) {
+ downloadFile(NAS_URL, "downloaded_file");
+ }
+
+ public static void downloadFile(String fileURL, String outputFileName) {
+ CredentialsProvider provider = new BasicCredentialsProvider();
+ provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(USERNAME, PASSWORD));
+
+ try (CloseableHttpClient httpClient = HttpClients.custom()
+ .setDefaultCredentialsProvider(provider)
+ .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
+ @Override
+ public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ return true;
+ }
+ }).build())
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+ .build()) {
+
+ HttpGet request = new HttpGet(fileURL);
+ HttpResponse response = httpClient.execute(request);
+
+ if (response.getStatusLine().getStatusCode() == 200) {
+ try (InputStream inputStream = response.getEntity().getContent();
+ FileOutputStream fileOutputStream = new FileOutputStream(outputFileName)) {
+
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ fileOutputStream.write(buffer, 0, bytesRead);
+ }
+ System.out.println("File downloaded successfully");
+ }
+ } else {
+ System.err.println("Failed to download file, HTTP status code: " + response.getStatusLine().getStatusCode());
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static byte[] downloadImage(String imagePath) {
+ String username = "aiuser";
+ String password = "hayNAS-0522";
+ String urlString = "https://haymanrccnas.synology.me:7106/" + imagePath;
+
+ try {
+ // Create a trust manager that does not validate certificate chains
+ TrustManager[] trustAllCerts = new TrustManager[]{
+ new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ public void checkClientTrusted(X509Certificate[] certs, String authType) { }
+ public void checkServerTrusted(X509Certificate[] certs, String authType) { }
+ }
+ };
+
+ // Install the all-trusting trust manager
+ SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, trustAllCerts, new java.security.SecureRandom());
+ HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+
+ // Create all-trusting host name verifier
+ HostnameVerifier allHostsValid = (hostname, session) -> true;
+
+ // Install the all-trusting host verifier
+ HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
+
+ URL url = new URL(urlString);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ String encoded = Base64.getEncoder().encodeToString((username + ":" + password).getBytes("UTF-8"));
+ connection.setRequestProperty("Authorization", "Basic " + encoded);
+ connection.setRequestMethod("GET");
+
+ try (InputStream inputStream = connection.getInputStream()) {
+ return IOUtils.toByteArray(inputStream);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static void saveImageToLocal(byte[] bytes, String fileName) {
+ try {
+ String userHome = System.getProperty("user.home");
+ String desktopPath = userHome + File.separator + "Desktop" + File.separator + "Nas";
+ Files.createDirectories(Paths.get(desktopPath));
+
+ String filePath = desktopPath + File.separator + fileName;
+ try (FileOutputStream fos = new FileOutputStream(filePath)) {
+ fos.write(bytes);
+ System.out.println("Image saved to: " + filePath);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/com/mixi/mapper/entity/MiTuMember.java b/src/main/java/com/mixi/mapper/entity/MiTuMember.java
index e70c4ab..c095d75 100644
--- a/src/main/java/com/mixi/mapper/entity/MiTuMember.java
+++ b/src/main/java/com/mixi/mapper/entity/MiTuMember.java
@@ -28,4 +28,7 @@ public class MiTuMember implements Serializable {
private Double sumBonus;
private String memberType;
private String mostFrequentColor;
+ private String mostFrequentSize;
+ private String mostFrequentSubCat;
+ private double avePrice;
}
diff --git a/src/main/java/com/mixi/model/dto/QueryProductPageDTO.java b/src/main/java/com/mixi/model/dto/QueryProductPageDTO.java
index 057ae96..f958fa4 100644
--- a/src/main/java/com/mixi/model/dto/QueryProductPageDTO.java
+++ b/src/main/java/com/mixi/model/dto/QueryProductPageDTO.java
@@ -37,4 +37,8 @@ public class QueryProductPageDTO extends PageQueryBaseVo implements Serializable
@ApiModelProperty("降序排列字段数组 ")
private List columnSortList;
+ private String pluCode;
+
+ private String color;
+
}
diff --git a/src/main/java/com/mixi/service/TProductService.java b/src/main/java/com/mixi/service/TProductService.java
index 97250e8..9247b51 100644
--- a/src/main/java/com/mixi/service/TProductService.java
+++ b/src/main/java/com/mixi/service/TProductService.java
@@ -123,6 +123,20 @@ public class TProductService extends ServiceImpl {
return PageBaseResponse.success(new Page<>());
}
queryWrapper.in("id", productIdsQuery);
+ if (!StringUtils.isEmpty(query.getPluCode())) {
+ QueryWrapper miTuProductQueryWrapper = new QueryWrapper<>();
+ miTuProductQueryWrapper.lambda().like(MiTuProduct::getPluCode, query.getPluCode());
+ List miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
+ List collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toList());
+ queryWrapper.in("id", collect);
+ }
+ if (!StringUtils.isEmpty(query.getColor())) {
+ QueryWrapper miTuProductQueryWrapper = new QueryWrapper<>();
+ miTuProductQueryWrapper.lambda().like(MiTuProduct::getColor, query.getColor());
+ List miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
+ List collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toList());
+ queryWrapper.in("id", collect);
+ }
if (Objects.nonNull(query.getCreateDateStart())) {
queryWrapper.ge("create_date", new Date(query.getCreateDateStart()));
}
@@ -263,7 +277,7 @@ public class TProductService extends ServiceImpl {
}else if (!CollectionUtils.isEmpty(productIds3) ){
return productIds3;
}
- return null;
+ return new ArrayList<>();
}
/**
* 导出商品
diff --git a/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java b/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java
index 7acf474..8242814 100644
--- a/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java
+++ b/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java
@@ -29,10 +29,7 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -154,12 +151,36 @@ public class MiTuExportServiceImpl implements MiTuExportService {
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 colorList = new ArrayList<>();
+ if (mostFrequentColor.contains(",")) {
+ colorList = Arrays.asList(mostFrequentColor.split(","));
+ }else {
+ colorList.add(mostFrequentColor);
+ }
+
+ List sizeList = new ArrayList<>();
+ if (mostFrequentSize.contains(",")) {
+ sizeList = Arrays.asList(mostFrequentSize.split(","));
+ }else {
+ sizeList.add(mostFrequentSize);
+ }
+
+ List subCatList = new ArrayList<>();
+ if (mostFrequentSubCat.contains(",")) {
+ subCatList = Arrays.asList(mostFrequentSubCat.split(","));
+ }else {
+ subCatList.add(mostFrequentSubCat);
+ }
+
String memberType = miTuMembers.get(0).getMemberType();
switch (memberType) {
case "Type D" : {
// 根据牌子、款式、颜色推荐
QueryWrapper miTuProductQueryWrapper = new QueryWrapper<>();
- miTuProductQueryWrapper.lambda().like(MiTuProduct::getColor, miTuMembers.get(0).getMostFrequentColor());
+ miTuProductQueryWrapper.lambda().in(MiTuProduct::getColor, colorList);
List miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper);
if (CollectionUtils.isEmpty(miTuProductList)) {
return new ArrayList<>();