add:1.增加同步ERP库存,立库单物料总库存,ERP动态同步条件构建,立库库存差异对比;

2.增加搜索库存变动,ERP回传查询搜索条件;
fix:1.修复仓库id动态取值,搜索条件bug;
     2.修复拣选取值bug,核对多生成的领料单物料数值,ERP单据平账;
This commit is contained in:
2025-01-10 09:06:38 +08:00
parent 0a14e0cd18
commit d3bcf0cd73
13 changed files with 267 additions and 104 deletions

View File

@@ -4,12 +4,14 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.javaparser.utils.Log;
import com.google.gson.JsonObject;
import com.kingdee.bos.webapi.entity.*;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nl.common.domain.exception.BadRequestException;
import org.nl.wms.external_system.erp.dto.ErpQuery;
import org.nl.wms.external_system.erp.dto.ErpQueryJson;
import org.nl.wms.external_system.erp.dto.ErpSec;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@@ -42,6 +44,7 @@ public class ErpServiceUtils {
}
/**
* 查询单据-单据明细
* @param query 查询条件
*/
public JSONArray queryBills(ErpQuery query) {
@@ -92,6 +95,39 @@ public class ErpServiceUtils {
return JSON.parseArray(JSON.toJSONString(result));
}
/**
* 查询单据指定结果
*/
public List<JSONObject> queryResult(ErpQueryJson query) {
if (StringUtils.isBlank(query.getFormId())) {
throw new BadRequestException("参数异常");
}
boolean islock = lock.tryLock();
List<JSONObject> result = new ArrayList<>();
try {
if (islock) {
String jsonString = JSON.toJSONString(query);
K3CloudApi cloudApi = getCloudApi();
List<List<Object>> lists = cloudApi.executeBillQuery(jsonString);
for (List<Object> list : lists) {
JSONObject jsonObject =new JSONObject();
jsonObject.put("material_code",list.get(0));
jsonObject.put("erpCounts",list.get(1));
result.add(jsonObject);
}
} else {
throw new BadRequestException("当前同步操作正在执行,稍后再试");
}
} catch (Exception ex) {
throw new BadRequestException(ex.getMessage());
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return result;
}
/**
* 单据保存

View File

@@ -2,6 +2,9 @@ package org.nl.wms.external_system.erp.dto;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class ErpQuery {
/**
@@ -12,16 +15,17 @@ public class ErpQuery {
* 需查询的字段key集合字符串类型格式"key1,key2,..."(必录) 注(查询单据体内码,需加单据体Key和下划线,如FEntryKey_FEntryId
*/
private String FieldKeys = "FID";
/**
* 过滤条件,数组类型,如:[{"Left":"(","FieldName":"Field1","Compare":"67","Value":"111","Right":")","Logic":"0"},{"Left":"(","FieldName":"Field2","Compare":"67","Value":"222","Right":")","Logic":"0"}]
* 过滤条件,字符串
*/
private String FilterString;
/**
* 排序字段,字符串类型(非必录)
*/
private String OrderString;
/**
*
* 返回总行数,整型(非必录)
*/
private Integer TopRowCount;

View File

@@ -0,0 +1,43 @@
package org.nl.wms.external_system.erp.dto;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class ErpQueryJson {
/**
* 业务对象表单Id必录
*/
private String FormId;
/**
* 需查询的字段key集合字符串类型格式"key1,key2,..."(必录) 注(查询单据体内码,需加单据体Key和下划线,如FEntryKey_FEntryId
*/
private String FieldKeys = "FID";
/**
* 过滤条件,数组类型,如:[{"Left":"(","FieldName":"Field1","Compare":"67","Value":"111","Right":")","Logic":"0"},{"Left":"(","FieldName":"Field2","Compare":"67","Value":"222","Right":")","Logic":"0"}]
*/
private List<Map<String, String>> FilterString;
/**
* 排序字段,字符串类型(非必录)
*/
private String OrderString;
/**
* 返回总行数,整型(非必录)
*/
private Integer TopRowCount;
/**
* 开始行索引,整型(非必录)
*/
private Integer StartRow = 0;
/**
* 行数
*/
private Integer Limit = 100;
/**
* 表单所在的子系统内码,字符串类型(非必录)
*/
private Integer SubSystemId;
}

View File

@@ -267,6 +267,7 @@ public class PdaIOService {
dtlJ.putAll((Map) dtlJ.remove("form_data"));
sourceFormData.putAll(dtlJ);
sourceFormData.put("pcsn",disPcsn);
sourceFormData.put("stock_code", "FStockId".equals(ivtDtl.getStor_code())?"25":"24");
ivtDtl.setSource_form_data(sourceFormData);
}
list.add(ivtDtl);

View File

@@ -52,7 +52,7 @@ public class PalletIostorinvService {
String material_id = form.getString("material_id");
BmVehicleInfo vehicleInfo = iBmVehicleInfoService.getOne(new QueryWrapper<BmVehicleInfo>().eq("vehicle_code", vehicle_code));
if (vehicleInfo ==null ){
throw new BadRequestException("入库失败:载具信息不存在已经存在");
throw new BadRequestException("入库失败:载具信息未注册,请录入载具信息");
}
int count = iMdPbVehicleMaterService.count(new QueryWrapper<MdPbVehicleMater>()
.eq("vehicle_code", vehicle_code)

View File

@@ -109,5 +109,11 @@ public class StIvtIostorinv implements Serializable {
@TableField(insertStrategy = FieldStrategy.NEVER,updateStrategy = FieldStrategy.NEVER)
private Boolean in_storage;
/**
* 仓库编号
*/
@TableField(exist = false)
private String stor_code;
}

View File

@@ -109,6 +109,7 @@ public class StIvtIostorinvServiceImpl extends ServiceImpl<StIvtIostorinvOutMapp
dtlJ.putAll((Map) dtlJ.remove("form_data"));
sourceFormData.putAll(dtlJ);
sourceFormData.put("pcsn",dtl.getPcsn());
sourceFormData.put("stock_code", "FStockId".equals(dtl.getStor_code())?"25":"24");
sourceFormData.put("now_assign_qty",dtl.getQty());
dtl.setSource_form_data(sourceFormData);
list.add(MapOf.of("qty",sourDtl.getQty().subtract(dtl.getQty())

View File

@@ -107,6 +107,6 @@ public class StIvtStructattrController {
null,
MapOf.linkOf("stor_code","仓库编码","struct_code","仓位","vehicle_code","载具编码",
"material_code","物料编号","material_code","物料名称","pcsn","批号"
,"forzen_qty","冻结数量","qty","存数量","create_time","组盘入库时间"));
,"forzen_qty","冻结数量","qty","位库存","counts","物料总库存","erpCounts","ERP实时库存","differCount","立库-ERP库存差异","create_time","组盘入库时间"));
}
}

View File

@@ -140,7 +140,10 @@
vm.parent_vehicle_code,
material.material_code,
material.material_name,
vm.create_time
vm.create_time,
struct.w as counts,
struct.l as erpCounts,
struct.weight as differCount
FROM
st_ivt_structattr struct
left join md_pb_vehicleMater vm on struct.vehicle_code = vm.vehicle_code

View File

@@ -1,9 +1,13 @@
package org.nl.wms.stor_manage.struct.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
@@ -11,9 +15,9 @@ import org.nl.common.TableDataInfo;
import org.nl.common.domain.entity.PageQuery;
import org.nl.common.domain.exception.BadRequestException;
import org.nl.common.enums.StatusEnum;
import org.nl.common.utils.ErpServiceUtils;
import org.nl.common.utils.IdUtil;
import org.nl.wms.external_system.erp.dto.ErpQueryJson;
import org.nl.wms.flow_manage.flow.framework.process.nodeType.excess.impl.DecisionHandler;
import org.nl.wms.md_manage.group_dick.service.IMdGruopDickService;
import org.nl.wms.md_manage.group_dick.service.dao.MdGruopDick;
@@ -21,11 +25,10 @@ import org.nl.wms.md_manage.vehicleMater.service.IMdPbVehicleMaterService;
import org.nl.wms.md_manage.vehicleMater.service.dao.MdPbVehicleMater;
import org.nl.wms.stor_manage.record.service.IStIvtStructivtflowService;
import org.nl.wms.stor_manage.record.service.dao.StIvtStructivtflow;
import org.nl.wms.stor_manage.struct.service.IStIvtStructattrService;
import org.nl.wms.stor_manage.struct.service.dao.StIvtStructattr;
import org.nl.wms.stor_manage.struct.service.dao.StructAssignQty;
import org.nl.wms.stor_manage.struct.service.dao.mapper.StIvtStructattrMapper;
import org.nl.wms.stor_manage.struct.service.IStIvtStructattrService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.nl.wms.stor_manage.struct.service.dto.StructattrQuery;
import org.nl.wms.stor_manage.struct.service.dto.StructattrVechielDto;
import org.nl.wms.system_manage.service.param.ISysParamService;
@@ -40,6 +43,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
@@ -64,12 +68,15 @@ public class StIvtStructattrServiceImpl extends ServiceImpl<StIvtStructattrMappe
@Autowired
@Lazy
private DecisionHandler decisionHandler;
@Autowired
@Lazy
private ErpServiceUtils erpServiceUtils;
public static void main(String[] args) {
Boolean in = StatusEnum.TASK_TYPE.check("10");
System.out.println(in);
}
@Override
public void changeStruct(String struct_code, String vehicle_code, String task_type, BigDecimal change_qty, Boolean growth) {
String now = DateUtil.now();
@@ -199,9 +206,68 @@ public class StIvtStructattrServiceImpl extends ServiceImpl<StIvtStructattrMappe
@Override
public TableDataInfo<Map> getStructIvt(StructattrQuery query, PageQuery pageQuery) {
if (StringUtils.isNotBlank(query.getMaterial()) || StringUtils.isNotBlank(query.getPcsn())) {
if (StringUtils.isNotBlank(query.getMaterial())) {
query.setMaterial(query.getMaterial().trim());
} else {
query.setPcsn(query.getPcsn().trim());
}
pageQuery.setSize(5000);
}
Page<Object> page = PageHelper.startPage(pageQuery.getPage() + 1, pageQuery.getSize());
page.setOrderBy("struct.update_time DESC");
List<Map> mst_detail = this.baseMapper.getStructIvt(query, pageQuery);
if (ObjectUtil.isNotEmpty(mst_detail)) {
if ((StringUtils.isNotBlank(query.getMaterial()) || StringUtils.isNotBlank(query.getPcsn()))) {
ErpQueryJson erpQuery = new ErpQueryJson();
erpQuery.setFormId("STK_Inventory");
erpQuery.setFieldKeys("FMaterialId.FNumber,FBaseQty");
erpQuery.setLimit(1000);
String filterString = "";
if (StringUtils.isNotBlank(query.getMaterial())) {
filterString = "[{\"FieldName\":\"FMaterialId.FNumber\",\"Compare\":\"67\",\"Value\":\"" + mst_detail.get(0).get("material_code").toString() + "\",\"Left\":\"\",\"Right\":\"\",\"Logic\":\"0\"},{\"FieldName\":\"FStockId.FNumber\",\"Compare\":\"67\",\"Value\":\"25\",\"Left\":\"\",\"Right\":\"\",\"Logic\":\"0\"}]";
} else {
filterString = "[{\"FieldName\":\"FLot.FNumber\",\"Compare\":\"67\",\"Value\":\"" + mst_detail.get(0).get("pcsn").toString() + "\",\"Left\":\"\",\"Right\":\"\",\"Logic\":\"0\"},{\"FieldName\":\"FStockId.FNumber\",\"Compare\":\"67\",\"Value\":\"25\",\"Left\":\"\",\"Right\":\"\",\"Logic\":\"0\"}]";
}
ObjectMapper objectMapper = new ObjectMapper();
try {
List<Map<String, String>> filterList = objectMapper.readValue(filterString, objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class));
erpQuery.setFilterString(filterList);
} catch (JsonProcessingException e) {
throw new BadRequestException("erp库存查询条件错误");
}
//根据物料编号或批次查询ERP即时库存
List<JSONObject> result = erpServiceUtils.queryResult(erpQuery);
Map<String, BigDecimal> erpCounts = result.stream()
.filter(item -> item.get("erpCounts") != null)
.collect(Collectors.groupingBy(
item -> (String) item.get("material_code"),
Collectors.reducing(BigDecimal.ZERO, item -> BigDecimal.valueOf((Double) item.get("erpCounts")), BigDecimal::add)
));
Map<String, BigDecimal> totals = mst_detail.stream()
.filter(item -> item.get("qty") != null)
.filter(item -> item.get("material_code") != null)
.collect(Collectors.groupingBy(
item -> (String) item.get("material_code"),
Collectors.reducing(BigDecimal.ZERO, item -> (BigDecimal) item.get("qty"), BigDecimal::add)
));
for (Map<String, Object> item : mst_detail) {
String key = (String) item.get("material_code");
BigDecimal totalQty = totals.getOrDefault(key, BigDecimal.ZERO);
BigDecimal totalErpQty = erpCounts.getOrDefault(key, BigDecimal.ZERO);
BigDecimal differCount = totalQty.subtract(totalErpQty);
item.put("differCount", differCount);
item.put("counts", totalQty);
item.put("erpCounts", totalErpQty);
}
} else {
for (Map item : mst_detail) {
item.put("differCount", null);
item.put("counts", null);
item.put("erpCounts", null);
}
}
}
TableDataInfo<Map> build = TableDataInfo.build(mst_detail);
build.setTotalElements(page.getTotal());
return build;

View File

@@ -3,7 +3,7 @@ window.g = {
VUE_APP_BASE_API: 'http://127.0.0.1:8012'
},
prod: {
VUE_APP_BASE_API: 'http://127.0.0.1:8012'
VUE_APP_BASE_API: 'http://192.168.18.218:8012'
}
}

View File

@@ -173,7 +173,7 @@
</el-table-column>
<el-table-column prop="vehicle_code" label="载具编号" show-overflow-tooltip width="120" />
<el-table-column prop="qty" label="物料数量" show-overflow-tooltip />
<el-table-column prop="material_id" label="物料id" show-overflow-tooltip width="120" />
<el-table-column prop="material_code" label="物料编码" show-overflow-tooltip width="120" />
<el-table-column prop="material_name" label="物料名称" show-overflow-tooltip width="120" />
<el-table-column prop="material_spec" label="物料规格" show-overflow-tooltip width="120" />
<el-table-column prop="pcsn" label="批次" show-overflow-tooltip width="120" />

View File

@@ -3,90 +3,90 @@
<!--工具栏-->
<div class="head-container">
<div v-if="crud.props.searchToggle">
<el-form
:inline="true"
class="demo-form-inline"
label-position="right"
label-width="80px"
label-suffix=":"
>
<el-form-item label="所属仓库">
<el-select
v-model="query.stor_code"
clearable
class="filter-item"
placeholder="所属仓库"
@change="crud.toQuery"
>
<el-option
v-for="item in tableEnum.st_ivt_bsrealstorattr"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="仓位信息">
<el-input
v-model="query.search"
clearable
size="mini"
placeholder="请输入仓位信息"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="物料信息">
<el-input
v-model="query.material"
clearable
size="mini"
placeholder="请输入物料信息"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="批号">
<el-input
v-model="query.pcsn"
clearable
size="mini"
placeholder="请输入批号"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="载具编码">
<el-input
v-model="query.vehicle_code"
clearable
size="mini"
placeholder="请输入载具编码"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="入库日期" prop="analyseData">
<el-date-picker
v-model="query.datepick"
type="daterange"
value-format="yyyy-MM-dd"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</el-form-item>
<rrOperation />
<el-button
class="filter-item"
size="mini"
type="success"
icon="el-icon-s-operation"
@click="downloadMethod"
<el-form
:inline="true"
class="demo-form-inline"
label-position="right"
label-width="80px"
label-suffix=":"
>
导出库存
</el-button>
</el-form>
<el-form-item label="所属仓库">
<el-select
v-model="query.stor_code"
clearable
class="filter-item"
placeholder="所属仓库"
@change="crud.toQuery"
>
<el-option
v-for="item in tableEnum.st_ivt_bsrealstorattr"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="仓位信息">
<el-input
v-model="query.search"
clearable
size="mini"
placeholder="请输入仓位信息"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="物料信息">
<el-input
v-model="query.material"
clearable
size="mini"
placeholder="请输入物料信息"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="批号">
<el-input
v-model="query.pcsn"
clearable
size="mini"
placeholder="请输入批号"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="载具编码">
<el-input
v-model="query.vehicle_code"
clearable
size="mini"
placeholder="请输入载具编码"
prefix-icon="el-icon-search"
class="filter-item"
/>
</el-form-item>
<el-form-item label="入库日期" prop="analyseData">
<el-date-picker
v-model="query.datepick"
type="daterange"
value-format="yyyy-MM-dd"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</el-form-item>
<rrOperation />
<el-button
class="filter-item"
size="mini"
type="success"
icon="el-icon-s-operation"
@click="downloadMethod"
>
导出库存
</el-button>
</el-form>
</div>
<!--如果想在工具栏加入更多按钮可以使用插槽方式 slot = 'left' or 'right'-->
<crudOperation :permission="permission" />
@@ -103,10 +103,13 @@
<el-table-column prop="material_code" label="物料编码" width="150" show-tooltip-when-overflow />
<el-table-column prop="material_name" label="物料名称" width="150" show-tooltip-when-overflow />
<el-table-column prop="vehicle_code" label="载具编码" width="150" show-tooltip-when-overflow />
<!-- <el-table-column prop="parent_vehicle_code" label="父载具编码" width="150" show-tooltip-when-overflow />-->
<!-- <el-table-column prop="parent_vehicle_code" label="父载具编码" width="150" show-tooltip-when-overflow />-->
<el-table-column prop="pcsn" label="批次" min-width="150" show-tooltip-when-overflow />
<el-table-column prop="qty" label="总库存" min-width="150" show-tooltip-when-overflow />
<el-table-column prop="qty" label="库位库存" show-tooltip-when-overflow />
<el-table-column prop="frozen_qty" label="冻结库存" show-tooltip-when-overflow />
<el-table-column prop="counts" label="物料总库存"min-width="90" show-tooltip-when-overflow />
<el-table-column prop="erpCounts" label="ERP实时库存" min-width="90"show-tooltip-when-overflow />
<el-table-column prop="differCount" label="立库-ERP库存差异" min-width="120"show-tooltip-when-overflow />
<el-table-column prop="unit_id" label="单位" show-tooltip-when-overflow>
<template slot-scope="scope">{{ tableEnum.label.bm_measure_unit[scope.row.unit_id] }}</template>
</el-table-column>
@@ -139,7 +142,7 @@ import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
import structattr from './structattr'
import { downloadFile,downloadFile2 } from '@/utils/index'
import { downloadFile, downloadFile2 } from '@/utils/index'
const defaultForm = {
id: null,
@@ -187,24 +190,24 @@ export default {
methods: {
// 钩子在获取表格数据之前执行false 则代表不获取数据
[CRUD.HOOK.beforeRefresh]() {
if (this.query.datepick){
if (this.query.datepick) {
this.query.start_time = this.query.datepick[0]
if (this.query.datepick.length>1){
if (this.query.datepick.length > 1) {
this.query.end_time = this.query.datepick[1]
}
}else {
} else {
this.query.start_time = ''
this.query.end_time = ''
}
return true
},
downloadMethod() {
if (this.query.datepick){
if (this.query.datepick) {
this.query.start_time = this.query.datepick[0]
if (this.query.datepick.length>1){
if (this.query.datepick.length > 1) {
this.query.end_time = this.query.datepick[1]
}
}else {
} else {
this.query.start_time = ''
this.query.end_time = ''
}