Merge remote-tracking branch 'origin/test' into test

This commit is contained in:
2025-11-26 10:04:29 +08:00
12 changed files with 234 additions and 41 deletions

View File

@@ -1,6 +1,5 @@
package com.czg.controller.admin;
import com.czg.annotation.SaStaffCheckPermission;
import com.czg.log.annotation.OperationLog;
import com.czg.product.dto.ConsStockFlowDTO;
import com.czg.product.param.ConsCheckStockParam;
@@ -41,10 +40,21 @@ public class ConsStockFlowController {
* @throws IOException
*/
@PostMapping("/ocr")
public CzgResult<ConsInOutStockHeadParam> ocr(@RequestParam MultipartFile file) throws IOException {
public CzgResult<Integer> ocr(@RequestParam MultipartFile file) throws IOException {
return CzgResult.success(consStockFlowService.ocr(file.getOriginalFilename(), file.getInputStream()));
}
/**
* ocr识别结果
* @param id ocrId
* @return 识别结果
*/
@GetMapping("/ocrResult")
public CzgResult<ConsInOutStockHeadParam> ocrResult(@RequestParam Long id) {
return CzgResult.success(consStockFlowService.ocrDetail(id));
}
/**
* 耗材入库
*/

View File

@@ -7,6 +7,9 @@ spring:
profiles:
active: dev
include: tools
servlet:
multipart:
max-file-size: 10MB
wx:
ysk:
appId: wx212769170d2c6b2a

View File

@@ -0,0 +1,43 @@
package com.czg.market.dto;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.experimental.Accessors;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* ocr识别结果 实体类。
*
* @author zs
* @since 2025-11-26
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class MkOcrDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Integer id;
/**
* 响应内容
*/
private String resp;
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
private Integer shopId;
}

View File

@@ -0,0 +1,49 @@
package com.czg.market.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* ocr识别结果 实体类。
*
* @author zs
* @since 2025-11-26
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("mk_ocr")
public class MkOcr implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
private Integer id;
/**
* 响应内容
*/
private String resp;
@Column(onInsertValue = "now()")
private LocalDateTime createTime;
@Column(onInsertValue = "now()", onUpdateValue = "now()")
private LocalDateTime updateTime;
private Long shopId;
}

View File

@@ -0,0 +1,14 @@
package com.czg.product.entity;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MkOcr;
/**
* ocr识别结果 服务层。
*
* @author zs
* @since 2025-11-26
*/
public interface MkOcrService extends IService<MkOcr> {
}

View File

@@ -78,5 +78,7 @@ public interface ConsStockFlowService extends IService<ConsStockFlow> {
*/
void saveFlow(ConsStockFlow entity);
ConsInOutStockHeadParam ocr(String originalFilename, InputStream inputStream);
Integer ocr(String originalFilename, InputStream inputStream);
ConsInOutStockHeadParam ocrDetail(Long id);
}

View File

