SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_CreateRecipeHistory]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[sp_CreateRecipeHistory]
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[APS].[sp_CreateRecipeHistory]') AND type in (N'P', N'PC'))
DROP PROCEDURE [APS].[sp_CreateRecipeHistory]
GO
-- =============================================
-- Author:      Vitacore (с)
-- Create date: 2015-07-29
-- Description: Сохранение истории рецепта
-- =============================================
CREATE PROCEDURE [APS].[sp_CreateRecipeHistory]
    @RecipeID uniqueidentifier,
    @StatusTo int,
    @IsNew bit = 0,
    @dateTime datetime = null,
    @User uniqueidentifier = null,
	@Storage uniqueidentifier = null,
	@Post uniqueidentifier = null,
    @ProcessName varchar(255) = null,
	@StatusInvoice int = null
AS
BEGIN

    SET NOCOUNT ON;

    declare @errorDescription varchar(max),
            @isValid bit,
            @num int,
			@Performed bit = 0,
			@Loaded bit = 0,
			@Cancel bit = 0
    declare @statusValidation table
        (
            statusFrom int,
            statusTo int,
            valid bit,
            error varchar(max)
        )

	--	--получаем статусы накладной
	select @Performed = ss.[State], @Cancel = case when ss.[State] = 1 then 0 else 1 end 
	from APS.T_RECIPE_INVOICE ri 
		join STOR.T_STORAGE_INVOICE ss on ss.InvoiceID = ri.InvoiceID
	where ri.Recipe = @RecipeID
	 and @StatusInvoice is null

	select @Performed = @StatusInvoice, @Cancel = case when @StatusInvoice = 1 then 0 else 1 end 
	where @StatusInvoice is not null

	select @Performed = ISNULL(@Performed, 0), @Cancel = ISNULL(@Cancel, 1)

	select @Loaded = case when @ProcessName = 'RecipeMessageHandlingProcess' then 1 else 0 end

    insert into @statusValidation(statusFrom, statusTo, valid, error)
    -- 0:Загружен
          select 0, 0, @IsNew,		'Невозможная операция (0:Загружен -> 0:Загружен)'
    union select 0, 1, @Performed,  'Невозможная операция (0:Загружен -> 1:Обработан)'
    union select 0, 2, 1,			'Невозможная операция (0:Загружен -> 2:Отсрочен)'
    union select 0, 3, 1,			'Невозможная операция (0:Загружен -> 3:Отбракован)'
    union select 0, 4, 0,			'Невозможная операция (0:Загружен -> 4:Не обработан)'
    union select 0, 5, @Performed,  'Невозможная операция (0:Загружен -> 5:Отложен)'
    -- 1:Обработан -- 
    union select 1, 0, 0,			'Невозможная операция (1:Обработан -> 0:Загружен)'
    union select 1, 1, 0,			'Невозможная операция (1:Обработан -> 1:Обработан)'
    union select 1, 2, 0,			'Невозможная операция (1:Обработан -> 2:Отсрочен)'
    union select 1, 3, 0,			'Невозможная операция (1:Обработан -> 3:Отбракован)'
    union select 1, 4, @Cancel,     'Невозможная операция (1:Обработан -> 4:Не обработан)'
    union select 1, 5, 0,			'Невозможная операция (1:Обработан -> 5:Отложен)'
    -- 2:Отсрочен
    union select 2, 0, 0,			'Невозможная операция (2:Отсрочен -> 0:Загружен)'
    union select 2, 1, @Performed,  'Невозможная операция (2:Отсрочен -> 1:Обработан)'
    union select 2, 2, 0,			'Невозможная операция (2:Отсрочен -> 2:Отсрочен)'
    union select 2, 3, 1,			'Невозможная операция (2:Отсрочен -> 3:Отбракован)'
    union select 2, 4, 1,			'Невозможная операция (2:Отсрочен -> 4:Не обработан)'
    union select 2, 5, @Performed,  'Невозможная операция (2:Отсрочен -> 5:Отложен)'
    -- 3:Отбракован
    union select 3, 0, 0,			'Невозможная операция (3:Отбракован -> 0:Загружен)'
    union select 3, 1, 0,			'Невозможная операция (3:Отбракован -> 1:Обработан)'
    union select 3, 2, 0,			'Невозможная операция (3:Отбракован -> 2:Отсрочен)'
    union select 3, 3, 0,			'Невозможная операция (3:Отбракован -> 3:Отбракован)'
    union select 3, 4, null,		'Невозможная операция (3:Отбракован -> 4:Не обработан)' -- разрешено, если предыдущее изменение тоже вручную
    union select 3, 5, 0,			'Невозможная операция (3:Отбракован -> 5:Отложен)'
    -- 4:Не обработан
    union select 4, 0, @Loaded,			'Невозможная операция (4:Не обработан -> 0:Загружен)'
    union select 4, 1, @Performed,  'Невозможная операция (4:Не обработан -> 1:Обработан)'
    union select 4, 2, 1,			'Невозможная операция (4:Не обработан -> 2:Отсрочен)'
    union select 4, 3, 1,			'Невозможная операция (4:Не обработан -> 3:Отбракован)'
    union select 4, 4, @IsNew,		'Невозможная операция (4:Не обработан -> 4:Не обработан)'
    union select 4, 5, @Performed,  'Невозможная операция (4:Не обработан -> 5:Отложен)'
    -- 5:Отложен
    union select 5, 0, 0,			'Невозможная операция (5:Отложен -> 0:Загружен)'
    union select 5, 1, @Performed,  'Невозможная операция (5:Отложен -> 1:Обработан)'
    union select 5, 2, 0,			'Невозможная операция (5:Отложен -> 2:Отсрочен)'
    union select 5, 3, 0,			'Невозможная операция (5:Отложен -> 3:Отбракован)'
    union select 5, 4, @Cancel,     'Невозможная операция (5:Отложен -> 4:Не обработан)'
    union select 5, 5, 0,			'Невозможная операция (5:Отложен -> 5:Отложен)'

    -- Заполняем необходимые переменные из таблиц, с блокировкой по рецепту
    select @num = r.HCounter
          ,@errorDescription = sv.error
          ,@isValid = case
                            when sv.valid is not null then sv.valid
                            -- разрешено, если предыдущее изменение тоже вручную
                            when sv.statusFrom = 3 and sv.statusTo = 4 and @ProcessName is null and (select top 1 rch.ProcessName from [APS].T_RECIPE_STATUS_HISTORY rch where rch.Recipe = r.RecipeID order by rch.OrderNumber desc) is null then 1
                            else 0
                      end
    from [APS].T_RECIPE r with(rowlock,xlock)
        join @statusValidation sv on sv.statusFrom = r.[Status]
                and
            sv.statusTo = @StatusTo
    where r.RecipeID = @RecipeID

    -- Если операция невозможна, возвращаем ошибку
    if (@isValid = 0)
        raiserror(@errorDescription, 16, 10)

    -- Добавляем запись истории
    select @dateTime = ISNULL(@dateTime, GETDATE())
         , @num = @num + 1
    INSERT INTO [APS].[T_RECIPE_STATUS_HISTORY]
               ([RecipeStatusHistoryID] ,[Recipe] ,[CreationDateTime] ,[StatusText] ,[StatusIndex] ,[OrderNumber] ,[Users], [Storage] ,[ProcessName])
    SELECT
               NEWID()--<RecipeStatusHistoryID, uniqueidentifier,>
              ,@RecipeID--<Recipe, uniqueidentifier,>
              ,@datetime--<CreationDateTime, datetime,>
              ,case
                    when @StatusTo = 0 then 'Загружен'
                    when @StatusTo = 1 then 'Обработан'
                    when @StatusTo = 2 then 'Отсрочен'
                    when @StatusTo = 3 then 'Отбракован'
                    when @StatusTo = 4 then 'Не обработан'
                    when @StatusTo = 5 then 'Отложен'
                    else 'Неизвестный индекс'
               end--<StatusText, varchar(255),>
              ,@StatusTo--<StatusIndex, int,>
              ,@num--<OrderNumber, int,>
              ,@User--<Users, uniqueidentifier,>
			  ,@Storage--<Storage, uniqueidentifier,>
              ,@ProcessName--<ProcessName, varchar(255),>)

    -- Обновляем статус и счетчик записи историй
    update r
    set r.HCounter = @num
       ,r.[Status] = @StatusTo
       ,r.Post = @Post
    from [APS].T_RECIPE r
    where r.RecipeID = @RecipeID

END
GO
