1
Jianw
9 天以前 70f29da38121b9a467841253e3268feb5df02902
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
--[[
    版本:     Version 2.1
    创建日期: 2024-7-26
    创建人:   HAN
 
    WMS-Basis-Model-Version: V15.5
 
    说明:
        INBP -- 是 Inbound_Palletization 的缩写,即码盘的意思
 
    功能:
        和码盘相关的操作
        -- Get_Current_INBP                     获取当前正在码盘的码盘对象
        -- Add_INBP_Detail                      新增码盘明细
        -- Set_INBP_State_Inbound_Pending       设置码盘作业为待入库状态
 
    更改说明:
        
--]]
 
wms_base = require ("wms_base")
wms_wh   = require ("wms_wh")
wms_inv  = require ("wms_inventory")
 
local wms_pallet = {_version = "0.2.1"}
 
--[[
    根据容器号获取当前正在作业中的【码盘】数据对象,状态 = 码盘中,码盘完成,待入库,入库中
--]]
function wms_pallet.Get_Current_INBP( strLuaDEID, cntr_code )
    local nRet, strRetInfo
 
    if ( cntr_code == nil or cntr_code == '' ) then 
        return 1, "Get_Current_INBP 函数中输入参数 cntr_code 必须有值!"
    end
    local strCondition = "S_CNTR_CODE = '"..cntr_code.."'"
    local strOrder = "T_CREATE Desc"
 
    nRet, inb_pallet = m3.GetDataObjByCondition( strLuaDEID, "Inbound_Palletization", strCondition, strOrder )
    if ( nRet > 1 ) then
        return 2, "查询【Inbound_Palletization】出错!"..inb_pallet
    end
    if ( nRet == 1 ) then
        -- 码盘对象不存在
        inb_pallet = nil
    else
        -- 如果该容器的【码盘】对象已经存在,如果状态是完成或取消
        if ( inb_pallet.b_state >= PALLET_STATE.Finish ) then
            inb_pallet = nil
        end
    end
    return 0, inb_pallet
