This commit is contained in:
磷叶 2024-11-20 22:09:39 +08:00
parent b6b7fd653a
commit 681462a70f
31 changed files with 507 additions and 165 deletions

View File

@ -5,7 +5,7 @@ import io.jsonwebtoken.Claims;
/**
* 通用常量信息
*
*
* @author ruoyi
*/
public class Constants
@ -170,4 +170,9 @@ public class Constants
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
/**
* 系统 用户ID
*/
public static final Long SYSTEM_USER_ID = 0L;
}

View File

@ -132,6 +132,13 @@ public class SysUser extends BaseEntity
this.userId = userId;
}
public static SysUser system() {
SysUser user = new SysUser();
user.setUserId(0L);
user.setNickName("系统");
return user;
}
public boolean isAdmin()
{
return isAdmin(this.userId);

View File

@ -106,6 +106,10 @@ public class CollectionUtils extends org.springframework.util.CollectionUtils {
return list.stream().map(keyMapper).filter(Objects::nonNull).distinct().collect(Collectors.toList());
}
public static <T, R> List<R> map(Function<? super T, ? extends R> keyMapper, T ...arrays) {
return map(Arrays.asList(arrays), keyMapper);
}
public static <T, R> Set<R> mapToSet(Collection<T> collection, Function<? super T, ? extends R> keyMapper) {
return collection.stream().map(keyMapper).filter(Objects::nonNull).collect(Collectors.toSet());
}

View File

@ -39,4 +39,7 @@ public class LogImport extends BaseEntity
@ApiModelProperty("完成时间")
private LocalDateTime finishedTime;
@Excel(name = "日志类型", readConverterExp = "1=导入日志,2=同步日志")
@ApiModelProperty("日志类型")
private String type;
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.web.yh.logImport.domain.enums;
import com.ruoyi.web.yh.logImportDetail.domain.interfaces.ImportContent;
import com.ruoyi.web.yh.price.domain.vo.PriceImportContentVO;
import com.ruoyi.web.yh.prodOrder.domain.vo.ProdOrderImportContentVO;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -14,7 +15,8 @@ import lombok.Getter;
@AllArgsConstructor
public enum LogImportBizType {
PRICE("1", "单价", PriceImportContentVO.class);
PRICE("1", "单价", PriceImportContentVO.class),
PROD_ORDER("2", "生产订单", ProdOrderImportContentVO.class);
private final String type;
private final String msg;

View File

@ -0,0 +1,20 @@
package com.ruoyi.web.yh.logImport.domain.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author wjh
* 2024/11/20
*/
@Getter
@AllArgsConstructor
public enum LogImportType {
IMPORT("1", "导入"),
SYNC("2", "同步");
private final String type;
private final String msg;
}

View File

@ -14,7 +14,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bli.create_id,
bli.create_by,
bli.create_time,
bli.finished_time
bli.finished_time,
bli.type
from bst_log_import bli
</sql>
@ -24,6 +25,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.bizType != null and query.bizType != ''"> and bli.biz_type = #{query.bizType}</if>
<if test="query.createId != null "> and bli.create_id = #{query.createId}</if>
<if test="query.finishedTime != null "> and bli.finished_time = #{query.finishedTime}</if>
<if test="query.type != null and query.type != ''"> and type = #{query.type}</if>
${query.params.dataScope}
</sql>
@ -48,6 +50,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="finishedTime != null">finished_time,</if>
<if test="type != null and type != ''">type,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="status != null and status != ''">#{status},</if>
@ -56,6 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="finishedTime != null">#{finishedTime},</if>
<if test="type != null and type != ''">#{type},</if>
</trim>
</insert>
@ -68,12 +72,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update>
<sql id="updateColumns">
<if test="data.status != null and data.status != ''">status = #{data.status},</if>
<if test="data.status != null and data.status != ''">`status` = #{data.status},</if>
<if test="data.bizType != null and data.bizType != ''">biz_type = #{data.bizType},</if>
<if test="data.createId != null">create_id = #{data.createId},</if>
<if test="data.createBy != null and data.createBy != ''">create_by = #{data.createBy},</if>
<if test="data.createTime != null">create_time = #{data.createTime},</if>
<if test="data.finishedTime != null">finished_time = #{data.finishedTime},</if>
<if test="data.type != null and data.type != ''">type = #{data.type},</if>
</sql>
<delete id="deleteLogImportByLogId" parameterType="Long">

View File

@ -7,8 +7,7 @@ import com.ruoyi.web.yh.logImport.domain.LogImport;
import com.ruoyi.web.yh.logImport.domain.LogImportVO;
import com.ruoyi.web.yh.logImport.domain.LogImportQuery;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportBizType;
import com.ruoyi.web.yh.logImportDetail.domain.enums.LogImportDetailType;
import com.ruoyi.web.yh.price.domain.PriceVO;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportType;
/**
* 导入日志Service接口
@ -69,10 +68,11 @@ public interface ILogImportService
/**
* 新增一个默认日志
*
* @param type
* @param bizType
* @param user
*/
LogImportVO addDefaultLog(LogImportBizType bizType, SysUser user);
LogImportVO addDefaultLog(LogImportType type, LogImportBizType bizType, SysUser user);
/**

View File

@ -1,6 +1,5 @@
package com.ruoyi.web.yh.logImport.service.impl;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@ -9,7 +8,7 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportBizType;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportStatus;
import com.ruoyi.web.yh.logImportDetail.domain.enums.LogImportDetailType;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.web.yh.logImport.mapper.LogImportMapper;
@ -107,12 +106,13 @@ public class LogImportServiceImpl implements ILogImportService
}
@Override
public LogImportVO addDefaultLog(LogImportBizType bizType, SysUser user) {
public LogImportVO addDefaultLog(LogImportType type, LogImportBizType bizType, SysUser user) {
LogImport po = new LogImport();
po.setStatus(LogImportStatus.PROCESSING.getStatus());
po.setBizType(bizType.getType());
po.setCreateId(user.getUserId());
po.setCreateBy(user.getNickName());
po.setType(type.getType());
int insert = this.insertLogImport(po);
ServiceUtil.assertion(insert != 1, "新增导入日志失败");

View File

@ -117,6 +117,7 @@ public class MaterialController extends BaseController
@Log(title = LOG_TITLE, businessType = BusinessType.SYNC, bizType = LogBizType.MATERIAL)
@PutMapping("/sync")
public AjaxResult sync() {
return success(materialService.sync());
materialService.sync();
return success();
}
}

View File

@ -61,6 +61,6 @@ public interface MaterialService
*/
public int deleteMaterialById(Long id);
int sync();
void sync();
}

View File

@ -124,43 +124,44 @@ public class MaterialServiceImpl implements MaterialService
}
@Override
public int sync() {
// 查询字段
List<String> fieldKeys = Arrays.asList(
K3MaterialField.F_MATERIAL_ID,
K3MaterialField.F_NUMBER,
K3MaterialField.F_NAME,
K3MaterialField.F_SPECIFICATION
);
int startRow = 0;
int limit = 10000;
int size = 0;
public void sync() {
scheduledExecutorService.schedule(() -> {
// 查询字段
List<String> fieldKeys = Arrays.asList(
K3MaterialField.F_MATERIAL_ID,
K3MaterialField.F_NUMBER,
K3MaterialField.F_NAME,
K3MaterialField.F_SPECIFICATION
);
int startRow = 0;
int limit = 10000;
int size = 0;
// 一直查询直到查到的数据量比limit小说明查完了
while(true) {
// 查询ERP数据
List<JSONArray> erpList = k3Service.selectList(K3FormIds.MATERIAL, fieldKeys, startRow, limit);
// 一直查询直到查到的数据量比limit小说明查完了
while(true) {
// 查询ERP数据
List<JSONArray> erpList = k3Service.selectList(K3FormIds.MATERIAL, fieldKeys, startRow, limit);
// 转为PO
List<Material> materialList = materialConverter.toPoByErpList(fieldKeys, erpList);
// 转为PO
List<Material> materialList = materialConverter.toPoByErpList(fieldKeys, erpList);
// 保存
for (Material material : materialList) {
scheduledExecutorService.schedule(() -> {
this.saveByErpId(material);
}, 0, TimeUnit.SECONDS);
// 保存
for (Material material : materialList) {
scheduledExecutorService.schedule(() -> {
this.saveByErpId(material);
}, 0, TimeUnit.SECONDS);
}
size += materialList.size();
if (materialList.size() < limit) {
break;
} else {
startRow += limit;
}
}
}, 0, TimeUnit.SECONDS);
size += materialList.size();
if (materialList.size() < limit) {
break;
} else {
startRow += limit;
}
}
return size;
}
/**

View File

@ -21,6 +21,7 @@ import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.yh.logImport.domain.LogImportVO;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportBizType;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportType;
import com.ruoyi.web.yh.logImport.service.ILogImportService;
import com.ruoyi.web.yh.logImportDetail.domain.enums.LogImportDetailType;
import com.ruoyi.web.yh.logImportDetail.service.ILogImportDetailService;
@ -305,7 +306,7 @@ public class PriceServiceImpl implements PriceService
ServiceUtil.assertion(user == null, "操作人不存在");
// 新增一个日志
LogImportVO importLog = logImportService.addDefaultLog(LogImportBizType.PRICE, user);
LogImportVO importLog = logImportService.addDefaultLog(LogImportType.IMPORT, LogImportBizType.PRICE, user);
ServiceUtil.assertion(importLog == null, "创建导入日志失败");
// 开始异步导入

View File

@ -3,9 +3,10 @@ package com.ruoyi.web.yh.prodOrder.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constants.LogTitle;
import com.ruoyi.common.enums.LogBizType;
import com.ruoyi.web.yh.prodOrder.domain.dto.ProdOrderSyncQuery;
import com.ruoyi.web.yh.prodOrder.domain.enums.ProdOrderErpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -124,8 +125,10 @@ public class ProdOrderController extends BaseController
@PreAuthorize("@ss.hasPermi('yh:productOrder:sync')")
@Log(title = LogTitle.PROD_ORDER, businessType = BusinessType.SYNC, bizType = LogBizType.PROD_ORDER)
@PutMapping("/sync")
public AjaxResult sync() {
return success(prodOrderService.sync());
public AjaxResult sync(@RequestBody ProdOrderSyncQuery query) {
query.setStatusList(ProdOrderErpStatus.canSync());
prodOrderService.sync(query, getUserId());
return success();
}
}

View File

@ -114,11 +114,17 @@ public class ProdOrder extends BaseEntity
@ApiModelProperty("ERP基本单位未入库数量")
private BigDecimal erpBaseNoStockInQty;
@Excel(name = "已审核通过的基数量")
@ApiModelProperty("已审核通过的基数量")
@Excel(name = "已审核通过的基数量")
@ApiModelProperty("已审核通过的基数量")
private BigDecimal verifiedBaseNum;
@Excel(name = "ERP明细基本单位ID")
@ApiModelProperty("ERP明细基本单位ID")
private String erpBaseUnitId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "最近同步时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("最近同步时间")
private LocalDateTime syncTime;
}

View File

@ -0,0 +1,22 @@
package com.ruoyi.web.yh.prodOrder.domain.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 同步生产订单的查询参数
* @author wjh
* 2024/11/20
*/
@Data
public class ProdOrderSyncQuery {
@ApiModelProperty("业务状态列表")
private List<String> statusList;
@ApiModelProperty("生产订单ID")
private String id;
}

View File

@ -0,0 +1,38 @@
package com.ruoyi.web.yh.prodOrder.domain.enums;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.web.yh.prodOrder.domain.dto.ProdOrderSyncQuery;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author wjh
* 2024/11/20
*/
@Getter
@AllArgsConstructor
public enum ProdOrderErpStatus {
PLAN("1", "计划"),
PLAN_CONFIRM("2", "计划确认"),
ISSUED("3", "下达"),
START_WORK("4", "开工"),
END_WORK("5", "完工"),
CLOSED("6", "结案"),
FINISHED("7", "结算");
private final String status;
private final String msg;
/**
* 允许同步的状态列表
*/
public static List<String> canSync() {
return CollectionUtils.map(ProdOrderErpStatus::getStatus, START_WORK, END_WORK, CLOSED, FINISHED);
}
}

View File

@ -0,0 +1,45 @@
package com.ruoyi.web.yh.prodOrder.domain.vo;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.constants.DictType;
import com.ruoyi.web.yh.logImportDetail.domain.interfaces.ImportContent;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrder;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrderVO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.poi.ss.usermodel.IndexedColors;
/**
* @author wjh
* 2024/11/20
*/
@Data
public class ProdOrderImportContentVO extends ProdOrder implements ImportContent {
@Excel(
name = "导入结果",
dictType = DictType.LOG_IMPORT_DETAIL_TYPE,
comboReadDict = true,
backgroundColor = IndexedColors.YELLOW,
headerBackgroundColor = IndexedColors.YELLOW,
color = IndexedColors.RED,
headerColor = IndexedColors.RED,
sort = 0
)
private String importResult;
@Excel(
name = "导入信息",
width = 30,
backgroundColor = IndexedColors.YELLOW,
headerBackgroundColor = IndexedColors.YELLOW,
color = IndexedColors.RED,
headerColor = IndexedColors.RED,
sort = 1
)
private String importMessage;
@Excel(name = "部门名称", prompt = "必填")
@ApiModelProperty("部门名称")
private String deptName;
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.web.yh.prodOrder.mapper;
import java.math.BigDecimal;
import java.util.List;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrder;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrderVO;
@ -61,4 +62,11 @@ public interface ProdOrderMapper
* @return 结果
*/
public int deleteProdOrderByIds(Long[] ids);
/**
* 增加已审核通过的基础数量
* @param orderId 订单ID
* @param num 基础数量
*/
int addVerifiedBaseNum(@Param("orderId") Long orderId, @Param("num") BigDecimal num);
}

View File

@ -35,6 +35,7 @@
bpo.erp_base_no_stock_in_qty,
bpo.verified_base_num,
bpo.erp_base_unit_id,
bpo.sync_time,
bm.erp_number as material_number,
sd.dept_name as work_shop_name,
sd.dept_id as dept_id,
@ -119,6 +120,7 @@
<if test="erpBaseNoStockInQty != null">erp_base_no_stock_in_qty,</if>
<if test="verifiedBaseNum != null">verified_base_num,</if>
<if test="erpBaseUnitId != null">erp_base_unit_id,</if>
<if test="syncTime != null">sync_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="erpId != null and erpId != ''">#{erpId},</if>
@ -145,9 +147,16 @@
<if test="erpBaseNoStockInQty != null">#{erpBaseNoStockInQty},</if>
<if test="verifiedBaseNum != null">#{verifiedBaseNum},</if>
<if test="erpBaseUnitId != null">#{erpBaseUnitId},</if>
<if test="syncTime != null">#{syncTime},</if>
</trim>
</insert>
<update id="addVerifiedBaseNum">
update bst_prod_order
set verified_base_num = verified_base_num + #{num}
where id = #{orderId}
</update>
<update id="updateProdOrder" parameterType="ProdOrder">
update bst_prod_order
<trim prefix="SET" suffixOverrides=",">
@ -181,6 +190,7 @@
<if test="data.erpBaseNoStockInQty != null">erp_base_no_stock_in_qty = #{data.erpBaseNoStockInQty},</if>
<if test="data.verifiedBaseNum != null">verified_base_num = #{data.verifiedBaseNum},</if>
<if test="data.erpBaseUnitId != null">erp_base_unit_id = #{data.erpBaseUnitId},</if>
<if test="data.syncTime != null">sync_time = #{data.syncTime},</if>
</sql>
<delete id="deleteProdOrderById" parameterType="Long">

View File

@ -1,9 +1,11 @@
package com.ruoyi.web.yh.prodOrder.service;
import java.math.BigDecimal;
import java.util.List;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrder;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrderVO;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrderQuery;
import com.ruoyi.web.yh.prodOrder.domain.dto.ProdOrderSyncQuery;
/**
* 生产订单Service接口
@ -64,7 +66,7 @@ public interface ProdOrderService
/**
* 从ERP同步数据
*/
int sync();
void sync(ProdOrderSyncQuery query, Long operaId);
/**
* 根据单据编号查询单据
@ -77,4 +79,11 @@ public interface ProdOrderService
* @return
*/
ProdOrderVO selectOne(ProdOrderQuery query);
/**
* 增加已审核的基本单位数量
* @param orderId 订单ID
* @param num 增加数量
*/
int addVerifiedBaseNum(Long orderId, BigDecimal num);
}

View File

@ -10,6 +10,7 @@ import com.ruoyi.web.yh.prodOrder.service.ProdOrderConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -21,9 +22,6 @@ import java.util.List;
@Service
public class ProdOrderConverterImpl implements ProdOrderConverter {
@Autowired
private MaterialService materialService;
/**
* 将ERP数据转为PO列表
*
@ -39,6 +37,8 @@ public class ProdOrderConverterImpl implements ProdOrderConverter {
// 创建erpList大小的对象列表
List<ProdOrder> result = new ArrayList<>(erpList.size());
LocalDateTime syncTime = LocalDateTime.now();
for (JSONArray row : erpList) {
ProdOrder po = new ProdOrder();
for (int i = 0; i < headers.size(); i++) {
@ -110,6 +110,10 @@ public class ProdOrderConverterImpl implements ProdOrderConverter {
default: break;
}
}
// 同步时间
po.setSyncTime(syncTime);
result.add(po);
}

View File

@ -1,13 +1,17 @@
package com.ruoyi.web.yh.prodOrder.service.impl;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.alibaba.fastjson2.JSONArray;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.exception.ServiceException;
@ -17,6 +21,15 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.k3cloud.constants.fileds.K3ProdField;
import com.ruoyi.common.k3cloud.constants.K3FormIds;
import com.ruoyi.common.k3cloud.service.K3Service;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.yh.logImport.domain.LogImportVO;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportBizType;
import com.ruoyi.web.yh.logImport.domain.enums.LogImportType;
import com.ruoyi.web.yh.logImport.service.ILogImportService;
import com.ruoyi.web.yh.logImportDetail.domain.enums.LogImportDetailType;
import com.ruoyi.web.yh.logImportDetail.service.ILogImportDetailService;
import com.ruoyi.web.yh.prodOrder.domain.dto.ProdOrderSyncQuery;
import com.ruoyi.web.yh.prodOrder.service.ProdOrderConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -26,7 +39,6 @@ import com.ruoyi.web.yh.prodOrder.domain.ProdOrder;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrderVO;
import com.ruoyi.web.yh.prodOrder.domain.ProdOrderQuery;
import com.ruoyi.web.yh.prodOrder.service.ProdOrderService;
import org.springframework.util.CollectionUtils;
/**
* 生产订单Service业务层处理
@ -53,6 +65,15 @@ public class ProdOrderServiceImpl implements ProdOrderService
@Autowired
private RedisLock redisLock;
@Autowired
private ILogImportService logImportService;
@Autowired
private ISysUserService userService;
@Autowired
private ILogImportDetailService logImportDetailService;
/**
* 查询生产订单
*
@ -128,62 +149,86 @@ public class ProdOrderServiceImpl implements ProdOrderService
}
@Override
public int sync() {
// 查询字段
List<String> fieldKeys = Arrays.asList(
K3ProdField.FID,
K3ProdField.F_BILL_NO,
K3ProdField.F_DOCUMENT_STATUS,
K3ProdField.F_CREATE_DATE,
K3ProdField.F_MODIFY_DATE,
K3ProdField.F_DESCRIPTION,
K3ProdField.F_DATE,
K3ProdField.F_IS_REWORK,
K3ProdField.F_ROW_ID,
K3ProdField.F_MEMO_ITEM,
K3ProdField.F_CONVEY_DATE,
K3ProdField.F_STATUS,
K3ProdField.F_WORK_SHOP_ID,
K3ProdField.F_REQ_SRC,
K3ProdField.F_BASE_UNIT_QTY,
K3ProdField.F_QTY,
K3ProdField.F_UNIT_ID,
K3ProdField.F_BASE_UNIT_ID,
K3ProdField.F_MATERIAL_ID,
K3ProdField.F_NO_STOCK_IN_QTY,
K3ProdField.F_BASE_NO_STOCK_IN_QTY
);
int startRow = 0;
int limit = 10000;
int size = 0;
String filterString = "FStatus in (4,5,6,7)";
// 一直查询直到查到的数据量比limit小说明查完了
while(true) {
// 查询ERP数据
List<JSONArray> erpList = k3Service.selectList(K3FormIds.PROD_ORDER, fieldKeys, startRow, limit, filterString, "");
// 转为PO
List<ProdOrder> prodOrderList = prodOrderConverter.toPoByErpList(fieldKeys, erpList);
// 保存
for (ProdOrder prodOrder : prodOrderList) {
scheduledExecutorService.schedule(() -> {
this.saveByErpRowId(prodOrder);
}, 0, TimeUnit.SECONDS);
}
size += prodOrderList.size();
if (prodOrderList.size() < limit) {
break;
} else {
startRow += limit;
}
public void sync(ProdOrderSyncQuery query, Long operaId) {
// 操作人
SysUser user = null;
if (Constants.SYSTEM_USER_ID.equals(operaId)) {
user = SysUser.system();
} else {
user = userService.selectUserById(operaId);
}
return size;
// 新增一个日志
LogImportVO importLog = logImportService.addDefaultLog(LogImportType.SYNC, LogImportBizType.PROD_ORDER, user);
ServiceUtil.assertion(importLog == null, "创建同步日志失败");
Long logId = importLog.getLogId();
scheduledExecutorService.schedule(() -> {
// 查询字段
List<String> fieldKeys = Arrays.asList(
K3ProdField.FID,
K3ProdField.F_BILL_NO,
K3ProdField.F_DOCUMENT_STATUS,
K3ProdField.F_CREATE_DATE,
K3ProdField.F_MODIFY_DATE,
K3ProdField.F_DESCRIPTION,
K3ProdField.F_DATE,
K3ProdField.F_IS_REWORK,
K3ProdField.F_ROW_ID,
K3ProdField.F_MEMO_ITEM,
K3ProdField.F_CONVEY_DATE,
K3ProdField.F_STATUS,
K3ProdField.F_WORK_SHOP_ID,
K3ProdField.F_REQ_SRC,
K3ProdField.F_BASE_UNIT_QTY,
K3ProdField.F_QTY,
K3ProdField.F_UNIT_ID,
K3ProdField.F_BASE_UNIT_ID,
K3ProdField.F_MATERIAL_ID,
K3ProdField.F_NO_STOCK_IN_QTY,
K3ProdField.F_BASE_NO_STOCK_IN_QTY
);
int startRow = 0;
int limit = 10000;
int size = 0;
// 构建过滤条件
StringBuilder fb = new StringBuilder();
if (CollectionUtils.isNotEmptyElement(query.getStatusList())) {
fb.append(" and FStatus in (").append(query.getStatusList().stream().map(Object::toString).collect(Collectors.joining(","))).append(")");
}
if (query.getId() != null) {
fb.append(" and FID = ").append(query.getId());
}
String filterString = fb.substring(4);
// 一直查询直到查到的数据量比limit小说明查完了
while(true) {
// 查询ERP数据
List<JSONArray> erpList = k3Service.selectList(K3FormIds.PROD_ORDER, fieldKeys, startRow, limit, filterString, "");
// 转为PO
List<ProdOrder> prodOrderList = prodOrderConverter.toPoByErpList(fieldKeys, erpList);
// 保存
for (ProdOrder prodOrder : prodOrderList) {
scheduledExecutorService.schedule(() -> {
this.saveByErpRowId(prodOrder, logId);
}, 0, TimeUnit.SECONDS);
}
size += prodOrderList.size();
if (prodOrderList.size() < limit) {
logImportService.updateLogToFinished(logId);
break;
} else {
startRow += limit;
}
}
return size;
}, 0, TimeUnit.SECONDS);
}
/**
@ -217,37 +262,50 @@ public class ProdOrderServiceImpl implements ProdOrderService
return list.get(0);
}
/**
* 增加已审核的基本单位数量
*
* @param orderId 订单ID
* @param num 增加数量
*/
@Override
public int addVerifiedBaseNum(Long orderId, BigDecimal num) {
if (orderId == null || num == null) {
return 0;
}
return prodOrderMapper.addVerifiedBaseNum(orderId, num);
}
/**
* 新增或修改
*/
private int saveByErpRowId(ProdOrder prodOrder) {
String errorMsg = "成功";
private int saveByErpRowId(ProdOrder prodOrder, Long logId) {
if (prodOrder == null || StringUtils.isBlank(prodOrder.getErpRowId())) {
throw new ServiceException("参数错误");
}
String lockKey = prodOrder.getErpRowId();
ServiceUtil.assertion(!redisLock.lock(RedisLockKey.SYNC_PROD_BILL, lockKey), "当前生产订单正在处理中,请稍后重试");
try {
if (prodOrder == null || StringUtils.isBlank(prodOrder.getErpRowId())) {
throw new ServiceException("参数错误");
}
String lockKey = prodOrder.getErpRowId();
ServiceUtil.assertion(!redisLock.lock(RedisLockKey.SYNC_PROD_BILL, lockKey), "当前生产订单正在处理中,请稍后重试");
try {
// 若数据库中没有,则新增,否则修改
ProdOrderVO old = this.selectByErpRowId(prodOrder.getErpRowId());
if (old == null) {
return this.insertProdOrder(prodOrder);
} else {
prodOrder.setId(old.getId());
return this.updateProdOrder(prodOrder);
}
} finally {
redisLock.unlock(RedisLockKey.SYNC_PROD_BILL, lockKey);
// 若数据库中没有,则新增,否则修改
ProdOrderVO old = this.selectByErpRowId(prodOrder.getErpRowId());
if (old == null) {
int insert = this.insertProdOrder(prodOrder);
ServiceUtil.assertion(insert != 1, "新增失败");
logImportDetailService.addResult(logId, LogImportDetailType.ADD, prodOrder, null);
return insert;
} else {
prodOrder.setId(old.getId());
int update = this.updateProdOrder(prodOrder);
ServiceUtil.assertion(update != 1, "修改失败");
logImportDetailService.addResult(logId, LogImportDetailType.UPDATE, prodOrder, null);
return update;
}
} catch (Exception e) {
errorMsg = e.getMessage();
logImportDetailService.addResult(logId, LogImportDetailType.FAIL, prodOrder, e.getMessage());
return 0;
} finally {
// TODO 记录日志
log.info("同步生产订单:{}", errorMsg);
redisLock.unlock(RedisLockKey.SYNC_PROD_BILL, lockKey);
}
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.web.yh.report.domain.dto;
import com.ruoyi.framework.web.domain.log.LogBizParam;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -12,7 +13,7 @@ import javax.validation.constraints.Size;
* 2024/11/8
*/
@Data
public class ReportVerifyDTO {
public class ReportVerifyDTO implements LogBizParam {
@ApiModelProperty("报表ID")
@NotNull(message = "报表ID不允许为空")
@ -26,4 +27,11 @@ public class ReportVerifyDTO {
@Size(max = 1000, message = "审核意见不允许超过1000个字符")
private String verifyRemark;
/**
* 获取日志业务ID
*/
@Override
public Object logBizId() {
return reportId;
}
}

View File

@ -1,6 +1,8 @@
package com.ruoyi.web.yh.report.service.impl;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@ -11,10 +13,13 @@ import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.common.utils.collection.DiffListVO;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.yh.prodOrder.service.ProdOrderService;
import com.ruoyi.web.yh.report.domain.bo.ReportBO;
import com.ruoyi.web.yh.report.domain.dto.ReportVerifyDTO;
import com.ruoyi.web.yh.report.domain.enums.ReportStatus;
import com.ruoyi.web.yh.report.service.ReportAssembler;
import com.ruoyi.web.yh.report.service.ReportValidator;
import com.ruoyi.web.yh.report.utils.ReportUtils;
import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProd;
import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
import com.ruoyi.web.yh.reportOrderProd.domain.bo.ReportOrderProdBO;
@ -66,6 +71,12 @@ public class ReportServiceImpl implements ReportService
@Autowired
private ReportValidator reportValidator;
@Autowired
private ProdOrderService prodOrderService;
@Autowired
private ReportAssembler reportAssembler;
/**
* 查询报表
*
@ -306,6 +317,8 @@ public class ReportServiceImpl implements ReportService
ReportVO report = selectReportByReportId(dto.getReportId());
ServiceUtil.assertion(report == null, "待审核的报表不存在");
ServiceUtil.assertion(!ReportStatus.canVerify().contains(report.getStatus()), "当前报表状态不允许审核,请刷新后重试");
// 拼接报表订单数据
reportAssembler.assembleProductList(Collections.singletonList(report), false, true);
// 组装修改数据
Report data = new Report();
@ -323,10 +336,30 @@ public class ReportServiceImpl implements ReportService
query.setReportId(report.getReportId());
query.setStatusList(ReportStatus.canVerify());
// 获取订单数据
List<ReportOrderProdVO> orderProdList = report.getProductList().stream()
.map(ReportProdVO::getOrderProdList).flatMap(List::stream).collect(Collectors.toList());
// 修改数据库
Integer result = transactionTemplate.execute(status -> {
int update = this.updateByQuery(data, query);
ServiceUtil.assertion(update != 1, "审核失败,当前报表状态已发生变化,请刷新后重试");
// 关联的订单全部增加已审核的数量
for (ReportOrderProdVO orderProd : orderProdList) {
if (orderProd == null) {
continue;
}
ServiceUtil.assertion(orderProd.getOrderId() == null
|| orderProd.getNum() == null
|| orderProd.getPriceQuantity() == null,
"修改订单审核数量出错:参数错误"
);
BigDecimal baseNum = ReportUtils.calcOrderProdBaseNum(orderProd);
int add = prodOrderService.addVerifiedBaseNum(orderProd.getOrderId(), baseNum);
ServiceUtil.assertion(add != 1, "更新关联订单失败");
}
return update;
});

View File

@ -0,0 +1,24 @@
package com.ruoyi.web.yh.report.utils;
import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
import java.math.BigDecimal;
/**
* @author wjh
* 2024/11/20
*/
public class ReportUtils {
/**
* 计算报表订单产量的基础数量
*/
public static BigDecimal calcOrderProdBaseNum(ReportOrderProdVO vo) {
if (vo == null || vo.getPriceQuantity() == null || vo.getNum() == null) {
return BigDecimal.ZERO;
}
return vo.getPriceQuantity().multiply(vo.getNum());
}
}

View File

@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* @author wjh
@ -15,6 +16,12 @@ public class ReportOrderProdVO extends ReportOrderProd {
@ApiModelProperty("报表ID")
private Long reportId;
@ApiModelProperty("报表日期")
private LocalDate reportDate;
@ApiModelProperty("报表状态")
private String reportStatus;
@ApiModelProperty("订单编号")
private String orderErpBillNo;
@ -42,4 +49,15 @@ public class ReportOrderProdVO extends ReportOrderProd {
@ApiModelProperty("订单已审核通过的基础产量")
private BigDecimal verifiedBaseNum;
@ApiModelProperty("工序倍数")
private BigDecimal priceQuantity;
@ApiModelProperty("工序单位")
private String priceUnit;
@ApiModelProperty("工序名称")
private String priceName;
@ApiModelProperty("工序单价")
private BigDecimal pricePrice;
}

View File

@ -14,6 +14,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
brop.num,
brop.deleted,
brp.report_id as report_id,
brp.price_quantity as price_quantity,
brp.price_unit as price_unit,
brp.price_name as price_name,
brp.price_price as price_price,
bpo.erp_bill_no as order_erp_bill_no,
bpo.erp_qty as order_erp_qty,
bpo.erp_no_stock_in_qty as order_erp_no_stock_in_qty,
@ -21,7 +25,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bpo.erp_base_no_stock_in_qty as order_erp_base_no_stock_in_qty,
bpo.verified_base_num as verified_base_num,
bu.erp_name as unit_name,
bu_b.erp_name as base_unit_name
bu_b.erp_name as base_unit_name,
br.report_date as report_date,
br.status as report_status
from bst_report_order_prod brop
left join bst_report_prod brp on brp.id = brop.report_prod_id
left join bst_report br on br.report_id = brp.report_id

View File

@ -118,6 +118,7 @@ public class UnitController extends BaseController
@PutMapping("/sync")
public AjaxResult sync()
{
return toAjax(unitService.sync());
unitService.sync();
return success();
}
}

View File

@ -64,6 +64,6 @@ public interface UnitService
/**
* 同步ERP单位
*/
int sync();
void sync();
}

View File

@ -124,43 +124,43 @@ public class UnitServiceImpl implements UnitService
}
@Override
public int sync() {
// 查询字段
List<String> fieldKeys = Arrays.asList(
public void sync() {
// 查询字段
scheduledExecutorService.schedule(() -> {
List<String> fieldKeys = Arrays.asList(
K3UnitField.F_UNIT_ID,
K3UnitField.F_NUMBER,
K3UnitField.F_NAME,
K3UnitField.F_FORBID_STATUS
);
int startRow = 0;
int limit = 10000;
int size = 0;
);
int startRow = 0;
int limit = 10000;
int size = 0;
// 一直查询直到查到的数据量比limit小说明查完了
while(true) {
// 查询ERP数据
List<JSONArray> erpList = k3Service.selectList(K3FormIds.UNIT, fieldKeys, startRow, limit);
// 一直查询直到查到的数据量比limit小说明查完了
while(true) {
// 查询ERP数据
List<JSONArray> erpList = k3Service.selectList(K3FormIds.UNIT, fieldKeys, startRow, limit);
// 转为PO
List<Unit> unitList = unitConverter.toPoByErpList(fieldKeys, erpList);
// 转为PO
List<Unit> unitList = unitConverter.toPoByErpList(fieldKeys, erpList);
// 保存
for (Unit unit : unitList) {
scheduledExecutorService.schedule(() -> {
this.saveByErpId(unit);
}, 0, TimeUnit.SECONDS);
// 保存
for (Unit unit : unitList) {
scheduledExecutorService.schedule(() -> {
this.saveByErpId(unit);
}, 0, TimeUnit.SECONDS);
}
size += unitList.size();
if (unitList.size() < limit) {
break;
} else {
startRow += limit;
}
}
size += unitList.size();
if (unitList.size() < limit) {
break;
} else {
startRow += limit;
}
}
return size;
}, 0, TimeUnit.SECONDS);
}
private int saveByErpId(Unit unit) {