自动化立体仓库 - WMS系统
zwl
2 天以前 605be0c8702fc7bfe4f7fcdd397c9f0d40722b69
1.商品档案新增最大限制和最小限制
2.mes空桶/余料回库修复
15个文件已修改
279 ■■■■■ 已修改文件
src/main/java/com/zy/api/service/impl/HmesApiServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LocDetlController.java 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/Mat.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/AbnormalLocDetlParam.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/MatExcelListener.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/entity/MatExcel.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/WcsController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocDetlMapper.xml 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/MatMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/locDetlGroup/locDetlGroup.js 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/mat/mat.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/locDetlGroup/locDetlGroup.html 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/mat/mat.html 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/api/service/impl/HmesApiServiceImpl.java
@@ -341,7 +341,7 @@
        }
        workService.updateWrkIsSuplus(String.valueOf(mast.getWrkNo()), HMES_USER_ID, backType);
        return workService.backLocOperation(String.valueOf(mast.getWrkNo()), HMES_USER_ID);
        return R.ok();
    }
    private HmesStationFreezeStatusDto buildStationFreezeStatus(LocAroundBind bind) {
src/main/java/com/zy/asrs/controller/LocDetlController.java
@@ -62,67 +62,27 @@
                          @RequestParam(required = false) String orderByType,
                          @RequestParam(required = false) String condition,
                          @RequestParam Map<String, Object> param) {
//        List<LocDetl> result = new ArrayList<>();
        List<AbnormalLocDetlParam> result = new ArrayList<>();
//        excludeTrash(param);
        param.put("curr", curr);
        param.put("limit", limit);
        Page<LocDetl> groupLocDetl = locDetlService.getStockStatis2(toPage(1, 10000, param, LocDetl.class));
//        List<LocDetl> groupLocDetl = locDetlService.selectGroupPage(param, curr, limit);
        for (LocDetl locDetl : groupLocDetl.getRecords()) {
            AbnormalLocDetlParam abnormalLocDetlParam = new AbnormalLocDetlParam();
            Mat mat = matService.selectOne(new EntityWrapper<Mat>()
                    .eq("matnr", locDetl.getMatnr()));
            if (Cools.isEmpty(mat)) {
                continue;
            }
            if (!Cools.isEmpty(mat.getStoreMax()) || !Cools.isEmpty(mat.getStoreMin())) {
                abnormalLocDetlParam.setStoreMax(mat.getStoreMax());
                abnormalLocDetlParam.setStoreMaxDate(mat.getStoreMaxDate());
                abnormalLocDetlParam.setStoreMin(mat.getStoreMin());
                abnormalLocDetlParam.setAnfme(locDetl.getAnfme());
                abnormalLocDetlParam.setMaktx(mat.getMaktx());
                abnormalLocDetlParam.setMatnr(mat.getMatnr());
                abnormalLocDetlParam.setSpecs(mat.getSpecs());
                abnormalLocDetlParam.setBatch(locDetl.getBatch());
//                SimpleDateFormat simple = new SimpleDateFormat("yyyyMMdd");
//                Date maxDate = simple.parse(locDetl.getBatch());
//                long time = maxDate.getTime();
//                Date now = new Date();
//                long time1 = now.getTime();
//                abnormalLocDetlParam.setNowTime((int) ((time1 - time) / (1000 * 60 * 60 * 24)));
                if (!Cools.isEmpty(mat.getStoreMax()) && locDetl.getAnfme() > mat.getStoreMax()) {
                    result.add(abnormalLocDetlParam);
                } else if (!Cools.isEmpty(mat.getStoreMin()) && locDetl.getAnfme() < mat.getStoreMin()) {
                    result.add(abnormalLocDetlParam);
                }
            }
        }
        Map<String, Object> queryParam = new HashMap<>();
        putIfPresent(queryParam, "matnr", param.get("matnr"));
        putIfPresent(queryParam, "maktx", param.get("maktx"));
        putIfPresent(queryParam, "specs", param.get("specs"));
        putIfPresent(queryParam, "warnStatus", param.get("warnStatus"));
        queryParam.put("pageNumber", curr);
        queryParam.put("pageSize", limit);
        Page<AbnormalLocDetlParam> locDetlPage = new Page<>();
        locDetlPage.setRecords(paging(result, curr, limit));
        locDetlPage.setTotal(result.size());
        locDetlPage.setRecords(locDetlMapper.groupLocList(queryParam));
        locDetlPage.setTotal(locDetlMapper.groupLocListCount(queryParam));
        locDetlPage.setCurrent(curr);
        locDetlPage.setSize(limit);
        return R.ok(locDetlPage);
    }
    private List<AbnormalLocDetlParam> paging(List<AbnormalLocDetlParam> result, Integer curr, Integer limit) {
        List<AbnormalLocDetlParam> pageRecord = new ArrayList<AbnormalLocDetlParam>();
        int minIndex = (curr - 1) * limit;
        int maxIndex = (curr * limit) - 1;
        if (result.size() < maxIndex) {
            maxIndex = result.size();
    private void putIfPresent(Map<String, Object> target, String key, Object value) {
        String normalized = normalizeFilterText(value);
        if (normalized != null) {
            target.put(key, normalized);
        }
        for (int i = minIndex; i < maxIndex; i++) {
            pageRecord.add(result.get(i));
        }
        return pageRecord;
    }
    @RequestMapping(value = "/locDetl/{id}/auth")
src/main/java/com/zy/asrs/entity/Mat.java
@@ -323,12 +323,16 @@
    /**
     * 库存预警数量上限
     */
    @ApiModelProperty(value= "库存预警数量上限")
    @ExcelProperty(value = "库存预警数量上限")
    @TableField("store_max")
    private Double storeMax;
    /**
     * 库存预警数量下限
     */
    @ApiModelProperty(value= "库存预警数量下限")
    @ExcelProperty(value = "库存预警数量下限")
    @TableField("store_min")
    private Double storeMin;
src/main/java/com/zy/asrs/entity/param/AbnormalLocDetlParam.java
@@ -175,6 +175,13 @@
     */
    private Integer nowTime;
    /**
     * 库存预警状态
     */
    @ApiModelProperty(value = "库存预警状态")
    @ExcelProperty("状态")
    private String warnStatus;
    public String getLocNo$() {
        LocMastService service = SpringUtils.getBean(LocMastService.class);
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.param.AbnormalLocDetlParam;
import com.zy.asrs.entity.result.LocDetlAll;
import com.zy.asrs.entity.result.LocDetlDTO;
import com.zy.asrs.entity.result.StockVo;
@@ -57,6 +58,10 @@
    List<LocDetl> getStockStatis2(Map<String, Object> map);
    List<AbnormalLocDetlParam> groupLocList(Map<String, Object> map);
    Integer groupLocListCount(Map<String, Object> map);
    List<LocDetl> getStockStatisExcel();
    @Select("select sum(a.anfme) as sum from asr_loc_detl a left join asr_loc_mast b on a.loc_no = b.loc_no where b.loc_sts = 'F' and a.matnr = #{matnr}")
src/main/java/com/zy/asrs/utils/MatExcelListener.java
@@ -126,7 +126,13 @@
        // 商品
        Mat mat = matService.selectByMatnr(excel.getMatnr());
        if (mat == null) {
            mat = excel;
            mat = new Mat();
            mat.setMatnr(excel.getMatnr());
            mat.setMaktx(excel.getMaktx());
            mat.setSafeQty(excel.getSafeQty());
            mat.setVolume(excel.getVolume());
            mat.setStoreMax(excel.getStoreMax());
            mat.setStoreMin(excel.getStoreMin());
            mat.setTagId(tagId);
            mat.setLocType(tagId);
            if (Objects.isNull(mat.getVolume())) {
src/main/java/com/zy/common/entity/MatExcel.java
@@ -2,17 +2,11 @@
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.zy.asrs.entity.Mat;
import lombok.Data;
/**
 * 0.A 1.B 2.C 3.D 4.E 5.F 6.G 7.H 8.I
 * 9.J 10.K 11.L 12.M 13.N 14.O 15.P 16.Q 17.R 18.S
 * 19.T 20.U 21.V 22.W 23.X 24.Y 25.Z
 */
@Data
@ExcelIgnoreUnannotated
public class MatExcel extends Mat {
public class MatExcel {
    @ExcelProperty(index = 0, value = "一级分类")
    private String priClass;
@@ -20,4 +14,21 @@
    @ExcelProperty(index = 1, value = "二级分类")
    private String secClass;
    @ExcelProperty(index = 2, value = "商品编码")
    private String matnr;
    @ExcelProperty(index = 3, value = "商品名称")
    private String maktx;
    @ExcelProperty(index = 4, value = "归零阀值")
    private Double safeQty;
    @ExcelProperty(index = 5, value = "每公斤长度")
    private Double volume;
    @ExcelProperty(index = 6, value = "库存预警数量上限")
    private Double storeMax;
    @ExcelProperty(index = 7, value = "库存预警数量下限")
    private Double storeMin;
}
src/main/java/com/zy/common/web/WcsController.java
@@ -125,6 +125,15 @@
            }
            m=m*mat.getVolume();
            Double currentStock = locDetlService.getSumAnfme(matnr);
            if (currentStock == null) {
                currentStock = 0D;
            }
            if (mat.getStoreMax() != null && currentStock + m > mat.getStoreMax()) {
                log.info("WCS入库拦截: 物料超过库存上限, matnr={}, currentStock={}, inboundQty={}, storeMax={}",
                        matnr, currentStock, m, mat.getStoreMax());
                return R.error("物料已到达上限禁止入库");
            }
            //Double val = Math.round((m - matnr.getSafeQty()) * 10000) / 10000.0;
            Config config = configService.selectConfigByCode("SimulationInbound");
            if (config != null && config.getValue().equals("Y")) {
src/main/resources/application-dev.yml
@@ -100,6 +100,8 @@
#wcs对接
wcs:
  #  开关
  switch: false
  status-sync:
    enabled: true
    initial-delay: 10000
src/main/resources/mapper/LocDetlMapper.xml
@@ -769,4 +769,70 @@
        ) t where t.row between ((#{pageNumber}-1)*#{pageSize}+1) and (#{pageNumber}*#{pageSize})
    </select>
    <sql id="groupLocWarnStatusCase">
        case
            when mm.store_max is null and mm.store_min is null then '未设置'
            when mm.store_max is not null and isnull(stock.anfme, 0) &gt; mm.store_max then '超上限'
            when mm.store_min is not null and isnull(stock.anfme, 0) &lt; mm.store_min then '超下限'
            else '正常'
        end
    </sql>
    <sql id="groupLocListCondition">
        where 1 = 1
        and (mm.memo is null or mm.memo != '打包上线')
        <if test="matnr != null and matnr != ''">
            and mm.matnr like '%' + #{matnr} + '%'
        </if>
        <if test="maktx != null and maktx != ''">
            and mm.maktx like '%' + #{maktx} + '%'
        </if>
        <if test="specs != null and specs != ''">
            and mm.specs like '%' + #{specs} + '%'
        </if>
        <if test="warnStatus != null and warnStatus != ''">
            and
            <include refid="groupLocWarnStatusCase"/>
            = #{warnStatus}
        </if>
    </sql>
    <select id="groupLocList" resultType="com.zy.asrs.entity.param.AbnormalLocDetlParam">
        select * from
        (
            select
                row_number() over (order by mm.matnr asc) as row_num,
                mm.matnr as matnr,
                mm.maktx as maktx,
                mm.specs as specs,
                isnull(stock.anfme, 0) as anfme,
                mm.store_max as storeMax,
                mm.store_min as storeMin,
                <include refid="groupLocWarnStatusCase"/> as warnStatus
            from man_mat mm
            left join (
                select
                    a.matnr,
                    sum(a.anfme) as anfme
                from asr_loc_detl a
                group by a.matnr
            ) stock on stock.matnr = mm.matnr
            <include refid="groupLocListCondition"/>
        ) t
        where t.row_num between ((#{pageNumber}-1)*#{pageSize}+1) and (#{pageNumber}*#{pageSize})
    </select>
    <select id="groupLocListCount" resultType="java.lang.Integer">
        select count(1)
        from man_mat mm
        left join (
            select
                a.matnr,
                sum(a.anfme) as anfme
            from asr_loc_detl a
            group by a.matnr
        ) stock on stock.matnr = mm.matnr
        <include refid="groupLocListCondition"/>
    </select>
</mapper>
src/main/resources/mapper/MatMapper.xml
@@ -42,6 +42,9 @@
        <result column="update_by" property="updateBy" />
        <result column="update_time" property="updateTime" />
        <result column="memo" property="memo" />
        <result column="store_max" property="storeMax" />
        <result column="store_min" property="storeMin" />
        <result column="store_max_date" property="storeMaxDate" />
        <result column="stock" property="stock" />
    </resultMap>
src/main/webapp/static/js/locDetlGroup/locDetlGroup.js
@@ -4,10 +4,21 @@
    var cols = [
        {field: 'matnr', align: 'center', title: '物料号', sort: true}
        , {field: 'maktx', align: 'center', title: '物料名称', sort: true}
        , {field: 'specs', align: 'center', title: '规格'}
        , {field: 'batch', align: 'center', title: '批号', width: 300, sort: true}
        , {field: 'storeMax', align: 'center', title: '数量上限', sort: true}
        , {field: 'storeMin', align: 'center', title: '数量下限', sort: true}
        , {
            field: 'warnStatus', align: 'center', title: '状态', sort: true, templet: function (d) {
                var colorMap = {
                    '未设置': '#999999',
                    '正常': '#5cb85c',
                    '超上限': '#d9534f',
                    '超下限': '#337ab7'
                };
                var text = d.warnStatus || '';
                var color = colorMap[text] || '#333333';
                return '<span style="color:' + color + ';">' + text + '</span>';
            }
        }
        // , {field: 'storeMaxDate', align: 'center', title: '库龄上限', sort: true}
        , {field: 'anfme', align: 'center', title: '实际数量'}
        // , {field: 'nowTime', align: 'center', title: '实际库龄'}
@@ -431,6 +442,7 @@
    form.on('submit(reset)', function (data) {
        pageCurr = 1;
        clearFormVal($('#search-box'));
        form.render('select');
        tableReload(false);
    });
@@ -467,6 +479,7 @@
        type: 'datetime'
    });
    form.render('select');
});
src/main/webapp/static/js/mat/mat.js
@@ -2,6 +2,22 @@
var printMatCodeNos = [];
var admin;
function createNumberCell(title, field) {
    return {
        field: field,
        align: 'center',
        title: title,
        templet: function (d) {
            var raw = d[field];
            if (raw === null || raw === undefined) return '';
            if (typeof raw === 'string' && raw.trim() === '') return '';
            var num = Number(raw);
            if (!isFinite(num)) return '';
            return num.toFixed(2);
        }
    };
}
function getCol() {
    var cols = [
        {type: 'checkbox'}
@@ -11,7 +27,14 @@
        // ,{field: 'store_min', align: 'center',title: '库存下限'}
        // ,{field: 'store_max_date', align: 'center',title: '库龄上限(天)'}
    ];
    cols.push.apply(cols, matCols);
    var pageMatCols = matCols.filter(function (col) {
        return ['specs', 'model', 'brand'].indexOf(col.field) === -1;
    });
    cols.push.apply(cols, pageMatCols);
    cols.push(
        createNumberCell('库存预警数量上限', 'storeMax'),
        createNumberCell('库存预警数量下限', 'storeMin')
    );
    cols.push(
        {fixed: 'right', title: '操作', align: 'center', toolbar: '#operate', width: 150}
    )
src/main/webapp/views/locDetlGroup/locDetlGroup.html
@@ -26,12 +26,13 @@
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="specs" placeholder="规格" autocomplete="off">
        </div>
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="batch" placeholder="批号" autocomplete="off">
            <select name="warnStatus">
                <option value="">状态</option>
                <option value="未设置">未设置</option>
                <option value="正常">正常</option>
                <option value="超上限">超上限</option>
                <option value="超下限">超下限</option>
            </select>
        </div>
    </div>
src/main/webapp/views/mat/mat.html
@@ -97,12 +97,6 @@
                                <input name="maktx" class="layui-input" placeholder="输入商品名称"/>
                            </div>
                        </div>
                        <div class="layui-inline">
                            <label class="layui-form-label" style="padding: 8px 15px 8px 15px">商品规格:</label>
                            <div class="layui-input-inline">
                                <input name="specs" class="layui-input" placeholder="输入商品规格"/>
                            </div>
                        </div>
                        <div class="layui-inline">&emsp;
                            <button class="layui-btn icon-btn" lay-filter="search" lay-submit>
                                <i class="layui-icon">&#xe615;</i>搜索
@@ -168,7 +162,6 @@
        <input name="uuid" type="hidden">
        <input name="nodeId" type="hidden">
        <input name="tag_id" type="hidden">
        <input name="model" type="hidden">
        <input name="name" type="hidden">
        <input name="batch" type="hidden">
        <input name="docId" type="hidden">
@@ -202,21 +195,15 @@
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">规格</label>
                    <label class="layui-form-label">库存预警数量上限</label>
                    <div class="layui-input-block">
                        <input name="specs" placeholder="请输入规格" class="layui-input">
                        <input name="storeMax" placeholder="请输入库存预警数量上限" class="layui-input">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">品牌</label>
                    <label class="layui-form-label">库存预警数量下限</label>
                    <div class="layui-input-block">
                        <input name="brand" placeholder="请输入单箱净重格" class="layui-input">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">型号</label>
                    <div class="layui-input-block">
                        <input name="model" placeholder="请输入型号" class="layui-input">
                        <input name="storeMin" placeholder="请输入库存预警数量下限" class="layui-input">
                    </div>
                </div>
            </div>
@@ -237,12 +224,6 @@
                    <label class="layui-form-label layui-form-required">每公斤长度</label>
                    <div class="layui-input-block">
                        <input id="volume" name="volume" placeholder="请输入" class="layui-input" lay-vertype="tips" lay-verify="required" required="">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">规格</label>
                    <div class="layui-input-block">
                        <input name="specs" placeholder="请输入代码" class="layui-input">
                    </div>
                </div>
                <div class="layui-form-item">