end
--[[
    码盘操作: 在容器里加入一个货品
    重要度:   ***
 
    数据类:   Inbound_Palletization/码盘 INB_Pallet_Detail/码盘明细
    说明:
        首先判断是否有 Inbound_Palletization 没有需要创建,
        如果容器有 混放规则 需要生成 Container_Ext
        需要根据混放规则判断是否可以加入 INB_Pallet_Detail
    参数:
        cntr_code -- 容器编码
        cell_no -- 料格编码可以为空
        detail_item_data -- 加入的货品信息数组{ { S_CELL_NO = "", S_ITEM_CODE = "", S_UDF01 = "", ..S_UDF20 } }
--]]
function wms_pallet.Add_INB_Pallet_Detail( strLuaDEID, cntr_code, detail_item_data )
    local nRet, strRetInfo, n
 
    -- 输入参数合规检查
    if ( lua.StrIsEmpty( cntr_code ) ) then
        return 1, "Add_INB_Pallet_Detail 函数中 cntr_code 必须有值!"
    end
    if ( type( detail_item_data ) ~= "table" or detail_item_data == nil ) then
        return 1, "Add_INB_Pallet_Detail 函数中 detail_item_data 必须有值!"
    end
    local item_count = #detail_item_data
    if ( item_count == 0 ) then
        return 1, "Add_INB_Pallet_Detail 函数中 detail_item_data 必须有值!"
    end
 
    -- 判断该容器是否可以进行码盘, 获取最近时间的 【码盘】对象
    local inb_pallet
    local new_inb_pallet = false
    local inb_no = ""
 
    nRet, inb_pallet = wms_pallet.Get_Current_INBP( strLuaDEID, cntr_code )
    if ( nRet ~= 0 ) then
        return 2, "查询【Inbound_Palletization】出错!"..inb_pallet
    end
    if ( inb_pallet == nil ) then
        -- 码盘对象不存在
        new_inb_pallet = true
    else
        -- 如果该容器的【码盘】对象码盘已经完成就不能继续码盘
        if ( inb_pallet.b_state >= PALLET_STATE.PalletOK ) then
            return 1, "容器'"..cntr_code.."'状态不能进行码盘!"
        end
        inb_no = inb_pallet.inb_no
    end
     
    -- 获取容器对象及容器类型定义
    local cntr
    nRet, cntr = wms_cntr.GetInfo( strLuaDEID, cntr_code )
    if (nRet ~= 0) then 
        return 2, "获取【容器】信息失败! " .. cntr
    end  
    if ( lua.StrIsEmpty( cntr.ctd_code ) ) then
        return 1, "容器'"..cnyt_code.."'没有定义容器类型定义!"
    end
 
    local ctd       -- 容器类型定义
    nRet, ctd = wms_cntr.GetCTDInfo( cntr.ctd_code )
    if ( nRet ~= 0 ) then
        return 2, ctd
    end
 
    -- 【码盘】对象是否存在,不存在新增
    if ( new_inb_pallet ) then
        inb_pallet  = m3.AllocObject( strLuaDEID, "Inbound_Palletization" )
        inb_pallet.cntr_code = cntr_code
        nRet, inb_pallet = m3.CreateDataObj( strLuaDEID, inb_pallet )
        if ( nRet ~= 0 ) then 
            lua.Stop( strLuaDEID, "创建[Inbound_Palletization]失败!"..inb_pallet)
            return
        end
    end
 
    -- 新增【码盘明细】
    local item, m
    local cntr_minxing_value = {}           -- 容器的混箱属性值
    local cntr_ext_data
    local mixing_attrs_count = #ctd.mixing_attrs
    if ( ctd.have_mixing_rule and new_inb_pallet == false ) then
        -- 从 Container_Ext 获取混箱属性值
        nRet, cntr_ext_data = m3.GetDataObjectByKey2( strLuaDEID, "Container_Ext", "S_CNTR_CODE", cntr_code )
        if ( nRet > 1 ) then
            return 2, "获取[Container_Ext]失败!"..cntr_ext_data
        end
        if ( nRet == 0 ) then
            for m = 1, mixing_attrs_count do
                cntr_minxing_value[ctd.mixing_attrs[m]] = cntr_ext_data[ctd.mixing_attrs[m]]
            end            
        end         
    end
 
    local canot_mixing, cell_no, item_code, item_state, storer, qty
    local strUpdateSql
    local data_objs, data_attrs, add_inb_pallet_detail
    local attrs_count = #INB_PALLET_DETAIL_ATTRS
 
    for n = 1, item_count do
        item = detail_item_data[n]
        item_code = item.S_ITEM_CODE
        item_state = item.S_ITEM_STATE
        storer = item.S_STORER
        qty = lua.Get_NumAttrValue( item.F_QTY )
        add_inb_pallet_detail = false               -- 是否新增 INB_Pallet_Detail
 
        if ( item_code == '' or item_state == '' or storer == '' ) then
            return 1, "Add_INB_Pallet_Detail 函数中 item_list 中参数不全: 物料/货品编码,货品状态,货主必须有值!"
        end
        if ( qty <= 0 ) then
            return 1, "Add_INB_Pallet_Detail 函数中 item_list 中参数不全: F_QTY 必须大于 0!"
        end
        -- 如果存在混箱规则需要判断是否符合混箱要求
        -- 获取加入货品的混箱属性,这个属性必须在 detail_item_data 如果不存在就为空
        local item_minxing_value = {}
        if ( ctd.have_mixing_rule ) then
            canot_mixing = false
            for m = 1, mixing_attrs_count do
                item_minxing_value[ctd.mixing_attrs[m]] = item[ctd.mixing_attrs[m]] or ''
            end
 
            -- 判断容器本身是否已经存在混箱参数
            if ( lua.isTableEmpty(cntr_minxing_value) ) then
                -- 如果是新增的【码盘】第一个货品的混箱参数就是料箱的混箱参数
                cntr_minxing_value = item_minxing_value
 
                -- 同时增加 Container_Ext
                local cntr_ext_data = m3.AllocObject2( strLuaDEID, "Container_Ext" )
                cntr_ext_data.S_CNTR_CODE  = cntr_code 
                for m = 1, mixing_attrs_count do
                    cntr_ext_data[ctd.mixing_attrs[m]] = item_minxing_value[ctd.mixing_attrs[m]]
                end
                nRet, cntr_ext_data = m3.CreateDataObj2( strLuaDEID, cntr_ext_data, 1 )
                if ( nRet ~= 0 ) then 
                    return 2, "创建[Container_Ext]失败!"..cntr_ext_data
                end                
            else
                -- 判断新增码盘货品的混箱参数和料箱是否匹配
                for m = 1, mixing_attrs_count do
                    if ( item_minxing_value[ctd.mixing_attrs[m]] ~= cntr_minxing_value[ctd.mixing_attrs[m]] ) then
                        canot_mixing = true
                        break
                    end
                end
            end
 
            -- 判断后 不能混箱
            if ( canot_mixing ) then
                return 1, "编码'"..item_code.."'的物料/货品不能加入编号='"..cntr_code.."', 原因是不符合混箱规则!"
            end
        end
 
        -- 如果是带料格的料箱,需要进行料格判断,是否可以进行码盘 
        if ( ctd.type == "Cell_Box" ) then
            -- 判断一下当前货品的料格是否已经存在 INB_Pallet_Detail
            cell_no = item.S_CELL_NO or ''
            if ( cell_no == '' ) then
                return 1, "编码'"..item_code.."'的物料/货品不能加入编号='"..cntr_code.."', 原因是不符合混箱规则!"
            end                
            -- 允许加入料格 必须 S_ITEM_CODE, S_ITEM_STATE, S_STORER 一样,如果料箱有定义 S_MERGE_ATTRS/附加数量合并属性
            strCondition = "S_IBP_NO = '"..inb_pallet.ibp_no.."' AND S_CNTR_CODE = '"..cntr_code.."' AND S_CELL_NO = '"..cell_no.."'"  
            nRet, data_objs = m3.QueryDataObject(strLuaDEID, "INB_Pallet_Detail", strCondition )
            if (nRet ~= 0) then return 2, "查询[INB_Pallet_Detail]失败! "..data_objs end   
            
            -- 如果 cell_no 料格已经有货品存在
            if ( data_objs ~= '' ) then
                -- 判断 S_ITEM_CODE, S_ITEM_STATE, S_STORER + ctd.cell_match_rule_attrs 是否一致,如果不一样表示输入参数有问题,不应该绑定在这个料格
                data_attrs = m3.KeyValueAttrsToObjAttr(data_objs[1].attrs)
                if ( data_attrs.S_ITEM_CODE ~= item_code or
                     data_attrs.S_ITEM_STATE ~= item_state or
                     data_attrs.S_STORER ~= storer ) then
                    return 1, "容器编码'"..cntr_code.."'的料格'"..cell_no.."'已经绑定了其它标识的货品, 请仔细检查一下该料格的货品再进行码盘!"
                end
                for m = 1, ctd.cell_match_attrs_count do
                    if ( data_attrs[ctd.cell_match_rule_attrs[m]] ~= item[ctd.cell_match_rule_attrs[m]] ) then
                        return 1, "容器编码'"..cntr_code.."'的料格'"..cell_no.."'已经绑定了其它标识的货品, 请仔细检查一下该料格的货品再进行码盘!"
                    end
                end
 
                -- 继续判断是否可以合并数量, 如果可以合并,不需要新增 INB_Pallet_Detail
                if ( ctd.merge_attrs_count == 0 ) then
                    -- 不需要合并数量
                    add_inb_pallet_detail = true
                else
                    -- 判断是否可以合并数量
                    local find
                    add_inb_pallet_detail = true
                    for i = 1, #data_objs do
                        data_attrs = m3.KeyValueAttrsToObjAttr(data_objs[i].attrs)
                        if ( data_attrs.S_ITEM_CODE == item_code and
                             data_attrs.S_ITEM_STATE == item_state and
                             data_attrs.S_STORER == storer ) then
                            find = true
                            for m = 1, ctd.merge_attrs_count do
                                if ( data_attrs[ctd.merge_rule_attrs[m]] ~= item[ctd.merge_rule_attrs[m]] ) then
                                    find = false
                                    break
                                end
                            end 
                            if ( find ) then
                                -- 更新数量
                                strCondition = "S_ID = '"..data_objs[i].id.."'"
                                strUpdateSql = "F_QTY = F_QTY + "..qty
                                nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "INB_Pallet_Detail", strCondition, strUpdateSql )
                                if ( nRet ~= 0 ) then  
                                    return 2, "更新[INB_Pallet_Detail]信息失败!"..strRetInfo 
                                end                                  
                                add_inb_pallet_detail = false
                                break
                            end      
                        end                   
                    end
                end
            else
                -- 新增 INB_Pallet_Detail
                add_inb_pallet_detail = true
            end
        end
 
        -- 新增 INB_Pallet_Detail
        if ( add_inb_pallet_detail ) then
            local detail_data = m3.AllocObject2( strLuaDEID, "INB_Pallet_Detail" )
            if ( detail_data == nil ) then return 1, "创建 INB_Pallet_Detail 失败!" end
 
            detail_data.S_IBP_NO = inb_pallet.ibp_no
            detail_data.S_CNTR_CODE = cntr_code
            for m = 1, attrs_count do
                detail_data[INB_PALLET_DETAIL_ATTRS[m]] = item[INB_PALLET_DETAIL_ATTRS[m]] or ''
            end
            nRet, detail_data = m3.CreateDataObj2( strLuaDEID, detail_data ) 
            if ( nRet ~= 0 ) then 
                return 2, "创建[INB_Pallet_Detail]失败!"..detail_data
            end     
        end
    end
    return 0
