1
Jianw
2025-07-09 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
--[[ 
 编码: 
 名称: CreateCountPlan 
 作者: 
 入口函数:Createcountplan 
 功能说明: 
 变更历史: 
            {
            "Name": "GetCountPlan",
            "Source": "ERP",
            "Data": {
                    "S_OP_TYPE":"采购入库",
                    "S_BS_NO": "20250528002",
                    "SourceKey": "",
                    "ITEMS": [
                        {
                        "S_BS_NO": "21",
                        "N_BS_ROW_MO": 21,
                        "S_ITEM_CODE": "A234"
                        },
                        {
                        "S_BS_NO": "31",
                        "N_BS_ROW_MO": 31,
                        "S_ITEM_CODE": "A234"
                        }
                        ]
                    }
            }
 --]] 
 function Createcountplan(strLuaDEID) 
    local nRet, inputData
    local SqlCondition
    local nRetl, strRetInfo
    local strCondition
    local num
    local area_groups = {}
    local err = {}
    local result_code_list = {}
    
    local seen_combinations = {}
    local duplicate_found = false
    local duplicate_items = {}
    
 
    -- 获取接口传入数据
    nRet, inputData = m3.GetSysDataJson(strLuaDEID)
    if (nRet ~= 0) then
        table.insert(err, "无法获取数据包!" )
        goto err_msg_process 
    end
 
    if not inputData or not inputData.ITEMS or #inputData.ITEMS == 0 then
        table.insert(err, "Data 或 ITEMS 不合法!" )
        goto err_msg_process 
    end
 
    -- 校验来源单号
    if (inputData.S_BS_NO == nil or inputData.S_BS_NO == "") then
        table.insert(err, "业务来源S_BS_NO不能为空或不合法" )
        goto err_msg_process 
    end
    strCondition = " S_BS_NO = '" ..inputData.S_BS_NO.. "' "
    nRetl, strRetInfo = mobox.existThisData(strLuaDEID, "Count_Plan", strCondition)
    if (nRetl ~= 0) then
        table.insert(err, "查询是否有相同来源单号的盘点计划出错" .. inputData.S_BS_NO )
        goto err_msg_process 
    end
    if (strRetInfo == 'yes') then
        table.insert(err, "来源单号存在" .. inputData.S_BS_NO )
        goto err_msg_process 
    end
    
    -- 从常量取工厂标识
    nRet,wh_code = wms_base.Get_sConst2("默认工厂标识" )
    if ( nRet ~= 0 ) then
        table.insert(errcode, "系统常量:默认工厂标识" .. inputData.S_BS_NO)
        goto err_msg_process
    end
    if ( wh_code == '' ) then
        table.insert(errcode, "系统常量'默认工厂标识'必须有值!" .. inputData.S_BS_NO)
        goto err_msg_process
    end
    
    -- 新增校验:检查重复的S_BS_NO和N_BS_ROW_MO组合
    for _, item in ipairs(inputData.ITEMS) do
        local combination_key = item.S_BS_NO .. "|" .. tostring(item.N_BS_ROW_MO)
        
        if seen_combinations[combination_key] then
            duplicate_found = true
            table.insert(duplicate_items, combination_key)
        else
            seen_combinations[combination_key] = true
        end
    end
    if duplicate_found then
        table.insert(err, "存在重复的来源单号和行号组合: " .. table.concat(duplicate_items, ", "))
        goto err_msg_process
    end
 
    -- 按 area_code 分组
    for _, item in ipairs(inputData.ITEMS) do
        if not item.S_ITEM_CODE or item.S_ITEM_CODE == "" then
            table.insert(err, "商品编码不能为空" ..item.S_ITEM_CODE)
        elseif not item.S_BS_NO or  item.S_BS_NO == "" then
            table.insert(err, "来源单号不能为空" ..item.S_ITEM_CODE)
        elseif not item.N_BS_ROW_MO or  item.N_BS_ROW_MO == "" then
            table.insert(err, "来源行号不能为空" ..item.S_ITEM_CODE)
        elseif (type(item.N_BS_ROW_MO) ~= "number") then
            table.insert(err, "来源行号非数字类型" ..item.S_ITEM_CODE)
        else
            -- 查询物料,获取 area_code
            local cond = "S_ITEM_CODE = '" .. item.S_ITEM_CODE .. "'"
            local ret1, id, materialAttrs = mobox.getDataObjAttrByKeyAttr(strLuaDEID, "SKU", cond)
            if ret1 ~= 0 or not materialAttrs then
                table.insert(err, "获取物料失败:" .. item.S_ITEM_CODE)
            else
                local ret2, materialJson = mobox.objAttrsToLuaJson("SKU", materialAttrs)
                if ret2 ~= 0 then
                    table.insert(err, "物料JSON转换失败:" .. item.S_ITEM_CODE)
                else
                    local ok, material = pcall(json.decode, materialJson)
                    if not ok or not material or not material.udf01 then
                        table.insert(err, "物料无有效area_code:" .. item.S_ITEM_CODE)
                    else
                        item._material = material
                        local area = material.udf01
                        if not area_groups[area] then
                            area_groups[area] = {}
                        end
                        table.insert(area_groups[area], item)
                    end
                end
            end
        end
    end
    
    ::err_msg_process::
    -- 如校验失败,返回错误结构
    if #err > 0 then
        local result = {
            SourceKey = inputData.SourceKey ,
            err_code = 1,
            err_msg = table.concat(err, ","),
            result = nil
        }
        mobox.returnValue(strLuaDEID, 1, lua.table2str(result))
        return
    end
 
    -- 创建入库单(按 area_code 拆分)
    for area_code, items in pairs(area_groups) do
        local header = 'PD' .. os.date("%y%m%d") .. '-'
        local ret, order_no = mobox.getSerialNumber("盘点计划", header, 4)
        if ret ~= 0 then
            table.insert(err, "申请盘点计划编码失败:" .. order_no)
            goto continue
        end
 
        local order = m3.AllocObject(strLuaDEID, "Count_Plan")
        order.type = 1
        order.cp_no = order_no                                                 -- 出库单号     
        order.bs_no = inputData.S_BS_NO                                     -- 来源单号 
        order.note = inputData.S_NOTE                                       -- 备注                 
 
        order.sour_no = inputData.SourceKey 
        order.wh_code = wh_code
        order.area_code = area_code                                         -- 库区编码       
        
 
 
        for _, item in ipairs(items) do
            local f_qty = 0
            local material = item._material
            local strCondition = " S_AREA_CODE = '" ..area_code.. "' and S_ITEM_CODE = '" .. material.item_code  .. "'"
            nRet, cntr_list = m3.QueryDataObject(strLuaDEID, "INV_Detail", strCondition)
            if (nRet ~= 0) then
                lua.Stop(strLuaDEID, "查询量表失败!"..cntr_list)
                return
            end
            for n = 1, #cntr_list do
                obj_attrs = m3.KeyValueAttrsToObjAttr(cntr_list[n].attrs)
                local qty = lua.Get_NumAttrValue(obj_attrs.F_QTY)
                f_qty = f_qty + qty
            end
            local detail = m3.AllocObject(strLuaDEID, "CP_Good_List")
            detail.cp_no = order_no
            detail.qty = f_qty
            detail.bs_no = item.S_BS_NO
            detail.bs_row_no = item.N_BS_ROW_MO
 
            detail.item_code = material.item_code
            detail.item_name = material.item_name
            
            detail.sour_no = inputData.SourceKey 
 
            local ret, msg = m3.CreateDataObj(strLuaDEID, detail)
            if ret ~= 0 then
                lua.Stop(strLuaDEID, "创建盘点明细失败:" .. msg)
                return
            end
 
        end
 
        local ret3, msg3 = m3.CreateDataObj(strLuaDEID, order)
        if ret3 ~= 0 then
            lua.Stop(strLuaDEID, "创建盘点明细失败:" .. msg3)
            return
        end
 
 
        ::continue::
    end
 
    -- 统一格式返回结果
    local final_result
    if #err > 0 then
        final_result = {
            SourceKey = inputData.SourceKey or "",
            err_code = 1,
            err_msg = "盘点单创建异常:" .. table.concat(err, ","),
            result = nil
        }
    else
        final_result = {
            SourceKey = inputData.SourceKey or "",
            err_code = 0,
            err_msg = "盘点单创建成功!",
            result = {
                S_NO = inputData.S_BS_NO
            }
        }
    end
 
    mobox.returnValue(strLuaDEID, 1, lua.table2str(final_result))
 end