﻿/*
库房管理隔离实施脚本（测试库 ERPTOOL_JY_20250826Back）
修改人:Ld 修改时间:2026-07-30 09:23:13;
说明：
1. 新增库房、库区、库房业务记录表。
2. 对库存管理_货位主文件仅补充可空字段，不改变原字段和原存储过程。
3. 新增存储过程全部使用“库房管理_”前缀，不覆盖现有“仓储管理_”过程。
*/

SET NOCOUNT ON;
GO

IF OBJECT_ID(N'dbo.库房管理_库房主文件', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.库房管理_库房主文件
    (
        库房流水号 INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_库房管理_库房主文件 PRIMARY KEY,
        库房编号 NVARCHAR(50) NOT NULL,
        库房名称 NVARCHAR(100) NOT NULL,
        库房类型 NVARCHAR(50) NULL,
        地址 NVARCHAR(200) NULL,
        负责人 INT NULL,
        状态 NVARCHAR(20) NOT NULL CONSTRAINT DF_库房管理_库房主文件_状态 DEFAULT(N'启用'),
        排数 INT NOT NULL CONSTRAINT DF_库房管理_库房主文件_排数 DEFAULT(8),
        每排列数 INT NOT NULL CONSTRAINT DF_库房管理_库房主文件_每排列数 DEFAULT(24),
        层数 INT NOT NULL CONSTRAINT DF_库房管理_库房主文件_层数 DEFAULT(3),
        备注 NVARCHAR(500) NULL,
        创建人 INT NULL,
        创建时间 DATETIME NOT NULL CONSTRAINT DF_库房管理_库房主文件_创建时间 DEFAULT(GETDATE()),
        修改人 INT NULL,
        修改时间 DATETIME NULL,
        CONSTRAINT UQ_库房管理_库房主文件_库房编号 UNIQUE(库房编号)
    );
END
GO

IF OBJECT_ID(N'dbo.库房管理_库区主文件', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.库房管理_库区主文件
    (
        库区流水号 INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_库房管理_库区主文件 PRIMARY KEY,
        库房流水号 INT NOT NULL,
        库区编号 NVARCHAR(50) NOT NULL,
        库区名称 NVARCHAR(100) NOT NULL,
        库区类型 NVARCHAR(50) NULL,
        状态 NVARCHAR(20) NOT NULL CONSTRAINT DF_库房管理_库区主文件_状态 DEFAULT(N'启用'),
        排序 INT NULL,
        备注 NVARCHAR(500) NULL,
        创建人 INT NULL,
        创建时间 DATETIME NOT NULL CONSTRAINT DF_库房管理_库区主文件_创建时间 DEFAULT(GETDATE()),
        修改人 INT NULL,
        修改时间 DATETIME NULL,
        CONSTRAINT FK_库房管理_库区主文件_库房 FOREIGN KEY(库房流水号) REFERENCES dbo.库房管理_库房主文件(库房流水号),
        CONSTRAINT UQ_库房管理_库区主文件_库房库区编号 UNIQUE(库房流水号, 库区编号)
    );
END
GO

IF OBJECT_ID(N'dbo.库房管理_业务记录', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.库房管理_业务记录
    (
        业务记录流水号 INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_库房管理_业务记录 PRIMARY KEY,
        业务类型 NVARCHAR(50) NOT NULL,
        业务单号 NVARCHAR(100) NULL,
        库房流水号 INT NULL,
        库区流水号 INT NULL,
        货位流水号 INT NULL,
        物料流水号 INT NULL,
        物料与货位流水号 INT NULL,
        变动数量 FLOAT NULL,
        变动前数量 FLOAT NULL,
        变动后数量 FLOAT NULL,
        备注 NVARCHAR(500) NULL,
        操作人 INT NULL,
        操作时间 DATETIME NOT NULL CONSTRAINT DF_库房管理_业务记录_操作时间 DEFAULT(GETDATE()),
        CONSTRAINT FK_库房管理_业务记录_库房 FOREIGN KEY(库房流水号) REFERENCES dbo.库房管理_库房主文件(库房流水号),
        CONSTRAINT FK_库房管理_业务记录_库区 FOREIGN KEY(库区流水号) REFERENCES dbo.库房管理_库区主文件(库区流水号)
    );
END
GO

IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'库房流水号') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 库房流水号 INT NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'库区流水号') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 库区流水号 INT NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'排号') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 排号 INT NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'列号') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 列号 INT NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'层号') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 层号 INT NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'库位状态') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 库位状态 NVARCHAR(20) NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'库位容量') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 库位容量 FLOAT NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'是否启用') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 是否启用 BIT NOT NULL CONSTRAINT DF_库存管理_货位主文件_是否启用 DEFAULT(1);
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'修改人') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 修改人 INT NULL;
GO
IF COL_LENGTH(N'dbo.库存管理_货位主文件', N'修改时间') IS NULL
    ALTER TABLE dbo.库存管理_货位主文件 ADD 修改时间 DATETIME NULL;
