/*
Customer-specific review draft for hr_4011 leave writes in the lserp_AI
compatibility-level-100 database.

THIS FILE IS INERT:
1. SET NOEXEC ON prevents CREATE PROCEDURE from being applied.
2. @customer_dba_reviewed is deliberately fixed to 0.
3. The script must never be edited into a production deployment artifact. A customer
   DBA must create and sign a separate script after reviewing every dependency below.

Reviewed design assumptions that still require customer DBA acceptance:
- p_lserp_agent_workflow_read_compat100 is the approved fixed-parameter read contract;
- hr_4011 is a newVer=1 base module backed by HR_EmpLeaveAloneTab;
- p_BaseSave70 is the exact ERP create path and generates hr_ela_no through the
  configured document-number rules;
- p_baseApply is the exact ERP submit path;
- p_SubsysPurviewTab.hrPurview is the customer menu permission source, menu
  16629 is hr_4011, and only the edit token (without the read-only "|" suffix)
  authorizes a write;
- p_agent_command_idempotency, p_agent_business_audit and
  p_agent_integration_outbox were created from 001_agent_business_idempotency.sql;
- the legacy procedures may emit diagnostic result sets; the trusted ERP gateway
  discards those and accepts exactly one result set whose ten columns exactly match
  the fixed BusinessWriteResult contract;
- the fixed INSERT column list below matches the approved UI save payload, including
  nullable department/post and secondary-hours fields that are intentionally omitted.

No table name, column name, SQL fragment or procedure name is accepted from the Agent.
The only dynamic SQL string is an internally constructed, fixed-template @base_sql
required by the legacy p_BaseSave70 contract. Every text value is length checked and
escaped inside this wrapper.
*/
SET NOEXEC ON;
GO

