diff --git a/hiver-admin/src/main/resources/application.yml b/hiver-admin/src/main/resources/application.yml index 8c812a20..479fb163 100644 --- a/hiver-admin/src/main/resources/application.yml +++ b/hiver-admin/src/main/resources/application.yml @@ -314,12 +314,11 @@ ignored: - /hiver/app/sale/savePresale - /hiver/app/productShare/getShareList - /hiver/app/productAttribute/selectAttributeAndValueByCategoryId + - /hiver/app/stock/productCount # 选择物流公司 - /hiver/app/logitics/chooseCompany # # 临时增加 - - /hiver/purchaseOcrPicture/batchSave - - /hiver/app/purchase/getPurchaseAllDataOfAi # 限流及黑名单不拦截的路径 limitUrls: diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html index c40f5870..1303a9fb 100644 --- a/hiver-admin/test-output/test-report.html +++ b/hiver-admin/test-output/test-report.html @@ -35,7 +35,7 @@ Hiver
  • -ʮ 18, 2023 11:51:47 + 29, 2024 14:41:12
  • @@ -84,7 +84,7 @@

    passTest

    -

    11:51:48 / 0.016 secs

    +

    14:41:13 / 0.019 secs

    @@ -92,9 +92,9 @@
    #test-id=1
    passTest
    -12.18.2023 11:51:48 -12.18.2023 11:51:48 -0.016 secs +05.29.2024 14:41:13 +05.29.2024 14:41:13 +0.019 secs
    @@ -104,7 +104,7 @@ Pass - 11:51:48 + 14:41:13 Test passed @@ -128,13 +128,13 @@

    Started

    -

    ʮ 18, 2023 11:51:47

    +

    29, 2024 14:41:12

    Ended

    -

    ʮ 18, 2023 11:51:48

    +

    29, 2024 14:41:13

    diff --git a/hiver-core/src/main/java/cc/hiver/core/common/utils/CommonUtil.java b/hiver-core/src/main/java/cc/hiver/core/common/utils/CommonUtil.java index a93ddbd7..78a0f9fe 100644 --- a/hiver-core/src/main/java/cc/hiver/core/common/utils/CommonUtil.java +++ b/hiver-core/src/main/java/cc/hiver/core/common/utils/CommonUtil.java @@ -1,20 +1,24 @@ package cc.hiver.core.common.utils; import cn.hutool.core.util.IdUtil; +import lombok.extern.slf4j.Slf4j; import java.security.SecureRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * 常用工具 * * @author Yazhi Li */ +@Slf4j public class CommonUtil { private CommonUtil() { throw new IllegalStateException("Utility class"); } - private static SecureRandom random = new SecureRandom(); + private static final SecureRandom random = new SecureRandom(); /** * 以UUID重命名 @@ -25,7 +29,7 @@ public class CommonUtil { public static String renamePic(String fileName) { String extName = ""; if (fileName.contains(".")) { - extName = fileName.substring(fileName.lastIndexOf(".")); + extName = fileName.substring(fileName.lastIndexOf('.')); } return IdUtil.simpleUUID() + extName; } @@ -34,9 +38,9 @@ public class CommonUtil { * 随机6位数生成 */ public static String getRandomNum() { - int num = random.nextInt(999999); + final int num = random.nextInt(999999); // 不足六位前面补0 - String str = String.format("%06d", num); + final String str = String.format("%06d", num); return str; } @@ -57,4 +61,18 @@ public class CommonUtil { } return flag; } + + public static String getProductSn(String productSn) { + log.info("需要提取的货号为:" + productSn); + // 更精确地假设货号在"商品名称:"之后,且紧跟着的是货号,直到遇到逗号 + final Pattern pattern = Pattern.compile("([\\w.-]+)"); + final Matcher matcher = pattern.matcher(productSn); + if (matcher.find()) { + productSn = matcher.group(); + log.info("提取后的货号为:" + productSn); + } else { + log.info(productSn + "未找到符合格式的货号"); + } + return productSn; + } } diff --git a/hiver-core/src/main/java/cc/hiver/core/serviceimpl/LogiticsCompanyServiceImpl.java b/hiver-core/src/main/java/cc/hiver/core/serviceimpl/LogiticsCompanyServiceImpl.java index 3bf7d890..8f4c633a 100644 --- a/hiver-core/src/main/java/cc/hiver/core/serviceimpl/LogiticsCompanyServiceImpl.java +++ b/hiver-core/src/main/java/cc/hiver/core/serviceimpl/LogiticsCompanyServiceImpl.java @@ -152,7 +152,7 @@ public class LogiticsCompanyServiceImpl implements LogiticsCompanyService { Predicate[] arr = new Predicate[list.size()]; cq.where(list.toArray(arr)); - cq.orderBy(cb.desc(root.get("isOnLine")),cb.asc(root.get("companyName"))); + cq.orderBy(cb.desc(root.get("isOnLine")),cb.desc(root.get("createTime")),cb.asc(root.get("companyName"))); return null; } }); diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java index a868eecc..57677274 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java @@ -25,8 +25,10 @@ import cc.hiver.mall.entity.ShopUser; import cc.hiver.mall.invitelog.constant.InviteLogConstant; import cc.hiver.mall.invitelog.entity.InviteLog; import cc.hiver.mall.invitelog.service.InviteLogService; +import cc.hiver.mall.pojo.vo.ShopVo; import cc.hiver.mall.service.ShopService; import cc.hiver.mall.service.ShopUserService; +import cc.hiver.mall.service.mybatis.ProductCategoryService; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.IdUtil; import io.swagger.annotations.Api; @@ -95,6 +97,8 @@ public class AuthController { @Autowired private ShopUserService shopUserService; + @Autowired + private ProductCategoryService productCategoryService; @PersistenceContext private EntityManager entityManager; @@ -328,10 +332,10 @@ public class AuthController { public Result register(@Valid RegisterShopVo registerShopVo) { // 新增用户表信息 User user = new User(); - if(StringUtils.isEmpty(registerShopVo.getMobile())){ + if (StringUtils.isEmpty(registerShopVo.getMobile())) { return ResultUtil.error("手机号不能为空!"); } - if(StringUtils.isEmpty(registerShopVo.getPassword())){ + if (StringUtils.isEmpty(registerShopVo.getPassword())) { return ResultUtil.error("密码不能为空!"); } // 一个用户可存在多个店铺 @@ -397,8 +401,8 @@ public class AuthController { shopUser.setType(UserConstant.SHOP_USER_ADMIN); shopUserService.save(shopUser); // 判断是否传递了邀请人及邀请店铺,设置了的话,新增邀请返佣信息 - if(StringUtils.isNotEmpty(registerShopVo.getInviteUserId()) && StringUtils.isNotEmpty(registerShopVo.getInviteShopId())){ - InviteLog inviteLog = new InviteLog(); + if (StringUtils.isNotEmpty(registerShopVo.getInviteUserId()) && StringUtils.isNotEmpty(registerShopVo.getInviteShopId())) { + final InviteLog inviteLog = new InviteLog(); inviteLog.setInviteUserId(registerShopVo.getInviteUserId()); inviteLog.setInviteShopId(registerShopVo.getInviteShopId()); inviteLog.setRegisterShopId(shop.getId()); @@ -407,6 +411,8 @@ public class AuthController { inviteLog.setIsOpen(InviteLogConstant.IS_OPEN[0]); inviteLogService.saveInviteLog(inviteLog); } + // 20240525 新增店铺,默认新增默认分类,颜色-均色;尺码-均码 + productCategoryService.addShopDefaultCategory(shop.getId()); return ResultUtil.data(user); } @@ -425,7 +431,11 @@ public class AuthController { // 获取店铺的商圈 final Shop shop = shopService.get(shopId); securityUtil.chooseShop(shopId, shop.getRegionId(), token); - return ResultUtil.success("成功选择商铺"); + final ShopVo shopVo = new ShopVo(); + shopVo.setShopIcon(shop.getShopIcon()); + shopVo.setShopAddress(shop.getShopAddress()); + shopVo.setRemark(shop.getRemark()); + return new ResultUtil().setData(shopVo); } /* @@ -453,20 +463,21 @@ public class AuthController { /** * 物流公司注销登录 - * @author 王富康 - * @date 2024/2/25 + * * @param companyId * @param companyName * @param response * @return Result + * @author 王富康 + * @date 2024/2/25 */ - @RequestMapping(value = "/loginOutOfCompany", method = RequestMethod.POST) + @RequestMapping(value = "/loginOutOfCompany", method = RequestMethod.POST) @ApiOperation("物流公司注销登录") - public Result loginOutOfCompany(String companyId,String companyName, HttpServletResponse response){ - if(StringUtils.isEmpty(companyId)){ + public Result loginOutOfCompany(String companyId, String companyName, HttpServletResponse response) { + if (StringUtils.isEmpty(companyId)) { return ResultUtil.error("配送公司id不能为空!"); } - if(StringUtils.isEmpty(companyName)){ + if (StringUtils.isEmpty(companyName)) { return ResultUtil.error("配送公司名称不能为空!"); } final String key = SecurityConstant.COMPANY_TOKEN + companyId + ':' + companyName; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/config/thread/AiPurchaseThread.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/config/thread/AiPurchaseThread.java index f41ba809..ff413929 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/config/thread/AiPurchaseThread.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/config/thread/AiPurchaseThread.java @@ -4,6 +4,7 @@ import cc.hiver.mall.common.constant.PurchaseConstant; import cc.hiver.mall.purchaseocr.entity.PurchaseOcrPicture; import cc.hiver.mall.purchaseocr.service.PurchaseOcrPictureService; import cc.hiver.mall.purchaseocr.vo.PurchaseOcrExample; +import cc.hiver.mall.service.mybatis.ProductCategoryService; import cc.hiver.mall.service.mybatis.ProductService; import cc.hiver.mall.service.mybatis.PurchaseDetailService; import cc.hiver.mall.service.mybatis.PurchaseService; @@ -31,11 +32,12 @@ public class AiPurchaseThread implements Runnable { private PurchaseDetailService purchaseDetailService; private PurchaseOcrPicture purchaseOcrPicture; private PurchaseOcrExample purchaseOcrExample; + private ProductCategoryService productCategoryService; public AiPurchaseThread() { } - public AiPurchaseThread(String purchaseId, PurchaseOcrPicture purchaseOcrPicture,PurchaseOcrExample purchaseOcrExample, PurchaseOcrPictureService purchaseOcrPictureService, ProductService productService, PurchaseDetailService purchaseDetailService, PurchaseService purchaseService) { + public AiPurchaseThread(String purchaseId, PurchaseOcrPicture purchaseOcrPicture,PurchaseOcrExample purchaseOcrExample, PurchaseOcrPictureService purchaseOcrPictureService, ProductService productService, PurchaseDetailService purchaseDetailService, PurchaseService purchaseService,ProductCategoryService productCategoryService) { this.purchaseId = purchaseId; this.purchaseOcrPicture = purchaseOcrPicture; this.purchaseOcrExample = purchaseOcrExample; @@ -43,6 +45,7 @@ public class AiPurchaseThread implements Runnable { this.productService = productService; this.purchaseDetailService = purchaseDetailService; this.purchaseService = purchaseService; + this.productCategoryService = productCategoryService; } public static class Result { @@ -69,7 +72,7 @@ public class AiPurchaseThread implements Runnable { log.info("当前线程名称:------------>>>>>" + Thread.currentThread().getName()); try { log.info("正在ocr识别:" + purchaseOcrPicture.getOcrPicture() + "
    线程池名称:" + Thread.currentThread().getName()); - jsonObject = AliOcrUtil.multiRoundConversationCall(purchaseOcrPicture,purchaseOcrExample, productService, purchaseDetailService); + jsonObject = AliOcrUtil.multiRoundConversationCall(purchaseOcrPicture,purchaseOcrExample, productService, purchaseDetailService, productCategoryService); // 得到处理结果之后,开始新增库存的详细信息 purchaseOcrPicture.setOcrMsg(jsonObject.getString("resultContent")); purchaseOcrPicture.setOcrStatus(PurchaseConstant.OCR_STATUS[1]); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/SaleController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/SaleController.java index 1a275f9c..086033bb 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/SaleController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/SaleController.java @@ -31,7 +31,6 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; @@ -493,8 +492,10 @@ public class SaleController { if (saleVO == null) { saleVO = new SaleVO(); } - startTime = saleVO.getStartTime() == null ? DateUtils.formatDate(new Date(), "yyyy-MM-dd") : saleVO.getStartTime(); - endTime = saleVO.getEndTime() == null ? DateUtils.formatDate(new Date(), "yyyy-MM-dd") : saleVO.getEndTime(); + final String dateText = DateUtil.COMMON.getDateText(new Date()); + startTime = saleVO.getStartTime() == null ? dateText : saleVO.getStartTime(); + final String tommorwText = DateUtil.getAfterDayTime(dateText, 1); + endTime = saleVO.getEndTime() == null ? tommorwText : saleVO.getEndTime(); saleAllVO = salesCalculateService.calculateService(startTime, endTime); // 获取本周营收统计 @@ -809,7 +810,7 @@ public class SaleController { orderService.update(orderXd); // 库存退回去 // 封装退货的信息 - List returnDetails = new ArrayList<>(); + final List returnDetails = new ArrayList<>(); final QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("product_id") .eq("sale_id", orderId) diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/ProductCategoryMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/ProductCategoryMapper.java index ea90d19a..c780b81b 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/ProductCategoryMapper.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/ProductCategoryMapper.java @@ -35,4 +35,5 @@ public interface ProductCategoryMapper extends BaseMapper { List selectByShopId(String shopId); List selectByCategoryIdList(@Param("categoryIdList") List categoryIdList); + } \ No newline at end of file diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/PurchaseDetail.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/PurchaseDetail.java index ad77f18a..235fa59e 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/PurchaseDetail.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/PurchaseDetail.java @@ -36,6 +36,11 @@ public class PurchaseDetail extends HiverBaseEntity { @ApiModelProperty(value = "商品分类") private String categoryId; + @Transient + @TableField(exist = false) + @ApiModelProperty(value = "分类名称") + private String categoryName; + @ApiModelProperty(value = "商品属性列表") private String attributeList; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Sale.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Sale.java index 064091df..920ac134 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Sale.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Sale.java @@ -77,6 +77,9 @@ public class Sale implements Serializable { @ApiModelProperty(value = "收款状态 0-未收款 1-已收款 2-部分收款") private String payStatus; + @ApiModelProperty(value = " 收款方式:0 现金 1微信 2支付宝 3银行卡转账 4收款码") + private String payType; + /** * 订单状态开单 * 0:待抢单 diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleCopyVO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleCopyVO.java index ae79c0cf..5408c65d 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleCopyVO.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleCopyVO.java @@ -1,12 +1,9 @@ package cc.hiver.mall.pojo.vo; -import cc.hiver.core.common.utils.SnowFlakeUtil; -import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import org.springframework.data.annotation.CreatedDate; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; @@ -57,6 +54,9 @@ public class SaleCopyVO implements Serializable { @ApiModelProperty(value = "收款状态 0-未收款 1-已收款 2-部分收款") private String payStatus; + @ApiModelProperty(value = " 收款方式:0 现金 1微信 2支付宝 3银行卡转账 4收款码") + private String payType; + @ApiModelProperty(value = "订单状态 1-拣货中 2-已预定 3-已作废 4-已取货 5-已送达") private String status; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleVO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleVO.java index 88a4b13c..ec5f27f9 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleVO.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/SaleVO.java @@ -17,6 +17,9 @@ public class SaleVO implements Serializable { @ApiModelProperty(value = "收款状态 0-未收款 1-已收款 2-部分收款") private String payStatus; + @ApiModelProperty(value = " 收款方式:0 现金 1微信 2支付宝 3银行卡转账 4收款码") + private String payType; + @ApiModelProperty(value = "订单状态 1-未预定 2-已预定 3-待自提 4-已取货 5-已送达") private String status; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/ShopVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/ShopVo.java new file mode 100644 index 00000000..4d7a3d8e --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/ShopVo.java @@ -0,0 +1,28 @@ +package cc.hiver.mall.pojo.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 选择店铺之后返回一些店铺信息 + * @author 王富康 + * @date 2024/5/23 + */ +@Data +@Accessors(chain = true) +public class ShopVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "店铺图标") + private String shopIcon; + + @ApiModelProperty(value = "地址") + private String shopAddress; + + @ApiModelProperty(value = "备注") + private String remark; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/controller/PurchaseOcrPictureController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/controller/PurchaseOcrPictureController.java index b10740ce..5fafb518 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/controller/PurchaseOcrPictureController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/controller/PurchaseOcrPictureController.java @@ -34,21 +34,36 @@ public class PurchaseOcrPictureController { @RequestMapping(value = "/batchSave", method = RequestMethod.POST) @ApiOperation("新增或编辑OCR识别信息") public Result batchSave(@RequestBody PurchaseOciPictureAddVo purchaseOciPictureAddVo) { - JSONObject jsonObject = purchaseOcrPictureService.batchSave(purchaseOciPictureAddVo); + final JSONObject jsonObject = purchaseOcrPictureService.batchSave(purchaseOciPictureAddVo); + return new ResultUtil().setData(jsonObject); + } + + /** + * Ai语音入库,获取商品信息 + * + * @param questionMsg + * @return Result + * @author 王富康 + * @date 2024/5/23 + */ + @RequestMapping(value = "/callWithMessageOfPurchase", method = RequestMethod.POST) + @ApiOperation("AI语音入库") + public Result callWithMessageOfPurchase(String questionMsg) throws NoApiKeyException, InputRequiredException { + final JSONObject jsonObject = purchaseOcrPictureService.callWithMessageOfPurchase(questionMsg); return new ResultUtil().setData(jsonObject); } @RequestMapping(value = "/invoicingAi", method = RequestMethod.POST) @ApiOperation("AI开单") public Result invoicingAi(String questionMsg) throws NoApiKeyException, InputRequiredException { - JSONObject jsonObject = purchaseOcrPictureService.invoicingAi(questionMsg); + final JSONObject jsonObject = purchaseOcrPictureService.invoicingAi(questionMsg); return new ResultUtil().setData(jsonObject); } @RequestMapping(value = "/multiRoundConversationCall", method = RequestMethod.POST) @ApiOperation("图片识别-多轮对话") - public List multiRoundConversationCall(String picturePath,Integer count) throws NoApiKeyException, InputRequiredException, UploadFileException { - List multiModalConversationResults = purchaseOcrPictureService.multiRoundConversationCall(picturePath,count); + public List multiRoundConversationCall(String picturePath, Integer count) throws NoApiKeyException, InputRequiredException, UploadFileException { + final List multiModalConversationResults = purchaseOcrPictureService.multiRoundConversationCall(picturePath, count); return multiModalConversationResults; } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/PurchaseOcrPictureService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/PurchaseOcrPictureService.java index 7bf5f9ec..98d8cf3d 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/PurchaseOcrPictureService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/PurchaseOcrPictureService.java @@ -23,4 +23,6 @@ public interface PurchaseOcrPictureService { List queryAllPictureStatus(String purchaseId); List getOcrCount(); + + JSONObject callWithMessageOfPurchase(String questionMsg) throws NoApiKeyException, InputRequiredException; } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/impl/PurchaseOcrPictureServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/impl/PurchaseOcrPictureServiceImpl.java index 8426a298..93475611 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/impl/PurchaseOcrPictureServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/impl/PurchaseOcrPictureServiceImpl.java @@ -1,41 +1,55 @@ package cc.hiver.mall.purchaseocr.service.impl; +import cc.hiver.core.common.utils.CommonUtil; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.core.entity.User; import cc.hiver.mall.common.constant.PurchaseConstant; import cc.hiver.mall.config.thread.AiPurchaseThread; import cc.hiver.mall.config.thread.ThreadPoolConfiguration; -import cc.hiver.mall.entity.Purchase; -import cc.hiver.mall.entity.Shop; +import cc.hiver.mall.entity.*; +import cc.hiver.mall.pojo.vo.ProductAttributeOfAddVo; +import cc.hiver.mall.pojo.vo.ProductAttributeValueVo; +import cc.hiver.mall.pojo.vo.ProductCategoryVo; +import cc.hiver.mall.pojo.vo.PurchaseVo; import cc.hiver.mall.purchaseocr.entity.PurchaseOcrPicture; import cc.hiver.mall.purchaseocr.mapper.PurchaseOcrPictureMapper; import cc.hiver.mall.purchaseocr.service.PurchaseOcrPictureService; import cc.hiver.mall.purchaseocr.vo.PurchaseOciPictureAddVo; import cc.hiver.mall.purchaseocr.vo.PurchaseOcrCountVo; import cc.hiver.mall.purchaseocr.vo.PurchaseOcrExample; +import cc.hiver.mall.saleaimsg.entity.SaleAiMsg; import cc.hiver.mall.service.ShopService; -import cc.hiver.mall.service.mybatis.ProductService; -import cc.hiver.mall.service.mybatis.PurchaseDetailService; -import cc.hiver.mall.service.mybatis.PurchaseService; +import cc.hiver.mall.service.mybatis.*; import cc.hiver.mall.utils.AliOcrUtil; +import cn.hutool.core.date.StopWatch; import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult; import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; import com.alibaba.dashscope.exception.UploadFileException; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.Date; -import java.util.List; +import java.math.BigDecimal; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Slf4j @Service public class PurchaseOcrPictureServiceImpl implements PurchaseOcrPictureService { + private static final Pattern productSn = Pattern.compile("货号"); + private static final Pattern COMPILE = Pattern.compile("\\D+"); + private static final Pattern SYYS = Pattern.compile("所有颜色", Pattern.LITERAL); + private static final Pattern SYCM = Pattern.compile("所有尺码", Pattern.LITERAL); + + @Autowired private PurchaseOcrPictureMapper purchaseOcrPictureMapper; @@ -60,6 +74,12 @@ public class PurchaseOcrPictureServiceImpl implements PurchaseOcrPictureService @Autowired private ThreadPoolConfiguration threadPoolConfiguration; + @Autowired + private StockService stockService; + @Autowired + private ProductCategoryService productCategoryService; + + @Override public JSONObject batchSave(PurchaseOciPictureAddVo purchaseOciPictureAddVo) { final JSONObject jsonObject = new JSONObject(); @@ -116,10 +136,10 @@ public class PurchaseOcrPictureServiceImpl implements PurchaseOcrPictureService // 异步处理ocr识别 try { // 获取参数示例 - PurchaseOcrExample purchaseOcrExample = purchaseOciPictureAddVo.getPurchaseOcrExample(); + final PurchaseOcrExample purchaseOcrExample = purchaseOciPictureAddVo.getPurchaseOcrExample(); AiPurchaseThread timerThread; for (PurchaseOcrPicture purchaseOcrPicture : purchaseOcrPictureAddList) { - timerThread = new AiPurchaseThread(purchaseId, purchaseOcrPicture,purchaseOcrExample, purchaseOcrPictureService, productService, purchaseDetailService, purchaseService); + timerThread = new AiPurchaseThread(purchaseId, purchaseOcrPicture, purchaseOcrExample, purchaseOcrPictureService, productService, purchaseDetailService, purchaseService, productCategoryService); // 这里可以使用线程池,也可以使用CompletionService处理,运行任务需要是callable的,需要最终结果。 threadPoolConfiguration.threadPoolTaskExecutor().execute(timerThread); } @@ -160,4 +180,287 @@ public class PurchaseOcrPictureServiceImpl implements PurchaseOcrPictureService final String shopId = securityUtil.getShopId(); return purchaseOcrPictureMapper.getOcrCount(shopId); } + + @Override + public JSONObject callWithMessageOfPurchase(String questionMsg) throws NoApiKeyException, InputRequiredException { + + final JSONObject returnJsonObject = new JSONObject(); + final StopWatch stopWatch = new StopWatch("Ai入库计时:"); + // 叉转X 文本纠错 使用正则表达式替换单个或多个连续的“叉”字符 + questionMsg = replaceAllX(questionMsg); + // 解析语句,根据“货号”分割换行一下,一个一个执行 + final String[] split = productSn.split(questionMsg); + final List saleAiMsgs = new ArrayList<>(); + for (String s : split) { + if (cc.hiver.core.common.utils.StringUtils.isNotEmpty(s)) { + final String oneAiMsg = "货号:" + s; + // 封装需要新增的ai开单记录表 + final SaleAiMsg saleAiMsg = new SaleAiMsg(); + saleAiMsg.setAiMsg(oneAiMsg); + saleAiMsgs.add(saleAiMsg); + } + } + final PurchaseVo purchaseVo = new PurchaseVo(); + // 定义一个map,货号为key,purchaseDetail 为value + final Map purchaseDetailMap = new HashMap<>(); + // shopId从缓存中设置 + final String shopId = securityUtil.getShopId(); + // 进行识别 + for (SaleAiMsg saleAiMsg : saleAiMsgs) { + stopWatch.start("Ai入库计时:" + saleAiMsg); + try { + final JSONObject jsonObject = AliOcrUtil.callWithMessageOfPurchase(saleAiMsg.getAiMsg()); + final String resultContent = jsonObject.get("resultContent").toString(); + final JSONArray json = JSON.parseArray(resultContent); + + for (int i = 0; i < json.size(); i++) { + final JSONObject object = json.getJSONObject(i); + String productSn = object.getString("productSn"); + // 尝试从货号中提取正确的货号,因为货号可能包含颜色等信息 + productSn = CommonUtil.getProductSn(productSn); + final String productName = object.getString("productName"); + final String priceStr = object.getString("price"); + BigDecimal price = BigDecimal.valueOf(0); + // 使用正则表达式提取数字部分 + final Pattern pattern = Pattern.compile("-?\\d+(\\.\\d+)?"); + final Matcher matcher = pattern.matcher(priceStr); + if (matcher.find()) { + // 获取匹配到的数字字符串并转换为BigDecimal + final String numericPart = matcher.group(); + price = new BigDecimal(numericPart); + + } + + final String attributeList = object.getString("attributeList"); + final JSONArray attributeListJsonArray = JSON.parseArray(attributeList); + // 根据货号去查询商品,如果 + final List byProductSn = productService.getByProductSn(productSn, shopId); + if (byProductSn != null && !byProductSn.isEmpty()) { + // 原则上一个店铺一个货号对应一个商品,这里如果查到了,直接拿第一个。 + final Product product = byProductSn.get(0); + final String productId = product.getId(); + // 查询商品所有的库存 + final List stockList = stockService.getProductStock(productId); + final Map stockMap = new HashMap<>(); + for (Stock stock : stockList) { + stockMap.put(stock.getAttributeList(), stock.getStockCount()); + } + final String categoryId = product.getCategoryId(); + final PurchaseDetail purchaseDetail = new PurchaseDetail(); + purchaseDetail.setProductId(productId); + purchaseDetail.setProductName(product.getProductName()); + purchaseDetail.setShopId(product.getShopId()); + purchaseDetail.setCategoryId(categoryId); + purchaseDetail.setPrice(product.getPrice()); + purchaseDetail.setPurchasePrice(price); + purchaseDetail.setWholesalePrice(product.getWholesalePrice()); + purchaseDetail.setProductPicture(product.getProductPicture()); + purchaseDetail.setProductSn(product.getProductSn()); + purchaseDetail.setProductCount(0); + purchaseDetail.setSupplierName(product.getSupplierName()); + final List stockLogList = new ArrayList<>(); + + // 获取商品分类及规格信息 + final List categoryIdList = new ArrayList<>(); + categoryIdList.add(categoryId); + final List shopCategory = productCategoryService.getShopCategory(categoryIdList); + final ProductCategoryVo productCategoryVo = shopCategory.get(0); + final List productAttributeOfAddVos = productCategoryVo.getProductAttributeOfAddVos(); + final Map productAttributeOfAddVoMap = new HashMap<>(); + for (ProductAttributeOfAddVo productAttributeOfAddVo : productAttributeOfAddVos) { + productAttributeOfAddVoMap.put(productAttributeOfAddVo.getAttributeName(), productAttributeOfAddVo); + } + //获取颜色及规格进行拼接 + List colorProductAttributeValueVoList = new ArrayList<>(); + List sizeProductAttributeValueVoList = new ArrayList<>(); + if (productAttributeOfAddVoMap.containsKey("颜色")) { + colorProductAttributeValueVoList = productAttributeOfAddVoMap.get("颜色").getProductAttributeValueVoList(); + } + // 将所有颜色放到一个集合中 + final CopyOnWriteArrayList colorList = new CopyOnWriteArrayList<>(); + for (ProductAttributeValueVo productAttributeValueVo : colorProductAttributeValueVoList) { + colorList.add(productAttributeValueVo.getValue()); + } + if (productAttributeOfAddVoMap.containsKey("尺码")) { + sizeProductAttributeValueVoList = productAttributeOfAddVoMap.get("尺码").getProductAttributeValueVoList(); + } + // 将所有尺码放到一个集合中 + final CopyOnWriteArrayList sizeList = new CopyOnWriteArrayList<>(); + for (ProductAttributeValueVo productAttributeValueVo : sizeProductAttributeValueVoList) { + sizeList.add(productAttributeValueVo.getValue()); + } + + for (int j = 0; j < attributeListJsonArray.size(); j++) { + final JSONObject attributeListObject = attributeListJsonArray.getJSONObject(j); + String color = attributeListObject.getString("color").toUpperCase(); + String size = attributeListObject.getString("size").toUpperCase(); + final String productCount1 = attributeListObject.getString("productCount"); + final int productCount = Integer.parseInt(COMPILE.matcher(productCount1).replaceAll("")); + // 20240330 只能新增颜色和尺码,颜色统一改为*色、尺码统一转大写,加‘码’; + // 根据规格id规格是颜色、还是尺码。 + if (!color.contains("色")) { + color += '色'; + } + if (!size.contains("码")) { + size += '码'; + } + size = size.toUpperCase(); + + if ("SYYS色".equals(color) && "SYCM码".equals(size)) { + for (ProductAttributeValueVo productAttributeValueVo : colorProductAttributeValueVoList) { + for (ProductAttributeValueVo attributeValueVo : sizeProductAttributeValueVoList) { + final StockLog stockLog = new StockLog(); + final String attribute = "{\"颜色\":\"" + productAttributeValueVo.getValue() + "\",\"尺码\":\"" + attributeValueVo.getValue() + "\"}"; + stockLog.setAttributeList(attribute); + stockLog.setProductCount(productCount); + purchaseDetail.setProductCount(purchaseDetail.getProductCount() + productCount); + stockLogList.add(stockLog); + } + } + continue; + // 所有颜色,所有尺码 + } + if ("SYYS色".equals(color)) { + // 所有颜色,固定尺码 + for (ProductAttributeValueVo productAttributeValueVo : colorProductAttributeValueVoList) { + final StockLog stockLog = new StockLog(); + final String attribute = "{\"颜色\":\"" + productAttributeValueVo.getValue() + "\",\"尺码\":\"" + size + "\"}"; + stockLog.setAttributeList(attribute); + stockLog.setProductCount(productCount); + purchaseDetail.setProductCount(purchaseDetail.getProductCount() + productCount); + stockLogList.add(stockLog); + } + + continue; + } + if ("SYCM码".equals(size)) { + // 所有尺码,固定颜色 + for (ProductAttributeValueVo attributeValueVo : sizeProductAttributeValueVoList) { + final StockLog stockLog = new StockLog(); + final String attribute = "{\"颜色\":\"" + color + "\",\"尺码\":\"" + attributeValueVo.getValue() + "\"}"; + stockLog.setAttributeList(attribute); + stockLog.setProductCount(productCount); + purchaseDetail.setProductCount(purchaseDetail.getProductCount() + productCount); + stockLogList.add(stockLog); + } + + continue; + } + // 不包含所有按照获取的拼接 + final StockLog stockLog = new StockLog(); + final String attribute = "{\"颜色\":\"" + color + "\",\"尺码\":\"" + size + "\"}"; + stockLog.setAttributeList(attribute); + stockLog.setProductCount(productCount); + purchaseDetail.setProductCount(purchaseDetail.getProductCount() + productCount); + stockLogList.add(stockLog); + + } + // 判断是否存在改货号,如果不存在,新增,存在,则追加stockLogList + if (purchaseDetailMap.containsKey(productSn)) { + final PurchaseDetail addPurchaseDetail = purchaseDetailMap.get(productSn); + addPurchaseDetail.getStockLogList1().addAll(stockLogList); + } else { + purchaseDetail.setStockLogList1(stockLogList); + purchaseDetailMap.put(productSn, purchaseDetail); + } + } else { + // 没查到,封装数据,货号为id + final PurchaseDetail purchaseDetail = new PurchaseDetail(); + purchaseDetail.setId(StringUtils.isEmpty(productSn) ? productName : productSn); + purchaseDetail.setProductName(productName); + purchaseDetail.setProductSn(productSn); + purchaseDetail.setPurchasePrice(price); + purchaseDetail.setProductCount(0); + // 获取默认分类 + final ProductCategoryVo defaultCategory = productCategoryService.getDefaultCategory(shopId); + if (defaultCategory != null) { + purchaseDetail.setCategoryId(defaultCategory.getCategoryId()); + purchaseDetail.setCategoryName(defaultCategory.getCategoryName()); + } + final List stockLogList = new ArrayList<>(); + for (int j = 0; j < attributeListJsonArray.size(); j++) { + final JSONObject attributeListObject = attributeListJsonArray.getJSONObject(j); + String color = attributeListObject.getString("color").toUpperCase(); + String size = attributeListObject.getString("size").toUpperCase(); + final String productCount1 = attributeListObject.getString("productCount"); + final int productCount = Integer.parseInt(COMPILE.matcher(productCount1).replaceAll("")); + // 20240330 只能新增颜色和尺码,颜色统一改为*色、尺码统一转大写,加‘码’; + // 根据规格id规格是颜色、还是尺码。 + if (!color.contains("色")) { + color += '色'; + } + if (!size.contains("码")) { + size += '码'; + } + size = size.toUpperCase(); + // 不包含所有按照获取的拼接 + final StockLog stockLog = new StockLog(); + final String attribute = "{\"颜色\":\"" + color + "\",\"尺码\":\"" + size + "\"}"; + stockLog.setAttributeList(attribute); + stockLog.setProductCount(productCount); + purchaseDetail.setProductCount(purchaseDetail.getProductCount() + productCount); + stockLogList.add(stockLog); + } + // 判断是否存在改货号,如果不存在,新增,存在,则追加stockLogList + if (purchaseDetailMap.containsKey(productSn)) { + final PurchaseDetail addPurchaseDetail = purchaseDetailMap.get(productSn); + addPurchaseDetail.getStockLogList1().addAll(stockLogList); + } else { + purchaseDetail.setStockLogList1(stockLogList); + purchaseDetailMap.put(productSn, purchaseDetail); + } + } + } + } catch (NoApiKeyException e) { + throw new RuntimeException(e); + } catch (InputRequiredException e) { + throw new RuntimeException(e); + } + stopWatch.stop(); + } + log.info(stopWatch.prettyPrint()); + final List purchaseDetails = new ArrayList<>(); + for (Map.Entry stringPurchaseDetailEntry : purchaseDetailMap.entrySet()) { + purchaseDetails.add(stringPurchaseDetailEntry.getValue()); + } + purchaseVo.setPurchaseDetails(purchaseDetails); + returnJsonObject.put("data", purchaseVo); + return returnJsonObject; + } + + /** + * 使用正则表达式替换输入字符串中连续的“叉”字符为相应数量的“X”字符。 + * + * @param input 待替换的字符串 + * @return 替换后的字符串 + */ + private static String replaceAllX(String input) { + // 定义正则表达式 + final Pattern pattern = Pattern.compile("(叉+)"); + // 创建匹配器 + final Matcher matcher = pattern.matcher(input); + + // 用于构建替换后的结果字符串 + final StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + // 获取匹配到的“叉”字符数 + final int count = matcher.group(1).length(); + // 创建一个字符数组,用于存放“X”字符 + final char[] xs = new char[count]; + // 填充数组 + Arrays.fill(xs, 'X'); + // 将字符数组转换为字符串 + final String replacement = new String(xs); + // 将替换后的字符串添加到结果缓冲区 + matcher.appendReplacement(sb, replacement); + } + // 添加剩余未匹配部分到结果缓冲区 + matcher.appendTail(sb); + // 对【所有】进行特殊处理 + String returnStr = sb.toString(); + returnStr = SYYS.matcher(returnStr).replaceAll(",SYYS色"); + returnStr = SYCM.matcher(returnStr).replaceAll(",SYCM码"); + // 返回最终替换后的字符串 + return returnStr; + } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java index 8a57248d..eb84b7a7 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java @@ -13,12 +13,33 @@ public interface ProductCategoryService extends IService { /** * AI入库的时候新增的分类信息,分类Id肯定是有的 - * @author 王富康 - * @date 2024/3/31 + * * @param productCategoryVoList * @return boolean + * @author 王富康 + * @date 2024/3/31 */ boolean batchSaveCategoryAndAttributeOfAi(List productCategoryVoList); CopyOnWriteArrayList getShopCategory(List categoryIdList); + + /** + * 注册店铺是新增默认分类 + * + * @param shopId + * @author 王富康 + * @date 2024/5/25 + */ + void addShopDefaultCategory(String shopId); + + /** + * 获取该店铺的默认分类,如果只有一个分类就返回,如果多个,就返回空 + * + * @return ProductCategory + * @author 王富康 + * @date 2024/5/25 + */ + ProductCategoryVo getDefaultCategory(String shopId); + + List getCategoryByCategoryIdList(List categoryIdList); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesCalculateServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesCalculateServiceImpl.java index d78ea419..f18a894b 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesCalculateServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesCalculateServiceImpl.java @@ -2,7 +2,6 @@ package cc.hiver.mall.serviceimpl; import cc.hiver.core.common.constant.SaleConstant; import cc.hiver.core.common.utils.SecurityUtil; -import cc.hiver.core.common.utils.StringUtils; import cc.hiver.mall.dao.mapper.ReturnSaleMapper; import cc.hiver.mall.dao.mapper.SaleMapper; import cc.hiver.mall.entity.ReturnSaleExample; @@ -58,22 +57,13 @@ public class SalesCalculateServiceImpl implements SalesCalculateService { // 店铺id从缓存中获取,并放到数据中去 final String shopId = securityUtil.getShopId(); + // 日期类型 Date startDate = new Date(); Date endDate = new Date(); // 查询日期范围内数据 try{ - if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) { - - startTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd") + " 00:00:00"; - endTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd") + " 23:59:59"; - startDate = DateUtil.COMMON_FULL.getTextDate(startTime); - endDate = DateUtil.COMMON_FULL.getTextDate(endTime); - } else { - startDate = DateUtil.COMMON_FULL.getTextDate(startTime + " 00:00:00"); - endDate = DateUtil.COMMON_FULL.getTextDate(endTime + " 23:59:59"); - // 如果根据时间查询,那么结束时间加1天, - endTime = DateUtil.addDay(endTime, 1); - } + startDate = DateUtil.COMMON.getTextDate(startTime); + endDate = DateUtil.COMMON.getTextDate(endTime); }catch (Exception e){ log.error("日期转换出错!"); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java index 9b10a538..7551dab5 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java @@ -14,6 +14,8 @@ import cc.hiver.mall.service.mybatis.ProductAttributeValueService; import cc.hiver.mall.service.mybatis.ProductCategoryService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -44,8 +46,14 @@ public class ProductCategoryServiceImpl extends ServiceImpl addProductAttributeValues = new ArrayList<>(); // 获取这些分类下都有哪些规格 final List shopCategory = getShopCategory(categoryIdList); - final Map> productAttributes =new HashMap<>(); + final Map> productAttributes = new HashMap<>(); for (ProductCategoryVo productCategoryVo : shopCategory) { productAttributes.put(productCategoryVo.getCategoryId(), productCategoryVo.getProductAttributeOfAddVos()); } @@ -132,7 +140,7 @@ public class ProductCategoryServiceImpl extends ServiceImpl attributeValueList = entry.getValue(); // 首先判断是否需要新增规格 - if(!stockAttributeNameList.contains(attributeName)){ + if (!stockAttributeNameList.contains(attributeName)) { final ProductAttribute productAttribute = new ProductAttribute(); productAttribute.setCreateTime(new Date()); productAttribute.setCategoryId(categoryId); @@ -147,12 +155,12 @@ public class ProductCategoryServiceImpl extends ServiceImpl(productCategoryMap.values()); } + + + @Override + public void addShopDefaultCategory(String shopId) { + final ProductCategoryVo productCategoryVo = new ProductCategoryVo(); + productCategoryVo.setShopId(shopId); + productCategoryVo.setCategoryName("默认分类"); + + final CopyOnWriteArrayList productAttributeOfAddVos = new CopyOnWriteArrayList<>(); + // 新增颜色 + final ProductAttributeOfAddVo productAttributeOfAddVo = new ProductAttributeOfAddVo(); + productAttributeOfAddVo.setAttributeName("颜色"); + final CopyOnWriteArrayList productAttributeValueVoList = new CopyOnWriteArrayList<>(); + final ProductAttributeValueVo productAttributeValueVo = new ProductAttributeValueVo(); + productAttributeValueVo.setValue("均色"); + productAttributeValueVoList.add(productAttributeValueVo); + // 回填到均色到颜色中 + productAttributeOfAddVo.setProductAttributeValueVoList(productAttributeValueVoList); + // 回填到颜色到分类中 + productAttributeOfAddVos.add(productAttributeOfAddVo); + // 新增尺码 + final ProductAttributeOfAddVo sizeProductAttributeOfAddVo = new ProductAttributeOfAddVo(); + sizeProductAttributeOfAddVo.setAttributeName("尺码"); + final CopyOnWriteArrayList sizeProductAttributeValueVoList = new CopyOnWriteArrayList<>(); + final ProductAttributeValueVo sizeProductAttributeValueVo = new ProductAttributeValueVo(); + sizeProductAttributeValueVo.setValue("均码"); + sizeProductAttributeValueVoList.add(sizeProductAttributeValueVo); + // 回填均码到尺码中 + sizeProductAttributeOfAddVo.setProductAttributeValueVoList(sizeProductAttributeValueVoList); + // 回填尺码到分类中 + productAttributeOfAddVos.add(sizeProductAttributeOfAddVo); + + productCategoryVo.setProductAttributeOfAddVos(productAttributeOfAddVos); + + // 批量去新增 + batchSaveCategoryAndAttribute(productCategoryVo); + + } + + /** + * 获取该店铺的默认分类,如果只有一个分类就返回,如果多个或者本来就没分类,就返回空 + * + * @return ProductCategory + * @author 王富康 + * @date 2024/5/25 + */ + @Nullable + @Override + public ProductCategoryVo getDefaultCategory(String shopId) { + final List productCategoryVoList = productCategoryMapper.selectByShopId(shopId); + if(productCategoryVoList.isEmpty()){ + return null; + }else{ + if(productCategoryVoList.size() == 1){ + return productCategoryVoList.get(0); + }else{ + return null; + } + } + } + + @Override + public List getCategoryByCategoryIdList(List categoryIdList) { + return productCategoryMapper.selectByCategoryIdList(categoryIdList); + } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/PurchaseServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/PurchaseServiceImpl.java index 7f1de21f..1e51471e 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/PurchaseServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/PurchaseServiceImpl.java @@ -8,15 +8,13 @@ import cc.hiver.mall.dao.mapper.PurchaseMapper; import cc.hiver.mall.entity.*; import cc.hiver.mall.pojo.dto.DebtSupplier; import cc.hiver.mall.pojo.query.PurchasePageQuery; +import cc.hiver.mall.pojo.vo.ProductCategoryVo; import cc.hiver.mall.pojo.vo.PurchaseVo; import cc.hiver.mall.purchaseocr.entity.PurchaseOcrPicture; import cc.hiver.mall.purchaseocr.service.PurchaseOcrPictureService; import cc.hiver.mall.purchaseocr.vo.PurchaseOcrCountVo; import cc.hiver.mall.service.SupplierService; -import cc.hiver.mall.service.mybatis.DealingsRecordService; -import cc.hiver.mall.service.mybatis.PurchaseDetailService; -import cc.hiver.mall.service.mybatis.PurchaseService; -import cc.hiver.mall.service.mybatis.StockLogService; +import cc.hiver.mall.service.mybatis.*; import cc.hiver.mall.utils.DateUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -25,6 +23,7 @@ import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.*; +import java.util.stream.Collectors; @Service public class PurchaseServiceImpl extends ServiceImpl implements PurchaseService { @@ -53,6 +52,9 @@ public class PurchaseServiceImpl extends ServiceImpl i @Autowired private PurchaseOcrPictureService purchaseOcrPictureService; + @Autowired + private ProductCategoryService productCategoryService; + @Override public Page getDebtByShopId(PurchasePageQuery purchasePageQuery) { @@ -317,6 +319,17 @@ public class PurchaseServiceImpl extends ServiceImpl i } // 获取商品信息 final List purchaseDetails = purchaseDetailService.getByPurchaseId(id); + // 20240525 需要返回分类名称 + final List categoryIds = purchaseDetails.stream().map(PurchaseDetail::getCategoryId).collect(Collectors.toList()); + // 根据分类id获取分类名称 + final List categoryByCategoryIdList = productCategoryService.getCategoryByCategoryIdList(categoryIds); + final Map categoryMap = categoryByCategoryIdList.stream().collect(Collectors.toMap(ProductCategoryVo::getCategoryId, ProductCategoryVo::getCategoryName)); + // 将分类名称封装到采购单明细中 + purchaseDetails.forEach(purchaseDetail -> { + final String categoryId = purchaseDetail.getCategoryId(); + purchaseDetail.setCategoryName(categoryMap.get(categoryId)); + }); + final List removePurchaseDetails = new ArrayList<>(); // 处理数据 diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/SaleServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/SaleServiceImpl.java index efe535b3..84abd0b3 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/SaleServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/SaleServiceImpl.java @@ -2,6 +2,7 @@ package cc.hiver.mall.serviceimpl.mybatis; import cc.hiver.core.common.constant.DealingsRecordConstant; import cc.hiver.core.common.constant.SaleConstant; +import cc.hiver.core.common.utils.CommonUtil; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.core.common.utils.StringUtils; import cc.hiver.core.common.utils.ThreadPoolUtil; @@ -583,7 +584,9 @@ public class SaleServiceImpl extends ServiceImpl implements Sa final JSONArray json = JSON.parseArray(resultContent); for (int i = 0; i < json.size(); i++) { final JSONObject object = json.getJSONObject(i); - final String productSn = object.getString("productSn"); + String productSn = object.getString("productSn"); + // 尝试从货号中提取正确的货号,因为货号可能包含颜色等信息 + productSn = CommonUtil.getProductSn(productSn); // 根据货号去查询商品,如果 final List byProductSn = productService.getByProductSn(productSn, shopId); if (byProductSn != null && !byProductSn.isEmpty()) { diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/StockServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/StockServiceImpl.java index 1ae0cdd5..41e13225 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/StockServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/StockServiceImpl.java @@ -659,6 +659,7 @@ public class StockServiceImpl extends ServiceImpl implements // Ai已经生成了入库单主表信息 final Purchase purchase = purchaseVo.getPurchase(); + purchase.setShopId(shopId); final String purchaseId = purchase.getId(); // 先根据入库单id 删除详情及库存履历表信息 purchaseDetailService.deleteByPurchaseId(purchaseId); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java index 5bd4c519..818695c1 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java @@ -1,6 +1,7 @@ package cc.hiver.mall.utils;// Copyright (c) Alibaba, Inc. and its affiliates. import cc.hiver.core.common.constant.CommonConstant; +import cc.hiver.core.common.utils.CommonUtil; import cc.hiver.mall.config.aliocr.AliOcrConfig; import cc.hiver.mall.entity.*; import cc.hiver.mall.pojo.vo.*; @@ -59,7 +60,7 @@ public class AliOcrUtil { * @author 王富康 * @date 2024/3/31 */ - public static JSONObject multiRoundConversationCall(PurchaseOcrPicture purchaseOcrPicture, PurchaseOcrExample purchaseOcrExample, ProductService productService, PurchaseDetailService purchaseDetailService) throws ApiException, NoApiKeyException, UploadFileException { + public static JSONObject multiRoundConversationCall(PurchaseOcrPicture purchaseOcrPicture, PurchaseOcrExample purchaseOcrExample, ProductService productService, PurchaseDetailService purchaseDetailService, ProductCategoryService productCategoryService) throws ApiException, NoApiKeyException, UploadFileException { final JSONObject jsonObject = new JSONObject(); final String ocrPictureId = purchaseOcrPicture.getId(); final String picturePath = purchaseOcrPicture.getOcrPicture(); @@ -71,13 +72,13 @@ public class AliOcrUtil { // 拼接的示例结果 String productSnExample = purchaseOcrExample.getProductSn(); String productNameExample = purchaseOcrExample.getProductName(); - if(StringUtils.isNotEmpty(ocrPictureOrder)){ + if (StringUtils.isNotEmpty(ocrPictureOrder)) { final String[] strings = ocrPictureOrder.split("-"); final String indexStr = strings[0]; productSnExample += indexStr; productNameExample += indexStr; } - final StopWatch stopWatch = new StopWatch(ocrPictureId+"Ai回答计时"); + final StopWatch stopWatch = new StopWatch(ocrPictureId + "Ai回答计时"); Constants.apiKey = "sk-bcfa4865b89548acb8225f910f13d682"; final CopyOnWriteArrayList multiModalConversationResults = new CopyOnWriteArrayList<>(); final MultiModalConversation conv = new MultiModalConversation(); @@ -96,7 +97,7 @@ public class AliOcrUtil { "5.如果按照你的理解在图中找到了productSn和productName字段对应的信息,则productSn和productName字段的值以图中内容为准。如果按照你的理解在图中没有找到productSn和productName字段对应的信息,则productSn和productName字段的值使用JSON示例中productSn和productName的值填充。 " + "6.请注意返回JSON符号解析格式正确 ,确保java程序能够正确解析。" + "7.严格返回" + count + "条JSON数据,如果数量有偏差按照实际条数返回,不能自动省略!"; - log.info("AI提问内容:"+firstQuestionMsg); + log.info("AI提问内容:" + firstQuestionMsg); MultiModalMessageItemText userText = new MultiModalMessageItemText(firstQuestionMsg); final MultiModalConversationMessage userMessage = MultiModalConversationMessage.builder().role(Role.USER.getValue()) @@ -114,7 +115,7 @@ public class AliOcrUtil { multiModalConversationResults.add(result); // 解析结果 String text = result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text").toString(); - log.info("一轮对话-的json======"+ text); + log.info("一轮对话-的json======" + text); // 根据{}截取数据 final int startIndex = text.indexOf('{'); final int endIndex = text.lastIndexOf('}'); @@ -127,45 +128,45 @@ public class AliOcrUtil { // 有时候返回的是productCounts,改为productCount jsonStr = fixJsonStr(jsonStr); JSONArray endJson = new JSONArray(); - try{ + try { endJson = JSON.parseArray(jsonStr); - }catch (Exception e){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,我把错误信息输出出来:"+e.getMessage(), e); + } catch (Exception e) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,没关系,我把错误信息输出出来:" + e.getMessage(), e); // 如果格式化报错,特殊处理下,再次进行转义。 final String message = e.getMessage(); boolean needAgain = true; // 以下是对目前可能出现的问题进行过滤处理 // attributeList格式不对 - if(message.contains("attributeList")){ + if (message.contains("attributeList")) { needAgain = false; - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,attributeList格式有问题,我来替换一下!"); + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,没关系,attributeList格式有问题,我来替换一下!"); // 如果是attributeList出现问题,那么尝试修复。 jsonStr = fixAttributeList(jsonStr); - try{ + try { endJson = JSON.parseArray(jsonStr); - }catch (Exception replaceOneException){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,attributeList替换了也没好使!"); + } catch (Exception replaceOneException) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,没关系,attributeList替换了也没好使!"); needAgain = true; } } // 识别多了个“}” - if(message.contains("not close endJson text")){ + if (message.contains("not close endJson text")) { needAgain = false; - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,可能是多了“}”,我来去掉试一下一下!"); + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,没关系,可能是多了“}”,我来去掉试一下一下!"); // - jsonStr = jsonStr.substring(0, jsonStr.length()-1); - try{ + jsonStr = jsonStr.substring(0, jsonStr.length() - 1); + try { endJson = JSON.parseArray(jsonStr); - }catch (Exception replaceOneException){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,可能是多了“}”,去掉了也没好使!"); + } catch (Exception replaceOneException) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,没关系,可能是多了“}”,去掉了也没好使!"); needAgain = true; } } - if(needAgain){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,我来重新识别一下!"); + if (needAgain) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,没关系,我来重新识别一下!"); //尝试重新识别一次 final String errorJsonQuestionMsg = "返回的json格式有误,请重新返回。"; final MultiModalMessageItemText assistentText = new MultiModalMessageItemText( @@ -183,7 +184,7 @@ public class AliOcrUtil { stopWatch.stop(); // 解析结果 text = result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text").toString(); - log.info("一轮对话--json格式错误,重新识别的结果======"+ text); + log.info("一轮对话--json格式错误,重新识别的结果======" + text); // 根据{}截取数据 final int secondStartIndex = text.indexOf('{'); final int secondEndIndex = text.lastIndexOf('}'); @@ -192,43 +193,43 @@ public class AliOcrUtil { // 有时候返回的是productCounts,改为productCount errorJsonJsonStr = fixJsonStr(errorJsonJsonStr); - try{ + try { // endJson = JSON.parseArray(errorJsonJsonStr); - }catch (Exception errorJsonException){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,没关系,我把错误信息输出出来:"+errorJsonException.getMessage(), errorJsonException); + } catch (Exception errorJsonException) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,重新识别又报错了,没关系,我把错误信息输出出来:" + errorJsonException.getMessage(), errorJsonException); // 如果格式化报错,特殊处理下,再次进行转义。 final String errorJsonExceptionMessage = errorJsonException.getMessage(); boolean firstCheckResult = true; - if(errorJsonExceptionMessage.contains("attributeList")){ + if (errorJsonExceptionMessage.contains("attributeList")) { firstCheckResult = false; - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,没关系,attributeList格式有问题,我来替换一下!"); + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,重新识别又报错了,没关系,attributeList格式有问题,我来替换一下!"); // 如果是attributeList出现问题,那么尝试修复。 errorJsonJsonStr = fixAttributeList(errorJsonJsonStr); - try{ + try { endJson = JSON.parseArray(errorJsonJsonStr); - }catch (Exception errorJsonJsonException){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,attributeList替换了也没好使!"); + } catch (Exception errorJsonJsonException) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,重新识别又报错了,attributeList替换了也没好使!"); firstCheckResult = true; } } // 识别多了个“}” - if(errorJsonExceptionMessage.contains("not close endJson text")){ + if (errorJsonExceptionMessage.contains("not close endJson text")) { firstCheckResult = false; - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,没关系,可能是多了“}”,我来去掉试一下一下!"); + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,重新识别又报错了,没关系,可能是多了“}”,我来去掉试一下一下!"); // - errorJsonJsonStr = errorJsonJsonStr.substring(0, errorJsonJsonStr.length()-1); - try{ + errorJsonJsonStr = errorJsonJsonStr.substring(0, errorJsonJsonStr.length() - 1); + try { endJson = JSON.parseArray(errorJsonJsonStr); - }catch (Exception replaceOneException){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,可能是多了“}”,去掉了也没好使!"); + } catch (Exception replaceOneException) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,重新识别又报错了,可能是多了“}”,去掉了也没好使!"); firstCheckResult = true; } } - if(firstCheckResult){ - log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,,重新识别又报错了,不识别了,直接毁灭吧!"); + if (firstCheckResult) { + log.error(Thread.currentThread().getName() + "-一轮对话--->json识别报错喽,,重新识别又报错了,不识别了,直接毁灭吧!"); throw errorJsonException; } } @@ -255,69 +256,69 @@ public class AliOcrUtil { stopWatch.stop(); // 解析结果 String secondText = result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text").toString(); - log.info("二轮对话识别结果:"+secondText); + log.info("二轮对话识别结果:" + secondText); // 根据{}截取数据 final int secondStartIndex = secondText.indexOf('{'); final int secondEndIndex = secondText.lastIndexOf('}'); if (secondStartIndex == -1 || secondEndIndex == -1) { // 二轮对话,没有查询到想要的数据,那么就使用一轮的结果 - log.info(Thread.currentThread().getName()+"-二轮对话--->识别数据失败,使用第一次的识别结果未找到指定标识符:识别结果为:" + text); - }else{ + log.info(Thread.currentThread().getName() + "-二轮对话--->识别数据失败,使用第一次的识别结果未找到指定标识符:识别结果为:" + text); + } else { String secondJsonStr = '[' + secondText.substring(secondStartIndex, secondEndIndex + 1) + ']'; // 有时候返回的是productCounts,改为productCount secondJsonStr = fixJsonStr(secondJsonStr); - try{ + try { final JSONArray secondJson = JSON.parseArray(secondJsonStr); final int secondResultCount = secondJson.size(); // 20240515 跟第一次的数据对比,哪个数量多,用哪个。 - if(secondResultCount > fristResultCount){ + if (secondResultCount > fristResultCount) { endJson = secondJson; } - }catch (Exception e){ + } catch (Exception e) { boolean needAgain = true; - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,没关系,我把错误信息输出出来:"+e.getMessage(),e); + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,没关系,我把错误信息输出出来:" + e.getMessage(), e); // 如果格式化报错,特殊处理下,再次进行转义。 final String message = e.getMessage(); - if(message.contains("attributeList")){ + if (message.contains("attributeList")) { needAgain = false; - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,没关系,attributeList格式有问题,我来替换一下!"); + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,没关系,attributeList格式有问题,我来替换一下!"); // 如果是attributeList出现问题,那么尝试修复。 secondJsonStr = fixAttributeList(secondJsonStr); - try{ + try { // endJson = JSON.parseArray(secondJsonStr); final JSONArray secondJson = JSON.parseArray(secondJsonStr); final int secondResultCount = secondJson.size(); // 20240515 跟第一次的数据对比,哪个数量多,用哪个。 - if(secondResultCount > fristResultCount){ + if (secondResultCount > fristResultCount) { endJson = secondJson; } - }catch (Exception exception){ - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,attributeList替换了也没好使!"); + } catch (Exception exception) { + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,attributeList替换了也没好使!"); needAgain = true; } } // 识别多了个“}” - if(message.contains("not close endJson text")){ + if (message.contains("not close endJson text")) { needAgain = false; - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,没关系,可能是多了“}”,我来去掉试一下一下!"); + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,没关系,可能是多了“}”,我来去掉试一下一下!"); // - secondJsonStr = secondJsonStr.substring(0, secondJsonStr.length()-1); - try{ + secondJsonStr = secondJsonStr.substring(0, secondJsonStr.length() - 1); + try { // endJson = JSON.parseArray(secondJsonStr); final JSONArray secondJson = JSON.parseArray(secondJsonStr); final int secondResultCount = secondJson.size(); // 20240515 跟第一次的数据对比,哪个数量多,用哪个。 - if(secondResultCount > fristResultCount){ + if (secondResultCount > fristResultCount) { endJson = secondJson; } - }catch (Exception replaceOneException){ - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,可能是多了“}”,去掉了也没好使!"); + } catch (Exception replaceOneException) { + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,可能是多了“}”,去掉了也没好使!"); needAgain = true; } } - if(needAgain){ - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,没关系,我来重新识别一下!"); + if (needAgain) { + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,没关系,我来重新识别一下!"); //尝试重新识别一次 final String errorJsonQuestionMsg = "返回的json格式有误,请重新返回。"; final MultiModalMessageItemText secondJsonErrorAssistentText = new MultiModalMessageItemText( @@ -335,7 +336,7 @@ public class AliOcrUtil { stopWatch.stop(); // 解析结果 secondText = result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text").toString(); - log.info("二轮对话-json格式错误,重新识别的结果======"+ secondText); + log.info("二轮对话-json格式错误,重新识别的结果======" + secondText); // 根据{}截取数据 final int errorSsecondStartIndex = secondText.indexOf('{'); final int errorSecondEndIndex = secondText.lastIndexOf('}'); @@ -343,58 +344,58 @@ public class AliOcrUtil { String errorJsonJsonStr = '[' + secondText.substring(errorSsecondStartIndex, errorSecondEndIndex + 1) + ']'; // 有时候返回的是productCounts,改为productCount errorJsonJsonStr = fixJsonStr(errorJsonJsonStr); - try{ + try { // // endJson = JSON.parseArray(errorJsonJsonStr); final JSONArray secondJson = JSON.parseArray(errorJsonJsonStr); final int secondResultCount = secondJson.size(); // 20240515 跟第一次的数据对比,哪个数量多,用哪个。 - if(secondResultCount > fristResultCount){ + if (secondResultCount > fristResultCount) { endJson = secondJson; } - }catch (Exception errorJsonException){ + } catch (Exception errorJsonException) { boolean secondCheckResult = true; final String errorJsonExceptionMessage = errorJsonException.getMessage(); - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,重新识别又报错了,没关系,我把错误信息输出出来:"+ errorJsonExceptionMessage, errorJsonException); - if(errorJsonExceptionMessage.contains("attributeList")){ + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,重新识别又报错了,没关系,我把错误信息输出出来:" + errorJsonExceptionMessage, errorJsonException); + if (errorJsonExceptionMessage.contains("attributeList")) { secondCheckResult = false; - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,,重新识别又报错了,没关系,,attributeList格式有问题,我来替换一下!"); + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,,重新识别又报错了,没关系,,attributeList格式有问题,我来替换一下!"); // 如果是attributeList出现问题,那么尝试修复。 errorJsonJsonStr = fixAttributeList(errorJsonJsonStr); - try{ + try { // endJson = JSON.parseArray(errorJsonJsonStr); final JSONArray secondJson = JSON.parseArray(errorJsonJsonStr); final int secondResultCount = secondJson.size(); // 20240515 跟第一次的数据对比,哪个数量多,用哪个。 - if(secondResultCount > fristResultCount){ + if (secondResultCount > fristResultCount) { endJson = secondJson; } - }catch (Exception secondCheckException){ - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,,重新识别又报错了,attributeList替换了也没好使!"); + } catch (Exception secondCheckException) { + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,,重新识别又报错了,attributeList替换了也没好使!"); secondCheckResult = true; } } - if(errorJsonExceptionMessage.contains("not close endJson text")){ + if (errorJsonExceptionMessage.contains("not close endJson text")) { secondCheckResult = false; - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,重新识别又报错了,没关系,可能是多了“}”,我来去掉试一下一下!"); + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,重新识别又报错了,没关系,可能是多了“}”,我来去掉试一下一下!"); // 如果是attributeList出现问题,那么尝试修复。 - errorJsonJsonStr = errorJsonJsonStr.substring(0, errorJsonJsonStr.length()-1); - try{ + errorJsonJsonStr = errorJsonJsonStr.substring(0, errorJsonJsonStr.length() - 1); + try { // endJson = JSON.parseArray(errorJsonJsonStr); final JSONArray secondJson = JSON.parseArray(errorJsonJsonStr); final int secondResultCount = secondJson.size(); // 20240515 跟第一次的数据对比,哪个数量多,用哪个。 - if(secondResultCount > fristResultCount){ + if (secondResultCount > fristResultCount) { endJson = secondJson; } - }catch (Exception secondCheckException){ - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,重新识别又报错了,可能是多了“}”,去掉了也没好使!"); + } catch (Exception secondCheckException) { + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,重新识别又报错了,可能是多了“}”,去掉了也没好使!"); secondCheckResult = true; } } - if(secondCheckResult){ - log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,,重新识别又报错了,不识别了,直接用第一次识别的结果吧!"); + if (secondCheckResult) { + log.error(Thread.currentThread().getName() + "-二轮对话--->json识别报错喽,,重新识别又报错了,不识别了,直接用第一次识别的结果吧!"); } } } @@ -408,7 +409,7 @@ public class AliOcrUtil { /*if (StringUtils.isNotEmpty(parentPicturePath)) { picturePath = parentPicturePath; }*/ - getPurchaseDetailMap(purchaseDetailService, productService, orderId, shopId, picturePath, endJson); + getPurchaseDetailMap(purchaseDetailService, productService, orderId, shopId, picturePath, endJson, productCategoryService); stopWatch.stop(); // 将map 转为list 进行落库操作 /*stopWatch.start("批量插入=="); @@ -446,7 +447,7 @@ public class AliOcrUtil { attributeList = attributeList.replace("productCounts", "productCount"); return attributeList; } - + /** * 1.有时候返回的是productCounts,改为productCount * 2. 有的时候中间会有...,需要特殊处理一下 @@ -458,16 +459,16 @@ public class AliOcrUtil { */ public static String fixJsonStr(String str) { // 如果包含"...",那么就截取掉,在商品中不会出现,并且在json应该只会出现一次,如果会出现多次的话,那这里需要再次优化 - if(str.contains("...")){ + if (str.contains("...")) { final String[] newStr = COMPILED.split(str); final int newStrLength = newStr.length; - if(newStrLength ==2){ + if (newStrLength == 2) { // 第一个字符串从开头截取到第一个} newStr[0] = newStr[0].substring(0, newStr[0].lastIndexOf('}')); // 第二个字符串从第一个{截取到最后 newStr[1] = newStr[1].substring(newStr[1].indexOf('{')); // 重新拼接,并且中间加上逗号 - str = newStr[0]+ ',' +newStr[1]; + str = newStr[0] + ',' + newStr[1]; } } str = str.replace("productCounts", "productCount"); @@ -487,7 +488,7 @@ public class AliOcrUtil { * @author 王富康 * @date 2024/5/10 */ - public static JSONObject streamCall(PurchaseOcrPicture purchaseOcrPicture, PurchaseOcrExample purchaseOcrExample, ProductService productService, PurchaseDetailService purchaseDetailService) + public static JSONObject streamCall(PurchaseOcrPicture purchaseOcrPicture, PurchaseOcrExample purchaseOcrExample, ProductService productService, PurchaseDetailService purchaseDetailService, ProductCategoryService productCategoryService) throws ApiException, NoApiKeyException, UploadFileException { final JSONObject jsonObject = new JSONObject(); final String picturePath = purchaseOcrPicture.getOcrPicture(); @@ -574,7 +575,7 @@ public class AliOcrUtil { /*if (StringUtils.isNotEmpty(parentPicturePath)) { picturePath = parentPicturePath; }*/ - getPurchaseDetailMap(purchaseDetailService, productService, orderId, shopId, picturePath, json); + getPurchaseDetailMap(purchaseDetailService, productService, orderId, shopId, picturePath, json, productCategoryService); stopWatch.stop(); log.info(stopWatch.prettyPrint()); @@ -597,7 +598,7 @@ public class AliOcrUtil { * @author 王富康 * @date 2024/3/31 */ - private static void getPurchaseDetailMap(PurchaseDetailService purchaseDetailService, ProductService productService, String orderId, String shopId, String ocrPicturePath, JSONArray json) { + private static void getPurchaseDetailMap(PurchaseDetailService purchaseDetailService, ProductService productService, String orderId, String shopId, String ocrPicturePath, JSONArray json, ProductCategoryService productCategoryService) { // 开始解析图片识别的数据,进行入库操作。 // 解析未实体对象 final CopyOnWriteArrayList purchaseOcrVos = new CopyOnWriteArrayList<>(); @@ -608,7 +609,10 @@ public class AliOcrUtil { for (int i = 0; i < json.size(); i++) { final JSONObject jsonObject = json.getJSONObject(i); final PurchaseOcrVo purchaseOcrVo = new PurchaseOcrVo(); - purchaseOcrVo.setProductSn(jsonObject.getString("productSn")); + String productSnOfJson = jsonObject.getString("productSn"); + // 尝试从货号中提取正确的货号,因为货号可能包含颜色等信息 + productSnOfJson = CommonUtil.getProductSn(productSnOfJson); + purchaseOcrVo.setProductSn(productSnOfJson); purchaseOcrVo.setProductName(jsonObject.getString("productName")); purchaseOcrVo.setPrice(jsonObject.getBigDecimal("price")); final String productCount = jsonObject.getString("productCount"); @@ -626,7 +630,7 @@ public class AliOcrUtil { final CopyOnWriteArrayList attributeList = new CopyOnWriteArrayList<>(); final String size = attributeListJson.getString("size"); - if(size.contains(",")){ + if (size.contains(",")) { final String[] sizeArray = size.split(","); for (String s : sizeArray) { final PurchaseOcrDetailVo purchaseOcrDetailVo = new PurchaseOcrDetailVo(); @@ -634,7 +638,7 @@ public class AliOcrUtil { purchaseOcrDetailVo.setSize(s); attributeList.add(purchaseOcrDetailVo); } - }else if(size.contains("-")){ + } else if (size.contains("-")) { final String[] sizeArray = size.split("-"); for (String s : sizeArray) { final PurchaseOcrDetailVo purchaseOcrDetailVo = new PurchaseOcrDetailVo(); @@ -642,7 +646,7 @@ public class AliOcrUtil { purchaseOcrDetailVo.setSize(s); attributeList.add(purchaseOcrDetailVo); } - }else{ + } else { final PurchaseOcrDetailVo purchaseOcrDetailVo = new PurchaseOcrDetailVo(); purchaseOcrDetailVo.setColor(attributeListJson.getString("color")); purchaseOcrDetailVo.setSize(size); @@ -794,6 +798,12 @@ public class AliOcrUtil { purchaseDetail.setWholesalePrice(product.getWholesalePrice()); purchaseDetail.setProductName(product.getProductName()); stockLog.setProductId(product.getId()); + }else{ + // 新商品,获取默认分类 + final ProductCategoryVo defaultCategory = productCategoryService.getDefaultCategory(shopId); + if (defaultCategory != null) { + purchaseDetail.setCategoryId(defaultCategory.getCategoryId()); + } } stockLogList.add(stockLog); purchaseDetail.setStockLogList1(stockLogList); @@ -822,7 +832,11 @@ public class AliOcrUtil { final MessageManager msgManager = new MessageManager(10); final Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build(); - questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}] }],只输出JSON数据即可,不用返回字段描述"; + //questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}] }]。以下是几点要求: 1.“货号”两个字和颜色中间的内容代表productSn,productSn可能包含\"新\"、\"退\"、\"旧\"、\"换\"、\"补\"。 2.\"SYYS色\"代表“所有颜色”,\"color\"字段返回“SYYS色”。 3.\"SYCM码\"代表“所有尺码”,\"size\"字段返回“SYCM码”。 4.只输出JSON数据即可,不用返回字段描述和解析过程。"; + questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}] }]," + + "productSn的返回值中去掉颜色,尺码等信息,\n" + + "如果没有识别到\"color\"的内容,则\"color\"赋值“均色”。如果没有识别到\"size\"的内容,则\"size\"赋值“均码”,\n" + + "只输出JSON数据即可,不用返回字段描述。"; final Message userMsg = Message.builder().role(Role.USER.getValue()).content(questionMsg).build(); msgManager.add(systemMsg); msgManager.add(userMsg); @@ -830,10 +844,6 @@ public class AliOcrUtil { final QwenParam param = QwenParam.builder().model(Generation.Models.QWEN_PLUS).messages(msgManager.get()) .resultFormat(QwenParam.ResultFormat.MESSAGE) - .temperature(1F) - .topP(0.1) - .topK(1) - .seed(500) .build(); final GenerationResult result = gen.call(param); log.info(result.toString()); @@ -850,6 +860,48 @@ public class AliOcrUtil { return jsonObject; } + /** + * ai语音入库 + * + * @param questionMsg + * @return JSONObject + * @author 王富康 + * @date 2024/5/23 + */ + public static JSONObject callWithMessageOfPurchase(String questionMsg) + throws NoApiKeyException, ApiException, InputRequiredException { + final JSONObject jsonObject = new JSONObject(); + Constants.apiKey = "sk-bcfa4865b89548acb8225f910f13d682"; + final Generation gen = new Generation(); + final MessageManager msgManager = new MessageManager(10); + final Message systemMsg = + Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build(); + // questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"productName\": \"名称\" , \"price\":\"单价\",\"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}] }]。以下是几点要求: 1.“货号”两个字和\"名称\"两个字中间的内容代表productSn的值,如果没有名称则“货号”两个字和颜色中间的内容代表productSn的值,productSn可能包含\"新\"、\"退\"、\"旧\"、\"换\"、\"补\"。2.\"SYYS色\"代表“所有颜色”,\"color\"字段返回“SYYS色”。 3.\"SYCM码\"代表“所有尺码”,\"size\"字段返回“SYCM码”。4.如果没有名称,productName字段返回\"\"。5.只输出JSON数据即可,不用返回字段描述和解析过程。"; + questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"productName\": \"名称\" , \"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}], \"price\":\"单价\" }]," + + "如果没有识别到\"price\"的内容,则\"price\"赋值\"0\"," + + "如果没有识别到\"color\"的内容,则\"color\"赋值“均色”," + + "如果没有识别到\"size\"的内容,则\"size\"赋值“均码”,\n" + + "如果没有识别到\"productName\"的内容,则\"productName\"使用\"productSn\"的值填充。只输出JSON数据即可,不用返回字段描述。"; + final Message userMsg = Message.builder().role(Role.USER.getValue()).content(questionMsg).build(); + msgManager.add(systemMsg); + msgManager.add(userMsg); + final QwenParam param = + QwenParam.builder().model(Generation.Models.QWEN_PLUS).messages(msgManager.get()) + .resultFormat(QwenParam.ResultFormat.MESSAGE) + .build(); + final GenerationResult result = gen.call(param); + log.info(result.toString()); + // 解析结果 + final String text = result.getOutput().getChoices().get(0).getMessage().getContent(); + // 根据{}截取数据 + final int startIndex = text.indexOf('{'); + final int endIndex = text.lastIndexOf('}'); + final String jsonStr = '[' + text.substring(startIndex, endIndex + 1) + ']'; + jsonObject.put("resultContent", jsonStr); + jsonObject.put("msg", result.getOutput().getChoices().get(0).getMessage().getContent()); + return jsonObject; + } + public static JSONObject callWithMessageSync(String questionMsg, String saleId, String shopId, String createBy, ProductService productService, ProductCategoryService productCategoryService, SaleService saleService, SaleDetailService saleDetailService) throws NoApiKeyException, ApiException, InputRequiredException { final JSONObject jsonObject = new JSONObject(); @@ -859,7 +911,11 @@ public class AliOcrUtil { final MessageManager msgManager = new MessageManager(10); final Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build(); - questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}] }],只输出JSON数据即可,不用返回字段描述"; + // questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}] }],只输出JSON数据即可,不用返回字段描述"; + questionMsg += "请帮我把所有内容封装为JSON,json格式为:[{ \"productSn\": \"货号\", \"attributeList\": [{\"color\":\"颜色\",\"size\":\"尺码\",\"productCount\": \"数量\"}] }]," + + "productSn的返回值中去掉颜色,尺码等信息,\n" + + "如果没有识别到\"color\"的内容,则\"color\"赋值“均色”。如果没有识别到\"size\"的内容,则\"size\"赋值“均码”,\n" + + "只输出JSON数据即可,不用返回字段描述。"; final Message userMsg = Message.builder().role(Role.USER.getValue()).content(questionMsg).build(); msgManager.add(systemMsg); msgManager.add(userMsg); @@ -867,10 +923,6 @@ public class AliOcrUtil { final QwenParam param = QwenParam.builder().model(Generation.Models.QWEN_PLUS).messages(msgManager.get()) .resultFormat(QwenParam.ResultFormat.MESSAGE) - .temperature(1F) - .topP(0.1) - .topK(1) - .seed(500) .build(); final GenerationResult result = gen.call(param); log.info(result.toString()); @@ -911,8 +963,10 @@ public class AliOcrUtil { final CopyOnWriteArrayList saleDetailList = new CopyOnWriteArrayList<>(); for (int i = 0; i < json.size(); i++) { final JSONObject object = json.getJSONObject(i); - final String productSn = object.getString("productSn"); - // 根据货号去查询商品,如果 + String productSn = object.getString("productSn"); + // 尝试从货号中提取正确的货号,因为货号可能包含颜色等信息 + productSn = CommonUtil.getProductSn(productSn); + // 根据货号去查询商品 final CopyOnWriteArrayList byProductSn = productService.getByProductSn(productSn, shopId); if (byProductSn != null && !byProductSn.isEmpty()) { // 原则上一个店铺一个货号对应一个商品,这里如果查到了,直接拿第一个。 diff --git a/hiver-modules/hiver-mall/src/main/resources/mapper/OperatingAreaMapper.xml b/hiver-modules/hiver-mall/src/main/resources/mapper/OperatingAreaMapper.xml index cf85dd8d..5ba41828 100644 --- a/hiver-modules/hiver-mall/src/main/resources/mapper/OperatingAreaMapper.xml +++ b/hiver-modules/hiver-mall/src/main/resources/mapper/OperatingAreaMapper.xml @@ -220,7 +220,7 @@ ) group by t.shipping_method_id, t.shipping_method - order by s.is_on_line desc,t.shipping_method + order by s.is_on_line desc,s.create_time desc, t.shipping_method