GO

IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = N'FK_库存管理_货位主文件_库房管理库房')
BEGIN
    ALTER TABLE dbo.库存管理_货位主文件 WITH CHECK
    ADD CONSTRAINT FK_库存管理_货位主文件_库房管理库房 FOREIGN KEY(库房流水号) REFERENCES dbo.库房管理_库房主文件(库房流水号);
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = N'FK_库存管理_货位主文件_库房管理库区')
BEGIN
    ALTER TABLE dbo.库存管理_货位主文件 WITH CHECK
    ADD CONSTRAINT FK_库存管理_货位主文件_库房管理库区 FOREIGN KEY(库区流水号) REFERENCES dbo.库房管理_库区主文件(库区流水号);
END
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'dbo.库存管理_货位主文件') AND name = N'IX_库存管理_货位主文件_库房库区排列层')
    CREATE INDEX IX_库存管理_货位主文件_库房库区排列层 ON dbo.库存管理_货位主文件(库房流水号, 库区流水号, 排号, 列号, 层号);
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'dbo.库房管理_业务记录') AND name = N'IX_库房管理_业务记录_库位物料时间')
    CREATE INDEX IX_库房管理_业务记录_库位物料时间 ON dbo.库房管理_业务记录(货位流水号, 物料流水号, 操作时间 DESC);
GO

IF NOT EXISTS (SELECT 1 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = N'KF-2F')
BEGIN
    INSERT INTO dbo.库房管理_库房主文件(库房编号, 库房名称, 库房类型, 地址, 状态, 排数, 每排列数, 层数, 备注, 创建人)
    VALUES(N'KF-2F', N'二楼隔层仓库', N'隔层仓库', N'二楼隔层', N'启用', 1, 99, 1, N'库位格式：字母数字-数字，例如 A1-1', 0);
END
GO
IF NOT EXISTS (SELECT 1 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = N'KF-LK')
BEGIN
    INSERT INTO dbo.库房管理_库房主文件(库房编号, 库房名称, 库房类型, 地址, 状态, 排数, 每排列数, 层数, 备注, 创建人)
    VALUES(N'KF-LK', N'立库仓库', N'立库仓库', N'立库区域', N'启用', 99, 99, 99, N'库位格式：xx-xx-xx，例如 01-01-01', 0);
END
GO
IF NOT EXISTS (SELECT 1 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = N'KF-3F')
BEGIN
    INSERT INTO dbo.库房管理_库房主文件(库房编号, 库房名称, 库房类型, 地址, 状态, 排数, 每排列数, 层数, 备注, 创建人)
    VALUES(N'KF-3F', N'三楼仓库', N'三楼可视化仓库', N'三楼仓库', N'启用', 8, 24, 3, N'库位格式：x-xx-xx-xx，可视化界面按三楼布局展示', 0);
END
GO

;WITH DefaultArea AS
(
    SELECT N'KF-2F' AS 库房编号, N'2F' AS 库区编号, N'二楼隔层库区' AS 库区名称, N'隔层库区' AS 库区类型, N'字母数字-数字库位区' AS 备注
    UNION ALL SELECT N'KF-LK', N'LK', N'立库库区', N'立库库区', N'xx-xx-xx 库位区'
    UNION ALL SELECT N'KF-3F', N'3F', N'三楼可视化库区', N'三楼库区', N'x-xx-xx-xx 可视化库位区'
)
INSERT INTO dbo.库房管理_库区主文件(库房流水号, 库区编号, 库区名称, 库区类型, 排序, 备注, 创建人)
SELECT k.库房流水号, a.库区编号, a.库区名称, a.库区类型, 1, a.备注, 0
FROM DefaultArea a
INNER JOIN dbo.库房管理_库房主文件 k ON a.库房编号 = k.库房编号
WHERE NOT EXISTS
(
    SELECT 1
    FROM dbo.库房管理_库区主文件 x
    WHERE x.库房流水号 = k.库房流水号
      AND x.库区编号 = a.库区编号
);
GO

IF EXISTS (SELECT 1 FROM dbo.库存管理_货位主文件 WHERE 货位名称 = N'KF-A-01-01-1')
BEGIN
    UPDATE dbo.库存管理_货位主文件
    SET 货位名称 = N'1-01-01-01',
        修改人 = 0,
        修改时间 = GETDATE()
    WHERE 货位名称 = N'KF-A-01-01-1';
END
GO

