ocr入库
This commit is contained in:
@@ -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<ConsInOutStockHeadParam> ocr(@RequestParam MultipartFile file) throws IOException {
|
||||
return CzgResult.success(consStockFlowService.ocr(file.getOriginalFilename(), file.getInputStream()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 耗材入库
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<Item> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ConsInOutStockBodyParam> bodyList;
|
||||
|
||||
/**
|
||||
* 原始识别信息
|
||||
*/
|
||||
private SaleOrderDTO ocrSaleOrder;
|
||||
/**
|
||||
* 未入库信息
|
||||
*/
|
||||
private List<SaleOrderDTO.Item> unInCons;
|
||||
}
|
||||
|
||||
@@ -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<ConsStockFlow> {
|
||||
* @param entity 库存变动记录实体
|
||||
*/
|
||||
void saveFlow(ConsStockFlow entity);
|
||||
|
||||
ConsInOutStockHeadParam ocr(String originalFilename, InputStream inputStream);
|
||||
}
|
||||
@@ -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<String, String> headers = (Map<String, String>) 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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<MemberOrderMapper, Membe
|
||||
LocalDateTime start = StrUtil.isBlank(startTime) ? null : DateUtil.parseLocalDateTime(startTime);
|
||||
LocalDateTime end = StrUtil.isBlank(endTime) ? null : DateUtil.parseLocalDateTime(endTime);
|
||||
|
||||
Map<String, Object> map = BeanUtil.beanToMap(page(PageUtil.buildPage(), QueryWrapper.create()
|
||||
Map<String, Object> 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<MemberOrderMapper, Membe
|
||||
});
|
||||
})
|
||||
.eq(MemberOrder::getShopId, StpKit.USER.getMainShopId())
|
||||
.orderBy(MemberOrder::getCreateTime, true)
|
||||
.select(MemberOrderTableDef.MEMBER_ORDER.ALL_COLUMNS)
|
||||
.select(ShopUserTableDef.SHOP_USER.NICK_NAME,
|
||||
ShopUserTableDef.SHOP_USER.PHONE)
|
||||
.orderBy(MemberOrder::getCreateTime, true), MmberOrderVO.class
|
||||
));
|
||||
map.put("totalAmount", getOneAsOpt(QueryWrapper.create()
|
||||
.leftJoin(UserInfoTableDef.USER_INFO).on(UserInfoTableDef.USER_INFO.ID.eq(MemberOrderTableDef.MEMBER_ORDER.USER_ID))
|
||||
|
||||
@@ -7,16 +7,15 @@ import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.product.dto.ConsStockFlowDTO;
|
||||
import com.czg.product.dto.SaleOrderDTO;
|
||||
import com.czg.product.entity.ConsInfo;
|
||||
import com.czg.product.entity.ConsStockFlow;
|
||||
import com.czg.product.enums.InOutItemEnum;
|
||||
import com.czg.product.enums.InOutTypeEnum;
|
||||
import com.czg.product.param.ConsCheckStockParam;
|
||||
import com.czg.product.param.ConsInOutStockHeadParam;
|
||||
import com.czg.product.param.ConsReportDamageParam;
|
||||
import com.czg.product.param.ConsStockFlowParam;
|
||||
import com.czg.product.param.*;
|
||||
import com.czg.product.service.ConsStockFlowService;
|
||||
import com.czg.product.vo.ConsCheckStockRecordVo;
|
||||
import com.czg.sa.StpKit;
|
||||
@@ -24,6 +23,7 @@ import com.czg.service.product.mapper.ConsInfoMapper;
|
||||
import com.czg.service.product.mapper.ConsStockFlowMapper;
|
||||
import com.czg.service.product.mapper.ProductMapper;
|
||||
import com.czg.service.product.util.WxAccountUtil;
|
||||
import com.czg.utils.AliOcrUtil;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
@@ -36,9 +36,11 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 耗材库存变动记录
|
||||
@@ -258,4 +260,41 @@ 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);
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user