/****** Object: StoredProcedure [dbo].[p_autoAllocateRetrieveCells] Script Date: 2017/11/8 星期三 22:24:24 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[p_autoAllocateRetrieveCells] @p_dh type_dh , @p_mxbh INT = NULL --允许只自动安排某个出库单明细记录的出库库位。为NULL则表示指定出库单的所有明细 , @p_kcjlh INT = NULL -- 是否指定出指定记录号的库存记录明细。手动安排时会传递实际值 , @p_czr VARCHAR(20) = NULL -- WITH ENCRYPTION AS /** * 对选定出库单或其明细记录安排出库库位 * * Created by jzx on 2006-07-21 * Used by 出库单上的自动出库库位。 * Modified by jzx on 2006-10-20 提取可选库位时,不再需要批号相同;并将批号信息存入出库指令表中 * Modified by jzx on 2006-12-19 更改参数:去除仓库、库位,改用库存记录号;在出库指令中记录入库物资的供应单位 * Modified by jzx on 2006-12-28 在出库指令中记录对应出入库单单号(存入ckzl表上的pzbh字段) * Modified by jzx on 2009-8-13 增加对明细确定了供应单位时,所出库位只能是指定供应单位的那部分,而不是全部。 * 当明细确定了批号时,取指定批号的库位 * Modified by jzx on 2009-8-22 将库存记录上的入库时间转出到指令表上 * Modified by jzx on 2010-8-8 将库存备注信息带入ckzl表中 * Modified by jzx on 2010-8-25 使用配置项 ckkw.zdap.kwgs 的当前值,确定安排的库位个数 * Modified by jzx on 2010-9-15 共用同一库位的指令号时,仅对非虚拟库位适用 * Modified by jzx on 2011-6-19 零散数量默认从虚拟库位或者扩展库位上出 * Modified by jzx on 2011-8-6 当确定批次出库时,不再按入库时间排序 * Modified by jzx on 2011-11-4 在手工确定出库库存记录的情况下,不检查批号是否匹配 * Modified by jzx on 2011-11-28 单据记录筛选条件中增加D.sflz=1 * Modified by jzx on 2014-9-26 329项目,原包装小件拉动出库(ckd.clfs=1)时,需要往上取整整件出库。 * Modified by jzx on 2014-10-15 329 项目开始,在ckzl表中存储bzl字段值,该值来自库存记录表,而不是ckdmx表 * Modified by jzx on 2014-10-24 在指定批次的情况下,按入库时间排序时,只需要精确到日就可以了,不需要精确到秒; 外侧(靠巷道堆垛机一侧)库位优先安排出库。 * Modified by jzx on 2014-10-31 在wzlb表中指定特定类别的物料是整箱出库还是整盘出库,抑或是按实际需求数量出库 * Modified by jzx on 2014-11-6 当某种物料在立库平库都有时,立库库位优先安排。主要考虑特殊物料情况。 * Modified by jzx on 2014-11-11 拉动出库时,特殊物料库位也不能安排。特殊物料出库是在收货确认时在特殊库位上扣减库存 * Modified by jzx on 2014-12-9 仅在双伸位都有货时才优先安排浅库位(wckw is null)出库; 优先安排数量少的库位而不是多的库位,为的是尽量减少拣选回库。 * Modified by jzx on 2015-1-8 增加SET NOCOUNT ON代码行 * Modified by jzx on 2015-9-6 严格按照先进现出原则,即使安排的是深货位 * Modified by jzx on 2015-10-20 重新启用系统配置项ckkw.zdap.kwgs的作用,且只安排单个库位情况下,自动修改ckdmx.shsl字段值为实际安排数量的值 * Modified by jzx on 2015-10-21 前一次更新代码中忘记更新ckdmx.js字段值 * Modified by jzx on 2015-10-23 将ckd表上新增字段“限定出库口”的值作为ckzl表记录tpcrk字段值的默认值 * Modified by jzx on 2015-10-24 仅对自动生成的拉动出库单明细记录才自动修改ckdmx.shsl字段值为yapsl字段值 * Modified by jzx on 2015-11-20 安排立库实体库位时,如果设定的托盘出入库口不同,则不能共享指令编号 * Modified by jzx on 2015-12-8 增加参数p_czr,用于传递调用这个过程的管理系统登录账号 * Modified by jzx on 2015-12-11 当参数@p_kcjlh不为空时,允许安排出库的出库数量为0 * Modified by jzx on 2016-1-4 debug: 当需要在立库库位上安排零头出库时,计算立库库位出库整箱(向下取整)数量时,用错了变量。 * Modified by jzx on 2016-3-23 同一入库日期的,先按storeDist的值排序,然后再按sl排序 * Modified by jzx on 2016-4-26 处理ckdmx表新字段“限定出库托盘”对库位安排的影响;将cfwzxx,piz,txm字段存入ckzl表 * Modified by jzx on 2016-4-27 debug 上一次修改代码中,对限定出库托盘条件筛选处理语句有错误。 * Modified by jzx on 2017-10-18 整托出库安排方式,如果出库单明细中没有托盘上有的其他物资,也需要安排掉;同时给ckzl.ysbj字段赋值 * Modified by jzx on 2017-11-8 debug: 遍历可出库位记录时,没有给@v_cpbh,@v_zlzt重新赋值,导致上次更新新增的游标给@v_cpbh赋值后,后续库位 对应的ckzl记录的cpbh、zlzt字段值被前面库位上其他产品覆盖了。 */ BEGIN DECLARE @v_cpbh type_cpbh, @v_lpxx type_ph, @v_cksl type_sl, @v_zlsl type_sl, @v_kcsl type_sl , @v_mxbh INT, @v_zlbh INT, @v_zlbh_length TINYINT , @v_kcjlh INT --库存记录号 , @v_ckmc type_ck, @v_kwbh type_kwbh, @v_tpbh nvarchar(50), @v_zljlh INT --出库指令表的记录号 , @v_zlzt CHAR(1)--出库物资的质量状态 , @v_kwzsl type_sl --出库库位上所有物资的总数量 , @v_kckwxx CURSOR , @c_sl type_sl --cpkcxx数量 , @v_gydw NVARCHAR(60) , @v_kc_rksj SMALLDATETIME, @v_kcbz VARCHAR(200) , @v_config CHAR(1) , @v_ckck type_ck , @v_jzl INT , @v_kzkw TINYINT , @v_xnkw TINYINT , @v_hasXnkw TINYINT , @v_clfs CHAR(1) , @v_wzlb VARCHAR(15) , @v_zlsl2 type_sl , @v_chkufs TINYINT -- 出库方式:0按需出库;1整箱出库;2整盘出库 , @v_浅库位 type_kwbh -- 如果不为null,则表示遍历的库位为深库位 , @v_浅库位有货 BIT -- 标识浅库位是否有货 , @v_跳过的库位数 INT , @v_跳过内侧库位 TINYINT -- 0表示没有遍历到深库位;1表示跳过一次,试图先安排外侧库位;2表示跳过两次遍历,安排的库位数还不够,只好最后尝试安排深库位 , @v_tpcrk NVARCHAR(20) , @v_限定出库托盘 varchar(12) , @piz NUMERIC(8,3), @txm VARCHAR(30), @cfwzxx TINYINT, @v_ysbj TINYINT; DECLARE c_ckdmx CURSOR FOR SELECT M.mxbh, M.cpbh, M.lpxx, M.shsl - M.yapsl AS cksl, D.zl, M.ghs, M.lpxx, D.ckbh ckck , ISNULL(D.clfs,'0') clfs, M.wzlb, W.chkufs, D.限定出库口, M.限定出库托盘--, ISNULL(M.jzl, 1) jzl FROM ckdmx M INNER JOIN ckd D ON M.ckdh = D.ckdh AND D.zt = 0 AND D.sflz=1 LEFT JOIN wzlb W ON M.wzlb = W.dm WHERE (M.ckdh = @p_dh) AND (@p_mxbh IS NULL OR mxbh = @p_mxbh) AND (shsl > yapsl OR (@p_kcjlh IS NOT NULL)) ORDER BY M.cpbh, M.lpxx SET NOCOUNT ON; SELECT @v_config = dqz FROM sys_config WHERE ID_pzx = 'ckkw.zdap.kwgs'; OPEN c_ckdmx WHILE 1 = 1 BEGIN FETCH c_ckdmx INTO @v_mxbh, @v_cpbh, @v_lpxx, @v_cksl, @v_zlzt, @v_gydw, @v_lpxx, @v_ckck, @v_clfs, @v_wzlb, @v_chkufs , @v_tpcrk, @v_限定出库托盘--, @v_jzl IF @@FETCH_STATUS <> 0 BREAK; SET @v_跳过内侧库位 = 0; 单项库位安排: IF (@v_lpxx IS NOT NULL) SET @v_kckwxx = CURSOR FOR SELECT I.jlh, I.ckmc, I.kwbh, I.sl, I.tpbh, I.kwzsl, I.cpbh, I.lpxx, I.zlzt, I.gydw, I.rksj, I.bz, I.xnkw, I.bzl, I.wckw, I.双伸位都有货 , I.piz, I.txm, I.cfwzxx, ysbj FROM cpkcxx_v I WHERE I.cpbh = @v_cpbh AND I.zlzt = @v_zlzt AND I.ckmc = @v_ckck -- 2011-6-19 jzx 必须从指定仓库中出 AND ( (@p_kcjlh IS NULL --AND (@v_gydw IS NULL OR gydw = @v_gydw) -- 限定出指定供应商的产品 AND lpxx = @v_lpxx ) OR jlh = @p_kcjlh )-- 329项目开始:拉动出库时,不能安排特殊物料库位和待发区库位 -- 2015-12-14 jzx 如果用户手工选定了库位,则可以选择特殊库位 AND (@v_clfs NOT IN('1','2') OR I.xnkw NOT IN(2,CASE WHEN @p_kcjlh IS NULL THEN 3 ELSE 2 END)) AND (@v_限定出库托盘 IS NULL OR (@p_kcjlh IS NOT NULL OR tpbh=@v_限定出库托盘)) -- 2016-1-13 346碧陆斯项目开始支持制单的时候就限定出库托盘 ORDER BY xnkw,CAST(I.rksj AS DATE), storeDist, I.sl, ceng; ELSE -- 不限定批号出库 SET @v_kckwxx = CURSOR FOR SELECT I.jlh, I.ckmc, I.kwbh, I.sl, I.tpbh, I.kwzsl, I.cpbh, I.lpxx, I.zlzt, I.gydw, I.rksj, I.bz, I.xnkw, I.bzl, I.wckw, I.双伸位都有货 , I.piz, I.txm, I.cfwzxx, ysbj FROM cpkcxx_v I WHERE I.cpbh = @v_cpbh AND I.zlzt = @v_zlzt AND I.ckmc = @v_ckck -- 2011-6-19 jzx 必须从指定仓库中出 AND ( (@p_kcjlh IS NULL AND (@v_gydw IS NULL OR gydw = @v_gydw) -- 限定出指定供应商的产品 ) OR jlh = @p_kcjlh )-- 329项目开始:拉动出库时,不能安排特殊物料库位和待发区库位 -- 2015-12-14 jzx 如果用户手工选定了库位,则可以选择特殊库位 AND (@v_clfs NOT IN('1','2') OR I.xnkw NOT IN(2,CASE WHEN @p_kcjlh IS NULL THEN 3 ELSE 2 END)) AND (@v_限定出库托盘 IS NULL OR (@p_kcjlh IS NOT NULL OR tpbh=@v_限定出库托盘)) -- 2016-1-13 346碧陆斯项目开始支持制单的时候就限定出库托盘 ORDER BY xnkw,CAST(I.rksj AS DATE), storeDist, I.sl, ceng; OPEN @v_kckwxx WHILE @v_cksl > 0 OR @p_kcjlh IS NOT NULL -- 2015-12-11 jzx 库存记录号指定情况下,不受@v_cksl是否大于0限制 BEGIN FETCH @v_kckwxx INTO @v_kcjlh, @v_ckmc, @v_kwbh, @v_kcsl, @v_tpbh, @v_kwzsl, @v_cpbh, @v_lpxx, @v_zlzt, @v_gydw, @v_kc_rksj, @v_kcbz, @v_xnkw , @v_jzl, @v_浅库位, @v_浅库位有货, @piz, @txm, @cfwzxx, @v_ysbj IF @@FETCH_STATUS <> 0 BREAK; --确定指令上的出库数量。 SET @v_zlsl = CASE WHEN @v_kcsl >= @v_cksl THEN @v_cksl ELSE @v_kcsl END; -- 329项目特性:从立库出库的小件,需要向上取整,整包装出库 IF @v_jzl > 1 AND 1=@v_chkufs BEGIN SET @v_zlsl2 = CEILING(@v_cksl/@v_jzl) * @v_jzl; IF @v_kcsl >= @v_zlsl2 AND @v_zlsl <> @v_zlsl2 SET @v_zlsl = @v_zlsl2; END; ELSE IF 2=@v_chkufs -- 2014-10-31 支持整盘出库 BEGIN SET @v_zlsl = @v_kcsl; END; -- 2011-6-19 jzx 默认整件出库。不足一件时,则从虚拟货库位上出 ELSE IF @p_kcjlh IS NULL -- 未指定选用单个库存记录行的情况下(手工选择出库库位时,@p_kcjlh IS NOT NULL) AND @v_jzl > 1 AND @v_zlsl > @v_jzl AND @v_zlsl > floor(@v_zlsl/@v_jzl)*@v_jzl BEGIN IF @v_hasXnkw IS NULL BEGIN SET @v_hasXnkw = 0; IF EXISTS(SELECT 1 FROM cpkcxx_v I WHERE I.cpbh = @v_cpbh AND I.zlzt = @v_zlzt AND I.ckmc = @v_ckck -- 2011-6-19 jzx 必须从指定仓库中出 AND ISNULL(I.lpxx, ' ') = ISNULL(@v_lpxx, ' ') AND I.kwbh != @v_kwbh AND I.xnkw != 0 AND (@v_clfs NOT IN('1','2') OR I.xnkw NOT IN(2,3)) ) BEGIN SET @v_hasXnkw = 1; END; END; IF (@v_hasXnkw != 0) -- 说明存在虚拟库位库存记录 BEGIN -- 2016-1-4 jzx debug: 之前用错变量了,不应该是@v_cksl,而是@v_kcsl --SET @v_zlsl = FLOOR(@v_cksl/@v_jzl) * @v_jzl; SET @v_zlsl = FLOOR(@v_kcsl/@v_jzl) * @v_jzl; END; END; --确定指令号 SET @v_zlbh = NULL; --共用同仓库库位,状态为0的出库指令的指令号 IF @v_xnkw = 0 SELECT @v_zlbh = zlbh FROM ckzl WHERE ckmc = @v_ckmc AND kwbh = @v_kwbh AND zt = 0 AND ISNULL(tpcrk,' ') = ISNULL(@v_tpcrk, ' '); -- 2015-11-20 jzx 必须是同一个出入库口的任务 ELSE -- 虚拟库位共用指令号时,必须是同一出库单 SELECT @v_zlbh = zlbh FROM ckzl WHERE ckmc = @v_ckmc AND kwbh = @v_kwbh AND zt = 0 AND pzbh = @p_dh; --如果没有找到,则新增一个 IF @v_zlbh IS NULL EXEC p_instNoCreator @v_zlbh OUT, 1; --提取指令记录号 SET @v_zljlh = NULL SELECT @v_zljlh = MAX(jlh) + 1 FROM ckzl; IF @v_zljlh IS NULL SET @v_zljlh = 1 --设置出库指令单号(pzbh) SELECT @p_dh= ckdh FROM ckdmx H WHERE mxbh=H.mxbh AND mxbh=@v_mxbh; --得到库存可出数量 -07-12-15 --SELECT @c_sl=J.sl FROM cpkcxx J WHERE jlh = @v_kcjlh SET @c_sl = @v_kcsl; --插入出库指令 INSERT INTO ckzl(jlh, zlbh, mxbh, kcjlh, ckmc, kwbh, tpbh, ykcs, sl, hkzt,cpbh, lpxx, gydw,pzbh,zlzt ,pkcsl,kc_rksj, kcbz, bzl, tpcrk, czr, cfwzxx, piz, txm, ysbj) VALUES (@v_zljlh, @v_zlbh, @v_mxbh, @v_kcjlh, @v_ckmc, @v_kwbh, @v_tpbh, @v_kwzsl, @v_zlsl , CASE WHEN @v_kwzsl > @v_zlsl AND @v_chkufs!=2 THEN 0 ELSE NULL END -- 2017-10-18 增加 AND @v_chkufs!=2 条件 , @v_cpbh, @v_lpxx, @v_gydw, @p_dh,@v_zlzt , @c_sl,@v_kc_rksj, @v_kcbz, @v_jzl, @v_tpcrk, @p_czr, @cfwzxx, @piz, @txm, @v_ysbj); -- 2017-10-18 增加下面分支 IF @v_chkufs = 2 AND EXISTS(SELECT 2 FROM cpkcxx_v WHERE kwbh=@v_kwbh AND tpbh=@v_tpbh AND jlh!=@v_kcjlh AND sl>0) BEGIN DECLARE @v_mxbh2 INT; DECLARE c_kckwxxOther CURSOR FOR SELECT I.jlh, I.sl, I.cpbh, I.lpxx, I.gydw, I.rksj, I.bz, I.bzl , I.piz, I.txm, I.cfwzxx, I.zlzt, I.tpbh FROM cpkcxx_v I WHERE kwbh=@v_kwbh AND tpbh=@v_tpbh AND jlh!=@v_kcjlh AND sl>0; OPEN c_kckwxxOther; WHILE 1=1 BEGIN FETCH c_kckwxxOther INTO @v_kcjlh, @v_kcsl, @v_cpbh, @v_lpxx, @v_gydw, @v_kc_rksj, @v_kcbz , @v_jzl, @piz, @txm, @cfwzxx, @v_zlzt, @v_tpbh IF @@FETCH_STATUS <> 0 BREAK; SET @v_zljlh = @v_zljlh + 1; -- 如果单据明细上有其他批次的物料,则绑定明细到这条记录上 SET @v_mxbh2 = NULL; SELECT @v_mxbh2 = mxbh FROM ckdmx WHERE cpbh=@v_cpbh AND ckdh=@p_dh AND mxbh != @v_mxbh; INSERT INTO ckzl(jlh, zlbh, mxbh, kcjlh, ckmc, kwbh, tpbh, ykcs, sl, hkzt,cpbh, lpxx, gydw,pzbh,zlzt ,pkcsl,kc_rksj, kcbz, bzl, tpcrk, czr, cfwzxx, piz, txm, ysbj) VALUES (@v_zljlh, @v_zlbh, ISNULL(@v_mxbh2, @v_mxbh), @v_kcjlh, @v_ckmc, @v_kwbh, @v_tpbh, @v_kwzsl, @v_kcsl , NULL, @v_cpbh, @v_lpxx, @v_gydw, @p_dh, @v_zlzt , @v_kcsl,@v_kc_rksj, @v_kcbz, @v_jzl, @v_tpcrk, @p_czr, @cfwzxx, @piz, @txm, @v_ysbj); SET @v_cksl = @v_cksl - @v_kcsl; END; CLOSE c_kckwxxOther; DEALLOCATE c_kckwxxOther; END; --递减尚未安排出库的数量 SET @v_cksl = @v_cksl - @v_zlsl; IF @v_config = '1' -- 如果仅安排一个库位情况下,立马退出循环 BEGIN -- 2015-10-20 jzx 还要自动修改shsl字段值为yapsl -- 2015-10-21 jzx 还要更新js字段值 -- 2015-10-24 jzx 仅对自动拉动出库单的出库指令才修改shsl字段值 IF @v_clfs IN('2') UPDATE ckdmx SET shsl=yapsl,js=CAST(yapsl/jzl AS DECIMAL(10,1)) WHERE mxbh=@v_mxbh AND shsl<>yapsl; BREAK; END; SET @v_hasXnkw = NULL; END CLOSE @v_kckwxx; DEALLOCATE @v_kckwxx; IF @v_cksl > 0 AND @v_跳过的库位数 > 0 BEGIN -- 再次打开游标处理 SET @v_跳过内侧库位 = @v_跳过内侧库位 + 1; GOTO 单项库位安排; END; END CLOSE c_ckdmx DEALLOCATE c_ckdmx; END go update kwjbxx set wzzls=zls from (select kwbh kw, count(distinct cpbh+'#'+isnull(lpxx,'')) zls from cpkcxx where sl>0 group by kwbh)t where kwbh=kw and wzzls!=zls go