IF OBJECT_ID(N'dbo.库房管理_库位编码归属_同步', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库位编码归属_同步;
GO
CREATE PROCEDURE dbo.库房管理_库位编码归属_同步
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @二楼库房 INT;
    DECLARE @二楼库区 INT;
    DECLARE @立库库房 INT;
    DECLARE @立库库区 INT;
    DECLARE @三楼库房 INT;
    DECLARE @三楼库区 INT;

    SELECT @二楼库房 = 库房流水号 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = N'KF-2F';
    SELECT @二楼库区 = 库区流水号 FROM dbo.库房管理_库区主文件 WHERE 库房流水号 = @二楼库房 AND 库区编号 = N'2F';
    SELECT @立库库房 = 库房流水号 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = N'KF-LK';
    SELECT @立库库区 = 库区流水号 FROM dbo.库房管理_库区主文件 WHERE 库房流水号 = @立库库房 AND 库区编号 = N'LK';
    SELECT @三楼库房 = 库房流水号 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = N'KF-3F';
    SELECT @三楼库区 = 库区流水号 FROM dbo.库房管理_库区主文件 WHERE 库房流水号 = @三楼库房 AND 库区编号 = N'3F';

    UPDATE h
    SET 库房流水号 = @二楼库房,
        库区流水号 = @二楼库区,
        排号 = NULL,
        列号 = NULL,
        层号 = NULL,
        库位状态 = ISNULL(h.库位状态, N'空库位'),
        修改时间 = GETDATE()
    FROM dbo.库存管理_货位主文件 h
    WHERE h.货位名称 LIKE N'[A-Za-z][0-9]%-[0-9]%'
      AND LEN(h.货位名称) - LEN(REPLACE(h.货位名称, N'-', N'')) = 1;

    UPDATE h
    SET 库房流水号 = @立库库房,
        库区流水号 = @立库库区,
        排号 = CONVERT(INT, PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 3)),
        列号 = CONVERT(INT, PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 2)),
        层号 = CONVERT(INT, PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 1)),
        库位状态 = ISNULL(h.库位状态, N'空库位'),
        修改时间 = GETDATE()
    FROM dbo.库存管理_货位主文件 h
    WHERE LEN(h.货位名称) - LEN(REPLACE(h.货位名称, N'-', N'')) = 2
      AND ISNUMERIC(PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 3)) = 1
      AND ISNUMERIC(PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 2)) = 1
      AND ISNUMERIC(PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 1)) = 1;

    UPDATE h
    SET 库房流水号 = @三楼库房,
        库区流水号 = @三楼库区,
        排号 = CONVERT(INT, PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 4)),
        列号 = CONVERT(INT, PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 3)),
        层号 = CONVERT(INT, PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 2)),
        库位状态 = ISNULL(h.库位状态, N'空库位'),
        修改时间 = GETDATE()
    FROM dbo.库存管理_货位主文件 h
    WHERE LEN(h.货位名称) - LEN(REPLACE(h.货位名称, N'-', N'')) = 3
      AND ISNUMERIC(PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 4)) = 1
      AND ISNUMERIC(PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 3)) = 1
      AND ISNUMERIC(PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 2)) = 1
      AND ISNUMERIC(PARSENAME(REPLACE(h.货位名称, N'-', N'.'), 1)) = 1;

    SELECT
        SUM(CASE WHEN 库房流水号 = @二楼库房 THEN 1 ELSE 0 END) AS 二楼隔层库位数,
        SUM(CASE WHEN 库房流水号 = @立库库房 THEN 1 ELSE 0 END) AS 立库库位数,
        SUM(CASE WHEN 库房流水号 = @三楼库房 THEN 1 ELSE 0 END) AS 三楼库位数
    FROM dbo.库存管理_货位主文件;
END
GO

EXEC dbo.库房管理_库位编码归属_同步;
GO