@@ -29,13 +29,13 @@ public class Main {
// orSqlTest();
String packageName = "system";
// String packageName = "system";
// String packageName = "account";
// String packageName = "product";
// String packageName = "market";
String packageName = "market";
// tableName 指定需要生成的表
String tableName = "sys_devices";
String author = "ww";
String tableName = "mk_ocr";
String author = "zs";
//是否生成DTO实体 默认生成
boolean isGenerateDto = true;

View File

@@ -1729,9 +1729,12 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
if (orderDetail == null) {
log.warn("订单详情不存在");
}
if (orderDetail.getSubStatus() == null) {
return;
}
if (!orderDetail.getSubStatus().equals(TableValueConstant.OrderDetail.SubStatus.READY_TO_SERVE.getCode())
&& !orderDetail.getSubStatus().equals(TableValueConstant.OrderDetail.SubStatus.SENT_OUT.getCode())) {
if (!TableValueConstant.OrderDetail.SubStatus.READY_TO_SERVE.getCode().equals(orderDetail.getSubStatus())
&& !TableValueConstant.OrderDetail.SubStatus.SENT_OUT.getCode().equals(orderDetail.getSubStatus())) {
log.warn("订单详情状态不正确");
return;
}

View File

@@ -0,0 +1,14 @@
package com.czg.service.product.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkOcr;
/**
* ocr识别结果 映射层。
*
* @author zs
* @since 2025-11-26
*/
public interface MkOcrMapper extends BaseMapper<MkOcr> {
}

View File

@@ -9,6 +9,8 @@ import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.czg.exception.CzgException;
import com.czg.market.entity.MkOcr;
import com.czg.product.entity.MkOcrService;
import com.czg.product.dto.ConsStockFlowDTO;
import com.czg.product.dto.SaleOrderDTO;
import com.czg.product.entity.ConsInfo;
@@ -57,6 +59,8 @@ public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, C
private final ProductMapper productMapper;
@Resource
private WxAccountUtil wxAccountUtil;
@Resource
private MkOcrService ocrService;
private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
@@ -261,40 +265,66 @@ public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, C
}
@Override
public ConsInOutStockHeadParam ocr(String originalFilename, InputStream inputStream) {
String infoStr = AliOcrUtil.appCall(inputStream, originalFilename);
SaleOrderDTO saleOrderDTO = JSONObject.parseObject(infoStr, SaleOrderDTO.class);
public Integer ocr(String originalFilename, InputStream inputStream) {
Long shopId = StpKit.USER.getShopId();
MkOcr mkOcr = new MkOcr();
mkOcr.setShopId(shopId);
ocrService.save(mkOcr);
ThreadUtil.execAsync(() -> {
try {
ArrayList<ConsInOutStockBodyParam> bodyList = new ArrayList<>();
Set<String> nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet());
Map<String, ConsInfo> consInfoMap = new HashMap<>();
if (!nameList.isEmpty()) {
consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList))
.stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo));
}
ArrayList<SaleOrderDTO.Item> unInCons = new ArrayList<>();
for (SaleOrderDTO.Item item : saleOrderDTO.getItems()) {
ConsInfo consInfo = consInfoMap.get(item.getConName());
if (consInfo == null) {
unInCons.add(item);
continue;
String infoStr = AliOcrUtil.appCall(inputStream, originalFilename);
SaleOrderDTO saleOrderDTO = JSONObject.parseObject(infoStr, SaleOrderDTO.class);
ArrayList<ConsInOutStockBodyParam> bodyList = new ArrayList<>();
Set<String> nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet());
Map<String, ConsInfo> consInfoMap = new HashMap<>();
if (!nameList.isEmpty()) {
consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList).eq(ConsInfo::getShopId, shopId))
.stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo));
}
ArrayList<SaleOrderDTO.Item> unInCons = new ArrayList<>();
for (SaleOrderDTO.Item item : saleOrderDTO.getItems()) {
ConsInfo consInfo = consInfoMap.get(item.getConName());
if (consInfo == null) {
unInCons.add(item);
continue;
}
bodyList.add(new ConsInOutStockBodyParam()
.setConId(consInfo.getId().toString())
.setConName(consInfo.getConName())
.setPurchasePrice(new BigDecimal(item.getPurchasePrice()))
.setUnitName(item.getUnitName())
.setSubTotal(new BigDecimal(item.getSubTotal()))
.setInOutNumber(new BigDecimal(item.getInOutNumber())));
}
ConsInOutStockHeadParam headParam = new ConsInOutStockHeadParam();
headParam.setBatchNo(saleOrderDTO.getOrderNumber())
.setInOutDate(LocalDate.parse(saleOrderDTO.getDate()))
.setAmountPayable(new BigDecimal(saleOrderDTO.getTotalAmount()))
.setBodyList(bodyList)
.setUnInCons(unInCons)
.setOcrSaleOrder(saleOrderDTO);
mkOcr.setResp(JSON.toJSONString(headParam));
ocrService.updateById(mkOcr);
}catch (Exception e) {
log.warn("ocr失败: {}", e.getMessage());
}
bodyList.add(new ConsInOutStockBodyParam()
.setConId(consInfo.getId().toString())
.setConName(consInfo.getConName())
.setPurchasePrice(new BigDecimal(item.getPurchasePrice()))
.setUnitName(item.getUnitName())
.setSubTotal(new BigDecimal(item.getSubTotal()))
.setInOutNumber(new BigDecimal(item.getInOutNumber())));
}
ConsInOutStockHeadParam headParam = new ConsInOutStockHeadParam();
headParam.setBatchNo(saleOrderDTO.getOrderNumber())
.setInOutDate(LocalDate.parse(saleOrderDTO.getDate()))
.setAmountPayable(new BigDecimal(saleOrderDTO.getTotalAmount()))
.setBodyList(bodyList)
.setUnInCons(unInCons)
.setOcrSaleOrder(saleOrderDTO);
return headParam;
});
return mkOcr.getId();
}
@Override
public ConsInOutStockHeadParam ocrDetail(Long id) {
MkOcr mkOcr = ocrService.getOne(new QueryWrapper().eq(MkOcr::getShopId, StpKit.USER.getShopId()).eq(MkOcr::getId, id));
if (StrUtil.isNotBlank(mkOcr.getResp())) {
return JSONObject.parseObject(mkOcr.getResp(), ConsInOutStockHeadParam.class);
}
return null;
}
}

View File

@@ -0,0 +1,18 @@
package com.czg.service.product.service.impl;
import com.czg.service.product.mapper.MkOcrMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkOcr;
import com.czg.product.entity.MkOcrService;
import org.springframework.stereotype.Service;
/**
* ocr识别结果 服务层实现。
*
* @author zs
* @since 2025-11-26
*/
@Service
public class MkOcrServiceImpl extends ServiceImpl<MkOcrMapper, MkOcr> implements MkOcrService{
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.product.mapper.MkOcrMapper">
</mapper>