end
 
--[[
    设置【码盘】为待入库状态
    重要度:   ***
 
    数据类:   Inbound_Palletization/码盘
    说明:
        -- 首先判断目前的 Inbound_Palletization 的状态是否可以设置“待入库”状态,
        -- 如果容器和货位没绑定,绑定货位
        -- 库存量表处理
    参数:
        cntr_code   -- 容器编码
        loc_code    -- 当前码盘容器需要绑定的货位,可以为空,为空的原因是容器已经和货位绑定
--]]
function wms_pallet.Set_INBP_State_Inbound_Pending( strLuaDEID, cntr_code, loc_code )
    local nRet, strRetInfo
    local inb_pallet
 
    if ( loc_code == nil ) then loc_code = '' end
 
    -- 获取码盘数据对象
    nRet, inb_pallet = wms_pallet.Get_Current_INBP( strLuaDEID, cntr_code )
    if ( nRet ~= 0 ) then
        return 2, "查询【Inbound_Palletization】出错!"..inb_pallet
    end
    if ( inb_pallet == nil ) then
        -- 码盘对象不存在
        return 1, "容器'"..cntr_code.."'不存在可设置为待入库状态的码盘对象!"
    else
        -- 如果该容器的【码盘】对象码盘的状态已经是 待码盘状态 就不能再做 待码盘状态设置
        if ( inb_pallet.b_state >= PALLET_STATE.Inbound_Pending ) then
            return 1, "容器'"..cntr_code.."'状态不能再次被设置为待码盘状态!"
        end
    end
 
    local need_binding = true
    local str_loc_code
 
    -- 容器货位判断
    -- 获取容器当前绑定货位
    nRet, str_loc_code = wms_cntr.Get_Container_Loc( strLuaDEID, cntr_code )
    if ( nRet ~= 0 ) then
        return 2, "Get_Container_Loc 失败! --> "..str_loc_code
    end    
    if  ( loc_code == '' ) then
        -- 没有容器需要绑定的货位
        if ( str_loc_code == '' ) then
            return 1, " Set_INBP_State_Inbound_Pending 需要输入一个绑定货位!"
        end
        loc_code = str_loc_code
        need_binding = false        -- 已经有绑定不需要继续绑定,可能在码盘前容器已经绑定了货位
    else
        if ( str_loc_code ~= '' ) then
            if ( loc_code ~= str_loc_code ) then
                return 1, "容器'"..cntr_code.."'已经和货位'"..str_loc_code.."'绑定,不能再绑定货位'"..loc_code.."'"
            end
            need_binding = false
        end
    end
 
    -- 绑定货位
    if ( need_binding ) then
        nRet, strRetInfo = wms_wh.Loc_Container_Binding( strLuaDEID, loc_code, cntr_code, "绑定解绑方法-系统", "码盘绑定" )
        if ( nRet ~= 0 ) then  
            return nRet, '货位容器绑定失败!'..strRetInfo
        end         
    end
 
    -- 库存量变变化
    nRet, strRetInfo = wms_inv.After_CntrLoc_Binding( strLuaDEID, inb_pallet, loc_code )
    if ( nRet ~= 0 ) then
        return nRet, strRetInfo
    end
 
    -- 设置【码盘】状态为 待入库
    local strUpdateSql = "N_B_STATE = "..PALLET_STATE.Inbound_Pending
    strCondition = "S_IBP_NO = '"..inb_pallet.ibp_no.."'"
    nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Inbound_Palletization", strCondition, strUpdateSql )
    if ( nRet ~= 0 ) then  
        return 2, "更新[Inbound_Palletization]信息失败!"..strRetInfo 
    end   
 
    return 0
end
 
return wms_pallet