TASK:mixi;

This commit is contained in:
shahaibo
2024-04-25 02:57:05 +08:00
parent d00810baf1
commit a7821a634f
18 changed files with 1099 additions and 103 deletions

View File

@@ -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<TProduct> bestSellIsNotNull = new QueryWrapper<>();
// bestSellIsNotNull.lambda().isNotNull(TProduct::getBestSell);
List<TProduct> 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<String, List<String>> itemNameMap = getBestSellItemNameList();
// for (String s : itemNameMap.keySet()) {
// if (s.equals("yesterdayItemNameList")) {
// QueryWrapper<MiTuProduct> qw = new QueryWrapper<>();
// qw.lambda().in(MiTuProduct::getItemName, itemNameMap.get(s));
// List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(qw);
// if (!CollectionUtils.isEmpty(miTuProductList)) {
// Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
// if (!CollectionUtils.isEmpty(collect)) {
// QueryWrapper<TProduct> qwBestSell = new QueryWrapper<>();
// qwBestSell.lambda().in(TProduct::getId, new ArrayList<>(collect));
// List<TProduct> productList = productMapper.selectList(qwBestSell);
// if (!CollectionUtils.isEmpty(productList)) {
// for (TProduct tProduct : productList) {
// tProduct.setBestSell("1");
// productMapper.updateById(tProduct);
// }
// }
// }
// }
// }
// if (s.equals("lastWeekItemNameList")) {
// QueryWrapper<MiTuProduct> qw = new QueryWrapper<>();
// qw.lambda().in(MiTuProduct::getItemName, itemNameMap.get(s));
// List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(qw);
// if (!CollectionUtils.isEmpty(miTuProductList)) {
// Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
// if (!CollectionUtils.isEmpty(collect)) {
// QueryWrapper<TProduct> qwBestSell = new QueryWrapper<>();
// qwBestSell.lambda().in(TProduct::getId, new ArrayList<>(collect));
// List<TProduct> 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<MiTuProduct> qw = new QueryWrapper<>();
// qw.lambda().in(MiTuProduct::getItemName, itemNameMap.get(s));
// List<MiTuProduct> miTuProductList = miTuProductMapper.selectList(qw);
// if (!CollectionUtils.isEmpty(miTuProductList)) {
// Set<Long> collect = miTuProductList.stream().map(MiTuProduct::getProductId).collect(Collectors.toSet());
// if (!CollectionUtils.isEmpty(collect)) {
// QueryWrapper<TProduct> qwBestSell = new QueryWrapper<>();
// qwBestSell.lambda().in(TProduct::getId, new ArrayList<>(collect));
// List<TProduct> 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<TProduct> 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<String, List<String>> getBestSellItemNameList() {
Map<String, List<String>> 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<String> 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<String> 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<String> 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<String> memberCodeList = getMemberCode();
// 遍历每个顾客的类型
List<MiTuMember> miTuMemberList = getMemberType(memberCodeList);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("接口执行完成!");
}
}
@Resource
private MiTuMemberMapper miTuMemberMapper;
private List<MiTuMember> getMemberType(List<String> memberCodeList) {
List<MiTuMember> 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<Transaction> 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<Transaction> transactionList) {
int discountNum = 0;
int currentSeasonNum = 0;
int leadingNum = 0;
Map<String, Integer> 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<String, Integer> 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<String> getMemberCode() {
List<String> 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;
}
}

View File

@@ -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;
}

View File

@@ -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<PageBaseResponse<AppNewProductVO>> 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<List<MiTuMember>> queryMiTuMemberList(@Valid @RequestBody QueryProductListDTO query) {
return Response.success(miTuExportService.queryMiTuMemberList(query.getPhone()));
}
}

View File

@@ -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<List<MiTuMember>> getProductListByMemberCode(@RequestParam("phone") String phone) {
return Response.success(miTuExportService.queryMiTuMemberList(phone));
}
}

View File

@@ -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<MiTuMember> {
}

View File

@@ -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<MiTuProductSellNum> {
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -80,5 +80,7 @@ public class TProduct implements Serializable {
@ApiModelProperty("更新时间")
private Date updateDate;
private String bestSell;
}

View File

@@ -20,4 +20,6 @@ public class ProductColorDTO implements Serializable {
@NotEmpty(message = "productRgbList cannot be empty!")
private List<AppProductColorExtractVO> productRgbList;
private String productColor;
}

View File

@@ -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;
}

View File

@@ -23,4 +23,6 @@ public class QueryProductRankDTO implements Serializable {
@ApiModelProperty("销量排行结束时间")
@NotNull(message = "createDateEnd cannot be empty!")
private Long createDateEnd;
private Integer type;
}

