298 lines
25 KiB
Transact-SQL
298 lines
25 KiB
Transact-SQL
/****** 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
|