From a995e8db2568ae253a7b7fca55dcd6947f3e9b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=9D=BE?= <8605635+zhang3064194730@user.noreply.gitee.com> Date: Tue, 25 Nov 2025 11:33:54 +0800 Subject: [PATCH] =?UTF-8?q?ocr=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/ConsStockFlowController.java | 13 ++++ .../java/com/czg/market/vo/MmberOrderVO.java | 12 ++++ .../com/czg/product/dto/SaleOrderDTO.java | 68 +++++++++++++++++++ .../param/ConsInOutStockBodyParam.java | 2 + .../param/ConsInOutStockHeadParam.java | 12 ++++ .../product/service/ConsStockFlowService.java | 5 +- .../main/java/com/czg/utils/AliOcrUtil.java | 33 +++++---- .../service/impl/MemberOrderServiceImpl.java | 8 ++- .../impl/ConsStockFlowServiceImpl.java | 51 ++++++++++++-- 9 files changed, 181 insertions(+), 23 deletions(-) create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/market/vo/MmberOrderVO.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/product/dto/SaleOrderDTO.java diff --git a/cash-api/product-server/src/main/java/com/czg/controller/admin/ConsStockFlowController.java b/cash-api/product-server/src/main/java/com/czg/controller/admin/ConsStockFlowController.java index a77433cd7..bfbcedde5 100644 --- a/cash-api/product-server/src/main/java/com/czg/controller/admin/ConsStockFlowController.java +++ b/cash-api/product-server/src/main/java/com/czg/controller/admin/ConsStockFlowController.java @@ -16,7 +16,9 @@ import com.czg.validator.group.DefaultGroup; import com.mybatisflex.core.paginate.Page; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.util.List; @@ -32,6 +34,17 @@ import java.util.List; public class ConsStockFlowController { private final ConsStockFlowService consStockFlowService; + /** + * 入库单识别 + * @param file 文件 + * @return + * @throws IOException + */ + @PostMapping("/ocr") + public CzgResult ocr(@RequestParam MultipartFile file) throws IOException { + return CzgResult.success(consStockFlowService.ocr(file.getOriginalFilename(), file.getInputStream())); + } + /** * 耗材入库 */ diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MmberOrderVO.java b/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MmberOrderVO.java new file mode 100644 index 000000000..85d38377f --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MmberOrderVO.java @@ -0,0 +1,12 @@ +package com.czg.market.vo; + +import com.czg.market.entity.MemberOrder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class MmberOrderVO extends MemberOrder { + private String nickname; + private String phone; +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/dto/SaleOrderDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/product/dto/SaleOrderDTO.java new file mode 100644 index 000000000..7c064708c --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/dto/SaleOrderDTO.java @@ -0,0 +1,68 @@ +package com.czg.product.dto; + +import lombok.*; + +import java.util.List; + +/** + * 销售单实体 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SaleOrderDTO { + + /** 单据类型 */ + private String documentType; + + /** 销售单号 */ + private String orderNumber; + + /** 日期 */ + private String date; + + /** 客户名称 */ + private String customerName; + + /** 操作员 */ + private String operator; + + /** 商品明细列表 */ + private List items; + + /** 总金额 */ + private String totalAmount; + + /** 备注 */ + private String remark; + + /** + * 销售单商品明细 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Item { + + /** 商品名称 */ + private String conName; + + /** 规格 */ + private String spec; + + /** 单位 */ + private String unitName; + + /** 数量 */ + private String inOutNumber; + + /** 单价 */ + private String purchasePrice; + + /** 金额 */ + private String subTotal; + } +} + diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockBodyParam.java b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockBodyParam.java index c64709d4d..ea7afc00e 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockBodyParam.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockBodyParam.java @@ -5,6 +5,7 @@ import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; +import lombok.experimental.Accessors; import java.io.Serial; import java.io.Serializable; @@ -17,6 +18,7 @@ import java.math.BigDecimal; * @since 1.0 2025-02-20 */ @Data +@Accessors(chain = true) public class ConsInOutStockBodyParam implements Serializable { @Serial diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java index 1bf91e833..50c6d80de 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java @@ -1,9 +1,11 @@ package com.czg.product.param; import com.alibaba.fastjson2.annotation.JSONField; +import com.czg.product.dto.SaleOrderDTO; import com.czg.validator.group.DefaultGroup; import jakarta.validation.constraints.NotNull; import lombok.Data; +import lombok.experimental.Accessors; import java.io.Serial; import java.io.Serializable; @@ -18,6 +20,7 @@ import java.util.List; * @since 1.0 2025-02-20 */ @Data +@Accessors(chain = true) public class ConsInOutStockHeadParam implements Serializable { @Serial @@ -57,4 +60,13 @@ public class ConsInOutStockHeadParam implements Serializable { * 耗材明细列表 */ List bodyList; + + /** + * 原始识别信息 + */ + private SaleOrderDTO ocrSaleOrder; + /** + * 未入库信息 + */ + private List unInCons; } diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/service/ConsStockFlowService.java b/cash-common/cash-common-service/src/main/java/com/czg/product/service/ConsStockFlowService.java index dcbc61014..77faab791 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/service/ConsStockFlowService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/service/ConsStockFlowService.java @@ -10,6 +10,7 @@ import com.czg.product.vo.ConsCheckStockRecordVo; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.service.IService; +import java.io.InputStream; import java.util.List; /** @@ -76,4 +77,6 @@ public interface ConsStockFlowService extends IService { * @param entity 库存变动记录实体 */ void saveFlow(ConsStockFlow entity); -} \ No newline at end of file + + ConsInOutStockHeadParam ocr(String originalFilename, InputStream inputStream); +} diff --git a/cash-common/cash-common-tools/src/main/java/com/czg/utils/AliOcrUtil.java b/cash-common/cash-common-tools/src/main/java/com/czg/utils/AliOcrUtil.java index 7e545a6a4..f3da6f718 100644 --- a/cash-common/cash-common-tools/src/main/java/com/czg/utils/AliOcrUtil.java +++ b/cash-common/cash-common-tools/src/main/java/com/czg/utils/AliOcrUtil.java @@ -1,6 +1,5 @@ package com.czg.utils; -import cn.hutool.core.io.FileUtil; import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; @@ -8,8 +7,6 @@ import com.alibaba.dashscope.app.Application; import com.alibaba.dashscope.app.ApplicationParam; import com.alibaba.dashscope.app.ApplicationResult; import com.alibaba.dashscope.app.RagOptions; -import com.alibaba.dashscope.exception.InputRequiredException; -import com.alibaba.dashscope.exception.NoApiKeyException; import com.aliyun.bailian20231229.Client; import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponse; import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponseBody; @@ -17,7 +14,7 @@ import com.czg.exception.CzgException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import java.io.File; +import java.io.InputStream; import java.util.List; import java.util.Map; @@ -56,12 +53,12 @@ public class AliOcrUtil { - public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(File file) { - String md5 = DigestUtil.md5Hex(file); + public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(InputStream stream, String fileName) { + String md5 = DigestUtil.md5Hex(stream); System.out.println(md5); com.aliyun.bailian20231229.Client client = createClient(); com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest() - .setFileName(file.getName()) + .setFileName(fileName) .setMd5(md5) .setSizeInBytes("100000") .setCategoryType("SESSION_FILE") @@ -80,9 +77,9 @@ public class AliOcrUtil { } } - public static String uploadFile(File file) { + public static String uploadFile(InputStream stream, String fileName) throws Exception { - ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyInfo = applyFileUpload(file); + ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyInfo = applyFileUpload(stream, fileName); // 获取预签名要求的所有头 Map headers = (Map) applyInfo.getParam().getHeaders(); @@ -95,7 +92,7 @@ public class AliOcrUtil { } // 设置文件内容 - request.body(FileUtil.readBytes(file)); + request.body(stream.readAllBytes()); HttpResponse resp = request.execute(); log.info(resp.body()); @@ -103,8 +100,13 @@ public class AliOcrUtil { } - public static void appCall(File file) { - String id = uploadFile(file); + public static String appCall(InputStream stream, String fileName) { + String id = null; + try { + id = uploadFile(stream, fileName); + } catch (Exception e) { + throw new RuntimeException(e); + } ApplicationParam param = ApplicationParam.builder() .apiKey("sk-2343af4413834ad1ab43b036e3a903de") .appId("3493340ef5e146c487364395fbca7bf3") @@ -121,13 +123,16 @@ public class AliOcrUtil { } catch (Exception e) { throw new RuntimeException(e); } - System.out.printf("%s\n", + log.info("{}", result.getOutput().getText()); + return result.getOutput().getText(); } + public static void main(String[] args) { + + } static void main() throws Exception { - appCall(new File("C:\\Users\\Administrator\\Downloads\\微信图片_20251121101326_2015_354.jpg")); } } diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MemberOrderServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MemberOrderServiceImpl.java index 65ec24d03..5c349db3e 100644 --- a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MemberOrderServiceImpl.java +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MemberOrderServiceImpl.java @@ -18,6 +18,7 @@ import com.czg.market.service.TbMemberConfigService; import com.czg.market.vo.MemberConfigVO; import com.czg.exception.CzgException; import com.czg.market.dto.MemberOrderDTO; +import com.czg.market.vo.MmberOrderVO; import com.czg.order.service.OrderInfoService; import com.czg.order.service.OrderPaymentService; import com.czg.sa.StpKit; @@ -64,7 +65,7 @@ public class MemberOrderServiceImpl extends ServiceImpl map = BeanUtil.beanToMap(page(PageUtil.buildPage(), QueryWrapper.create() + Map map = BeanUtil.beanToMap(pageAs(PageUtil.buildPage(), QueryWrapper.create() .leftJoin(UserInfoTableDef.USER_INFO).on(UserInfoTableDef.USER_INFO.ID.eq(MemberOrderTableDef.MEMBER_ORDER.USER_ID)) .leftJoin(ShopUserTableDef.SHOP_USER).on(ShopUserTableDef.SHOP_USER.MAIN_SHOP_ID.eq(MemberOrderTableDef.MEMBER_ORDER.SHOP_ID) .and(ShopUserTableDef.SHOP_USER.USER_ID.eq(MemberOrderTableDef.MEMBER_ORDER.USER_ID))) @@ -80,7 +81,10 @@ public class MemberOrderServiceImpl extends ServiceImpl bodyList = new ArrayList<>(); + Set nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet()); + Map consInfoMap = new HashMap<>(); + if (!nameList.isEmpty()) { + consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList)) + .stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo)); + } + ArrayList 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); + return headParam; + } }