View File

@@ -15,4 +15,6 @@ public class QueryRecommendPageDTO extends PageQueryBaseVo implements Serializab
@ApiModelProperty("商品一级标签类型 top dress 等等")
private String labelItem;
private String memberCode;
}

View File

@@ -24,4 +24,6 @@ public class SearchProductPageDTO extends PageQueryBaseVo implements Serializabl
@ApiModelProperty("商品二级标签类型及对应标签map")
private Map<String, List<String>> labelTypeMap;
private String memberCode;
}

View File

@@ -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<MiTuExportVO> queryMiTuExportPage(QueryMiTuExportPageDTO query);
void exportMiTuReport(Long id, HttpServletResponse response) throws IOException, MinioException;
List<MiTuMember> queryMiTuMemberList(String phone);
List<Long> getProductIdsByMiTuMemberCode(String memberCode);
}

View File

@@ -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<TProduct> 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<String, Object> 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<TProduct> similarityMatchToList(JSONObject parseObject) {
List<TProduct> 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<TProduct> qw = new QueryWrapper<>();
qw.lambda().eq(TProduct::getPictureUrl, imagePath);
qw.lambda().eq(TProduct::getPictureName, itemName);
List<TProduct> productList1 = tProductMapper.selectList(qw);
if (CollectionUtil.isNotEmpty(productList1)) {
productList.add(productList1.get(0));
}
}
return productList;
}
}

View File

