USE [YL_MESDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[生产管理_结算工时_查询]
    @合同号 NVARCHAR(50) = NULL,
    @产品编码 NVARCHAR(100) = NULL,
    @订单号 NVARCHAR(50) = NULL,
    @工位 NVARCHAR(50) = NULL,
    @开始日期 DATE = NULL,
    @结束日期 DATE = NULL,
    @数据条数 INT = 100
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @TopCount INT = CASE WHEN ISNULL(@数据条数, 0) <= 0 THEN 100 ELSE @数据条数 END;

    CREATE TABLE #任务
    (
        TaskAID BIGINT NOT NULL PRIMARY KEY,
        订单编号 INT NOT NULL,
        订单行号 INT NULL,
        产品编码 NVARCHAR(1000) NULL,
        产品名称 NVARCHAR(1000) NULL,
        工序名称 NVARCHAR(100) NULL,
        工位名称 NVARCHAR(100) NULL,
        物料编号 NVARCHAR(1000) NULL,
        物料描述 NVARCHAR(1000) NULL,
        合同号 NVARCHAR(100) NULL
    );

    INSERT INTO #任务
    (
        TaskAID,
        订单编号,
        订单行号,
        产品编码,
        产品名称,
        工序名称,
        工位名称,
        物料编号,
        物料描述,
        合同号
    )
    SELECT TOP (@TopCount)
        q.AID AS TaskAID,
        q.订单编号,
        q.订单行号,
        q.物料编码 AS 产品编码,
        q.物料名称 AS 产品名称,
        q.工序名称,
        q.指派对象 AS 工位名称,
        p.物料编号,
        p.物料描述,
        p.合同号
    FROM dbo.MES_接口_生产计划 AS p
    INNER JOIN dbo.MES_接口_生产计划_生产任务 AS q
      ON q.订单编号 = p.订单编号
     AND q.物料类型 = N'pit_Resource'
    WHERE p.单据状态 IS NOT NULL
      AND p.订单编号 > 6000
      AND (@合同号 IS NULL OR @合同号 = N'' OR p.合同号 LIKE N'%' + @合同号 + N'%')
      AND (@产品编码 IS NULL OR @产品编码 = N'' OR q.物料编码 LIKE N'%' + @产品编码 + N'%')
      AND (@订单号 IS NULL OR @订单号 = N'' OR CONVERT(NVARCHAR(50), q.订单编号) = @订单号)
      AND (@工位 IS NULL OR @工位 = N'' OR q.指派对象 LIKE N'%' + @工位 + N'%')
    ORDER BY q.订单编号 DESC, q.订单行号;

    CREATE TABLE #基础数据
    (
        TaskAID BIGINT NULL,
        开始时间 DATETIME NULL,
        操作内容 NVARCHAR(1000) NULL,
        操作类别 NVARCHAR(100) NULL,
        操作人 NVARCHAR(100) NULL,
        加工工时 INT NULL,
        操作数值 INT NULL,
        订单合同号 NVARCHAR(100) NULL,
        订单号 INT NOT NULL,
        订单行号 INT NULL,
        产品编码 NVARCHAR(1000) NULL,
        产品名称 NVARCHAR(1000) NULL,
        工序名称 NVARCHAR(100) NULL,
        工位名称 NVARCHAR(100) NULL,
        物料编号 NVARCHAR(1000) NULL,
        物料描述 NVARCHAR(1000) NULL
    );

    INSERT INTO #基础数据
    (
        TaskAID,
        开始时间,
        操作内容,
        操作类别,
        操作人,
        加工工时,
        操作数值,
        订单合同号,
        订单号,
        订单行号,
        产品编码,
        产品名称,
        工序名称,
        工位名称,
        物料编号,
        物料描述
    )
    SELECT
        t.TaskAID,
        v.开始时间,
        v.操作内容,
        v.操作类别,
        v.操作人,
        v.加工工时,
        v.操作数值,
        t.合同号 AS 订单合同号,
        t.订单编号 AS 订单号,
        t.订单行号,
        t.产品编码,
        t.产品名称,
        t.工序名称,
        t.工位名称,
        t.物料编号,
        t.物料描述
    FROM #任务 AS t
    OUTER APPLY
    (
        SELECT
            ISNULL(c.操作类别, o.操作类别) AS 操作类别,
            ISNULL(c.操作人, o.操作人) AS 操作人,
            ISNULL(c.操作数值, o.操作数值) AS 操作数值,
            ISNULL(c.操作内容, o.操作内容) AS 操作内容,
            ISNULL(c.开始时间, o.开始时间) AS 开始时间,
            ISNULL(c.结束时间, o.结束时间) AS 结束时间,
            ISNULL(c.工时, o.实际工时) AS 加工工时
        FROM dbo.YL_加工中心_操作记录表 AS o
        LEFT JOIN dbo.生产管理_工时校验_校验工时表 AS c
          ON o.AID = c.报工记录id
        WHERE o.TaskAID = t.TaskAID
          AND o.工位名称 <> N'外协'
          AND (o.操作类别 <> N'报工' OR ISNULL(c.结束时间, o.结束时间) IS NOT NULL)
          AND (c.AID IS NOT NULL OR o.操作类别 <> N'收料')
          AND (
                c.AID IS NOT NULL
                OR o.操作内容 NOT IN (N'开始加工', N'辅助开始')
                OR o.结束时间 IS NOT NULL
                OR NOT EXISTS
                   (
                       SELECT 1
                       FROM dbo.YL_加工中心_操作记录表 AS t2
                       WHERE t2.操作内容 IN (N'报工', N'辅助结束')
                         AND t2.TaskAID = o.TaskAID
                         AND t2.开始时间 = o.开始时间
                   )
              )
          AND (
                o.操作内容 NOT IN (N'辅助结束')
                OR NOT EXISTS
                   (
                       SELECT 1
                       FROM dbo.YL_加工中心_操作记录表 AS p
                       WHERE p.操作内容 = N'辅助结束'
                         AND p.TaskAID = o.TaskAID
                         AND p.结束时间 IS NULL
                   )
              )
          AND (
                o.操作内容 NOT IN (N'开始加工', N'辅助开始')
                OR NOT EXISTS
                   (
                       SELECT 1
                       FROM dbo.YL_加工中心_操作记录表 AS p
                       WHERE p.操作内容 = N'暂停'
                         AND p.TaskAID = o.TaskAID
                         AND p.结束时间 = o.开始时间
                         AND p.操作人 = o.操作人
                   )
              )
          AND (
                o.操作数值 IS NOT NULL
                OR (o.操作内容 IN (N'开始加工', N'辅助开始') AND o.结束时间 IS NULL)
                OR o.操作描述 <> N''
              )
    ) AS v
    WHERE (@开始日期 IS NULL OR @开始日期 = N'' OR v.开始时间 >= @开始日期)
      AND (@结束日期 IS NULL OR @结束日期 = N'' OR v.开始时间 < DATEADD(DAY, 1, @结束日期));

    CREATE INDEX IX_基础数据_TaskStart ON #基础数据 (TaskAID, 开始时间);

    CREATE TABLE #操作人拼接
    (
        TaskAID BIGINT NOT NULL,
        开始时间 VARCHAR(19) NOT NULL,
        操作人 NVARCHAR(MAX) NULL,
        PRIMARY KEY (TaskAID, 开始时间)
    );

    INSERT INTO #操作人拼接 (TaskAID, 开始时间, 操作人)
    SELECT
        TaskAID,
        开始时间,
        STRING_AGG(CONVERT(NVARCHAR(MAX), 操作人), N',') AS 操作人
    FROM
    (
        SELECT DISTINCT
            k.TaskAID,
            k.开始时间,
            LTRIM(RTRIM(s.value)) AS 操作人
        FROM
        (
            SELECT DISTINCT
                TaskAID,
                CONVERT(VARCHAR(19), 开始时间, 120) AS 开始时间
            FROM #基础数据
            WHERE TaskAID IS NOT NULL
              AND 开始时间 IS NOT NULL
        ) AS k
        INNER JOIN dbo.YL_加工中心_操作记录表 AS o
          ON o.TaskAID = k.TaskAID
         AND o.开始时间 >= CONVERT(DATETIME, k.开始时间, 120)
         AND o.开始时间 < DATEADD(SECOND, 1, CONVERT(DATETIME, k.开始时间, 120))
        LEFT JOIN dbo.生产管理_工时校验_校验工时表 AS c
          ON o.AID = c.报工记录id
        CROSS APPLY STRING_SPLIT(REPLACE(REPLACE(ISNULL(ISNULL(c.操作人, o.操作人), N''), N'，', N','), N'、', N','), N',') AS s
        WHERE ISNULL(ISNULL(c.工时, o.实际工时), 0) <= 0
          AND NULLIF(LTRIM(RTRIM(s.value)), N'') IS NOT NULL
    ) AS x
    GROUP BY TaskAID, 开始时间;

    ;WITH 结算明细 AS
    (
        SELECT
            ISNULL(b.物料编号, b.产品编码) AS 物料编号,
            ISNULL(b.物料描述, b.产品名称) AS 物料描述,
            b.订单号,
            b.工位名称,
            b.TaskAID,
            b.工序名称,
            b.订单行号,
            ISNULL(o.操作人, N'') AS 操作人,
            CASE
                WHEN ISNULL(b.操作内容, N'') LIKE N'%辅助%' OR ISNULL(b.操作类别, N'') LIKE N'%辅助%' THEN N'辅助结束'
                ELSE N'报工'
            END AS 操作类型,
            CAST(ISNULL(b.加工工时, 0) / 60.0 / 60.0 AS DECIMAL(18, 4)) AS 工时小时,
            ISNULL(b.操作数值, 0) AS 完成数
        FROM #基础数据 AS b
        LEFT JOIN #操作人拼接 AS o
          ON o.TaskAID = b.TaskAID
         AND o.开始时间 = CONVERT(VARCHAR(19), b.开始时间, 120)
    ),
    订单工位汇总基础 AS
    (
        SELECT
            物料编号,
            物料描述,
            订单号,
            工位名称,
            MAX(工序名称) AS 工序名称,
            订单行号 AS 工序顺序,
            COUNT(*) AS 记录数,
            SUM(CASE WHEN 操作类型 = N'报工' THEN 工时小时 ELSE 0 END) AS 报工工时,
            SUM(CASE WHEN 操作类型 = N'辅助结束' THEN 工时小时 ELSE 0 END) AS 主辅工时,
            SUM(CASE WHEN 操作类型 = N'报工' THEN 完成数 ELSE 0 END) AS 报工完成数,
            SUM(CASE WHEN 操作类型 = N'辅助结束' THEN 完成数 ELSE 0 END) AS 辅助完成数,
            SUM(工时小时) AS 合计工时
        FROM 结算明细
        GROUP BY 物料编号, 物料描述, 订单号, 工位名称, 订单行号
    ),
    订单工位操作人 AS
    (
        SELECT
            物料编号,
            订单号,
            ISNULL(工位名称, N'') AS 工位名称,
            STRING_AGG(CONVERT(NVARCHAR(MAX), 操作人), N',') AS 操作人
        FROM
        (
            SELECT DISTINCT
                j.物料编号,
                j.订单号,
                ISNULL(j.工位名称, N'') AS 工位名称,
                LTRIM(RTRIM(s.value)) AS 操作人
            FROM 结算明细 AS j
            CROSS APPLY STRING_SPLIT(REPLACE(REPLACE(ISNULL(j.操作人, N''), N'，', N','), N'、', N','), N',') AS s
            WHERE NULLIF(LTRIM(RTRIM(s.value)), N'') IS NOT NULL
        ) AS x
        GROUP BY 物料编号, 订单号, ISNULL(工位名称, N'')
    ),
    订单工位汇总 AS
    (
        SELECT
            b.物料编号,
            b.物料描述,
            b.订单号,
            b.工位名称,
            b.工序名称,
            b.工序顺序,
            b.记录数,
            b.报工工时,
            b.主辅工时,
            b.报工完成数,
            b.辅助完成数,
            b.合计工时,
            ISNULL(o.操作人, N'') AS 操作人
        FROM 订单工位汇总基础 AS b
        LEFT JOIN 订单工位操作人 AS o
          ON o.物料编号 = b.物料编号
         AND o.订单号 = b.订单号
         AND o.工位名称 = ISNULL(b.工位名称, N'')
    ),
    物料汇总 AS
    (
        SELECT
            物料编号,
            物料描述,
            SUM(记录数) AS 记录数,
            SUM(报工工时) AS 报工工时,
            SUM(主辅工时) AS 主辅工时,
            SUM(报工完成数) AS 报工完成数,
            SUM(辅助完成数) AS 辅助完成数,
            SUM(合计工时) AS 合计工时
        FROM 订单工位汇总
        GROUP BY 物料编号, 物料描述
    )
    SELECT
        1 AS [Level],
        物料编号 AS materialCode,
        物料描述 AS materialDesc,
        ISNULL(物料描述, N'') + N' ' + ISNULL(物料编号, N'') AS taskDescription,
        CAST(0 AS INT) AS productionOrderNo,
        N'' AS station,
        CAST(报工工时 AS VARCHAR(20)) AS reportWorkHours,
        CAST(主辅工时 AS VARCHAR(20)) AS auxiliaryWorkHours,
        CAST(报工完成数 AS VARCHAR(20)) AS reportFinishQty,
        CAST(辅助完成数 AS VARCHAR(20)) AS auxiliaryFinishQty,
        CAST(合计工时 AS VARCHAR(20)) AS totalWorkHours,
        CAST(CASE WHEN 报工完成数 > 0 THEN (报工工时 - 0 * 报工完成数) / 报工完成数 ELSE 0 END AS VARCHAR(20)) AS clampingTime,
        CAST(0 AS VARCHAR(20)) AS programTime,
        CAST(CASE WHEN 报工完成数 > 0 THEN 报工工时 / 报工完成数 ELSE 0 END AS VARCHAR(20)) AS settlementReportPieceHours,
        CAST(CASE WHEN 辅助完成数 > 0 THEN 主辅工时 / 辅助完成数 ELSE 0 END AS VARCHAR(20)) AS settlementAuxiliaryPieceHours,
        N'' AS operatorNames,
        CAST(记录数 AS VARCHAR(20)) AS recordCount,
        CAST(0 AS INT) AS 工序顺序
    FROM 物料汇总

    UNION ALL

    SELECT
        2 AS [Level],
        物料编号 AS materialCode,
        物料描述 AS materialDesc,
        ISNULL(物料描述, N'') + N' ' + ISNULL(物料编号, N'')
            + CASE WHEN NULLIF(ISNULL(工序名称, N''), N'') IS NULL THEN N'' ELSE N' ' + 工序名称 END
            + CASE WHEN 工序顺序 IS NULL THEN N'' ELSE N' 序' + CAST(工序顺序 AS VARCHAR(20)) END AS taskDescription,
        订单号 AS productionOrderNo,
        ISNULL(工位名称, N'') AS station,
        CAST(报工工时 AS VARCHAR(20)) AS reportWorkHours,
        CAST(主辅工时 AS VARCHAR(20)) AS auxiliaryWorkHours,
        CAST(报工完成数 AS VARCHAR(20)) AS reportFinishQty,
        CAST(辅助完成数 AS VARCHAR(20)) AS auxiliaryFinishQty,
        CAST(合计工时 AS VARCHAR(20)) AS totalWorkHours,
        CAST(CASE WHEN 报工完成数 > 0 THEN (报工工时 - 0 * 报工完成数) / 报工完成数 ELSE 0 END AS VARCHAR(20)) AS clampingTime,
        CAST(0 AS VARCHAR(20)) AS programTime,
        CAST(CASE WHEN 报工完成数 > 0 THEN 报工工时 / 报工完成数 ELSE 0 END AS VARCHAR(20)) AS settlementReportPieceHours,
        CAST(CASE WHEN 辅助完成数 > 0 THEN 主辅工时 / 辅助完成数 ELSE 0 END AS VARCHAR(20)) AS settlementAuxiliaryPieceHours,
        ISNULL(操作人, N'') AS operatorNames,
        CAST(记录数 AS VARCHAR(20)) AS recordCount,
        工序顺序
    FROM 订单工位汇总

    ORDER BY productionOrderNo, 工序顺序, materialCode, [Level], station;
END
GO