IF OBJECT_ID(N'dbo.库房管理_库房_查询', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库房_查询;
GO
CREATE PROCEDURE dbo.库房管理_库房_查询
    @库房名称_check BIT = 0,
    @库房名称 NVARCHAR(100) = NULL,
    @状态_check BIT = 0,
    @状态 NVARCHAR(20) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SELECT
        k.库房流水号,
        k.库房编号,
        k.库房名称,
        k.库房类型,
        k.地址,
        k.负责人,
        k.状态,
        k.排数,
        k.每排列数,
        k.层数,
        k.备注,
        ISNULL(q.库区数, 0) AS 库区数,
        ISNULL(h.库位数, 0) AS 库位数,
        ISNULL(s.有库存库位数, 0) AS 有库存库位数,
        ISNULL(s.库存数量, 0) AS 库存数量,
        k.创建时间,
        k.修改时间
    FROM dbo.库房管理_库房主文件 k
    LEFT JOIN
    (
        SELECT 库房流水号, COUNT(1) AS 库区数
        FROM dbo.库房管理_库区主文件
        GROUP BY 库房流水号
    ) q ON k.库房流水号 = q.库房流水号
    LEFT JOIN
    (
        SELECT 库房流水号, COUNT(1) AS 库位数
        FROM dbo.库存管理_货位主文件
        WHERE 库房流水号 IS NOT NULL
        GROUP BY 库房流水号
    ) h ON k.库房流水号 = h.库房流水号
    LEFT JOIN
    (
        SELECT
            h.库房流水号,
            COUNT(DISTINCT h.货位流水号) AS 有库存库位数,
            SUM(ISNULL(m.货位存量, 0)) AS 库存数量
        FROM dbo.库存管理_货位主文件 h
        INNER JOIN dbo.库存管理_物料与货位对照表 m ON h.货位流水号 = m.货位流水号 AND ISNULL(m.货位存量, 0) > 0
        WHERE h.库房流水号 IS NOT NULL
        GROUP BY h.库房流水号
    ) s ON k.库房流水号 = s.库房流水号
    WHERE (@库房名称_check = 0 OR k.库房编号 LIKE N'%' + ISNULL(@库房名称, N'') + N'%' OR k.库房名称 LIKE N'%' + ISNULL(@库房名称, N'') + N'%')
      AND (@状态_check = 0 OR k.状态 = @状态)
    ORDER BY k.库房编号;
END
GO

IF OBJECT_ID(N'dbo.库房管理_库房_保存', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库房_保存;
GO
CREATE PROCEDURE dbo.库房管理_库房_保存
    @库房流水号 INT = NULL,
    @库房编号 NVARCHAR(50),
    @库房名称 NVARCHAR(100),
    @库房类型 NVARCHAR(50) = NULL,
    @地址 NVARCHAR(200) = NULL,
    @负责人 INT = NULL,
    @状态 NVARCHAR(20) = N'启用',
    @排数 INT = 8,
    @每排列数 INT = 24,
    @层数 INT = 3,
    @备注 NVARCHAR(500) = NULL,
    @UserID INT = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF EXISTS (SELECT 1 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = @库房编号 AND ISNULL(@库房流水号, 0) <> 库房流水号)
    BEGIN
        SELECT '0' AS result, N'库房编号已存在' AS msg;
        RETURN;
    END

    IF ISNULL(@库房流水号, 0) = 0
    BEGIN
        INSERT INTO dbo.库房管理_库房主文件(库房编号, 库房名称, 库房类型, 地址, 负责人, 状态, 排数, 每排列数, 层数, 备注, 创建人)
        VALUES(@库房编号, @库房名称, @库房类型, @地址, @负责人, ISNULL(@状态, N'启用'), ISNULL(@排数, 8), ISNULL(@每排列数, 24), ISNULL(@层数, 3), @备注, @UserID);

        SELECT '1' AS result, SCOPE_IDENTITY() AS 库房流水号, N'新增成功' AS msg;
    END
    ELSE
    BEGIN
        UPDATE dbo.库房管理_库房主文件
        SET 库房编号 = @库房编号,
            库房名称 = @库房名称,
            库房类型 = @库房类型,
            地址 = @地址,
            负责人 = @负责人,
            状态 = ISNULL(@状态, 状态),
            排数 = ISNULL(@排数, 排数),
            每排列数 = ISNULL(@每排列数, 每排列数),
            层数 = ISNULL(@层数, 层数),
            备注 = @备注,
            修改人 = @UserID,
            修改时间 = GETDATE()
        WHERE 库房流水号 = @库房流水号;

        SELECT '1' AS result, @库房流水号 AS 库房流水号, N'编辑成功' AS msg;
    END
END
GO

IF OBJECT_ID(N'dbo.库房管理_库房_停用', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库房_停用;
GO
CREATE PROCEDURE dbo.库房管理_库房_停用
    @库房流水号 INT,
    @UserID INT = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF EXISTS
    (
        SELECT 1
        FROM dbo.库存管理_货位主文件 h
        INNER JOIN dbo.库存管理_物料与货位对照表 m ON h.货位流水号 = m.货位流水号
        WHERE h.库房流水号 = @库房流水号 AND ISNULL(m.货位存量, 0) > 0
    )
    BEGIN
        SELECT '0' AS result, N'库房下仍有库存，不能停用' AS msg;
        RETURN;
    END

    UPDATE dbo.库房管理_库房主文件
    SET 状态 = N'停用', 修改人 = @UserID, 修改时间 = GETDATE()
    WHERE 库房流水号 = @库房流水号;

    UPDATE dbo.库存管理_货位主文件
    SET 是否启用 = 0, 修改人 = @UserID, 修改时间 = GETDATE()
    WHERE 库房流水号 = @库房流水号;

    SELECT '1' AS result, N'停用成功' AS msg;
END
GO

IF OBJECT_ID(N'dbo.库房管理_库区_查询', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库区_查询;
GO
CREATE PROCEDURE dbo.库房管理_库区_查询
    @库房流水号 INT = NULL,
    @状态_check BIT = 0,
    @状态 NVARCHAR(20) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET @库房流水号 = NULLIF(@库房流水号, 0);
    SELECT
        q.库区流水号,
        q.库房流水号,
        k.库房名称,
        q.库区编号,
        q.库区名称,
        q.库区类型,
        q.状态,
        q.排序,
        q.备注,
        ISNULL(h.库位数, 0) AS 库位数
    FROM dbo.库房管理_库区主文件 q
    INNER JOIN dbo.库房管理_库房主文件 k ON q.库房流水号 = k.库房流水号
    LEFT JOIN
    (
        SELECT 库区流水号, COUNT(1) AS 库位数
        FROM dbo.库存管理_货位主文件
        WHERE 库区流水号 IS NOT NULL
        GROUP BY 库区流水号
    ) h ON q.库区流水号 = h.库区流水号
    WHERE (@库房流水号 IS NULL OR q.库房流水号 = @库房流水号)
      AND (@状态_check = 0 OR q.状态 = @状态)
    ORDER BY q.排序, q.库区编号;
END
GO

IF OBJECT_ID(N'dbo.库房管理_库区_保存', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库区_保存;
GO
CREATE PROCEDURE dbo.库房管理_库区_保存
    @库区流水号 INT = NULL,
    @库房流水号 INT,
    @库区编号 NVARCHAR(50),
    @库区名称 NVARCHAR(100),
    @库区类型 NVARCHAR(50) = NULL,
    @状态 NVARCHAR(20) = N'启用',
    @排序 INT = NULL,
    @备注 NVARCHAR(500) = NULL,
    @UserID INT = NULL
AS
BEGIN
    SET NOCOUNT ON;
    IF EXISTS (SELECT 1 FROM dbo.库房管理_库区主文件 WHERE 库房流水号 = @库房流水号 AND 库区编号 = @库区编号 AND ISNULL(@库区流水号, 0) <> 库区流水号)
    BEGIN
        SELECT '0' AS result, N'库区编号已存在' AS msg;
        RETURN;
    END

    IF ISNULL(@库区流水号, 0) = 0
    BEGIN
        INSERT INTO dbo.库房管理_库区主文件(库房流水号, 库区编号, 库区名称, 库区类型, 状态, 排序, 备注, 创建人)
        VALUES(@库房流水号, @库区编号, @库区名称, @库区类型, ISNULL(@状态, N'启用'), @排序, @备注, @UserID);

        SELECT '1' AS result, SCOPE_IDENTITY() AS 库区流水号, N'新增成功' AS msg;
    END
    ELSE
    BEGIN
        UPDATE dbo.库房管理_库区主文件
        SET 库房流水号 = @库房流水号,
            库区编号 = @库区编号,
            库区名称 = @库区名称,
            库区类型 = @库区类型,
            状态 = ISNULL(@状态, 状态),
            排序 = @排序,
            备注 = @备注,
            修改人 = @UserID,
            修改时间 = GETDATE()
        WHERE 库区流水号 = @库区流水号;

        SELECT '1' AS result, @库区流水号 AS 库区流水号, N'编辑成功' AS msg;
    END
END
GO

IF OBJECT_ID(N'dbo.库房管理_库位_查询', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库位_查询;
GO
CREATE PROCEDURE dbo.库房管理_库位_查询
    @库房流水号 INT = NULL,
    @库区流水号 INT = NULL,
    @库位名称_check BIT = 0,
    @库位名称 NVARCHAR(50) = NULL,
    @库位状态_check BIT = 0,
    @库位状态 NVARCHAR(20) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET @库房流水号 = NULLIF(@库房流水号, 0);
    SET @库区流水号 = NULLIF(@库区流水号, 0);
    SELECT
        h.货位流水号 AS 库位流水号,
        h.货位名称 AS 库位名称,
        h.库房流水号,
        k.库房名称,
        h.库区流水号,
        q.库区名称,
        h.排号,
        h.列号,
        h.层号,
        CASE
            WHEN ISNULL(h.是否启用, 1) = 0 THEN N'停用'
            WHEN ISNULL(s.库存数量, 0) > 0 AND ISNULL(h.库位容量, 0) > 0 AND ISNULL(s.库存数量, 0) >= ISNULL(h.库位容量, 0) THEN N'满库位'
            WHEN ISNULL(s.库存数量, 0) > 0 THEN N'有库存'
            ELSE ISNULL(h.库位状态, N'空库位')
        END AS 库位状态,
        ISNULL(h.库位容量, 0) AS 库位容量,
        ISNULL(s.物料种类, 0) AS 物料种类,
        ISNULL(s.库存数量, 0) AS 库存数量,
        h.操作日期,
        h.修改时间
    FROM dbo.库存管理_货位主文件 h
    LEFT JOIN dbo.库房管理_库房主文件 k ON h.库房流水号 = k.库房流水号
    LEFT JOIN dbo.库房管理_库区主文件 q ON h.库区流水号 = q.库区流水号
    LEFT JOIN
    (
        SELECT 货位流水号, COUNT(DISTINCT 物料流水号) AS 物料种类, SUM(ISNULL(货位存量, 0)) AS 库存数量
        FROM dbo.库存管理_物料与货位对照表
        WHERE ISNULL(货位存量, 0) > 0
        GROUP BY 货位流水号
    ) s ON h.货位流水号 = s.货位流水号
    WHERE (@库房流水号 IS NULL OR h.库房流水号 = @库房流水号)
      AND (@库区流水号 IS NULL OR h.库区流水号 = @库区流水号)
      AND (@库位名称_check = 0 OR h.货位名称 LIKE N'%' + ISNULL(@库位名称, N'') + N'%')
      AND (@库位状态_check = 0 OR
           CASE
               WHEN ISNULL(h.是否启用, 1) = 0 THEN N'停用'
               WHEN ISNULL(s.库存数量, 0) > 0 AND ISNULL(h.库位容量, 0) > 0 AND ISNULL(s.库存数量, 0) >= ISNULL(h.库位容量, 0) THEN N'满库位'
               WHEN ISNULL(s.库存数量, 0) > 0 THEN N'有库存'
               ELSE ISNULL(h.库位状态, N'空库位')
           END = @库位状态)
    ORDER BY h.排号, h.列号, h.层号, h.货位名称;
END
GO

IF OBJECT_ID(N'dbo.库房管理_库位_保存', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库位_保存;
GO
CREATE PROCEDURE dbo.库房管理_库位_保存
    @库位流水号 INT = NULL,
    @库位名称 NVARCHAR(50),
    @库房流水号 INT,
    @库区流水号 INT = NULL,
    @排号 INT = NULL,
    @列号 INT = NULL,
    @层号 INT = NULL,
    @库位状态 NVARCHAR(20) = N'空库位',
    @库位容量 FLOAT = NULL,
    @是否启用 BIT = 1,
    @UserID INT = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET @库区流水号 = NULLIF(@库区流水号, 0);
    IF EXISTS (SELECT 1 FROM dbo.库存管理_货位主文件 WHERE 货位名称 = @库位名称 AND ISNULL(@库位流水号, 0) <> 货位流水号)
    BEGIN
        SELECT '0' AS result, N'库位名称已存在' AS msg;
        RETURN;
    END

    IF ISNULL(@库位流水号, 0) = 0
    BEGIN
        INSERT INTO dbo.库存管理_货位主文件(货位名称, 库房流水号, 库区流水号, 排号, 列号, 层号, 库位状态, 库位容量, 是否启用, 操作日期, 修改人, 修改时间)
        VALUES(@库位名称, @库房流水号, @库区流水号, @排号, @列号, @层号, ISNULL(@库位状态, N'空库位'), @库位容量, ISNULL(@是否启用, 1), GETDATE(), @UserID, GETDATE());

        SELECT '1' AS result, SCOPE_IDENTITY() AS 库位流水号, N'新增成功' AS msg;
    END
    ELSE
    BEGIN
        UPDATE dbo.库存管理_货位主文件
        SET 货位名称 = @库位名称,
            库房流水号 = @库房流水号,
            库区流水号 = @库区流水号,
            排号 = @排号,
            列号 = @列号,
            层号 = @层号,
            库位状态 = ISNULL(@库位状态, 库位状态),
            库位容量 = @库位容量,
            是否启用 = ISNULL(@是否启用, 是否启用),
            修改人 = @UserID,
            修改时间 = GETDATE()
        WHERE 货位流水号 = @库位流水号;

        SELECT '1' AS result, @库位流水号 AS 库位流水号, N'编辑成功' AS msg;
    END
END
GO

IF OBJECT_ID(N'dbo.库房管理_可视化库位_查询', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_可视化库位_查询;
GO
CREATE PROCEDURE dbo.库房管理_可视化库位_查询
    @库房流水号 INT = NULL,
    @库区流水号 INT = NULL,
    @层号 INT = 1
AS
BEGIN
    SET NOCOUNT ON;
    SET @库房流水号 = NULLIF(@库房流水号, 0);
    SET @库区流水号 = NULLIF(@库区流水号, 0);
    IF @库房流水号 IS NULL
        SELECT @库房流水号 = 库房流水号 FROM dbo.库房管理_库房主文件 WHERE 库房编号 = N'KF-3F';

    DECLARE @排数 INT = 8;
    DECLARE @每排列数 INT = 24;
    DECLARE @层数 INT = 3;
    DECLARE @库房编号 NVARCHAR(50) = N'KF';

    SELECT TOP 1
        @排数 = ISNULL(排数, 8),
        @每排列数 = ISNULL(每排列数, 24),
        @层数 = ISNULL(层数, 3),
        @库房编号 = ISNULL(库房编号, N'KF')
    FROM dbo.库房管理_库房主文件
    WHERE (@库房流水号 IS NULL OR 库房流水号 = @库房流水号)
    ORDER BY 库房流水号;

    ;WITH row_num AS
    (
        SELECT 1 AS n
        UNION ALL SELECT n + 1 FROM row_num WHERE n < @排数
    ),
    col_num AS
    (
        SELECT 1 AS n
        UNION ALL SELECT n + 1 FROM col_num WHERE n < @每排列数
    ),
    cell AS
    (
        SELECT r.n AS 排号, c.n AS 列号, @层号 AS 层号
        FROM row_num r
        CROSS JOIN col_num c
    ),
    stock AS
    (
        SELECT 货位流水号, COUNT(DISTINCT 物料流水号) AS 物料种类, SUM(ISNULL(货位存量, 0)) AS 库存数量
        FROM dbo.库存管理_物料与货位对照表
        WHERE ISNULL(货位存量, 0) > 0
        GROUP BY 货位流水号
    )
    SELECT
        cell.排号,
        cell.列号,
        cell.层号,
        ISNULL(h.货位名称, CONVERT(NVARCHAR(10), cell.排号) + N'-' + RIGHT(N'00' + CONVERT(NVARCHAR(10), cell.列号), 2) + N'-' + RIGHT(N'00' + CONVERT(NVARCHAR(10), cell.层号), 2) + N'-01') AS 库位编号,
        h.货位流水号 AS 库位流水号,
        CASE
            WHEN h.货位流水号 IS NULL THEN N'未建库位'
            WHEN ISNULL(h.是否启用, 1) = 0 THEN N'停用'
            WHEN ISNULL(stock.库存数量, 0) > 0 AND ISNULL(h.库位容量, 0) > 0 AND ISNULL(stock.库存数量, 0) >= ISNULL(h.库位容量, 0) THEN N'满库位'
            WHEN ISNULL(stock.库存数量, 0) > 0 THEN N'有库存'
            ELSE ISNULL(h.库位状态, N'空库位')
        END AS 库位状态,
        ISNULL(stock.物料种类, 0) AS 物料种类,
        ISNULL(stock.库存数量, 0) AS 库存数量,
        ISNULL(h.库位容量, 0) AS 库位容量
    FROM cell
    LEFT JOIN dbo.库存管理_货位主文件 h
        ON h.排号 = cell.排号
       AND h.列号 = cell.列号
       AND h.层号 = cell.层号
       AND (@库房流水号 IS NULL OR h.库房流水号 = @库房流水号)
       AND (@库区流水号 IS NULL OR h.库区流水号 = @库区流水号)
       AND LEN(h.货位名称) - LEN(REPLACE(h.货位名称, N'-', N'')) = 3
    LEFT JOIN stock ON h.货位流水号 = stock.货位流水号
    ORDER BY cell.排号, cell.列号
    OPTION (MAXRECURSION 0);
END
GO

IF OBJECT_ID(N'dbo.库房管理_物料库位_查询', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_物料库位_查询;
GO
CREATE PROCEDURE dbo.库房管理_物料库位_查询
    @查询方向 NVARCHAR(10) = N'综合',
    @关键字_check BIT = 0,
    @关键字 NVARCHAR(100) = NULL,
    @库房流水号 INT = NULL,
    @库位流水号 INT = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET @库房流水号 = NULLIF(@库房流水号, 0);
    SET @库位流水号 = NULLIF(@库位流水号, 0);
    SELECT
        m.物料流水号,
        m.物料编码,
        m.名称 AS 物料名称,
        m.代号 AS 图号或型号,
        h.货位流水号 AS 库位流水号,
        h.货位名称 AS 库位名称,
        h.库房流水号,
        k.库房名称,
        h.库区流水号,
        q.库区名称,
        h.排号,
        h.列号,
        h.层号,
        d.货位存量 AS 库存数量,
        d.批次号,
        CASE
            WHEN ISNULL(d.货位存量, 0) > 0 THEN N'有库存'
            ELSE N'无库存'
        END AS 库存状态,
        d.操作日期,
        @查询方向 AS 查询方向
    FROM dbo.库存管理_物料与货位对照表 d
    INNER JOIN dbo.库存管理_物料主文件_基本 m ON d.物料流水号 = m.物料流水号
    INNER JOIN dbo.库存管理_货位主文件 h ON d.货位流水号 = h.货位流水号
    LEFT JOIN dbo.库房管理_库房主文件 k ON h.库房流水号 = k.库房流水号
    LEFT JOIN dbo.库房管理_库区主文件 q ON h.库区流水号 = q.库区流水号
    WHERE ISNULL(d.货位存量, 0) > 0
      AND (@库房流水号 IS NULL OR h.库房流水号 = @库房流水号)
      AND (@库位流水号 IS NULL OR h.货位流水号 = @库位流水号)
      AND
      (
          @关键字_check = 0
          OR m.物料编码 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
          OR m.名称 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
          OR m.代号 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
          OR h.货位名称 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
      )
    ORDER BY k.库房名称, h.排号, h.列号, h.层号, m.物料编码;
END
GO

IF OBJECT_ID(N'dbo.库房管理_库存流水_查询', N'P') IS NOT NULL
    DROP PROCEDURE dbo.库房管理_库存流水_查询;
GO
CREATE PROCEDURE dbo.库房管理_库存流水_查询
    @关键字_check BIT = 0,
    @关键字 NVARCHAR(100) = NULL,
    @库房流水号 INT = NULL,
    @开始日期 DATE = NULL,
    @结束日期 DATE = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET @库房流水号 = NULLIF(@库房流水号, 0);
    SELECT TOP 500 *
    FROM
    (
        SELECT
            N'入库' AS 业务类型,
            r.入库记录流水号 AS 业务流水号,
            m.物料编码,
            m.名称 AS 物料名称,
            m.代号 AS 图号或型号,
            h.货位名称 AS 库位名称,
            k.库房名称,
            CONVERT(FLOAT, r.实际到货数量) AS 数量,
            r.入库时间 AS 业务时间
        FROM dbo.库存管理_外购件_入库记录 r
        LEFT JOIN dbo.库存管理_物料主文件_基本 m ON r.标准件和外购件流水号 = m.物料流水号
        LEFT JOIN dbo.库存管理_货位主文件 h ON r.货位流水号 = h.货位流水号
        LEFT JOIN dbo.库房管理_库房主文件 k ON h.库房流水号 = k.库房流水号
        UNION ALL
        SELECT
            N'出库' AS 业务类型,
            r.出库记录流水号 AS 业务流水号,
            m.物料编码,
            m.名称 AS 物料名称,
            m.代号 AS 图号或型号,
            h.货位名称 AS 库位名称,
            k.库房名称,
            CONVERT(FLOAT, r.出库数量) AS 数量,
            r.操作日期 AS 业务时间
        FROM dbo.库存管理_物料出库_出库记录 r
        LEFT JOIN dbo.库存管理_物料主文件_基本 m ON r.物料流水号 = m.物料流水号
        LEFT JOIN dbo.库存管理_货位主文件 h ON r.货位流水号 = h.货位流水号
        LEFT JOIN dbo.库房管理_库房主文件 k ON h.库房流水号 = k.库房流水号
        UNION ALL
        SELECT
            N'盘点' AS 业务类型,
            r.修改记录流水号 AS 业务流水号,
            m.物料编码,
            m.名称 AS 物料名称,
            m.代号 AS 图号或型号,
            h.货位名称 AS 库位名称,
            k.库房名称,
            CONVERT(FLOAT, ISNULL(r.更改后数量, 0) - ISNULL(r.原数量, 0)) AS 数量,
            r.修改时间 AS 业务时间
        FROM dbo.库存盘点_修改记录 r
        LEFT JOIN dbo.库存管理_物料主文件_基本 m ON r.物料流水号 = m.物料流水号
        LEFT JOIN dbo.库存管理_物料与货位对照表 d ON r.物料与货位流水号 = d.物料与货位流水号
        LEFT JOIN dbo.库存管理_货位主文件 h ON d.货位流水号 = h.货位流水号
        LEFT JOIN dbo.库房管理_库房主文件 k ON h.库房流水号 = k.库房流水号
    ) x
    WHERE (@库房流水号 IS NULL OR x.库房名称 IN (SELECT 库房名称 FROM dbo.库房管理_库房主文件 WHERE 库房流水号 = @库房流水号))
      AND (@开始日期 IS NULL OR x.业务时间 >= @开始日期)
      AND (@结束日期 IS NULL OR x.业务时间 < DATEADD(DAY, 1, @结束日期))
      AND
      (
          @关键字_check = 0
          OR x.物料编码 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
          OR x.物料名称 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
          OR x.图号或型号 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
          OR x.库位名称 LIKE N'%' + ISNULL(@关键字, N'') + N'%'
      )
    ORDER BY x.业务时间 DESC;
END
GO