@@ -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<TProductMapper, TProduct> {
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<TProductMapper, TProduct> {
}
queryWrapper.in("id", productIds);
}
if (!org.springframework.util.StringUtils.isEmpty(query.getLabelItem())) {
if (!StringUtils.isEmpty(query.getLabelItem())) {
List<Long> productIds = tProductAttributeService.findByItemAndType(query.getLabelItem(),null);
if (CollectionUtils.isEmpty(productIds)) {
return PageBaseResponse.success(new Page<>());
@@ -136,6 +148,7 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
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<TProductMapper, TProduct> {
* @returnN
*/
public PageBaseResponse<AppNewProductVO> queryRecommendPage(QueryRecommendPageDTO query) {
if (StringUtils.isEmpty(query.getMemberCode())) {
query.setMemberCode("100002");
}
// 分页数据
QueryWrapper<TProduct> queryWrapper = new QueryWrapper<>();
if (!org.springframework.util.StringUtils.isEmpty(query.getLabelItem())) {
List<Long> productIds = tProductAttributeService.findByItemAndType(query.getLabelItem(),null);
List<Long> productIds = new ArrayList<>();
if (!StringUtils.isEmpty(query.getMemberCode())) {
List<Long> productIdsByMemberCode = miTuExportService.getProductIdsByMiTuMemberCode(query.getMemberCode());
productIds.addAll(productIdsByMemberCode);
if (CollectionUtils.isEmpty(productIds)) {
return PageBaseResponse.success(new Page<>());
}
queryWrapper.in("id", productIds);
}
//个性化商品筛选
List<TCustomBuriedPointRecord> customBuriedPointRecords = tCustomBuriedPointRecordService.getRecommendProduct("BROWSE");
if(CollectionUtils.isEmpty(customBuriedPointRecords)){
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);
}
productIds.addAll(byItemAndType);
}
if (CollectionUtils.isEmpty(productIds)) {
return PageBaseResponse.success(new Page<>());
}
List<String> selectProductIds = customBuriedPointRecords.stream().map(v->v.getProductId().toString()).collect(Collectors.toList());
queryWrapper.in("id", selectProductIds);
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);
//上架
queryWrapper.eq("on_sale_state", 1);
@@ -175,8 +206,8 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
if (CollectionUtils.isEmpty(page.getRecords())) {
return PageBaseResponse.success(new Page<>());
}
List<Long> productIds = page.getRecords().stream().map(TProduct::getId).collect(Collectors.toList());
Map<Long,List<TProductLabel>> productToLabelMap = productLabelService.findByProductIds(productIds);
List<Long> collect = page.getRecords().stream().map(TProduct::getId).collect(Collectors.toList());
Map<Long,List<TProductLabel>> productToLabelMap = productLabelService.findByProductIds(collect);
List<Long> labelIds = productToLabelMap.values()
.stream()
.map(list->list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList()))
@@ -188,6 +219,7 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
{
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<TProductMapper, TProduct> {
* @param query
* @returnN
*/
// public List<AppProductSaleRankVO> queryProductSaleRank(QueryProductRankDTO query) {
// //商品排行
// List<AppProductSaleRankVO> appProductSaleRankVOS = tCustomBuriedPointRecordService.queryProductSaleRank(query);
// if(CollectionUtils.isEmpty(appProductSaleRankVOS)){
// return Lists.newArrayList();
// }
// List<Long> selectProductIds = appProductSaleRankVOS.stream().map(v->Long.valueOf(v.getId())).collect(Collectors.toList());
//
// List<TProduct> tProducts = tProductMapper.selectBatchIds(selectProductIds);
// if(CollectionUtil.isEmpty(tProducts)){
// //埋点的商品可能被删除
// return Lists.newArrayList();
// }
// Map<Long,String> productIdToUrlMap =
// CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl));
//
// Map<Long,TProduct> productIdToObject =
// CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,Function.identity()));
//
// Map<Long,List<TProductLabel>> productToLabelMap = productLabelService.findByProductIds(selectProductIds);
// List<Long> labelIds = productToLabelMap.values()
// .stream()
// .map(list->list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList()))
// .flatMap(List::stream).collect(Collectors.toList());
// //标签map
// Map<Long,TLabel> 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<AppProductSaleRankVO> queryProductSaleRank(QueryProductRankDTO query) {
//商品排行
List<AppProductSaleRankVO> appProductSaleRankVOS = tCustomBuriedPointRecordService.queryProductSaleRank(query);
if(CollectionUtils.isEmpty(appProductSaleRankVOS)){
return Lists.newArrayList();
}
List<Long> selectProductIds = appProductSaleRankVOS.stream().map(v->Long.valueOf(v.getId())).collect(Collectors.toList());
List<TProduct> tProducts = tProductMapper.selectBatchIds(selectProductIds);
// //商品排行
// List<AppProductSaleRankVO> appProductSaleRankVOS = tCustomBuriedPointRecordService.queryProductSaleRank(query);
// if(CollectionUtils.isEmpty(appProductSaleRankVOS)){
// return Lists.newArrayList();
// }
// List<Long> selectProductIds = appProductSaleRankVOS.stream().map(v->Long.valueOf(v.getId())).collect(Collectors.toList());
Map<Long, Integer> productIdNumMap = getProductIdListByQueryType(query.getType());
List<Long> collect = productIdNumMap.keySet().stream().collect(Collectors.toList());
QueryWrapper<TProduct> qw = new QueryWrapper<>();
qw.lambda().in(TProduct::getId, collect);
List<TProduct> tProducts = tProductMapper.selectList(qw);
if(CollectionUtil.isEmpty(tProducts)){
//埋点的商品可能被删除
return Lists.newArrayList();
}
List<Long> selectProductIds = tProducts.stream().map(TProduct::getId).collect(Collectors.toList());
Map<Long,String> productIdToUrlMap =
CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl));
@@ -230,63 +310,165 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
//标签map
Map<Long,TLabel> 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<AppProductSaleRankVO> 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<AppProductSaleRankVO> 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<Long, Integer> 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<MiTuProductSellNum> 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<MiTuProductSellNum> miTuProductSellNums = miTuProductSellNumMapper.selectList(qw);
if (CollectionUtils.isEmpty(miTuProductSellNums)) {
return new HashMap<>();
}
Map<Long, Integer> map = new HashMap<>();
for (MiTuProductSellNum miTuProductSellNum : miTuProductSellNums) {
map.put(miTuProductSellNum.getProductId(), miTuProductSellNum.getSellNum());
}
return map;
}
/**
* 商品相似度搭配
*
* @param query
* @returnN
*/
// public List<AppNewProductVO> productSimilarityMatch(ProductSimilaDTO query) {
// //获取该用户所有店铺下所有商品
// //查询用户店铺
// List<StoreVO> storeVOS = storeService.queryUserStore(null,null);
// List<Long> productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList()));
// List<TProduct> dataBase = CollectionUtil.isEmpty(productIds)? Lists.newArrayList() : tProductMapper.selectBatchIds(productIds);
// if(CollectionUtils.isEmpty(dataBase) || dataBase.size() <= 5){
// //商品数不够 不支持相似度搭配
// return Lists.newArrayList();
// }
//
// Map<Long, String> tProductIdToAttributeItemNewMap = CollectionUtil.isEmpty(dataBase) ? Maps.newHashMap()
// : tProductAttributeService.findByProductAttributesItem(dataBase.stream().map(TProduct::getId).collect(Collectors.toList()));
//
// Map<String, GenerateCollocationDataBaseDTO> 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<String,List<String>> 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<Long> selectProductIds = similarityRecognitionMap.get("666666").stream().map(v->Long.valueOf(v)).collect(Collectors.toList());
//
// List<TProduct> tProducts = tProductMapper.selectBatchIds(selectProductIds);
// Map<Long,String> productIdToUrlMap =
// CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl));
//
// Map<Long,List<TProductLabel>> productToLabelMap = productLabelService.findByProductIds(selectProductIds);
// List<Long> labelIds = productToLabelMap.values()
// .stream()
// .map(list->list.stream().map(TProductLabel::getLabelId).collect(Collectors.toList()))
// .flatMap(List::stream).collect(Collectors.toList());
// //标签map
// Map<Long,TLabel> 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<AppNewProductVO> productSimilarityMatch(ProductSimilaDTO query) {
//获取该用户所有店铺下所有商品
//查询用户店铺
List<StoreVO> storeVOS = storeService.queryUserStore(null,null);
List<Long> productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList()));
List<TProduct> 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<Long, String> tProductIdToAttributeItemNewMap = CollectionUtil.isEmpty(dataBase) ? Maps.newHashMap()
: tProductAttributeService.findByProductAttributesItem(dataBase.stream().map(TProduct::getId).collect(Collectors.toList()));
Map<String, GenerateCollocationDataBaseDTO> 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<String,List<String>> 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<TProduct> tProducts = pythonService.similarityMatch(result);
if(CollectionUtils.isEmpty(tProducts)){
return Lists.newArrayList();
}
List<Long> selectProductIds = similarityRecognitionMap.get("666666").stream().map(v->Long.valueOf(v)).collect(Collectors.toList());
List<TProduct> tProducts = tProductMapper.selectBatchIds(selectProductIds);
List<Long> selectProductIds = tProducts.stream().map(TProduct::getId).collect(Collectors.toList());
Map<Long,String> productIdToUrlMap =
CollectionUtil.emptyIfNull(tProducts).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl));
@@ -300,6 +482,7 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
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<TProductMapper, TProduct> {
* @returnN
*/
public List<AppNewProductVO> productColorMatch(ProductColorDTO query) {
log.info("app端商品颜色搭配入参###{}",JSON.toJSONString(query));
//获取该用户所有店铺下所有商品
//查询用户店铺
List<StoreVO> storeVOS = storeService.queryUserStore(null,null);
List<Long> productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList()));
List<TProduct> 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<StoreVO> storeVOS = storeService.queryUserStore(null,null);
// List<Long> productIds = tProductStockService.findByStoreIds(storeVOS.stream().map(StoreVO::getId).collect(Collectors.toList()));
// List<TProduct> 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<Integer> 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<Integer> 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<TProduct> qw = new QueryWrapper<>();
qw.lambda().eq(TProduct::getColor, query.getProductColor());
List<TProduct> dataBase = tProductMapper.selectList(qw);
Map<Long,String> productIdToUrlMap =
CollectionUtil.emptyIfNull(dataBase).stream().collect(Collectors.toMap(TProduct::getId,TProduct::getPictureUrl));
@@ -354,6 +542,7 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
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<TProductMapper, TProduct> {
* @returnN
*/
public PageBaseResponse<AppNewProductVO> searchProductPage(SearchProductPageDTO query) {
// // 根据顾客获取对应商品推荐
// if (!StringUtils.isEmpty(query.getMemberCode())) {
// QueryWrapper<MiTuMember> qw = new QueryWrapper<>();
// qw.lambda().eq(MiTuMember::getMbrCode, query.getMemberCode());
// miTuMemberMapper.selectList(qw).get(0);
// }
// 分页数据
QueryWrapper<TProduct> queryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(query.getStoreId())) {
@@ -426,6 +622,7 @@ public class TAppProductService extends ServiceImpl<TProductMapper, TProduct> {
{
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());

View File

@@ -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<MiTuExportVO> queryMiTuExportPage(QueryMiTuExportPageDTO query) {
// 分页数据
@@ -117,4 +138,68 @@ public class MiTuExportServiceImpl implements MiTuExportService {
throw new RuntimeException("Failed to export report", e);
}
}
@Override
public List<MiTuMember> queryMiTuMemberList(String phone) {
QueryWrapper<MiTuMember> qw = new QueryWrapper<>();
qw.lambda().like(MiTuMember::getMbrMobile, phone);
List<MiTuMember> miTuMembers = miTuMemberMapper.selectList(qw);
if (CollectionUtils.isEmpty(miTuMembers)) {
return new ArrayList<>();
}
return miTuMembers;
}
@Override
public List<Long> getProductIdsByMiTuMemberCode(String memberCode) {
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 memberType = miTuMembers.get(0).getMemberType();
switch (memberType) {
case "Type D" : {
// 根据牌子、款式、颜色推荐
return new ArrayList<>();
}
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
return new ArrayList<>();
}
default :
throw new BusinessException("Unknown memberType.");
}
// return null;
}
}