Files
old_jintiantongye_wms/db/数据库更新20171108(安排库位存储过程debug).sql
2025-09-12 17:30:18 +08:00

298 lines
25 KiB
Transact-SQL
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****** 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