CREATE PROCEDURE dbo.p_lserp_agent_workflow_write_leave_compat100
    @action VARCHAR(64),
    @module_code NVARCHAR(64),
    @account_book NVARCHAR(64),
    @subsystem_id NVARCHAR(32),
    @user_id NVARCHAR(64),
    @correlation_id VARCHAR(128),
    @idempotency_key VARCHAR(128),
    @input_fingerprint CHAR(64),
    @employee_id NVARCHAR(64) = NULL,
    @leave_type_code NVARCHAR(64) = NULL,
    @flow_type_code NVARCHAR(64) = NULL,
    @start_local DATETIME = NULL,
    @end_local DATETIME = NULL,
    @requested_hours DECIMAL(18, 6) = NULL,
    @reason NVARCHAR(500) = NULL,
    @submit_after_save_intent BIT = NULL,
    @record_id NVARCHAR(128) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    DECLARE @customer_dba_reviewed BIT;
    SET @customer_dba_reviewed = 0;

    IF @customer_dba_reviewed <> 1
    BEGIN
        RAISERROR(N'customer_dba_review_required', 16, 1);
        RETURN;
    END;

    IF DB_NAME() <> N'lserp_AI'
       OR @module_code <> N'hr_4011'
       OR @subsystem_id <> N'7'
       OR @action NOT IN ('create_draft', 'submit')
       OR NULLIF(LTRIM(RTRIM(@account_book)), N'') IS NULL
       OR NULLIF(LTRIM(RTRIM(@user_id)), N'') IS NULL
       OR @@TRANCOUNT < 1 OR XACT_STATE() <> 1
    BEGIN
        RAISERROR(N'leave_write_scope_invalid', 16, 1);
        RETURN;
    END;

    IF @correlation_id IS NULL
       OR LEN(@correlation_id) < 8 OR LEN(@correlation_id) > 128
       OR @correlation_id LIKE '%[^A-Za-z0-9_.:-]%'
       OR @idempotency_key IS NULL
       OR LEN(@idempotency_key) < 8 OR LEN(@idempotency_key) > 128
       OR @idempotency_key LIKE '%[^A-Za-z0-9_.:-]%'
       OR @input_fingerprint IS NULL OR LEN(@input_fingerprint) <> 64
       OR @input_fingerprint LIKE '%[^A-Fa-f0-9]%'
    BEGIN
        RAISERROR(N'leave_write_evidence_invalid', 16, 1);
        RETURN;
    END;

    DECLARE @context TABLE
    (
        current_employee_id NVARCHAR(64) NOT NULL,
        can_apply_for_others BIT NOT NULL,
        now_local DATETIME NOT NULL
    );
    INSERT INTO @context
        (current_employee_id, can_apply_for_others, now_local)
    EXEC dbo.p_lserp_agent_workflow_read_compat100
        @workflow = 'leave',
        @action = 'context',
        @module_code = @module_code,
        @account_book = @account_book,
        @subsystem_id = @subsystem_id,
        @user_id = @user_id;

    IF (SELECT COUNT_BIG(*) FROM @context) <> 1
    BEGIN
        RAISERROR(N'leave_context_contract_invalid', 16, 1);
        RETURN;
    END;

    DECLARE @current_employee_text NVARCHAR(64);
    DECLARE @can_apply_for_others BIT;
    DECLARE @now_local DATETIME;
    SELECT
        @current_employee_text = current_employee_id,
        @can_apply_for_others = can_apply_for_others,
        @now_local = now_local
    FROM @context;

    IF LEN(@current_employee_text) > 10
       OR @current_employee_text LIKE N'%[^0-9]%'
    BEGIN
        RAISERROR(N'leave_context_contract_invalid', 16, 1);
        RETURN;
    END;

    DECLARE @current_employee_number DECIMAL(10, 0);
    DECLARE @current_employee_id INT;
    SET @current_employee_number = CONVERT(DECIMAL(10, 0), @current_employee_text);
    IF @current_employee_number < 1 OR @current_employee_number > 2147483647
    BEGIN
        RAISERROR(N'leave_context_contract_invalid', 16, 1);
        RETURN;
    END;
    SET @current_employee_id = CONVERT(INT, @current_employee_number);

    IF @user_id IS NULL OR LEN(@user_id) > 10
       OR @user_id LIKE N'%[^0-9]%'
    BEGIN
        RAISERROR(N'leave_user_scope_invalid', 16, 1);
        RETURN;
    END;
    DECLARE @user_number DECIMAL(10, 0);
    SET @user_number = CONVERT(DECIMAL(10, 0), @user_id);
    IF @user_number < 1 OR @user_number > 2147483647
       OR CONVERT(INT, @user_number) <> @current_employee_id
    BEGIN
        RAISERROR(N'leave_user_scope_invalid', 16, 1);
        RETURN;
    END;

    DECLARE @operator_name NVARCHAR(50);
    SELECT @operator_name = CONVERT(NVARCHAR(50), EmployeeName)
    FROM dbo.p_employeetab WITH (HOLDLOCK)
    WHERE employeeid = @current_employee_id
      AND ISNULL(p_emp_status, '') <> N'离职';
    IF @operator_name IS NULL
    BEGIN
        RAISERROR(N'leave_context_contract_invalid', 16, 1);
        RETURN;
    END;

    /*
    Read-only menu tokens end in "|". A write must have the exact edit token
    ",16629,"; the trusted WinForm authorizer performs the same check before
    confirmation, and this database check closes the time-of-check/use gap.
    */
    DECLARE @leave_permission_text NVARCHAR(MAX);
    SET @leave_permission_text = N',';
    SELECT TOP (1)
        @leave_permission_text = N','
            + CONVERT(NVARCHAR(MAX), ISNULL(hrPurview, '')) + N','
    FROM dbo.p_SubsysPurviewTab WITH (UPDLOCK, HOLDLOCK)
    WHERE employeeid = @current_employee_id;
    IF (@current_employee_id <> 1 OR @operator_name <> N'管理员')
       AND CHARINDEX(N',16629,', @leave_permission_text) = 0
    BEGIN
        RAISERROR(N'leave_write_permission_denied', 16, 1);
        RETURN;
    END;

    DECLARE @command_name VARCHAR(128);
    SET @command_name = CASE WHEN @action = 'create_draft'
        THEN 'hr.leave.create' ELSE 'hr.leave.submit' END;

    IF OBJECT_ID(N'dbo.p_agent_command_idempotency', N'U') IS NULL
       OR OBJECT_ID(N'dbo.p_agent_business_audit', N'U') IS NULL
       OR OBJECT_ID(N'dbo.p_agent_integration_outbox', N'U') IS NULL
    BEGIN
        RAISERROR(N'leave_agent_evidence_schema_missing', 16, 1);
        RETURN;
    END;

    DECLARE @application_lock_result INT;
    DECLARE @application_lock_resource NVARCHAR(255);
    SET @application_lock_resource = N'lserp-agent:leave:'
        + LEFT(@account_book, 40) + N':' + LEFT(@subsystem_id, 20)
        + N':' + LEFT(@user_id, 10) + N':' + @command_name
        + N':' + CONVERT(NVARCHAR(128), @idempotency_key);
    EXEC @application_lock_result = sys.sp_getapplock
        @Resource = @application_lock_resource,
        @LockMode = 'Exclusive',
        @LockOwner = 'Transaction',
        @LockTimeout = 10000;
    IF @application_lock_result < 0
    BEGIN
        RAISERROR(N'leave_idempotency_lock_failed', 16, 1);
        RETURN;
    END;

    DECLARE @idempotency_id BIGINT;
    DECLARE @stored_fingerprint CHAR(64);
    DECLARE @stored_status TINYINT;
    DECLARE @stored_result_code VARCHAR(128);
    DECLARE @stored_record_id NVARCHAR(128);
    DECLARE @stored_transaction_id VARCHAR(128);
    DECLARE @stored_audit_id VARCHAR(128);

    SELECT
        @idempotency_id = id,
        @stored_fingerprint = input_fingerprint,
        @stored_status = status,
        @stored_result_code = result_code,
        @stored_record_id = record_id,
        @stored_transaction_id = transaction_evidence_id,
        @stored_audit_id = business_audit_id
    FROM dbo.p_agent_command_idempotency WITH (UPDLOCK, HOLDLOCK)
    WHERE account_book = @account_book
      AND subsystem_id = @subsystem_id
      AND user_id = @user_id
      AND command_name = @command_name
      AND idempotency_key = @idempotency_key;

    IF @idempotency_id IS NOT NULL
       AND @stored_fingerprint <> @input_fingerprint
    BEGIN
        SELECT
            CONVERT(BIT, 0) AS success,
            CONVERT(VARCHAR(128), 'idempotency_key_conflict') AS code,
            CONVERT(NVARCHAR(1000), N'同一幂等键已绑定不同的业务输入。') AS message,
            CONVERT(NVARCHAR(128), NULL) AS record_id,
            CONVERT(BIT, 0) AS needs_ui,
            CONVERT(BIT, 0) AS idempotency_replayed,
            @idempotency_key AS applied_idempotency_key,
            @input_fingerprint AS applied_input_fingerprint,
            CONVERT(VARCHAR(128), NULL) AS transaction_evidence_id,
            CONVERT(VARCHAR(128), NULL) AS business_audit_id;
        RETURN;
    END;

    IF @idempotency_id IS NOT NULL AND @stored_status = 1
    BEGIN
        SELECT
            CONVERT(BIT, 1) AS success,
            @stored_result_code AS code,
            CONVERT(NVARCHAR(1000), N'已返回同一幂等请求的原事务结果。') AS message,
            @stored_record_id AS record_id,
            CONVERT(BIT, 0) AS needs_ui,
            CONVERT(BIT, 1) AS idempotency_replayed,
            @idempotency_key AS applied_idempotency_key,
            @input_fingerprint AS applied_input_fingerprint,
            @stored_transaction_id AS transaction_evidence_id,
            @stored_audit_id AS business_audit_id;
        RETURN;
    END;

    IF @idempotency_id IS NOT NULL
    BEGIN
        SELECT
            CONVERT(BIT, 0) AS success,
            CONVERT(VARCHAR(128), 'idempotency_request_not_replayable') AS code,
            CONVERT(NVARCHAR(1000), N'同一幂等请求尚未形成可重放的成功结果。') AS message,
            CONVERT(NVARCHAR(128), NULL) AS record_id,
            CONVERT(BIT, 0) AS needs_ui,
            CONVERT(BIT, 0) AS idempotency_replayed,
            @idempotency_key AS applied_idempotency_key,
            @input_fingerprint AS applied_input_fingerprint,
            CONVERT(VARCHAR(128), NULL) AS transaction_evidence_id,
            CONVERT(VARCHAR(128), NULL) AS business_audit_id;
        RETURN;
    END;

    INSERT INTO dbo.p_agent_command_idempotency
    (
        account_book, subsystem_id, user_id, command_name,
        idempotency_key, input_fingerprint, status
    )
    VALUES
    (
        @account_book, @subsystem_id, @user_id, @command_name,
        @idempotency_key, @input_fingerprint, 0
    );
    SET @idempotency_id = CONVERT(BIGINT, SCOPE_IDENTITY());

    DECLARE @effective_record_id NVARCHAR(128);
    DECLARE @result_code VARCHAR(128);
    DECLARE @result_message NVARCHAR(1000);

    IF @action = 'create_draft'
    BEGIN
        SET @employee_id = NULLIF(LTRIM(RTRIM(@employee_id)), N'');
        SET @leave_type_code = NULLIF(LTRIM(RTRIM(@leave_type_code)), N'');
        SET @flow_type_code = NULLIF(LTRIM(RTRIM(@flow_type_code)), N'');
        SET @reason = NULLIF(LTRIM(RTRIM(@reason)), N'');

        IF @employee_id IS NULL OR LEN(@employee_id) > 10
           OR @employee_id LIKE N'%[^0-9]%'
           OR @leave_type_code IS NULL OR LEN(@leave_type_code) > 10
           OR @leave_type_code LIKE N'%[^0-9]%'
           OR @flow_type_code IS NULL OR LEN(@flow_type_code) > 10
           OR @flow_type_code LIKE N'%[^0-9]%'
           OR @start_local IS NULL OR @end_local IS NULL
           OR @end_local <= @start_local
           OR DATEDIFF(DAY, CONVERT(DATE, @start_local),
                             CONVERT(DATE, @end_local)) > 31
           OR @requested_hours IS NULL
           OR @requested_hours < 0 OR @requested_hours > 744
           OR @reason IS NULL OR LEN(@reason) < 2 OR LEN(@reason) > 500
           OR DATALENGTH(CONVERT(VARCHAR(8000), @reason)) > 500
           OR CONVERT(NVARCHAR(500), CONVERT(VARCHAR(500), @reason)) <> @reason
        BEGIN
            RAISERROR(N'leave_create_input_invalid', 16, 1);
            RETURN;
        END;

        DECLARE @control_code INT;
        SET @control_code = 1;
        WHILE @control_code <= 31
        BEGIN
            IF CHARINDEX(NCHAR(@control_code), @reason) > 0
            BEGIN
                RAISERROR(N'leave_create_input_invalid', 16, 1);
                RETURN;
            END;
            SET @control_code = @control_code + 1;
        END;
        IF CHARINDEX(NCHAR(127), @reason) > 0
        BEGIN
            RAISERROR(N'leave_create_input_invalid', 16, 1);
            RETURN;
        END;

        DECLARE @requested_employee_number DECIMAL(10, 0);
        DECLARE @leave_type_number DECIMAL(10, 0);
        DECLARE @flow_type_number DECIMAL(10, 0);
        SET @requested_employee_number = CONVERT(DECIMAL(10, 0), @employee_id);
        SET @leave_type_number = CONVERT(DECIMAL(10, 0), @leave_type_code);
        SET @flow_type_number = CONVERT(DECIMAL(10, 0), @flow_type_code);
        IF @requested_employee_number < 1
           OR @requested_employee_number > 2147483647
           OR @leave_type_number < 1 OR @leave_type_number > 2147483647
           OR @flow_type_number < 1 OR @flow_type_number > 2147483647
           OR (@requested_employee_number <> @current_employee_id
               AND ISNULL(@can_apply_for_others, 0) <> 1)
        BEGIN
            RAISERROR(N'leave_apply_for_others_denied', 16, 1);
            RETURN;
        END;

        IF @start_local < CONVERT(DATE, @now_local)
        BEGIN
            RAISERROR(N'leave_past_start_denied', 16, 1);
            RETURN;
        END;

        DECLARE @type_state TABLE (enabled BIT NOT NULL);
        INSERT INTO @type_state(enabled)
        EXEC dbo.p_lserp_agent_workflow_read_compat100
            @workflow = 'leave',
            @action = 'type_enabled',
            @module_code = @module_code,
            @account_book = @account_book,
            @subsystem_id = @subsystem_id,
            @user_id = @user_id,
            @leave_type_code = @leave_type_code;
        IF (SELECT COUNT_BIG(*) FROM @type_state) <> 1
           OR NOT EXISTS (SELECT 1 FROM @type_state WHERE enabled = 1)
        BEGIN
            RAISERROR(N'leave_type_not_enabled', 16, 1);
            RETURN;
        END;

        DECLARE @flow_state TABLE (enabled BIT NOT NULL);
        INSERT INTO @flow_state(enabled)
        EXEC dbo.p_lserp_agent_workflow_read_compat100
            @workflow = 'leave',
            @action = 'flow_type_enabled',
            @module_code = @module_code,
            @account_book = @account_book,
            @subsystem_id = @subsystem_id,
            @user_id = @user_id,
            @flow_type_code = @flow_type_code;
        IF (SELECT COUNT_BIG(*) FROM @flow_state) <> 1
           OR NOT EXISTS (SELECT 1 FROM @flow_state WHERE enabled = 1)
        BEGIN
            RAISERROR(N'leave_flow_type_not_enabled', 16, 1);
            RETURN;
        END;

        DECLARE @hours_state TABLE (hours DECIMAL(18, 6) NOT NULL);
        INSERT INTO @hours_state(hours)
        EXEC dbo.p_lserp_agent_workflow_read_compat100
            @workflow = 'leave',
            @action = 'calculate_hours',
            @module_code = @module_code,
            @account_book = @account_book,
            @subsystem_id = @subsystem_id,
            @user_id = @user_id,
            @employee_id = @employee_id,
            @start_local = @start_local,
            @end_local = @end_local;
        IF (SELECT COUNT_BIG(*) FROM @hours_state) <> 1
        BEGIN
            RAISERROR(N'leave_hours_contract_invalid', 16, 1);
            RETURN;
        END;

        DECLARE @calculated_hours DECIMAL(18, 6);
        SELECT @calculated_hours = hours FROM @hours_state;
        IF @calculated_hours <= 0
           OR (@requested_hours > 0
               AND ABS(@requested_hours - @calculated_hours) > 0.01)
        BEGIN
            RAISERROR(N'leave_hours_mismatch', 16, 1);
            RETURN;
        END;

        DECLARE @conflict_state TABLE (has_conflict BIT NOT NULL);
        INSERT INTO @conflict_state(has_conflict)
        EXEC dbo.p_lserp_agent_workflow_read_compat100
            @workflow = 'leave',
            @action = 'has_conflict',
            @module_code = @module_code,
            @account_book = @account_book,
            @subsystem_id = @subsystem_id,
            @user_id = @user_id,
            @employee_id = @employee_id,
            @start_local = @start_local,
            @end_local = @end_local;
        IF (SELECT COUNT_BIG(*) FROM @conflict_state) <> 1
           OR EXISTS (SELECT 1 FROM @conflict_state WHERE has_conflict = 1)
        BEGIN
            RAISERROR(N'leave_time_conflict', 16, 1);
            RETURN;
        END;

        DECLARE @employee_name NVARCHAR(50);
        DECLARE @employee_department_id INT;
        DECLARE @employee_post_id INT;
        SELECT
            @employee_name = CONVERT(NVARCHAR(50), EmployeeName),
            @employee_department_id = Departmentid,
            @employee_post_id = p_emp_postid
        FROM dbo.p_employeetab WITH (HOLDLOCK)
        WHERE employeeid = CONVERT(INT, @requested_employee_number)
          AND ISNULL(p_emp_status, '') <> N'离职';
        IF @employee_name IS NULL
           OR @employee_department_id IS NULL
           OR @employee_post_id IS NULL
           OR DATALENGTH(CONVERT(VARCHAR(8000), @employee_name)) > 50
           OR DATALENGTH(CONVERT(VARCHAR(8000), @operator_name)) > 10
        BEGIN
            RAISERROR(N'leave_employee_not_available', 16, 1);
            RETURN;
        END;

        DECLARE @standard_day_hours DECIMAL(18, 6);
        DECLARE @calculated_days DECIMAL(18, 6);
        SELECT TOP (1)
            @standard_day_hours = CONVERT(DECIMAL(18, 6),
                CASE WHEN ISNULL(check_param.shichang, 0) = 0
                     THEN 7.5 ELSE check_param.shichang END)
        FROM dbo.HR_ScheduleTab AS schedule WITH (HOLDLOCK)
        LEFT JOIN dbo.P_SystemCheckParamTab AS check_param WITH (HOLDLOCK)
          ON schedule.HR_Schedule_billdocument_d = check_param.Billdocument_Id
        WHERE schedule.HR_Schedule_employeeid =
              CONVERT(INT, @requested_employee_number)
          AND schedule.HR_Schedule_Date <= CONVERT(DATE, @start_local)
        ORDER BY schedule.HR_Schedule_Date DESC;
        IF @standard_day_hours IS NULL OR @standard_day_hours <= 0
        BEGIN
            RAISERROR(N'leave_day_hours_not_configured', 16, 1);
            RETURN;
        END;
        SET @calculated_days = ROUND(
            @calculated_hours / @standard_day_hours, 1);
        IF @calculated_days <= 0 OR @calculated_days > 366
        BEGIN
            RAISERROR(N'leave_calculated_days_invalid', 16, 1);
            RETURN;
        END;

        DECLARE @number_lock_result INT;
        EXEC @number_lock_result = sys.sp_getapplock
            @Resource = N'lserp-agent:hr_4011:document-number',
            @LockMode = 'Exclusive',
            @LockOwner = 'Transaction',
            @LockTimeout = 10000;
        IF @number_lock_result < 0
        BEGIN
            RAISERROR(N'leave_document_number_lock_failed', 16, 1);
            RETURN;
        END;

        /*
        Hold the identity tail until the outer transaction completes. The legacy
        save procedure can overwrite @msg after assigning the document number, so
        the created row is identified by the protected identity interval instead of
        trusting that output text.
        */
        DECLARE @identity_before INT;
        SELECT @identity_before = ISNULL(MAX(hr_ela_id), 0)
        FROM dbo.HR_EmpLeaveAloneTab WITH (UPDLOCK, HOLDLOCK);

        DECLARE @base_sql NVARCHAR(MAX);
        SET @base_sql =
            N'INSERT INTO dbo.HR_EmpLeaveAloneTab '
            + N'(hr_ela_empid,hr_ela_employeename,hr_ela_depid,hr_ela_postid,'
            + N'hr_ela_type,hr_ela_billtype,'
            + N'hr_ela_Leavebak,hr_ela_starttime,hr_ela_finishtime,'
            + N'hr_ela_totals,hr_ela_totals1,hr_ela_operatorid,hr_ela_operatorname,'
            + N'hr_ela_operatedate) VALUES ('
            + CONVERT(NVARCHAR(20), CONVERT(INT, @requested_employee_number))
            + N',N''' + REPLACE(@employee_name, N'''', N'''''') + N''','
            + N'N''' + CONVERT(NVARCHAR(20), @employee_department_id) + N''','
            + N'N''' + CONVERT(NVARCHAR(20), @employee_post_id) + N''','
            + CONVERT(NVARCHAR(20), CONVERT(INT, @leave_type_number))
            + N',' + CONVERT(NVARCHAR(20), CONVERT(INT, @flow_type_number)) + N','
            + N'N''' + REPLACE(@reason, N'''', N'''''') + N''','''
            + CONVERT(NVARCHAR(23), @start_local, 121) + N''','''
            + CONVERT(NVARCHAR(23), @end_local, 121) + N''','
            + CONVERT(NVARCHAR(50), @calculated_hours) + N','
            + CONVERT(NVARCHAR(50), @calculated_days) + N','
            + CONVERT(NVARCHAR(20), @current_employee_id) + N',N'''
            + REPLACE(@operator_name, N'''', N'''''') + N''','''
            + CONVERT(NVARCHAR(23), @now_local, 121) + N''')';

        DECLARE @legacy_message NVARCHAR(4000);
        DECLARE @legacy_return INT;
        SET @legacy_message = N'';
        EXEC @legacy_return = dbo.p_BaseSave70
            @baseSql = @base_sql,
            @saveType = 1,
            @modid = 'hr_4011',
            @tablename = 'HR_EmpLeaveAloneTab',
            @keyfield = 'hr_ela_id',
            @keyvalue = '',
            @Operatorid = @current_employee_id,
            @operatorName = @operator_name,
            @msg = @legacy_message OUTPUT,
            @comfirmFlag = 0;

        IF @legacy_return <> 1 OR @@TRANCOUNT < 1 OR XACT_STATE() <> 1
        BEGIN
            RAISERROR(N'leave_legacy_create_failed', 16, 1);
            RETURN;
        END;

        DECLARE @created_record_count BIGINT;
        DECLARE @created_identity INT;
        SELECT
            @created_record_count = COUNT_BIG(*),
            @created_identity = MAX(hr_ela_id),
            @effective_record_id = MAX(CONVERT(NVARCHAR(50), hr_ela_no))
        FROM dbo.HR_EmpLeaveAloneTab WITH (UPDLOCK, HOLDLOCK)
        WHERE hr_ela_id > @identity_before;
        IF @created_record_count <> 1
           OR @created_identity IS NULL
           OR NULLIF(LTRIM(RTRIM(@effective_record_id)), N'') IS NULL
           OR NOT EXISTS
           (
               SELECT 1
               FROM dbo.HR_EmpLeaveAloneTab WITH (UPDLOCK, HOLDLOCK)
               WHERE hr_ela_id = @created_identity
                 AND CONVERT(NVARCHAR(50), hr_ela_no) = @effective_record_id
                 AND hr_ela_empid = CONVERT(INT, @requested_employee_number)
                 AND hr_ela_employeename = CONVERT(VARCHAR(50), @employee_name)
                 AND hr_ela_depid = CONVERT(VARCHAR(20), @employee_department_id)
                 AND hr_ela_postid = CONVERT(VARCHAR(20), @employee_post_id)
                 AND hr_ela_type = CONVERT(INT, @leave_type_number)
                 AND hr_ela_billtype = CONVERT(INT, @flow_type_number)
                 AND hr_ela_starttime = @start_local
                 AND hr_ela_finishtime = @end_local
                 AND ABS(ISNULL(hr_ela_totals, 0) - @calculated_hours) <= 0.01
                 AND ABS(ISNULL(hr_ela_totals1, 0) - @calculated_days) <= 0.01
                 AND hr_ela_Leavebak = CONVERT(VARCHAR(500), @reason)
                 AND hr_ela_operatorid = @current_employee_id
                 AND ISNULL(hr_ela_cancelFlag, 0) = 0
           )
        BEGIN
            RAISERROR(N'leave_legacy_create_evidence_invalid', 16, 1);
            RETURN;
        END;

        SET @result_code = 'leave_draft_created';
        SET @result_message = N'请假申请草稿已通过 ERP 原保存链创建。';

        /* submit_after_save_intent is intentionally never executed here. */
        SET @submit_after_save_intent = ISNULL(@submit_after_save_intent, 0);
    END
    ELSE
    BEGIN
        SET @record_id = NULLIF(LTRIM(RTRIM(@record_id)), N'');
        IF @record_id IS NULL OR LEN(@record_id) > 128
        BEGIN
            RAISERROR(N'leave_submit_record_invalid', 16, 1);
            RETURN;
        END;

        IF DATALENGTH(CONVERT(VARCHAR(8000), @operator_name)) > 20
        BEGIN
            RAISERROR(N'leave_submit_operator_invalid', 16, 1);
            RETURN;
        END;

        /* p_baseApply contains legacy self-migration branches; never let an Agent
           request reach those branches. Schema repair remains a DBA operation. */
        IF COL_LENGTH('dbo.p_systemdlltabflowtypestep', 'autoStep') IS NULL
           OR COL_LENGTH('dbo.p_systemdlltabflowtypestep', 'comfirmOper') IS NULL
           OR COL_LENGTH('dbo.p_systemNotification', 'stepCode') IS NULL
        BEGIN
            RAISERROR(N'leave_approval_schema_not_ready', 16, 1);
            RETURN;
        END;

        DECLARE @submit_state TABLE
        (
            can_submit BIT NOT NULL,
            reason NVARCHAR(1000) NULL
        );
        INSERT INTO @submit_state(can_submit, reason)
        EXEC dbo.p_lserp_agent_workflow_read_compat100
            @workflow = 'leave',
            @action = 'can_submit',
            @module_code = @module_code,
            @account_book = @account_book,
            @subsystem_id = @subsystem_id,
            @user_id = @user_id,
            @record_id = @record_id;
        IF (SELECT COUNT_BIG(*) FROM @submit_state) <> 1
           OR NOT EXISTS (SELECT 1 FROM @submit_state WHERE can_submit = 1)
        BEGIN
            RAISERROR(N'leave_submit_not_allowed', 16, 1);
            RETURN;
        END;

        DECLARE @submit_employee_id INT;
        DECLARE @submit_record_count BIGINT;
        SELECT
            @submit_record_count = COUNT_BIG(*),
            @submit_employee_id = MAX(hr_ela_empid),
            @effective_record_id = MAX(CONVERT(NVARCHAR(50), hr_ela_no))
        FROM dbo.HR_EmpLeaveAloneTab WITH (UPDLOCK, HOLDLOCK)
        WHERE CONVERT(NVARCHAR(32), hr_ela_id) = @record_id
           OR CONVERT(NVARCHAR(50), hr_ela_no) = @record_id;
        IF @submit_record_count <> 1
           OR @submit_employee_id <> @current_employee_id
           OR NULLIF(@effective_record_id, N'') IS NULL
        BEGIN
            RAISERROR(N'leave_submit_record_scope_invalid', 16, 1);
            RETURN;
        END;

        DECLARE @apply_message NVARCHAR(4000);
        DECLARE @apply_return INT;
        SET @apply_message = N'';
        EXEC @apply_return = dbo.p_baseApply
            @typeCode = 'hr_4011',
            @billDocumentId = @effective_record_id,
            @Operatorid = @current_employee_id,
            @operatorName = @operator_name,
            @comfirmType = 1,
            @msg = @apply_message OUTPUT;
        IF @apply_return <> 1 OR @@TRANCOUNT < 1 OR XACT_STATE() <> 1
        BEGIN
            RAISERROR(N'leave_legacy_submit_failed', 16, 1);
            RETURN;
        END;

        IF NOT EXISTS
        (
            SELECT 1
            FROM dbo.HR_EmpLeaveAloneTab AS leave_record WITH (UPDLOCK, HOLDLOCK)
            JOIN dbo.p_baseflowOper AS flow_record WITH (UPDLOCK, HOLDLOCK)
              ON flow_record.modid = 'hr_4011'
             AND flow_record.keyvalue = leave_record.hr_ela_no
             AND flow_record.billtype = leave_record.hr_ela_billtype
            WHERE leave_record.hr_ela_no = @effective_record_id
              AND leave_record.hr_ela_empid = @current_employee_id
        )
        BEGIN
            RAISERROR(N'leave_legacy_submit_evidence_invalid', 16, 1);
            RETURN;
        END;

        SET @result_code = 'leave_submitted';
        SET @result_message = N'请假申请已通过 ERP 原审批流提交。';
    END;

    DECLARE @guid_text VARCHAR(32);
    DECLARE @transaction_evidence_id VARCHAR(128);
    DECLARE @business_audit_id VARCHAR(128);
    DECLARE @outbox_event_id VARCHAR(128);
    SET @guid_text = LOWER(REPLACE(CONVERT(VARCHAR(36), NEWID()), '-', ''));
    SET @transaction_evidence_id = 'tx-leave-' + @guid_text;
    SET @business_audit_id = 'audit-leave-' + @guid_text;
    SET @outbox_event_id = 'outbox-leave-' + @guid_text;

    INSERT INTO dbo.p_agent_business_audit
    (
        business_audit_id, transaction_evidence_id, correlation_id,
        idempotency_id, account_book, subsystem_id, user_id,
        command_name, module_code, action_name, record_id,
        input_fingerprint
    )
    VALUES
    (
        @business_audit_id, @transaction_evidence_id, @correlation_id,
        @idempotency_id, @account_book, @subsystem_id, @user_id,
        @command_name, @module_code, @action, @effective_record_id,
        @input_fingerprint
    );

    INSERT INTO dbo.p_agent_integration_outbox
    (
        event_id, business_audit_id, correlation_id, account_book,
        subsystem_id, module_code, action_name, record_id, status
    )
    VALUES
    (
        @outbox_event_id, @business_audit_id, @correlation_id, @account_book,
        @subsystem_id, @module_code, @action, @effective_record_id, 0
    );

    UPDATE dbo.p_agent_command_idempotency
    SET status = 1,
        result_code = @result_code,
        record_id = @effective_record_id,
        transaction_evidence_id = @transaction_evidence_id,
        business_audit_id = @business_audit_id,
        completed_at_utc = SYSUTCDATETIME()
    WHERE id = @idempotency_id AND status = 0;
    IF @@ROWCOUNT <> 1
    BEGIN
        RAISERROR(N'leave_idempotency_completion_failed', 16, 1);
        RETURN;
    END;

    SELECT
        CONVERT(BIT, 1) AS success,
        @result_code AS code,
        @result_message AS message,
        @effective_record_id AS record_id,
        CONVERT(BIT, 0) AS needs_ui,
        CONVERT(BIT, 0) AS idempotency_replayed,
        @idempotency_key AS applied_idempotency_key,
        @input_fingerprint AS applied_input_fingerprint,
        @transaction_evidence_id AS transaction_evidence_id,
        @business_audit_id AS business_audit_id;
END;
GO
