From a7821a634f6e78ea1d8f31de20dfcc8a038116b6 Mon Sep 17 00:00:00 2001 From: shahaibo <1023316923@qq.com> Date: Thu, 25 Apr 2024 02:57:05 +0800 Subject: [PATCH] TASK:mixi; --- .../common/tasks/MiTuExportScheduledTask.java | 456 +++++++++++++++++- .../tasks/mituExportEntity/Transaction.java | 87 ++++ .../mixi/controller/AppProductController.java | 10 + .../mixi/controller/MiTuExportController.java | 11 +- .../com/mixi/mapper/MiTuMemberMapper.java | 16 + .../mixi/mapper/MiTuProductSellNumMapper.java | 15 + .../com/mixi/mapper/entity/MiTuMember.java | 30 ++ .../mapper/entity/MiTuProductSellNum.java | 24 + .../java/com/mixi/mapper/entity/TProduct.java | 2 + .../com/mixi/model/dto/ProductColorDTO.java | 2 + .../mixi/model/dto/QueryProductListDTO.java | 10 + .../mixi/model/dto/QueryProductRankDTO.java | 2 + .../mixi/model/dto/QueryRecommendPageDTO.java | 2 + .../mixi/model/dto/SearchProductPageDTO.java | 2 + .../com/mixi/service/MiTuExportService.java | 6 + .../java/com/mixi/service/PythonService.java | 69 +++ .../com/mixi/service/TAppProductService.java | 373 ++++++++++---- .../service/impl/MiTuExportServiceImpl.java | 85 ++++ 18 files changed, 1099 insertions(+), 103 deletions(-) create mode 100644 src/main/java/com/mixi/common/tasks/mituExportEntity/Transaction.java create mode 100644 src/main/java/com/mixi/mapper/MiTuMemberMapper.java create mode 100644 src/main/java/com/mixi/mapper/MiTuProductSellNumMapper.java create mode 100644 src/main/java/com/mixi/mapper/entity/MiTuMember.java create mode 100644 src/main/java/com/mixi/mapper/entity/MiTuProductSellNum.java create mode 100644 src/main/java/com/mixi/model/dto/QueryProductListDTO.java diff --git a/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java b/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java index d1f1b38..faf45b2 100644 --- a/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java +++ b/src/main/java/com/mixi/common/tasks/MiTuExportScheduledTask.java @@ -1,9 +1,10 @@ package com.mixi.common.tasks; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.mixi.common.tasks.mituExportEntity.*; import com.mixi.common.utils.MinioUtil; -import com.mixi.mapper.MiTuExportMapper; -import com.mixi.mapper.entity.MiTuExport; +import com.mixi.mapper.*; +import com.mixi.mapper.entity.*; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.commons.fileupload.FileItem; @@ -11,7 +12,6 @@ import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartFile; @@ -22,16 +22,10 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.sql.*; -import java.text.SimpleDateFormat; -import java.time.DayOfWeek; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.YearMonth; +import java.time.*; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; +import java.util.*; import java.util.Date; -import java.util.Iterator; -import java.util.List; import java.util.stream.Collectors; @Component @@ -49,7 +43,13 @@ public class MiTuExportScheduledTask { @Resource private MiTuExportMapper miTuExportMapper; + @Resource + private MiTuProductMapper miTuProductMapper; + @Resource + private TProductMapper productMapper; + @Resource + private MiTuProductSellNumMapper miTuProductSellNumMapper; @PostConstruct public void executeWeeklyHeavyStockReport() { // customerPurchaseReport(); @@ -57,6 +57,254 @@ public class MiTuExportScheduledTask { // weeklySellThrReport(); // WeeklyHeavyStockReport(); // QuarterlyProductGroupingReport(); +// customerTypeAnalysis(); + getBestSell(); + } + +// public static void main(String[] args) { +// LocalDate today = LocalDate.now(); +// for (int i = 0; i < 30; i++) { +// // 将这一天的商品销售数量入库 +// test(today); +// System.out.println(today); +//// miTuProductSellNumEntry(today, productListAll); +// today = today.minusDays(1); +// } +// } +// public static void test(LocalDate today) { +// today = today.minusDays(1); +// } + private void getBestSell() { + QueryWrapper bestSellIsNotNull = new QueryWrapper<>(); +// bestSellIsNotNull.lambda().isNotNull(TProduct::getBestSell); + List productListAll = productMapper.selectList(bestSellIsNotNull); + LocalDate today = LocalDate.now(); + for (int i = 0; i < 30; i++) { + // 将这一天的商品销售数量入库 + miTuProductSellNumEntry(today, productListAll); + today = today.minusDays(1); + } +// for (TProduct tProduct : productList1) { +// tProduct.setBestSell(null); +// productMapper.updateById(tProduct); +// } +// Map> itemNameMap = getBestSellItemNameList(); +// for (String s : itemNameMap.keySet()) { +// if (s.equals("yesterdayItemNameList")) { +// QueryWrapper qw = new QueryWrapper<>(); +// qw.lambda().in(MiTuProduct::getItemName, itemNameMap.get(s)); +// List miTuProductList = miTuProductMapper.selectList(qw); +// if (!CollectionUtils.isEmpty(miTuProductList)) { +// Set collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet()); +// if (!CollectionUtils.isEmpty(collect)) { +// QueryWrapper qwBestSell = new QueryWrapper<>(); +// qwBestSell.lambda().in(TProduct::getId, new ArrayList<>(collect)); +// List productList = productMapper.selectList(qwBestSell); +// if (!CollectionUtils.isEmpty(productList)) { +// for (TProduct tProduct : productList) { +// tProduct.setBestSell("1"); +// productMapper.updateById(tProduct); +// } +// } +// } +// } +// } +// if (s.equals("lastWeekItemNameList")) { +// QueryWrapper qw = new QueryWrapper<>(); +// qw.lambda().in(MiTuProduct::getItemName, itemNameMap.get(s)); +// List miTuProductList = miTuProductMapper.selectList(qw); +// if (!CollectionUtils.isEmpty(miTuProductList)) { +// Set collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet()); +// if (!CollectionUtils.isEmpty(collect)) { +// QueryWrapper qwBestSell = new QueryWrapper<>(); +// qwBestSell.lambda().in(TProduct::getId, new ArrayList<>(collect)); +// List productList = productMapper.selectList(qwBestSell); +// if (!CollectionUtils.isEmpty(productList)) { +// for (TProduct tProduct : productList) { +// if (StringUtils.isEmpty(tProduct.getBestSell())) { +// tProduct.setBestSell("2"); +// }else { +// tProduct.setBestSell(tProduct.getBestSell() + ",2"); +// } +// productMapper.updateById(tProduct); +// } +// } +// } +// } +// } +// if (s.equals("lastMonthItemNameList")) { +// QueryWrapper qw = new QueryWrapper<>(); +// qw.lambda().in(MiTuProduct::getItemName, itemNameMap.get(s)); +// List miTuProductList = miTuProductMapper.selectList(qw); +// if (!CollectionUtils.isEmpty(miTuProductList)) { +// Set collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet()); +// if (!CollectionUtils.isEmpty(collect)) { +// QueryWrapper qwBestSell = new QueryWrapper<>(); +// qwBestSell.lambda().in(TProduct::getId, new ArrayList<>(collect)); +// List productList = productMapper.selectList(qwBestSell); +// if (!CollectionUtils.isEmpty(productList)) { +// for (TProduct tProduct : productList) { +// if (StringUtils.isEmpty(tProduct.getBestSell())) { +// tProduct.setBestSell("3"); +// }else { +// tProduct.setBestSell(tProduct.getBestSell() + ",3"); +// } +// productMapper.updateById(tProduct); +// } +// } +// } +// } +// } +// } + } + + private void miTuProductSellNumEntry(LocalDate today, List productListAll) { + String endDate = formatDate(today); + String startDate = formatDate(today.minusDays(1)); + for (TProduct product : productListAll) { + String pictureName = product.getPictureName(); + String[] split = pictureName.split("_"); + String itemName = split[0]; + String color = split[1]; + MiTuProductSellNum miTuProductSellNum = getProductSellNum(itemName, color, startDate, endDate); + miTuProductSellNum.setProductId(product.getId()); + miTuProductSellNumMapper.insert(miTuProductSellNum); + } + } + + private MiTuProductSellNum getProductSellNum(String itemName, String color, String startDate, String endDate) { + Connection conn = null; + Statement stmt = null; + MiTuProductSellNum miTuProductSellNum = new MiTuProductSellNum(); + try { + // 注册 JDBC 驱动器 + Class.forName(JDBC_DRIVER); + + // 打开一个连接 + System.out.println("连接数据库..."); + conn = DriverManager.getConnection(DB_URL, USER, PASS); + + // 执行查询 + System.out.println("创建声明..."); + stmt = conn.createStatement(); + String sql; + sql = "SELECT count(1) as num FROM v_MZG020B\n" + + "WHERE TRX_DATE >= '" + startDate + "'\n" + + "AND TRX_DATE < '" + endDate + "'\n" + + "AND ITEM_NAME = '" + itemName + "'\n" + + "AND COLOR = '" + color + "'"; + + ResultSet rs = stmt.executeQuery(sql); + // 处理结果集 + while (rs.next()) { + miTuProductSellNum.setSellNum(rs.getInt("num")); + miTuProductSellNum.setSellDate(LocalDate.parse(startDate)); + } + // 清理环境 + rs.close(); + stmt.close(); + conn.close(); + } catch (SQLException | ClassNotFoundException e) { + // 处理异常 + e.printStackTrace(); + } + System.out.println("查询执行完成!"); + return miTuProductSellNum; + } + + // 格式化日期为字符串 + private static String formatDate(LocalDate date) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + return date.format(formatter); + } + private Map> getBestSellItemNameList() { + Map> result = new HashMap<>(); + // 获取当前日期 + LocalDate currentDate = LocalDate.now(); + // 格式化当前日期 + String currentDateString = formatDate(currentDate); + + // 获取前一天日期 + LocalDate yesterdayDate = currentDate.minusDays(1); + // 格式化前一天日期 + String yesterdayDateString = formatDate(yesterdayDate); + + // 获取前一周日期 + LocalDate lastWeekDate = currentDate.minusWeeks(1); + // 格式化前一周日期 + String lastWeekDateString = formatDate(lastWeekDate); + + // 获取前一个月日期 + LocalDate lastMonthDate = currentDate.minusMonths(1); + // 格式化前一个月日期 + String lastMonthDateString = formatDate(lastMonthDate); + Connection conn = null; + Statement stmt = null; + try { + // 注册 JDBC 驱动器 + Class.forName(JDBC_DRIVER); + + // 打开一个连接 + System.out.println("连接数据库..."); + conn = DriverManager.getConnection(DB_URL, USER, PASS); + + // 执行查询 + System.out.println("创建声明..."); + stmt = conn.createStatement(); + String sql; + sql = "SELECT TOP 20 ITEM_NAME FROM v_MZG020B\n" + + " WHERE TRX_DATE >= '" + yesterdayDateString + "'\n" + + " AND TRX_DATE < '" + currentDateString + "'\n" + + " AND ITEM_NAME != 'Shopping Bag Fee'\n" + + " GROUP BY ITEM_NAME\n" + + " ORDER BY COUNT(1) DESC"; + + ResultSet rs = stmt.executeQuery(sql); + // 处理结果集 + List yesterdayItemNameList = new ArrayList<>(); + while (rs.next()) { + yesterdayItemNameList.add(rs.getString("ITEM_NAME")); + } + result.put("yesterdayItemNameList", yesterdayItemNameList); + sql = "SELECT TOP 20 ITEM_NAME FROM v_MZG020B\n" + + " WHERE TRX_DATE >= '" + lastWeekDateString + "'\n" + + " AND TRX_DATE < '" + currentDateString + "'\n" + + " AND ITEM_NAME != 'Shopping Bag Fee'\n" + + " GROUP BY ITEM_NAME\n" + + " ORDER BY COUNT(1) DESC"; + + rs = stmt.executeQuery(sql); + // 处理结果集 + List lastWeekItemNameList = new ArrayList<>(); + while (rs.next()) { + lastWeekItemNameList.add(rs.getString("ITEM_NAME")); + } + result.put("lastWeekItemNameList", lastWeekItemNameList); + sql = "SELECT TOP 20 ITEM_NAME FROM v_MZG020B\n" + + " WHERE TRX_DATE >= '" + lastMonthDateString + "'\n" + + " AND TRX_DATE < '" + currentDateString + "'\n" + + " AND ITEM_NAME != 'Shopping Bag Fee'\n" + + " GROUP BY ITEM_NAME\n" + + " ORDER BY COUNT(1) DESC"; + + rs = stmt.executeQuery(sql); + // 处理结果集 + List lastMonthItemNameList = new ArrayList<>(); + while (rs.next()) { + lastMonthItemNameList.add(rs.getString("ITEM_NAME")); + } + result.put("lastMonthItemNameList", lastMonthItemNameList); + + // 清理环境 + rs.close(); + stmt.close(); + conn.close(); + } catch (SQLException | ClassNotFoundException e) { + // 处理异常 + e.printStackTrace(); + } + System.out.println("查询执行完成!"); + return result; } /** @@ -1505,4 +1753,190 @@ public class MiTuExportScheduledTask { writer.close(); } + + @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) +// @Scheduled(cron = "0 0 22 L * ?") + public void customerTypeAnalysis() { + try { + // 根据近三个月购买记录获取顾客member_code + List memberCodeList = getMemberCode(); + // 遍历每个顾客的类型 + List miTuMemberList = getMemberType(memberCodeList); + } catch (Exception e) { + e.printStackTrace(); + } finally { + System.out.println("接口执行完成!"); + } + } + + @Resource + private MiTuMemberMapper miTuMemberMapper; + private List getMemberType(List memberCodeList) { + List miTuMemberList = new ArrayList<>(); + for (String memberCode : memberCodeList) { + if (memberCode == null) { + continue; + } + String memberType = getMemberTypeByMemberCode(memberCode); + MiTuMember miTuMember = new MiTuMember(); + miTuMember.setMbrCode(memberCode); + miTuMember.setMemberType(memberType); + miTuMemberList.add(miTuMember); + miTuMemberMapper.insert(miTuMember); + } + return miTuMemberList; + } + + private String getMemberTypeByMemberCode(String memberCode) { + List transactionList = new ArrayList<>(); + Connection conn = null; + Statement stmt = null; + try { + // 注册 JDBC 驱动器 + Class.forName(JDBC_DRIVER); + + // 打开一个连接 + System.out.println("连接数据库..."); + conn = DriverManager.getConnection(DB_URL, USER, PASS); + + // 执行查询 + System.out.println("创建声明..."); + stmt = conn.createStatement(); + String sql; + String threeMonthsAgoDateAsString = getThreeMonthsAgoDateAsString(); + sql = "SELECT\n" + + "*\n" + + "FROM v_MZG016A\n" + + "WHERE TRX_DATE >= '" + threeMonthsAgoDateAsString +"'\n" + + "AND member_code = '" + memberCode + "'"; + + ResultSet rs = stmt.executeQuery(sql); + // 处理结果集 + while (rs.next()) { + Transaction transaction = new Transaction(); + double itemDiscount = rs.getDouble("item_discount"); + if (!rs.wasNull()) { + transaction.setItemDiscount(itemDiscount); + } + double discountPer = rs.getDouble("discount_per"); + if (!rs.wasNull()) { + transaction.setDiscountPer(discountPer); + } + transaction.setYear(rs.getString("YEAR")); + transaction.setSeason(rs.getString("SEASON")); + transaction.setColor(rs.getString("COLOR")); + transaction.setSubCat(rs.getString("SUB_CAT")); + transactionList.add(transaction); + } + + // 清理环境 + rs.close(); + stmt.close(); + conn.close(); + } catch (SQLException | ClassNotFoundException e) { + // 处理异常 + e.printStackTrace(); + } + + return analysis(transactionList); + } + + private String analysis(List transactionList) { + int discountNum = 0; + int currentSeasonNum = 0; + int leadingNum = 0; + + Map colorCountMap = new HashMap<>(); + int totalCount = transactionList.size(); + + // 统计每种颜色的出现次数 + for (Transaction transaction : transactionList) { + String color = transaction.getColor(); + colorCountMap.put(color, colorCountMap.getOrDefault(color, 0) + 1); + } + + // 计算每种颜色的出现频率 + double mean = (double) totalCount / colorCountMap.size(); + double varianceSum = 0; + for (Map.Entry entry : colorCountMap.entrySet()) { + int count = entry.getValue(); + varianceSum += Math.pow(count - mean, 2); + } + + // 计算方差 + 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"; + } + if (variance <= 0.2) { + return "Type D"; + } + return "Type S"; + } + + private List getMemberCode() { + List result = new ArrayList<>(); + Connection conn = null; + Statement stmt = null; + try { + // 注册 JDBC 驱动器 + Class.forName(JDBC_DRIVER); + + // 打开一个连接 + System.out.println("连接数据库..."); + conn = DriverManager.getConnection(DB_URL, USER, PASS); + + // 执行查询 + System.out.println("创建声明..."); + stmt = conn.createStatement(); + String sql; + String threeMonthsAgoDateAsString = getThreeMonthsAgoDateAsString(); + sql = "SELECT\n" + + "member_code\n" + + "FROM v_MZG016A\n" + + "WHERE TRX_DATE > '" + threeMonthsAgoDateAsString + "'\n" + + "GROUP BY member_code"; + + ResultSet rs = stmt.executeQuery(sql); + // 处理结果集 + while (rs.next()) { + result.add(rs.getString("member_code")); + } + + // 清理环境 + rs.close(); + stmt.close(); + conn.close(); + } catch (SQLException | ClassNotFoundException e) { + // 处理异常 + e.printStackTrace(); + } + System.out.println("查询执行完成!"); + return result; + } + + public static String getThreeMonthsAgoDateAsString() { + // 获取当前日期和时间 + LocalDateTime currentDateTime = LocalDateTime.now(); + + // 计算三个月前的日期和时间 + LocalDateTime threeMonthsAgoDateTime = currentDateTime.minusMonths(3); + + // 格式化日期和时间为字符串 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String threeMonthsAgoDateTimeAsString = threeMonthsAgoDateTime.format(formatter); + + return threeMonthsAgoDateTimeAsString; + } } diff --git a/src/main/java/com/mixi/common/tasks/mituExportEntity/Transaction.java b/src/main/java/com/mixi/common/tasks/mituExportEntity/Transaction.java new file mode 100644 index 0000000..4b97a7b --- /dev/null +++ b/src/main/java/com/mixi/common/tasks/mituExportEntity/Transaction.java @@ -0,0 +1,87 @@ +package com.mixi.common.tasks.mituExportEntity; + +import lombok.Data; + +import java.time.LocalDate; + +@Data +public class Transaction { + private String dummy; + private String shCode; + private String trxNo; + private LocalDate trxDate; + private int trxYear; + private int trxMonth; + private String docType; + private char trxStatus; + private String salesmanCode; + private String clientCode; + private String memberCode; + private Double discountPer; + private double disAmt; + private int lineNo; + private String itemCode; + private double itemQty; + private double itemPrice; + private Double itemDiscount; + private double itemDisamt; + private double trxSubAmt; + private double trxSubDisamt; + private double netAmt; + private String pmtNo; + private String pluCode; + private String itemName; + private double priceOriginal; + private double priceSales; + private String alternate1; + private String productType; + private String brand; + private String gender; + private String year; + private String season; + private String sample; + private String category; + private String subCat; + private String country; + private String supplier; + private String collection; + private String color; + private String size; + private String anlyCode11; + private String anlyCode12; + private String anlyCode13; + private String anlyCode14; + private String anlyCode15; + private String anlyCode16; + private String anlyCode17; + private String anlyCode18; + private String anlyCode19; + private String anlyCode20; + private String catDesc; + private String subCatDesc; + private String countryDesc; + private String supplierDesc; + private String whType; + private String whDivision; + private double anlyCode1Val; + private double anlyCode2Val; + private double anlyCode3Val; + private double anlyCode4Val; + private double anlyCode5Val; + private int totQty; + private double dDisamt; + private String refDocNo; + private double memoAmt; + private double netUnitPrice; + private double itemOrigPrice; + private double netDiscPercent; + private String spCode; + private String memberName; + private String itemType; + private String salesmanName; + private double itemOrigAmt; + private String itemImage; + private String refNo; + private String remark; + private String mbrGroup; +} diff --git a/src/main/java/com/mixi/controller/AppProductController.java b/src/main/java/com/mixi/controller/AppProductController.java index 9c1c01d..0e21777 100644 --- a/src/main/java/com/mixi/controller/AppProductController.java +++ b/src/main/java/com/mixi/controller/AppProductController.java @@ -3,6 +3,7 @@ package com.mixi.controller; import com.mixi.common.response.PageBaseResponse; import com.mixi.common.response.Response; import com.mixi.common.utils.MD5Utils; +import com.mixi.mapper.entity.MiTuMember; import com.mixi.model.dto.*; import com.mixi.model.vo.*; import com.mixi.service.*; @@ -34,6 +35,9 @@ public class AppProductController { @Resource private TAppProductService tAppProductService; + @Resource + private MiTuExportService miTuExportService; + @ApiOperation(value = "新品推荐列表") @PostMapping("/queryNewProductPage") public Response> queryNewProductPage(@Valid @RequestBody QueryNewProductPageDTO query) { @@ -94,5 +98,11 @@ public class AppProductController { return Response.success(tAppProductService.singleUploadProduct(file, MD5Utils.encryptFile(file))); } + @ApiOperation(value = "MiTu顾客获取根据手机号模糊查询") + @PostMapping("/getMiTuMember") + public Response> queryMiTuMemberList(@Valid @RequestBody QueryProductListDTO query) { + return Response.success(miTuExportService.queryMiTuMemberList(query.getPhone())); + } + } diff --git a/src/main/java/com/mixi/controller/MiTuExportController.java b/src/main/java/com/mixi/controller/MiTuExportController.java index 90de535..b878fd2 100644 --- a/src/main/java/com/mixi/controller/MiTuExportController.java +++ b/src/main/java/com/mixi/controller/MiTuExportController.java @@ -3,10 +3,8 @@ package com.mixi.controller; import com.mixi.common.response.PageBaseResponse; import com.mixi.common.response.Response; import com.mixi.mapper.entity.MiTuExport; -import com.mixi.model.dto.QueryMiTuExportPageDTO; -import com.mixi.model.dto.QueryStorePageDTO; -import com.mixi.model.dto.StoreAddOrEditDTO; -import com.mixi.model.dto.StoreDeleteDTO; +import com.mixi.mapper.entity.MiTuMember; +import com.mixi.model.dto.*; import com.mixi.model.vo.MiTuExportVO; import com.mixi.model.vo.StoreVO; import com.mixi.service.MiTuExportService; @@ -48,5 +46,10 @@ public class MiTuExportController { miTuExportService.exportMiTuReport(id, response); } + @ApiOperation(value = "根据顾客类型获取商品列表") + @GetMapping("/getProductListByMemberCode") + public Response> getProductListByMemberCode(@RequestParam("phone") String phone) { + return Response.success(miTuExportService.queryMiTuMemberList(phone)); + } } diff --git a/src/main/java/com/mixi/mapper/MiTuMemberMapper.java b/src/main/java/com/mixi/mapper/MiTuMemberMapper.java new file mode 100644 index 0000000..9edf790 --- /dev/null +++ b/src/main/java/com/mixi/mapper/MiTuMemberMapper.java @@ -0,0 +1,16 @@ +package com.mixi.mapper; + + +import com.mixi.common.config.mybatis.plus.CommonMapper; +import com.mixi.mapper.entity.MiTuMember; + +/** + * Mapper 接口 + * + * @author easy-generator + * @since 2022-09-30 + */ +public interface MiTuMemberMapper extends CommonMapper { + + +} diff --git a/src/main/java/com/mixi/mapper/MiTuProductSellNumMapper.java b/src/main/java/com/mixi/mapper/MiTuProductSellNumMapper.java new file mode 100644 index 0000000..5c11f09 --- /dev/null +++ b/src/main/java/com/mixi/mapper/MiTuProductSellNumMapper.java @@ -0,0 +1,15 @@ +package com.mixi.mapper; + + +import com.mixi.common.config.mybatis.plus.CommonMapper; +import com.mixi.mapper.entity.MiTuProductSellNum; + +/** + * Mapper 接口 + * + * @author easy-generator + * @since 2022-09-30 + */ +public interface MiTuProductSellNumMapper extends CommonMapper { + +} diff --git a/src/main/java/com/mixi/mapper/entity/MiTuMember.java b/src/main/java/com/mixi/mapper/entity/MiTuMember.java new file mode 100644 index 0000000..2fe01ff --- /dev/null +++ b/src/main/java/com/mixi/mapper/entity/MiTuMember.java @@ -0,0 +1,30 @@ +package com.mixi.mapper.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDate; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("mi_tu_member") +public class MiTuMember implements Serializable { + private static final long serialVersionUID = 1L; + private String mbrCode; + private String mbrName; + private String mbrMobile; + private String mbrGroup; + private char mbrStatus; + private LocalDate joinDate; + private String mbrIssue; + private int birthMonth; + private char mbrSex; + private Double offBonus; + private Double effBonus; + private Double sumBonus; + private String memberType; +} diff --git a/src/main/java/com/mixi/mapper/entity/MiTuProductSellNum.java b/src/main/java/com/mixi/mapper/entity/MiTuProductSellNum.java new file mode 100644 index 0000000..f00591a --- /dev/null +++ b/src/main/java/com/mixi/mapper/entity/MiTuProductSellNum.java @@ -0,0 +1,24 @@ +package com.mixi.mapper.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDate; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("mi_tu_product_sell_num") +public class MiTuProductSellNum implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private Long productId; + private Integer sellNum; + private LocalDate sellDate; +} diff --git a/src/main/java/com/mixi/mapper/entity/TProduct.java b/src/main/java/com/mixi/mapper/entity/TProduct.java index 80a2f0e..3afe6cb 100644 --- a/src/main/java/com/mixi/mapper/entity/TProduct.java +++ b/src/main/java/com/mixi/mapper/entity/TProduct.java @@ -80,5 +80,7 @@ public class TProduct implements Serializable { @ApiModelProperty("更新时间") private Date updateDate; + private String bestSell; + } diff --git a/src/main/java/com/mixi/model/dto/ProductColorDTO.java b/src/main/java/com/mixi/model/dto/ProductColorDTO.java index b28c118..b408e4a 100644 --- a/src/main/java/com/mixi/model/dto/ProductColorDTO.java +++ b/src/main/java/com/mixi/model/dto/ProductColorDTO.java @@ -20,4 +20,6 @@ public class ProductColorDTO implements Serializable { @NotEmpty(message = "productRgbList cannot be empty!") private List productRgbList; + private String productColor; + } diff --git a/src/main/java/com/mixi/model/dto/QueryProductListDTO.java b/src/main/java/com/mixi/model/dto/QueryProductListDTO.java new file mode 100644 index 0000000..ded46f0 --- /dev/null +++ b/src/main/java/com/mixi/model/dto/QueryProductListDTO.java @@ -0,0 +1,10 @@ +package com.mixi.model.dto; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class QueryProductListDTO implements Serializable { + private String phone; +} diff --git a/src/main/java/com/mixi/model/dto/QueryProductRankDTO.java b/src/main/java/com/mixi/model/dto/QueryProductRankDTO.java index a9d5254..6291090 100644 --- a/src/main/java/com/mixi/model/dto/QueryProductRankDTO.java +++ b/src/main/java/com/mixi/model/dto/QueryProductRankDTO.java @@ -23,4 +23,6 @@ public class QueryProductRankDTO implements Serializable { @ApiModelProperty("销量排行结束时间") @NotNull(message = "createDateEnd cannot be empty!") private Long createDateEnd; + + private Integer type; } diff --git a/src/main/java/com/mixi/model/dto/QueryRecommendPageDTO.java b/src/main/java/com/mixi/model/dto/QueryRecommendPageDTO.java index e887cd8..68c12d5 100644 --- a/src/main/java/com/mixi/model/dto/QueryRecommendPageDTO.java +++ b/src/main/java/com/mixi/model/dto/QueryRecommendPageDTO.java @@ -15,4 +15,6 @@ public class QueryRecommendPageDTO extends PageQueryBaseVo implements Serializab @ApiModelProperty("商品一级标签类型 top dress 等等") private String labelItem; + private String memberCode; + } diff --git a/src/main/java/com/mixi/model/dto/SearchProductPageDTO.java b/src/main/java/com/mixi/model/dto/SearchProductPageDTO.java index aa5ded8..fbbafa3 100644 --- a/src/main/java/com/mixi/model/dto/SearchProductPageDTO.java +++ b/src/main/java/com/mixi/model/dto/SearchProductPageDTO.java @@ -24,4 +24,6 @@ public class SearchProductPageDTO extends PageQueryBaseVo implements Serializabl @ApiModelProperty("商品二级标签类型及对应标签map") private Map> labelTypeMap; + private String memberCode; + } diff --git a/src/main/java/com/mixi/service/MiTuExportService.java b/src/main/java/com/mixi/service/MiTuExportService.java index c48e043..d33f538 100644 --- a/src/main/java/com/mixi/service/MiTuExportService.java +++ b/src/main/java/com/mixi/service/MiTuExportService.java @@ -3,6 +3,7 @@ package com.mixi.service; import com.mixi.common.response.PageBaseResponse; import com.mixi.common.response.Response; import com.mixi.mapper.entity.MiTuExport; +import com.mixi.mapper.entity.MiTuMember; import com.mixi.model.dto.QueryMiTuExportPageDTO; import com.mixi.model.vo.MiTuExportVO; import io.minio.errors.MinioException; @@ -12,6 +13,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.List; /** * 店铺服务实现类 @@ -25,4 +27,8 @@ public interface MiTuExportService { PageBaseResponse queryMiTuExportPage(QueryMiTuExportPageDTO query); void exportMiTuReport(Long id, HttpServletResponse response) throws IOException, MinioException; + + List queryMiTuMemberList(String phone); + + List getProductIdsByMiTuMemberCode(String memberCode); } diff --git a/src/main/java/com/mixi/service/PythonService.java b/src/main/java/com/mixi/service/PythonService.java index 2b9eca8..73f059c 100644 --- a/src/main/java/com/mixi/service/PythonService.java +++ b/src/main/java/com/mixi/service/PythonService.java @@ -5,11 +5,13 @@ import cn.hutool.core.exceptions.ExceptionUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mixi.common.config.FileProperties; import com.mixi.common.config.exception.BusinessException; import com.mixi.common.utils.AccessLimitUtils; +import com.mixi.mapper.TProductMapper; import com.mixi.mapper.entity.TProduct; import com.mixi.model.dto.GenerateCollocationDataBaseDTO; import com.mixi.model.dto.GenerateCollocationQueryDTO; @@ -497,4 +499,71 @@ public class PythonService { } + public List similarityMatch(String pictureUrl) { + //限流校验 + AccessLimitUtils.validate("similarityMatch", 20); + OkHttpClient client = new OkHttpClient().newBuilder() + .connectTimeout(30, TimeUnit.SECONDS) + .pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒) + .readTimeout(300, TimeUnit.SECONDS)//读取超时(单位:秒) + .writeTimeout(300, TimeUnit.SECONDS)//写入超时(单位:秒) + .build(); + MediaType mediaType = MediaType.parse("application/json"); + Map content = Maps.newHashMap(); + content.put("image_path", pictureUrl); + content.put("result_number", 5); + RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content)); + Request request = new Request.Builder() + .url(accessPythonIp + ":9993/api/similar_matchsimilar_match") + .method("POST", body) + .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==") + .addHeader("Content-Type", "application/json") + .build(); + Response response = null; + String bodyStr = null; + try { + log.info("获取python获取相似商品请求入参content###{}", JSON.toJSONString(content)); + response = client.newCall(request).execute(); + bodyStr = response.body().string(); + } catch (IOException ioException) { + log.error("PythonService##similarityMatch异常###{}", ExceptionUtil.getThrowableList(ioException)); + } + log.info("识获取python获取相似商品请求结果###{}", bodyStr.trim()); + //去除限流 + AccessLimitUtils.validateOut("similarityMatch"); + if (Objects.isNull(response)) { + log.error("PythonService##similarityMatch异常###{}", "response or body is empty!"); + throw new BusinessException("SimilarityMatch exception."); + } + JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(response)); + Boolean result = jsonObject.getBoolean("successful"); + if (result) { + JSONObject parseObject = JSON.parseObject(bodyStr.trim()); + return similarityMatchToList(parseObject); + } + log.info("获取python获取相似商品请求异常###{}", jsonObject); + //生成失败 + throw new BusinessException("SimilarityMatch exception."); + } + + @Resource + private TProductMapper tProductMapper; + + private List similarityMatchToList(JSONObject parseObject) { + List productList = new ArrayList<>(); + JSONArray data = parseObject.getJSONArray("data"); + for (int i = 0; i < data.size(); i++) { + JSONObject jsonObject = data.getJSONObject(i); + String imagePath = jsonObject.getString("image_path"); + String itemName = jsonObject.getString("item_name"); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(TProduct::getPictureUrl, imagePath); + qw.lambda().eq(TProduct::getPictureName, itemName); + List productList1 = tProductMapper.selectList(qw); + if (CollectionUtil.isNotEmpty(productList1)) { + productList.add(productList1.get(0)); + } + } + return productList; + } } diff --git a/src/main/java/com/mixi/service/TAppProductService.java b/src/main/java/com/mixi/service/TAppProductService.java index 41894a4..b46ef5f 100644 --- a/src/main/java/com/mixi/service/TAppProductService.java +++ b/src/main/java/com/mixi/service/TAppProductService.java @@ -9,12 +9,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mixi.common.config.FileProperties; +import com.mixi.common.config.exception.BusinessException; import com.mixi.common.context.UserContext; import com.mixi.common.response.PageBaseResponse; -import com.mixi.common.utils.CopyUtil; -import com.mixi.common.utils.DateUtil; -import com.mixi.common.utils.FileUtil; -import com.mixi.common.utils.LocalCacheUtils; +import com.mixi.common.utils.*; +import com.mixi.mapper.MiTuMemberMapper; +import com.mixi.mapper.MiTuProductSellNumMapper; import com.mixi.mapper.TProductMapper; import com.mixi.mapper.entity.*; import com.mixi.model.dto.*; @@ -32,6 +32,8 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.File; import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; @@ -71,6 +73,16 @@ public class TAppProductService extends ServiceImpl { private FileProperties fileProperties; @Resource private PanToneService panToneService; + @Resource + private MinioUtil minioUtil; + + @Resource + private MiTuMemberMapper miTuMemberMapper; + + @Resource + private MiTuExportService miTuExportService; + @Resource + private MiTuProductSellNumMapper miTuProductSellNumMapper; /** @@ -89,7 +101,7 @@ public class TAppProductService extends ServiceImpl { } queryWrapper.in("id", productIds); } - if (!org.springframework.util.StringUtils.isEmpty(query.getLabelItem())) { + if (!StringUtils.isEmpty(query.getLabelItem())) { List productIds = tProductAttributeService.findByItemAndType(query.getLabelItem(),null); if (CollectionUtils.isEmpty(productIds)) { return PageBaseResponse.success(new Page<>()); @@ -136,6 +148,7 @@ public class TAppProductService extends ServiceImpl { d.setName(labelMap.get(o.getLabelId()).getName()); d.setType(labelMap.get(o.getLabelId()).getType()); })); + result.setPictureUrl(minioUtil.getPresignedUrl(result.getPictureUrl(), 24 * 60)); return result; }); return PageBaseResponse.success(convert); @@ -148,22 +161,40 @@ public class TAppProductService extends ServiceImpl { * @returnN */ public PageBaseResponse queryRecommendPage(QueryRecommendPageDTO query) { + if (StringUtils.isEmpty(query.getMemberCode())) { + query.setMemberCode("100002"); + } // 分页数据 QueryWrapper queryWrapper = new QueryWrapper<>(); - if (!org.springframework.util.StringUtils.isEmpty(query.getLabelItem())) { - List productIds = tProductAttributeService.findByItemAndType(query.getLabelItem(),null); + List productIds = new ArrayList<>(); + if (!StringUtils.isEmpty(query.getMemberCode())) { + List productIdsByMemberCode = miTuExportService.getProductIdsByMiTuMemberCode(query.getMemberCode()); + productIds.addAll(productIdsByMemberCode); if (CollectionUtils.isEmpty(productIds)) { return PageBaseResponse.success(new Page<>()); } - queryWrapper.in("id", productIds); } - //个性化商品筛选 - List customBuriedPointRecords = tCustomBuriedPointRecordService.getRecommendProduct("BROWSE"); - if(CollectionUtils.isEmpty(customBuriedPointRecords)){ + if (!StringUtils.isEmpty(query.getLabelItem())) { + List byItemAndType = tProductAttributeService.findByItemAndType(query.getLabelItem(), null); + if (CollectionUtils.isEmpty(byItemAndType)) { + return PageBaseResponse.success(new Page<>()); + } + if (!StringUtils.isEmpty(query.getMemberCode())) { + productIds.retainAll(byItemAndType); + } + productIds.addAll(byItemAndType); + } + if (CollectionUtils.isEmpty(productIds)) { return PageBaseResponse.success(new Page<>()); } - List selectProductIds = customBuriedPointRecords.stream().map(v->v.getProductId().toString()).collect(Collectors.toList()); - queryWrapper.in("id", selectProductIds); + queryWrapper.in("id", productIds); + //个性化商品筛选 + List customBuriedPointRecords = tCustomBuriedPointRecordService.getRecommendProduct("BROWSE"); +// if(CollectionUtils.isEmpty(customBuriedPointRecords)){ +// return PageBaseResponse.success(new Page<>()); +// } +// List selectProductIds = customBuriedPointRecords.stream().map(v->v.getProductId().toString()).collect(Collectors.toList()); +// queryWrapper.in("id", selectProductIds); //上架 queryWrapper.eq("on_sale_state", 1); @@ -175,8 +206,8 @@ public class TAppProductService extends ServiceImpl { if (CollectionUtils.isEmpty(page.getRecords())) { return PageBaseResponse.success(new Page<>()); } - List productIds = page.getRecords().stream().map(TProduct::getId).collect(Collectors.toList()); - Map> productToLabelMap = productLabelService.findByProductIds(productIds); + List collect = page.getRecords().stream().map(TProduct::getId).collect(Collectors.toList()); + Map> productToLabelMap = productLabelService.findByProductIds(collect); List labelIds = productToLabelMap.values() .stream() .map(list->list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList())) @@ -188,6 +219,7 @@ public class TAppProductService extends ServiceImpl { { 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) ->{ d.setId(o.getLabelId().toString()); d.setName(labelMap.get(o.getLabelId()).getName()); @@ -203,19 +235,67 @@ public class TAppProductService extends ServiceImpl { * @param query * @returnN */ +// public List queryProductSaleRank(QueryProductRankDTO query) { +// //商品排行 +// List appProductSaleRankVOS = tCustomBuriedPointRecordService.queryProductSaleRank(query); +// if(CollectionUtils.isEmpty(appProductSaleRankVOS)){ +// return Lists.newArrayList(); +// } +// List selectProductIds = appProductSaleRankVOS.stream().map(v->Long.valueOf(v.getId())).collect(Collectors.toList()); +// +// List tProducts = tProductMapper.selectBatchIds(selectProductIds); +// if(CollectionUtil.isEmpty(tProducts)){ +// //埋点的商品可能被删除 +// return Lists.newArrayList(); +// } +// Map productIdToUrlMap = +// CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl)); +// +// Map productIdToObject = +// CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,Function.identity())); +// +// Map> productToLabelMap = productLabelService.findByProductIds(selectProductIds); +// List labelIds = productToLabelMap.values() +// .stream() +// .map(list->list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList())) +// .flatMap(List::stream).collect(Collectors.toList()); +// //标签map +// Map labelMap = labelService.queryMapByIds(labelIds); +// //过滤埋点的商品可能被删除 +// appProductSaleRankVOS = appProductSaleRankVOS.stream().filter(rank->productIdToUrlMap.containsKey(Long.valueOf(rank.getId()))).collect(Collectors.toList()); +// appProductSaleRankVOS.forEach(rank ->{ +// rank.setPictureUrl(productIdToUrlMap.get(Long.valueOf(rank.getId()))); +// rank.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(Long.valueOf(rank.getId())),ProductLabelVO.class,(o,d) ->{ +// d.setId(o.getLabelId().toString()); +// d.setName(labelMap.get(o.getLabelId()).getName()); +// d.setType(labelMap.get(o.getLabelId()).getType()); +// })); +// TProduct product = productIdToObject.get(Long.valueOf(rank.getId())); +// if(Objects.nonNull(product)){ +// rank.setColor(product.getColor()); +// rank.setRgb(product.getRgb()); +// rank.setPrice(product.getPrice()); +// } +// }); +// return appProductSaleRankVOS; +// } public List queryProductSaleRank(QueryProductRankDTO query) { - //商品排行 - List appProductSaleRankVOS = tCustomBuriedPointRecordService.queryProductSaleRank(query); - if(CollectionUtils.isEmpty(appProductSaleRankVOS)){ - return Lists.newArrayList(); - } - List selectProductIds = appProductSaleRankVOS.stream().map(v->Long.valueOf(v.getId())).collect(Collectors.toList()); - - List tProducts = tProductMapper.selectBatchIds(selectProductIds); +// //商品排行 +// List appProductSaleRankVOS = tCustomBuriedPointRecordService.queryProductSaleRank(query); +// if(CollectionUtils.isEmpty(appProductSaleRankVOS)){ +// return Lists.newArrayList(); +// } +// List selectProductIds = appProductSaleRankVOS.stream().map(v->Long.valueOf(v.getId())).collect(Collectors.toList()); + Map productIdNumMap = getProductIdListByQueryType(query.getType()); + List collect = productIdNumMap.keySet().stream().collect(Collectors.toList()); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().in(TProduct::getId, collect); + List tProducts = tProductMapper.selectList(qw); if(CollectionUtil.isEmpty(tProducts)){ //埋点的商品可能被删除 return Lists.newArrayList(); } + List selectProductIds = tProducts.stream().map(TProduct::getId).collect(Collectors.toList()); Map productIdToUrlMap = CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl)); @@ -230,63 +310,165 @@ public class TAppProductService extends ServiceImpl { //标签map Map labelMap = labelService.queryMapByIds(labelIds); //过滤埋点的商品可能被删除 - appProductSaleRankVOS = appProductSaleRankVOS.stream().filter(rank->productIdToUrlMap.containsKey(Long.valueOf(rank.getId()))).collect(Collectors.toList()); - appProductSaleRankVOS.forEach(rank ->{ - rank.setPictureUrl(productIdToUrlMap.get(Long.valueOf(rank.getId()))); - rank.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(Long.valueOf(rank.getId())),ProductLabelVO.class,(o,d) ->{ + List appProductSaleRankVOS = new ArrayList<>(); + for (TProduct tProduct : tProducts) { + AppProductSaleRankVO vo = CopyUtil.copyObject(tProduct, AppProductSaleRankVO.class); + vo.setId(String.valueOf(tProduct.getId())); + vo.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(Long.valueOf(tProduct.getId())),ProductLabelVO.class,(o,d) ->{ d.setId(o.getLabelId().toString()); d.setName(labelMap.get(o.getLabelId()).getName()); d.setType(labelMap.get(o.getLabelId()).getType()); })); - TProduct product = productIdToObject.get(Long.valueOf(rank.getId())); - if(Objects.nonNull(product)){ - rank.setColor(product.getColor()); - rank.setRgb(product.getRgb()); - rank.setPrice(product.getPrice()); - } - }); - return appProductSaleRankVOS; + vo.setPictureUrl(minioUtil.getPresignedUrl(vo.getPictureUrl(), 24 * 60)); + vo.setTotal(String.valueOf(productIdNumMap.get(tProduct.getId()))); + appProductSaleRankVOS.add(vo); + } + List sortedList = appProductSaleRankVOS.stream() + .sorted(Comparator.comparing(AppProductSaleRankVO::getTotal).reversed()) + .collect(Collectors.toList()); +// appProductSaleRankVOS = appProductSaleRankVOS.stream().filter(rank->productIdToUrlMap.containsKey(Long.valueOf(rank.getId()))).collect(Collectors.toList()); +// appProductSaleRankVOS.forEach(rank ->{ +// rank.setPictureUrl(productIdToUrlMap.get(Long.valueOf(rank.getId()))); +// rank.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(Long.valueOf(rank.getId())),ProductLabelVO.class,(o,d) ->{ +// d.setId(o.getLabelId().toString()); +// d.setName(labelMap.get(o.getLabelId()).getName()); +// d.setType(labelMap.get(o.getLabelId()).getType()); +// })); +// TProduct product = productIdToObject.get(Long.valueOf(rank.getId())); +// if(Objects.nonNull(product)){ +// rank.setColor(product.getColor()); +// rank.setRgb(product.getRgb()); +// rank.setPrice(product.getPrice()); +// } +// }); + return sortedList; } + + private Map getProductIdListByQueryType(Integer type) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + LocalDate today = LocalDate.now(); + String startDate = ""; + String endDate = ""; + endDate = today.format(formatter); + if (type == 1) { + startDate = today.minusDays(1).format(formatter); + }else if (type == 2){ + startDate = today.minusDays(7).format(formatter); + }else if (type == 3) { + startDate = today.minusDays(30).format(formatter); + }else { + throw new BusinessException("Unknown bestSell type."); + } + QueryWrapper qw = new QueryWrapper<>(); + qw.select("product_id", "sum(sell_num) as sell_num") + .ge("sell_date", LocalDate.parse(startDate)) + .lt("sell_date", LocalDate.parse(endDate)) + .groupBy("product_id") + .orderByDesc("sell_num") + .last("LIMIT 10"); + List miTuProductSellNums = miTuProductSellNumMapper.selectList(qw); + if (CollectionUtils.isEmpty(miTuProductSellNums)) { + return new HashMap<>(); + } + Map map = new HashMap<>(); + for (MiTuProductSellNum miTuProductSellNum : miTuProductSellNums) { + map.put(miTuProductSellNum.getProductId(), miTuProductSellNum.getSellNum()); + } + return map; + } + /** * 商品相似度搭配 * * @param query * @returnN */ +// public List productSimilarityMatch(ProductSimilaDTO query) { +// //获取该用户所有店铺下所有商品 +// //查询用户店铺 +// List storeVOS = storeService.queryUserStore(null,null); +// List productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList())); +// List dataBase = CollectionUtil.isEmpty(productIds)? Lists.newArrayList() : tProductMapper.selectBatchIds(productIds); +// if(CollectionUtils.isEmpty(dataBase) || dataBase.size() <= 5){ +// //商品数不够 不支持相似度搭配 +// return Lists.newArrayList(); +// } +// +// Map tProductIdToAttributeItemNewMap = CollectionUtil.isEmpty(dataBase) ? Maps.newHashMap() +// : tProductAttributeService.findByProductAttributesItem(dataBase.stream().map(TProduct::getId).collect(Collectors.toList())); +// +// Map dataBaseMap = dataBase.stream().collect(Collectors.toMap(p -> p.getId().toString(), +// p2 -> GenerateCollocationDataBaseDTO +// .builder() +// .category(tProductIdToAttributeItemNewMap.get(p2.getId())) +// .path(p2.getPictureUrl()).build(),(v1,v2)->v2)); +// //商品排行 +// Map> similarityRecognitionMap = pythonService.similarityRecognition( +// "hash_feature", +// Collections.singletonList(GenerateCollocationQueryDTO.builder() +// //写死,python只根据本地图片url来识别 +// .item_category("top") +// .path(query.getPictureUrl()) +// //商品id写死,python不需要 java只做映射用 +// .item_id("666666").build()),dataBaseMap,null); +// if(CollectionUtils.isEmpty(similarityRecognitionMap)){ +// return Lists.newArrayList(); +// } +// List selectProductIds = similarityRecognitionMap.get("666666").stream().map(v->Long.valueOf(v)).collect(Collectors.toList()); +// +// List tProducts = tProductMapper.selectBatchIds(selectProductIds); +// Map productIdToUrlMap = +// CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl)); +// +// Map> productToLabelMap = productLabelService.findByProductIds(selectProductIds); +// List labelIds = productToLabelMap.values() +// .stream() +// .map(list->list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList())) +// .flatMap(List::stream).collect(Collectors.toList()); +// //标签map +// Map labelMap = labelService.queryMapByIds(labelIds); +// return CopyUtil.copyList(tProducts,AppNewProductVO.class,(oo,dd)->{ +// dd.setId(oo.getId().toString()); +// dd.setPictureUrl(productIdToUrlMap.get(oo.getId())); +// dd.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(oo.getId()),ProductLabelVO.class,(o,d) ->{ +// d.setId(o.getLabelId().toString()); +// d.setName(labelMap.get(o.getLabelId()).getName()); +// d.setType(labelMap.get(o.getLabelId()).getType()); +// })); +// }); +// } public List productSimilarityMatch(ProductSimilaDTO query) { - //获取该用户所有店铺下所有商品 - //查询用户店铺 - List storeVOS = storeService.queryUserStore(null,null); - List productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList())); - List dataBase = CollectionUtil.isEmpty(productIds)? Lists.newArrayList() : tProductMapper.selectBatchIds(productIds); - if(CollectionUtils.isEmpty(dataBase) || dataBase.size() <= 5){ - //商品数不够 不支持相似度搭配 - return Lists.newArrayList(); + String url = query.getPictureUrl(); + int thirdSlashIndex = -1; + int firstQuestionMarkIndex = -1; + + // 找到第三个 "/" 和第一个 "?" 的索引 + for (int i = 0, count = 0; i < url.length(); i++) { + char ch = url.charAt(i); + if (ch == '/') { + count++; + if (count == 3) { + thirdSlashIndex = i; + } + } else if (ch == '?' && thirdSlashIndex != -1) { + firstQuestionMarkIndex = i; + break; + } } - Map tProductIdToAttributeItemNewMap = CollectionUtil.isEmpty(dataBase) ? Maps.newHashMap() - : tProductAttributeService.findByProductAttributesItem(dataBase.stream().map(TProduct::getId).collect(Collectors.toList())); - - Map dataBaseMap = dataBase.stream().collect(Collectors.toMap(p -> p.getId().toString(), - p2 -> GenerateCollocationDataBaseDTO - .builder() - .category(tProductIdToAttributeItemNewMap.get(p2.getId())) - .path(p2.getPictureUrl()).build(),(v1,v2)->v2)); + // 如果找到了第三个 "/" 和第一个 "?",则截取对应的子字符串 + String result = ""; + if (thirdSlashIndex != -1 && firstQuestionMarkIndex != -1) { + result = url.substring(thirdSlashIndex + 1, firstQuestionMarkIndex); + } else { + throw new BusinessException("substring exception."); + } //商品排行 - Map> similarityRecognitionMap = pythonService.similarityRecognition( - "hash_feature", - Collections.singletonList(GenerateCollocationQueryDTO.builder() - //写死,python只根据本地图片url来识别 - .item_category("top") - .path(query.getPictureUrl()) - //商品id写死,python不需要 java只做映射用 - .item_id("666666").build()),dataBaseMap,null); - if(CollectionUtils.isEmpty(similarityRecognitionMap)){ + List tProducts = pythonService.similarityMatch(result); + if(CollectionUtils.isEmpty(tProducts)){ return Lists.newArrayList(); } - List selectProductIds = similarityRecognitionMap.get("666666").stream().map(v->Long.valueOf(v)).collect(Collectors.toList()); - - List tProducts = tProductMapper.selectBatchIds(selectProductIds); + List selectProductIds = tProducts.stream().map(TProduct::getId).collect(Collectors.toList()); Map productIdToUrlMap = CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl)); @@ -300,6 +482,7 @@ public class TAppProductService extends ServiceImpl { return CopyUtil.copyList(tProducts,AppNewProductVO.class,(oo,dd)->{ dd.setId(oo.getId().toString()); dd.setPictureUrl(productIdToUrlMap.get(oo.getId())); + dd.setPictureUrl(minioUtil.getPresignedUrl(dd.getPictureUrl(), 24 * 60)); dd.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(oo.getId()),ProductLabelVO.class,(o,d) ->{ d.setId(o.getLabelId().toString()); d.setName(labelMap.get(o.getLabelId()).getName()); @@ -315,32 +498,37 @@ public class TAppProductService extends ServiceImpl { * @returnN */ public List productColorMatch(ProductColorDTO query) { - log.info("app端商品颜色搭配入参###{}",JSON.toJSONString(query)); - //获取该用户所有店铺下所有商品 - //查询用户店铺 - List storeVOS = storeService.queryUserStore(null,null); - List productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList())); - List dataBase = CollectionUtil.isEmpty(productIds)? Lists.newArrayList() : tProductMapper.selectBatchIds(productIds); - if(CollectionUtils.isEmpty(dataBase) || dataBase.size() <= 5){ - //商品数不够 不支持相似度搭配 - return Lists.newArrayList(); +// log.info("app端商品颜色搭配入参###{}",JSON.toJSONString(query)); +// //获取该用户所有店铺下所有商品 +// //查询用户店铺 +// List storeVOS = storeService.queryUserStore(null,null); +// List productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList())); +// List dataBase = CollectionUtil.isEmpty(productIds)? Lists.newArrayList() : tProductMapper.selectBatchIds(productIds); +// if(CollectionUtils.isEmpty(dataBase) || dataBase.size() <= 5){ +// //商品数不够 不支持相似度搭配 +// return Lists.newArrayList(); +// } +// AppProductColorExtractVO rgbObject= query.getProductRgbList().get(0); +// List hsv = pythonService.rgb2hsv(Integer.valueOf(rgbObject.getR()),Integer.valueOf(rgbObject.getG()),Integer.valueOf(rgbObject.getB())); +// if(CollectionUtils.isEmpty(hsv) ){ +// //hsv查询不到 +// return Lists.newArrayList(); +// } +// PantoneVO pantoneVO = panToneService.getByHSV(hsv.get(0),hsv.get(1),hsv.get(2)); +// if(Objects.isNull(pantoneVO)){ +// return Lists.newArrayList(); +// } +// dataBase = dataBase.stream().filter(data -> !StringUtils.isEmpty(data.getColor()) && data.getColor().equals(pantoneVO.getTcx())).collect(Collectors.toList()); +// if(CollectionUtils.isEmpty(dataBase)){ +// //匹配不到 +// return Lists.newArrayList(); +// } + if (StringUtils.isEmpty(query.getProductColor())) { + query.setProductColor("0BLK"); } - AppProductColorExtractVO rgbObject= query.getProductRgbList().get(0); - List hsv = pythonService.rgb2hsv(Integer.valueOf(rgbObject.getR()),Integer.valueOf(rgbObject.getG()),Integer.valueOf(rgbObject.getB())); - if(CollectionUtils.isEmpty(hsv) ){ - //hsv查询不到 - return Lists.newArrayList(); - } - PantoneVO pantoneVO = panToneService.getByHSV(hsv.get(0),hsv.get(1),hsv.get(2)); - if(Objects.isNull(pantoneVO)){ - return Lists.newArrayList(); - } - dataBase = dataBase.stream().filter(data -> !StringUtils.isEmpty(data.getColor()) && data.getColor().equals(pantoneVO.getTcx())).collect(Collectors.toList()); - if(CollectionUtils.isEmpty(dataBase)){ - //匹配不到 - return Lists.newArrayList(); - } - + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(TProduct::getColor, query.getProductColor()); + List dataBase = tProductMapper.selectList(qw); Map productIdToUrlMap = CollectionUtil.emptyIfNull(dataBase).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl)); @@ -354,6 +542,7 @@ public class TAppProductService extends ServiceImpl { return CopyUtil.copyList(dataBase,AppNewProductVO.class,(oo,dd)->{ dd.setId(oo.getId().toString()); dd.setPictureUrl(productIdToUrlMap.get(oo.getId())); + dd.setPictureUrl(minioUtil.getPresignedUrl(dd.getPictureUrl(), 24 * 60)); dd.setProductLabelInfo(CopyUtil.copyList(productToLabelMap.get(oo.getId()),ProductLabelVO.class,(o,d) ->{ d.setId(o.getLabelId().toString()); d.setName(labelMap.get(o.getLabelId()).getName()); @@ -379,6 +568,13 @@ public class TAppProductService extends ServiceImpl { * @returnN */ public PageBaseResponse searchProductPage(SearchProductPageDTO query) { +// // 根据顾客获取对应商品推荐 +// if (!StringUtils.isEmpty(query.getMemberCode())) { +// QueryWrapper qw = new QueryWrapper<>(); +// qw.lambda().eq(MiTuMember::getMbrCode, query.getMemberCode()); +// miTuMemberMapper.selectList(qw).get(0); +// } + // 分页数据 QueryWrapper queryWrapper = new QueryWrapper<>(); if (!StringUtils.isEmpty(query.getStoreId())) { @@ -426,6 +622,7 @@ public class TAppProductService extends ServiceImpl { { 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) ->{ d.setId(o.getLabelId().toString()); d.setName(labelMap.get(o.getLabelId()).getName()); diff --git a/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java b/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java index 83fb196..0282567 100644 --- a/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java +++ b/src/main/java/com/mixi/service/impl/MiTuExportServiceImpl.java @@ -9,16 +9,24 @@ import com.mixi.common.response.Response; import com.mixi.common.utils.CopyUtil; import com.mixi.common.utils.MinioUtil; import com.mixi.mapper.MiTuExportMapper; +import com.mixi.mapper.MiTuMemberMapper; +import com.mixi.mapper.MiTuProductMapper; +import com.mixi.mapper.TProductMapper; import com.mixi.mapper.entity.MiTuExport; +import com.mixi.mapper.entity.MiTuMember; +import com.mixi.mapper.entity.MiTuProduct; +import com.mixi.mapper.entity.TProduct; import com.mixi.model.dto.QueryMiTuExportPageDTO; import com.mixi.model.vo.MiTuExportVO; import com.mixi.service.MiTuExportService; +import com.mixi.service.TProductService; import io.minio.errors.MinioException; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -28,7 +36,11 @@ import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import java.util.function.Function; +import java.util.stream.Collectors; //import com.ai.da.common.utils.SendSmsUtil; @@ -48,6 +60,15 @@ public class MiTuExportServiceImpl implements MiTuExportService { @Resource private MinioUtil minioUtil; + @Resource + private MiTuMemberMapper miTuMemberMapper; + + @Resource + private MiTuProductMapper miTuProductMapper; + + @Resource + private TProductMapper productMapper; + @Override public PageBaseResponse queryMiTuExportPage(QueryMiTuExportPageDTO query) { // 分页数据 @@ -117,4 +138,68 @@ public class MiTuExportServiceImpl implements MiTuExportService { throw new RuntimeException("Failed to export report", e); } } + + @Override + public List queryMiTuMemberList(String phone) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().like(MiTuMember::getMbrMobile, phone); + List miTuMembers = miTuMemberMapper.selectList(qw); + if (CollectionUtils.isEmpty(miTuMembers)) { + return new ArrayList<>(); + } + return miTuMembers; + } + + @Override + public List getProductIdsByMiTuMemberCode(String memberCode) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(MiTuMember::getMbrCode, memberCode); + List miTuMembers = miTuMemberMapper.selectList(qw); + if (CollectionUtils.isEmpty(miTuMembers)) { + return new ArrayList<>(); + } + String memberType = miTuMembers.get(0).getMemberType(); + switch (memberType) { + case "Type D" : { + // 根据牌子、款式、颜色推荐 + return new ArrayList<>(); + } + case "Type i" : { + QueryWrapper miTuProductQueryWrapper = new QueryWrapper<>(); + miTuProductQueryWrapper.lambda().eq(MiTuProduct::getYear, "TE"); + miTuProductQueryWrapper.lambda().eq(MiTuProduct::getSeason, "A"); + List miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper); + if (CollectionUtils.isEmpty(miTuProductList)) { + return new ArrayList<>(); + } + Set collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(collect)) { + return new ArrayList<>(); + } + return new ArrayList<>(collect); + } + case "Type C" : { + + QueryWrapper miTuProductQueryWrapper = new QueryWrapper<>(); + miTuProductQueryWrapper.lambda().eq(MiTuProduct::getSubGroup, "TWIN SET"); + List miTuProductList = miTuProductMapper.selectList(miTuProductQueryWrapper); + if (CollectionUtils.isEmpty(miTuProductList)) { + return new ArrayList<>(); + } + Set 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 + return new ArrayList<>(); + } + default : + throw new BusinessException("Unknown memberType."); + } + +// return null; + } }