ocr识别修改
This commit is contained in:
@@ -21,6 +21,15 @@ import java.math.BigDecimal;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class OrderInfoAddDTO implements Serializable {
|
public class OrderInfoAddDTO implements Serializable {
|
||||||
|
/**
|
||||||
|
* 上菜方式
|
||||||
|
* 待起菜 PENDING_PREP
|
||||||
|
* 待出菜 READY_TO_SERVE
|
||||||
|
* 已出菜 SENT_OUT
|
||||||
|
* 已上菜 DELIVERED
|
||||||
|
* 已超时 EXPIRED
|
||||||
|
*/
|
||||||
|
private String subStatus;
|
||||||
//限时折扣部分
|
//限时折扣部分
|
||||||
private LimitRateDTO limitRate;
|
private LimitRateDTO limitRate;
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,17 @@ import com.alibaba.dashscope.app.ApplicationParam;
|
|||||||
import com.alibaba.dashscope.app.ApplicationResult;
|
import com.alibaba.dashscope.app.ApplicationResult;
|
||||||
import com.alibaba.dashscope.app.RagOptions;
|
import com.alibaba.dashscope.app.RagOptions;
|
||||||
import com.aliyun.bailian20231229.Client;
|
import com.aliyun.bailian20231229.Client;
|
||||||
|
import com.aliyun.bailian20231229.models.AddFileResponse;
|
||||||
import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponse;
|
import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponse;
|
||||||
import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponseBody;
|
import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponseBody;
|
||||||
|
import com.aliyun.bailian20231229.models.DescribeFileResponse;
|
||||||
import com.czg.exception.CzgException;
|
import com.czg.exception.CzgException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.DataOutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -53,13 +57,14 @@ public class AliOcrUtil {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(InputStream stream, String fileName) {
|
public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) {
|
||||||
String md5 = DigestUtil.md5Hex(stream);
|
|
||||||
|
String md5 = DigestUtil.md5Hex(bytes);
|
||||||
com.aliyun.bailian20231229.Client client = createClient();
|
com.aliyun.bailian20231229.Client client = createClient();
|
||||||
com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest()
|
com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest()
|
||||||
.setFileName(fileName)
|
.setFileName(fileName)
|
||||||
.setMd5(md5)
|
.setMd5(md5)
|
||||||
.setSizeInBytes("100000")
|
.setSizeInBytes(String.valueOf(bytes.length))
|
||||||
.setCategoryType("SESSION_FILE")
|
.setCategoryType("SESSION_FILE")
|
||||||
.setUseInternalEndpoint(false);
|
.setUseInternalEndpoint(false);
|
||||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||||
@@ -76,40 +81,94 @@ public class AliOcrUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String uploadFile(InputStream stream, String fileName) throws Exception {
|
public static String getSessionId(byte[] bytes, String fileName) {
|
||||||
|
String leaseId = null;
|
||||||
|
try {
|
||||||
|
leaseId = uploadFile(bytes, fileName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
com.aliyun.bailian20231229.Client client = createClient();
|
||||||
|
com.aliyun.bailian20231229.models.AddFileRequest addFileRequest = new com.aliyun.bailian20231229.models.AddFileRequest()
|
||||||
|
.setLeaseId(leaseId)
|
||||||
|
.setParser("DASHSCOPE_DOCMIND")
|
||||||
|
.setCategoryId("default")
|
||||||
|
.setCategoryType("SESSION_FILE");
|
||||||
|
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||||
|
java.util.Map<String, String> headers = new java.util.HashMap<>();
|
||||||
|
try {
|
||||||
|
// 复制代码运行请自行打印 API 的返回值
|
||||||
|
AddFileResponse addFileResponse = client.addFileWithOptions("llm-9zg04s7wlbvi32tq", addFileRequest, headers, runtime);
|
||||||
|
String fileId = addFileResponse.getBody().getData().getFileId();
|
||||||
|
while (!getFileStatus(fileId)) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
return fileId;
|
||||||
|
} catch (Exception error) {
|
||||||
|
throw new RuntimeException(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyInfo = applyFileUpload(stream, fileName);
|
public static boolean getFileStatus(String fileId) {
|
||||||
|
com.aliyun.bailian20231229.Client client = createClient();
|
||||||
|
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||||
|
java.util.Map<String, String> headers = new java.util.HashMap<>();
|
||||||
|
try {
|
||||||
|
// 复制代码运行请自行打印 API 的返回值
|
||||||
|
DescribeFileResponse describeFileResponse = client.describeFileWithOptions("llm-9zg04s7wlbvi32tq", fileId, headers, runtime);
|
||||||
|
|
||||||
|
log.info("file status: {}", describeFileResponse.getBody());
|
||||||
|
return describeFileResponse.getBody().getData() != null && "FILE_IS_READY".equals(describeFileResponse.getBody().getData().getStatus());
|
||||||
|
} catch (Exception error) {
|
||||||
|
throw new RuntimeException(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String uploadFile(byte[] bytes, String fileName) throws Exception {
|
||||||
|
|
||||||
|
ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyInfo = applyFileUpload(bytes, fileName);
|
||||||
|
|
||||||
// 获取预签名要求的所有头
|
|
||||||
Map<String, String> headers = (Map<String, String>) applyInfo.getParam().getHeaders();
|
Map<String, String> headers = (Map<String, String>) applyInfo.getParam().getHeaders();
|
||||||
|
|
||||||
|
// 补充必须的 Content-Type
|
||||||
|
if (!headers.containsKey("Content-Type")) {
|
||||||
|
headers.put("Content-Type", "application/octet-stream");
|
||||||
|
}
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.put(applyInfo.getParam().getUrl());
|
HttpRequest request = HttpRequest.put(applyInfo.getParam().getUrl());
|
||||||
|
|
||||||
// 必须一模一样地设置所有 headers(否则签名失效)
|
// 设置所有 header
|
||||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||||
request.header(entry.getKey(), entry.getValue());
|
request.header(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置文件内容
|
// 设置文件内容
|
||||||
request.body(stream.readAllBytes());
|
request.body(bytes);
|
||||||
|
|
||||||
HttpResponse resp = request.execute();
|
HttpResponse resp = request.execute();
|
||||||
log.info(resp.body());
|
|
||||||
|
log.info("upload status: {}", resp.getStatus());
|
||||||
|
if (resp.getStatus() != 200) {
|
||||||
|
throw new CzgException("OSS 上传失败: " + resp.body());
|
||||||
|
}
|
||||||
|
|
||||||
return applyInfo.getFileUploadLeaseId();
|
return applyInfo.getFileUploadLeaseId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String appCall(InputStream stream, String fileName) {
|
|
||||||
|
public static String appCall(byte[] bytes, String fileName) {
|
||||||
String id = null;
|
String id = null;
|
||||||
try {
|
try {
|
||||||
id = uploadFile(stream, fileName);
|
id = getSessionId(bytes, fileName);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
ApplicationParam param = ApplicationParam.builder()
|
ApplicationParam param = ApplicationParam.builder()
|
||||||
.apiKey("sk-2343af4413834ad1ab43b036e3a903de")
|
.apiKey("sk-2343af4413834ad1ab43b036e3a903de")
|
||||||
.appId("3493340ef5e146c487364395fbca7bf3")
|
.appId("cd612ac509a4499f8ac68a656532d4ae")
|
||||||
.prompt("开始处理")
|
.prompt("你是一名票据OCR结构化专家,请从我提供的票据图片中智能提取信息并只输出JSON,不得添加解释、不补充不存在内容、不得返回空字符串、字段缺失填null、字段不可省略、数字一律用字符串,使用以下固定JSON结构:{\"documentType\":\"\",\"orderNumber\":\"\",\"date\":\"\",\"customerName\":\"\",\"operator\":\"\",\"items\":[{\"conName\":\"\",\"spec\":\"\",\"unitName\":\"\",\"inOutNumber\":\"\",\"purchasePrice\":\"\",\"subTotal\":\"\"}],\"totalAmount\":\"\",\"remark\":\"\"}。字段映射规则:documentType对应单据类型/销售单/采购单/出货单;orderNumber对应单号/编号/No;date对应日期/开单日期;customerName对应客户名称/收货单位/供应商;operator对应业务员/经办人/制单人/操作员;items.conName对应品名/名称;items.spec对应规格/型号;items.unitName对应单位;items.inOutNumber对应数量;items.purchasePrice对应单价;items.subTotal对应金额/小计;totalAmount对应总金额/合计金额;remark对应备注。严禁生成图片中不存在的字段内容,看不清或未出现的字段必须为null,不允许推测或补全,不得生成多余字段;items只能根据识别到的行生成,不得虚构。必须能识别旋转、倾斜、模糊、撕裂、光照差异、列顺序混乱、无表格线等情况并尽量恢复信息。最终输出必须是纯JSON,不得包含任何非JSON字符。")
|
||||||
.ragOptions(RagOptions.builder()
|
.ragOptions(RagOptions.builder()
|
||||||
.sessionFileIds(List.of(id))
|
.sessionFileIds(List.of(id))
|
||||||
.build())
|
.build())
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<OrderDetail> orderDetails = cartService.getCartByTableCode(shopInfo.getId(), param.getTableCode(), param.getPlaceNum());
|
List<OrderDetail> orderDetails = cartService.getCartByTableCode(shopInfo.getId(), param.getTableCode(), param.getPlaceNum());
|
||||||
|
// if (param.)
|
||||||
AssertUtil.isListEmpty(orderDetails, "下单失败 购物车为空");
|
AssertUtil.isListEmpty(orderDetails, "下单失败 购物车为空");
|
||||||
processOrderDetails(orderDetails, param.getLimitRate());
|
processOrderDetails(orderDetails, param.getLimitRate());
|
||||||
//生成订单
|
//生成订单
|
||||||
|
|||||||
@@ -1,340 +1,349 @@
|
|||||||
package com.czg.service.product.service.impl;
|
package com.czg.service.product.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.bean.copier.CopyOptions;
|
import cn.hutool.core.bean.copier.CopyOptions;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.thread.ThreadUtil;
|
import cn.hutool.core.thread.ThreadUtil;
|
||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.crypto.digest.DigestUtil;
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.czg.exception.CzgException;
|
import com.czg.exception.CzgException;
|
||||||
import com.czg.market.entity.MkOcr;
|
import com.czg.market.entity.MkOcr;
|
||||||
import com.czg.product.entity.MkOcrService;
|
import com.czg.product.entity.MkOcrService;
|
||||||
import com.czg.product.dto.ConsStockFlowDTO;
|
import com.czg.product.dto.ConsStockFlowDTO;
|
||||||
import com.czg.product.dto.SaleOrderDTO;
|
import com.czg.product.dto.SaleOrderDTO;
|
||||||
import com.czg.product.entity.ConsInfo;
|
import com.czg.product.entity.ConsInfo;
|
||||||
import com.czg.product.entity.ConsStockFlow;
|
import com.czg.product.entity.ConsStockFlow;
|
||||||
import com.czg.product.enums.InOutItemEnum;
|
import com.czg.product.enums.InOutItemEnum;
|
||||||
import com.czg.product.enums.InOutTypeEnum;
|
import com.czg.product.enums.InOutTypeEnum;
|
||||||
import com.czg.product.param.*;
|
import com.czg.product.param.*;
|
||||||
import com.czg.product.service.ConsStockFlowService;
|
import com.czg.product.service.ConsStockFlowService;
|
||||||
import com.czg.product.vo.ConsCheckStockRecordVo;
|
import com.czg.product.vo.ConsCheckStockRecordVo;
|
||||||
import com.czg.sa.StpKit;
|
import com.czg.sa.StpKit;
|
||||||
import com.czg.service.product.mapper.ConsInfoMapper;
|
import com.czg.service.product.mapper.ConsInfoMapper;
|
||||||
import com.czg.service.product.mapper.ConsStockFlowMapper;
|
import com.czg.service.product.mapper.ConsStockFlowMapper;
|
||||||
import com.czg.service.product.mapper.ProductMapper;
|
import com.czg.service.product.mapper.ProductMapper;
|
||||||
import com.czg.service.product.util.WxAccountUtil;
|
import com.czg.service.product.util.WxAccountUtil;
|
||||||
import com.czg.utils.AliOcrUtil;
|
import com.czg.utils.AliOcrUtil;
|
||||||
import com.czg.utils.PageUtil;
|
import com.czg.utils.PageUtil;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.math.BigDecimal;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.io.InputStream;
|
||||||
import java.util.*;
|
import java.math.BigDecimal;
|
||||||
import java.util.stream.Collectors;
|
import java.time.LocalDate;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 耗材库存变动记录
|
* 耗材库存变动记录
|
||||||
*
|
*
|
||||||
* @author Tankaikai tankaikai@aliyun.com
|
* @author Tankaikai tankaikai@aliyun.com
|
||||||
* @since 1.0 2025-02-21
|
* @since 1.0 2025-02-21
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, ConsStockFlow> implements ConsStockFlowService {
|
public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, ConsStockFlow> implements ConsStockFlowService {
|
||||||
|
|
||||||
private final ConsInfoMapper consInfoMapper;
|
private final ConsInfoMapper consInfoMapper;
|
||||||
private final ProductMapper productMapper;
|
private final ProductMapper productMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private WxAccountUtil wxAccountUtil;
|
private WxAccountUtil wxAccountUtil;
|
||||||
@Resource
|
@Resource
|
||||||
private MkOcrService ocrService;
|
private MkOcrService ocrService;
|
||||||
|
|
||||||
private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) {
|
private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) {
|
||||||
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
|
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
|
||||||
/*if (StrUtil.isNotEmpty(param.getName())) {
|
/*if (StrUtil.isNotEmpty(param.getName())) {
|
||||||
queryWrapper.like(ConsStockFlow::getName, param.getName());
|
queryWrapper.like(ConsStockFlow::getName, param.getName());
|
||||||
}*/
|
}*/
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
queryWrapper.eq(ConsStockFlow::getShopId, shopId);
|
queryWrapper.eq(ConsStockFlow::getShopId, shopId);
|
||||||
queryWrapper.orderBy(ConsStockFlow::getId, false);
|
queryWrapper.orderBy(ConsStockFlow::getId, false);
|
||||||
return queryWrapper;
|
return queryWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void inStock(ConsInOutStockHeadParam param) {
|
public void inStock(ConsInOutStockHeadParam param) {
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||||
String createUserName = StpKit.USER.getAccount();
|
String createUserName = StpKit.USER.getAccount();
|
||||||
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
||||||
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
||||||
List<ConsStockFlow> insertList = new ArrayList<>();
|
List<ConsStockFlow> insertList = new ArrayList<>();
|
||||||
List<ConsInfo> updateStockList = new ArrayList<>();
|
List<ConsInfo> updateStockList = new ArrayList<>();
|
||||||
for (ConsStockFlow entity : entityList) {
|
for (ConsStockFlow entity : entityList) {
|
||||||
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
||||||
entity.setShopId(shopId);
|
entity.setShopId(shopId);
|
||||||
entity.setInOutType(InOutTypeEnum.IN.value());
|
entity.setInOutType(InOutTypeEnum.IN.value());
|
||||||
entity.setInOutItem(InOutItemEnum.MANUAL_IN.value());
|
entity.setInOutItem(InOutItemEnum.MANUAL_IN.value());
|
||||||
|
entity.setCreateUserId(createUserId);
|
||||||
|
entity.setCreateUserName(createUserName);
|
||||||
|
Long conId = entity.getConId();
|
||||||
|
ConsInfo consInfo = consInfoMapper.selectOneById(conId);
|
||||||
|
if (consInfo == null) {
|
||||||
|
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
||||||
|
}
|
||||||
|
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||||
|
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
||||||
|
insertList.add(entity);
|
||||||
|
consInfo.setStockNumber(entity.getAfterNumber());
|
||||||
|
updateStockList.add(consInfo);
|
||||||
|
}
|
||||||
|
super.saveBatch(insertList);
|
||||||
|
for (ConsInfo consInfo : updateStockList) {
|
||||||
|
consInfoMapper.update(consInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void outStock(ConsInOutStockHeadParam param) {
|
||||||
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
|
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||||
|
String createUserName = StpKit.USER.getAccount();
|
||||||
|
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
||||||
|
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
||||||
|
List<ConsStockFlow> insertList = new ArrayList<>();
|
||||||
|
List<ConsInfo> updateStockList = new ArrayList<>();
|
||||||
|
for (ConsStockFlow entity : entityList) {
|
||||||
|
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
||||||
|
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, entity.getInOutNumber()));
|
||||||
|
entity.setShopId(shopId);
|
||||||
|
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||||
|
entity.setInOutItem(InOutItemEnum.MANUAL_OUT.value());
|
||||||
|
entity.setCreateUserId(createUserId);
|
||||||
|
entity.setCreateUserName(createUserName);
|
||||||
|
Long conId = entity.getConId();
|
||||||
|
ConsInfo consInfo = consInfoMapper.selectOneById(conId);
|
||||||
|
if (consInfo == null) {
|
||||||
|
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
||||||
|
}
|
||||||
|
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||||
|
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
||||||
|
insertList.add(entity);
|
||||||
|
consInfo.setStockNumber(entity.getAfterNumber());
|
||||||
|
updateStockList.add(consInfo);
|
||||||
|
}
|
||||||
|
super.saveBatch(insertList);
|
||||||
|
for (ConsInfo consInfo : updateStockList) {
|
||||||
|
consInfoMapper.update(consInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void checkStock(ConsCheckStockParam param) {
|
||||||
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
|
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||||
|
String createUserName = StpKit.USER.getAccount();
|
||||||
|
ConsStockFlow entity = new ConsStockFlow();
|
||||||
entity.setCreateUserId(createUserId);
|
entity.setCreateUserId(createUserId);
|
||||||
entity.setCreateUserName(createUserName);
|
entity.setCreateUserName(createUserName);
|
||||||
Long conId = entity.getConId();
|
entity.setShopId(shopId);
|
||||||
ConsInfo consInfo = consInfoMapper.selectOneById(conId);
|
entity.setConId(param.getConId());
|
||||||
|
entity.setConName(param.getConName());
|
||||||
|
entity.setPurchasePrice(param.getPrice());
|
||||||
|
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
||||||
if (consInfo == null) {
|
if (consInfo == null) {
|
||||||
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
||||||
}
|
}
|
||||||
|
BigDecimal winLossNumber = NumberUtil.sub(param.getActualNumber(), param.getStockNumber());
|
||||||
|
if (!NumberUtil.equals(winLossNumber, param.getWinLossNumber())) {
|
||||||
|
throw new CzgException(StrUtil.format("耗材{}库存在发生变动,请刷新后重试", entity.getConName()));
|
||||||
|
}
|
||||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||||
|
entity.setInOutNumber(winLossNumber);
|
||||||
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
||||||
insertList.add(entity);
|
if (NumberUtil.isLess(winLossNumber, BigDecimal.ZERO)) {
|
||||||
|
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||||
|
entity.setInOutItem(InOutItemEnum.LOSS_OUT.value());
|
||||||
|
} else {
|
||||||
|
entity.setInOutType(InOutTypeEnum.IN.value());
|
||||||
|
entity.setInOutItem(InOutItemEnum.WIN_IN.value());
|
||||||
|
}
|
||||||
|
entity.setSubTotal(NumberUtil.mul(winLossNumber, param.getPrice()));
|
||||||
|
entity.setRemark(param.getRemark());
|
||||||
|
saveFlow(entity);
|
||||||
consInfo.setStockNumber(entity.getAfterNumber());
|
consInfo.setStockNumber(entity.getAfterNumber());
|
||||||
updateStockList.add(consInfo);
|
|
||||||
}
|
|
||||||
super.saveBatch(insertList);
|
|
||||||
for (ConsInfo consInfo : updateStockList) {
|
|
||||||
consInfoMapper.update(consInfo);
|
consInfoMapper.update(consInfo);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
public Page<ConsCheckStockRecordVo> getCheckStockRecordPage(Long conId) {
|
||||||
public void outStock(ConsInOutStockHeadParam param) {
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
return super.pageAs(PageUtil.buildPage(), query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
||||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
}
|
||||||
String createUserName = StpKit.USER.getAccount();
|
|
||||||
ConsStockFlow head = BeanUtil.copyProperties(param, ConsStockFlow.class);
|
@Override
|
||||||
List<ConsStockFlow> entityList = BeanUtil.copyToList(param.getBodyList(), ConsStockFlow.class);
|
public List<ConsCheckStockRecordVo> getCheckStockRecordList(Long conId) {
|
||||||
List<ConsStockFlow> insertList = new ArrayList<>();
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
List<ConsInfo> updateStockList = new ArrayList<>();
|
return super.mapper.selectListByQueryAs(query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
||||||
for (ConsStockFlow entity : entityList) {
|
}
|
||||||
BeanUtil.copyProperties(head, entity, CopyOptions.create().ignoreNullValue());
|
|
||||||
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, entity.getInOutNumber()));
|
@Override
|
||||||
entity.setShopId(shopId);
|
public void reportDamage(ConsReportDamageParam param) {
|
||||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
entity.setInOutItem(InOutItemEnum.MANUAL_OUT.value());
|
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||||
|
String createUserName = StpKit.USER.getAccount();
|
||||||
|
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
||||||
|
if (consInfo == null) {
|
||||||
|
throw new CzgException("耗材不存在");
|
||||||
|
}
|
||||||
|
ConsStockFlow entity = new ConsStockFlow();
|
||||||
entity.setCreateUserId(createUserId);
|
entity.setCreateUserId(createUserId);
|
||||||
entity.setCreateUserName(createUserName);
|
entity.setCreateUserName(createUserName);
|
||||||
Long conId = entity.getConId();
|
entity.setShopId(shopId);
|
||||||
ConsInfo consInfo = consInfoMapper.selectOneById(conId);
|
entity.setConId(param.getConId());
|
||||||
if (consInfo == null) {
|
entity.setConName(consInfo.getConName());
|
||||||
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
entity.setPurchasePrice(consInfo.getPrice());
|
||||||
|
BigDecimal balance = NumberUtil.sub(consInfo.getStockNumber(), param.getNumber());
|
||||||
|
if (NumberUtil.isLess(balance, BigDecimal.ZERO)) {
|
||||||
|
throw new CzgException(StrUtil.format("耗材{}报损数量不能大于当前库存{}", entity.getConName(), consInfo.getStockNumber()));
|
||||||
}
|
}
|
||||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
entity.setBeforeNumber(consInfo.getStockNumber());
|
||||||
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, param.getNumber()));
|
||||||
insertList.add(entity);
|
entity.setAfterNumber(balance);
|
||||||
|
entity.setInOutType(InOutTypeEnum.OUT.value());
|
||||||
|
entity.setInOutItem(InOutItemEnum.DAMAGE_OUT.value());
|
||||||
|
entity.setSubTotal(NumberUtil.mul(param.getNumber(), consInfo.getPrice()));
|
||||||
|
entity.setImgUrls(JSON.toJSONString(param.getImgUrls()));
|
||||||
|
saveFlow(entity);
|
||||||
consInfo.setStockNumber(entity.getAfterNumber());
|
consInfo.setStockNumber(entity.getAfterNumber());
|
||||||
updateStockList.add(consInfo);
|
|
||||||
}
|
|
||||||
super.saveBatch(insertList);
|
|
||||||
for (ConsInfo consInfo : updateStockList) {
|
|
||||||
consInfoMapper.update(consInfo);
|
consInfoMapper.update(consInfo);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
public Page<ConsStockFlowDTO> findConsStockFlowPage(ConsStockFlowParam param) {
|
||||||
public void checkStock(ConsCheckStockParam param) {
|
Long shopId = StpKit.USER.getShopId(0L);
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
PageHelper.startPage(PageUtil.buildPageHelp());
|
||||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
return PageUtil.convert(new PageInfo<>(mapper.findConsStockFlowPage(shopId, param.getInOutType(), param.getInOutItem(), param.getConId())));
|
||||||
String createUserName = StpKit.USER.getAccount();
|
|
||||||
ConsStockFlow entity = new ConsStockFlow();
|
|
||||||
entity.setCreateUserId(createUserId);
|
|
||||||
entity.setCreateUserName(createUserName);
|
|
||||||
entity.setShopId(shopId);
|
|
||||||
entity.setConId(param.getConId());
|
|
||||||
entity.setConName(param.getConName());
|
|
||||||
entity.setPurchasePrice(param.getPrice());
|
|
||||||
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
|
||||||
if (consInfo == null) {
|
|
||||||
throw new CzgException(StrUtil.format("耗材{}不存在", entity.getConName()));
|
|
||||||
}
|
}
|
||||||
BigDecimal winLossNumber = NumberUtil.sub(param.getActualNumber(), param.getStockNumber());
|
|
||||||
if (!NumberUtil.equals(winLossNumber, param.getWinLossNumber())) {
|
|
||||||
throw new CzgException(StrUtil.format("耗材{}库存在发生变动,请刷新后重试", entity.getConName()));
|
|
||||||
}
|
|
||||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
|
||||||
entity.setInOutNumber(winLossNumber);
|
|
||||||
entity.setAfterNumber(NumberUtil.add(entity.getBeforeNumber(), entity.getInOutNumber()));
|
|
||||||
if (NumberUtil.isLess(winLossNumber, BigDecimal.ZERO)) {
|
|
||||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
|
||||||
entity.setInOutItem(InOutItemEnum.LOSS_OUT.value());
|
|
||||||
} else {
|
|
||||||
entity.setInOutType(InOutTypeEnum.IN.value());
|
|
||||||
entity.setInOutItem(InOutItemEnum.WIN_IN.value());
|
|
||||||
}
|
|
||||||
entity.setSubTotal(NumberUtil.mul(winLossNumber, param.getPrice()));
|
|
||||||
entity.setRemark(param.getRemark());
|
|
||||||
saveFlow(entity);
|
|
||||||
consInfo.setStockNumber(entity.getAfterNumber());
|
|
||||||
consInfoMapper.update(consInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<ConsCheckStockRecordVo> getCheckStockRecordPage(Long conId) {
|
public void saveFlow(ConsStockFlow entity) {
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
super.save(entity);
|
||||||
return super.pageAs(PageUtil.buildPage(), query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
Long shopId = entity.getShopId();
|
||||||
}
|
BigDecimal afterNumber = entity.getAfterNumber();
|
||||||
|
ConsInfo consInfo = consInfoMapper.selectOneById(entity.getConId());
|
||||||
@Override
|
String shopName = "";
|
||||||
public List<ConsCheckStockRecordVo> getCheckStockRecordList(Long conId) {
|
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
|
||||||
return super.mapper.selectListByQueryAs(query().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getConId, conId).orderBy(ConsStockFlow::getId, false), ConsCheckStockRecordVo.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reportDamage(ConsReportDamageParam param) {
|
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
|
||||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
|
||||||
String createUserName = StpKit.USER.getAccount();
|
|
||||||
ConsInfo consInfo = consInfoMapper.selectOneById(param.getConId());
|
|
||||||
if (consInfo == null) {
|
|
||||||
throw new CzgException("耗材不存在");
|
|
||||||
}
|
|
||||||
ConsStockFlow entity = new ConsStockFlow();
|
|
||||||
entity.setCreateUserId(createUserId);
|
|
||||||
entity.setCreateUserName(createUserName);
|
|
||||||
entity.setShopId(shopId);
|
|
||||||
entity.setConId(param.getConId());
|
|
||||||
entity.setConName(consInfo.getConName());
|
|
||||||
entity.setPurchasePrice(consInfo.getPrice());
|
|
||||||
BigDecimal balance = NumberUtil.sub(consInfo.getStockNumber(), param.getNumber());
|
|
||||||
if (NumberUtil.isLess(balance, BigDecimal.ZERO)) {
|
|
||||||
throw new CzgException(StrUtil.format("耗材{}报损数量不能大于当前库存{}", entity.getConName(), consInfo.getStockNumber()));
|
|
||||||
}
|
|
||||||
entity.setBeforeNumber(consInfo.getStockNumber());
|
|
||||||
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, param.getNumber()));
|
|
||||||
entity.setAfterNumber(balance);
|
|
||||||
entity.setInOutType(InOutTypeEnum.OUT.value());
|
|
||||||
entity.setInOutItem(InOutItemEnum.DAMAGE_OUT.value());
|
|
||||||
entity.setSubTotal(NumberUtil.mul(param.getNumber(), consInfo.getPrice()));
|
|
||||||
entity.setImgUrls(JSON.toJSONString(param.getImgUrls()));
|
|
||||||
saveFlow(entity);
|
|
||||||
consInfo.setStockNumber(entity.getAfterNumber());
|
|
||||||
consInfoMapper.update(consInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Page<ConsStockFlowDTO> findConsStockFlowPage(ConsStockFlowParam param) {
|
|
||||||
Long shopId = StpKit.USER.getShopId(0L);
|
|
||||||
PageHelper.startPage(PageUtil.buildPageHelp());
|
|
||||||
return PageUtil.convert(new PageInfo<>(mapper.findConsStockFlowPage(shopId, param.getInOutType(), param.getInOutItem(), param.getConId())));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveFlow(ConsStockFlow entity) {
|
|
||||||
super.save(entity);
|
|
||||||
Long shopId = entity.getShopId();
|
|
||||||
BigDecimal afterNumber = entity.getAfterNumber();
|
|
||||||
ConsInfo consInfo = consInfoMapper.selectOneById(entity.getConId());
|
|
||||||
String shopName = "";
|
|
||||||
try {
|
|
||||||
shopName = StpKit.USER.getShopName();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取店铺名称失败");
|
|
||||||
}
|
|
||||||
if (StrUtil.isEmpty(shopName)) {
|
|
||||||
shopName = productMapper.getShopName(shopId);
|
|
||||||
}
|
|
||||||
BigDecimal conWarning = consInfo.getConWarning();
|
|
||||||
// 库存小于警告值,发送消息提醒
|
|
||||||
if (NumberUtil.isLess(afterNumber, conWarning)) {
|
|
||||||
List<String> openIdList = consInfoMapper.findOpenIdList(shopId, "con");
|
|
||||||
if (CollUtil.isEmpty(openIdList)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String conName = StrUtil.format("{}数量<预警值{}", consInfo.getConName(), conWarning);
|
|
||||||
String finalShopName = shopName;
|
|
||||||
ThreadUtil.execAsync(() -> {
|
|
||||||
openIdList.parallelStream().forEach(openId -> {
|
|
||||||
wxAccountUtil.sendStockMsg(finalShopName, conName, afterNumber, openId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer ocr(String originalFilename, InputStream inputStream) {
|
|
||||||
Long shopId = StpKit.USER.getShopId();
|
|
||||||
String md5 = DigestUtil.md5Hex(inputStream);
|
|
||||||
MkOcr ocr = ocrService.getOne(new QueryWrapper().eq(MkOcr::getShopId, shopId).eq(MkOcr::getMd5, md5));
|
|
||||||
if (ocr != null) {
|
|
||||||
return ocr.getId();
|
|
||||||
}
|
|
||||||
MkOcr mkOcr = new MkOcr();
|
|
||||||
mkOcr.setShopId(shopId);
|
|
||||||
mkOcr.setMd5(md5);
|
|
||||||
ocrService.save(mkOcr);
|
|
||||||
ThreadUtil.execAsync(() -> {
|
|
||||||
try {
|
try {
|
||||||
String infoStr = AliOcrUtil.appCall(inputStream, originalFilename);
|
shopName = StpKit.USER.getShopName();
|
||||||
SaleOrderDTO saleOrderDTO = JSONObject.parseObject(infoStr, SaleOrderDTO.class);
|
} catch (Exception e) {
|
||||||
|
log.error("获取店铺名称失败");
|
||||||
ArrayList<ConsInOutStockBodyParam> bodyList = new ArrayList<>();
|
}
|
||||||
Set<String> nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet());
|
if (StrUtil.isEmpty(shopName)) {
|
||||||
Map<String, ConsInfo> consInfoMap = new HashMap<>();
|
shopName = productMapper.getShopName(shopId);
|
||||||
if (!nameList.isEmpty()) {
|
}
|
||||||
consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList).eq(ConsInfo::getShopId, shopId))
|
BigDecimal conWarning = consInfo.getConWarning();
|
||||||
.stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo));
|
// 库存小于警告值,发送消息提醒
|
||||||
}
|
if (NumberUtil.isLess(afterNumber, conWarning)) {
|
||||||
ArrayList<SaleOrderDTO.Item> unInCons = new ArrayList<>();
|
List<String> openIdList = consInfoMapper.findOpenIdList(shopId, "con");
|
||||||
for (SaleOrderDTO.Item item : saleOrderDTO.getItems()) {
|
if (CollUtil.isEmpty(openIdList)) {
|
||||||
ConsInfo consInfo = consInfoMap.get(item.getConName());
|
return;
|
||||||
if (consInfo == null) {
|
}
|
||||||
unInCons.add(item);
|
String conName = StrUtil.format("{}数量<预警值{}", consInfo.getConName(), conWarning);
|
||||||
continue;
|
String finalShopName = shopName;
|
||||||
}
|
ThreadUtil.execAsync(() -> {
|
||||||
bodyList.add(new ConsInOutStockBodyParam()
|
openIdList.parallelStream().forEach(openId -> {
|
||||||
.setConId(consInfo.getId().toString())
|
wxAccountUtil.sendStockMsg(finalShopName, conName, afterNumber, openId);
|
||||||
.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.setStatus("SUCCESS");
|
|
||||||
mkOcr.setResp(JSON.toJSONString(headParam));
|
|
||||||
}catch (Exception e) {
|
|
||||||
mkOcr.setErr(e.getMessage());
|
|
||||||
mkOcr.setStatus("FAILED");
|
|
||||||
log.warn("ocr失败: {}", e.getMessage());
|
|
||||||
}finally {
|
|
||||||
ocrService.updateById(mkOcr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
@Override
|
||||||
|
public Integer ocr(String originalFilename, InputStream inputStream) {
|
||||||
|
Long shopId = StpKit.USER.getShopId();
|
||||||
|
byte[] readAllBytes = null;
|
||||||
|
try {
|
||||||
|
readAllBytes = inputStream.readAllBytes();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
String md5 = DigestUtil.md5Hex(readAllBytes);
|
||||||
|
MkOcr ocr = ocrService.getOne(new QueryWrapper().eq(MkOcr::getShopId, shopId).eq(MkOcr::getMd5, md5));
|
||||||
|
if (ocr != null) {
|
||||||
|
// return ocr.getId();
|
||||||
|
}
|
||||||
|
MkOcr mkOcr = new MkOcr();
|
||||||
|
mkOcr.setShopId(shopId);
|
||||||
|
mkOcr.setMd5(md5);
|
||||||
|
ocrService.save(mkOcr);
|
||||||
|
byte[] finalReadAllBytes1 = readAllBytes;
|
||||||
|
ThreadUtil.execAsync(() -> {
|
||||||
|
try {
|
||||||
|
String infoStr = AliOcrUtil.appCall(finalReadAllBytes1, 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.setStatus("SUCCESS");
|
||||||
|
mkOcr.setResp(JSON.toJSONString(headParam));
|
||||||
|
}catch (Exception e) {
|
||||||
|
mkOcr.setErr(e.getMessage());
|
||||||
|
mkOcr.setStatus("FAILED");
|
||||||
|
log.error("ocr失败:", e);
|
||||||
|
}finally {
|
||||||
|
ocrService.updateById(mkOcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user