-- ================================================
-- PT_PAP Program Type + Workflow Configuration Seed
-- 2026-08-07
-- DRAFT ONLY — not executed against any database, not yet reviewed/approved.
-- No schema changes. Seed data only.
-- Idempotent: inserts use ON CONFLICT DO NOTHING.
--
-- Scope of this migration: program_type_v1, workflow_configuration, and
-- workflow_stage (REGISTRATION, PAYMENT, TRAVEL) ONLY.
--
-- program_template / template_form_section rows for PT_PAP are intentionally
-- NOT created here — planned as a follow-up via the admin API
-- (POST /v1/program-templates, :id/clone-from-master, :id/form, :id/publish).
-- See docs/product-spec-docs/PT_PAP_PROGRAM_TYPE_NOTES.md §3 for the plan and
-- the known template_key int->varchar clone bug to verify first
-- (database/migrations/2026-06-10-01-template-key-varchar.sql).
--
-- Source rows cloned from the live DB:
--   PT_TAT          program_type_v1.id = 14   (used only for §1 program_type_v1 column modeling)
--   PT_ENTRAINMENT  program_type_v1.id = 8    (used only for §1 program_type_v1 column modeling)
--
-- Workflow (workflow_configuration + all 3 workflow_stage rows, §2/§3 below) is cloned
-- entirely from PT_HDBMSD's live workflow, WF_HDBMSD_V8
-- (database/workflow-config-hdb-msd-insert.sql), per explicit instruction. This REPLACES
-- an earlier draft of this file where REGISTRATION/PAYMENT were cloned from PT_TAT
-- (WF_TAT_TA26_V7) and TRAVEL from PT_ENTRAINMENT (WF_ENTRAINMENT_V5) — HDB/MSD is the
-- better source since it's the only other existing type with requires_approval = true,
-- so its approval-gating logic (and generic, non-program-specific success-screen copy)
-- applies to PAP directly without needing to be merged in from elsewhere.
--
-- Two deliberate deviations from WF_HDBMSD_V8, both per explicit instruction:
--   1. REGISTRATION stage's FS_MAHATRIAQUESTIONS section is dropped — only FS_BASICDETAILS
--      is kept.
--   2. The GOODIES stage (HDB/MSD's stage 4) is dropped entirely, and GOODIES_STATUS /
--      PROGRAM_HAS_GOODIES are excluded from the variable-linking step (§2b) — PT_PAP has
--      has_goodies = false and no goodies stage.
-- HDB/MSD's workflow_action rows (SEAT_APPROVAL, DEFAULTER_MARKING, SWAP_*, SEND_INVOICE,
-- etc.) are NOT cloned here — out of scope per the Scope note above. Flagging as a likely
-- follow-up if PAP needs the same admin actions (approval, defaulter marking, swaps, invoice
-- resend/download) that HDB/MSD's workflow exposes.
-- ================================================

BEGIN;

-- ================================================
-- 1. program_type_v1 — Insert PT_PAP
-- Model per docs/product-spec-docs/PT_PAP_PROGRAM_TYPE_NOTES.md:
--   Registration + Payment behavior follows PT_TAT.
--   Post-payment (travel/residence) behavior follows PT_ENTRAINMENT.
--   Single session (unlike TAT's multi-session structure).
-- ================================================

INSERT INTO program_type_v1 (
    mode_of_operation,
    online_type,
    name,
    description,
    key,
    no_of_session,
    has_multiple_sessions,
    requires_residence,
    involves_travel,
    has_checkin_checkout,
    requires_payment,
    requires_attendance_all_sessions,
    allows_minors,
    allows_proxy_registration,
    requires_approval,
    registration_level,
    is_active,
    waitlist_applicable,
    limited_seats,
    is_grouped_program,
    is_special_program,
    has_goodies,
    sub_program_type,
    allow_save_as_draft,
    currency,
    max_session_duration_days,
    frequency,
    default_duration,
    max_proxy_registrations,
    should_send_terms,
    is_proforma_allowed,
    parental_consent_enabled,
    parental_consent_form_content,
    parental_consent_upload_deadline,
    parental_consent_form_as_attachment,
    gst_percentage,
    cgst,
    sgst,
    igst,
    logo_url,
    banner_url,
    venue,
    venue_name_in_emails,
    meta,
    max_capacity,
    gst_number,
    tds_percent,
    tds_applicability,
    invoice_sender_name,
    invoice_sender_pan,
    invoice_sender_cin,
    invoice_sender_address,
    invoice_code,
    services_accounting_code,
    helpline_number,
    email_sender_name,
    email_sender_address,
    email_bcc_name,
    email_bcc_address,
    seeker_can_share_experience,
    created_by,
    updated_by
) VALUES (
    'offline',                    -- mode_of_operation: residential/travel program, matches ENTRAINMENT. OPEN: confirm with Product — not stated explicitly in the notes doc.
    'NA',                          -- online_type: follows PT_HDBMSD ('NA') per explicit instruction — consistent with mode_of_operation = 'offline' (TAT's own value is 'meeting', since TAT is online).
    'PAP',           -- name. OPEN: confirm exact display name/branding with Product (notes doc only gives "PROFIT AND PEACE" as the parenthetical key expansion).
    'Profit and Peace program',   -- description. OPEN: confirm final seeker-facing copy with Product/Marketing.
    'PT_PAP',
    1,                             -- no_of_session: single session, per notes doc §4.
    true,                         -- has_multiple_sessions: single session, per notes doc §4.
    true,                          -- requires_residence: like ENTRAINMENT, per notes doc §1/§5.
    true,                          -- involves_travel: like ENTRAINMENT, per notes doc §1/§5. NOTE (notes doc §5, open decision): Program entity has a second, separate `isTravelInvolved` flag whose relationship to `involvesTravel` is unresolved — this migration only sets the program_type_v1-level `involves_travel` column; the program-level flag(s) are out of scope here and must be confirmed before programs are created under this type.
    true,                          -- has_checkin_checkout: OPEN — assumed true to match ENTRAINMENT (residential program); not explicitly confirmed in notes doc.
    true,                          -- requires_payment: like TAT, per notes doc §1.
    true,                          -- requires_attendance_all_sessions: true on both TAT and ENTRAINMENT source rows.
    false,                         -- allows_minors: CHANGED to follow PT_HDBMSD's actual value (false) per explicit instruction — overrides the earlier TAT/ENTRAINMENT-consensus true (both of those source rows have this true).
    false,                         -- allows_proxy_registration: CHANGED to follow PT_HDBMSD's actual value (false) per explicit instruction — overrides the earlier TAT/ENTRAINMENT-consensus true.
    true,                          -- requires_approval: CONFIRMED true per explicit instruction (deviates from both TAT and ENTRAINMENT source rows, which are false). Registrations must be approved (approvalStatus = 'approved') before the PAYMENT stage becomes accessible — see the approval-gating conditions added to the PAYMENT stage below, cloned from database/workflow-config-hdb-msd-insert.sql (PT_HDBMSD is the only existing type with requires_approval = true).
    'program',                     -- registration_level: matches both TAT and ENTRAINMENT source rows.
    true,                          -- is_active
    false,                          -- waitlist_applicable: kept true per explicit instruction, even though PT_HDBMSD's own row actually has this false (TAT/ENTRAINMENT both have true). FLAG: confirm with Product whether PAP should follow HDB/MSD here too, now that allows_minors/allows_proxy_registration below have been switched to HDB/MSD's values.
    true,                          -- limited_seats: true on both TAT and ENTRAINMENT source rows.
    true,                          -- is_grouped_program: CHANGED to true per explicit instruction — overrides both TAT and ENTRAINMENT source rows, which have this false.
    true,                          -- is_special_program: new column, HDB/MSD and TAT both true, no conflict. NOTE: not present on the ProgramType TypeScript entity (src/common/entities/program-type.entity.ts) even though it exists in the DB schema (database/base-script/portal-base-schema-script.sql:1011) — pre-existing entity/schema drift, unrelated to PAP.
    false,                         -- has_goodies: OPEN — no signal in either source row's intent per notes doc; defaulted to false (entity column default).
    'PST_PAP',                     -- sub_program_type: OPEN — follows the PST_TAT / PST_ENTRAINMENT naming convention by inference; not confirmed with Product.
    true,                          -- allow_save_as_draft: CHANGED to follow PT_HDBMSD's actual value (true) per explicit instruction — resolves the earlier OPEN flag (TAT's own program_type_v1 row has this false despite exposing a SAVE_DRAFT button on its REGISTRATION stage).
    'INR',
    3,                              -- max_session_duration_days: CONFIRMED 3 per explicit instruction. Not present in the source TAT/ENTRAINMENT columns copied above; left unset it would have silently fallen back to the schema default of 8 (program_type_v1.max_session_duration_days default), which matches HDB/MSD's 8-day residential retreat and is wrong for PAP's single-session (no_of_session = 1) structure.
    'yearly',                       -- frequency: new column, HDB/MSD and TAT both 'yearly', no conflict (also the schema default).
    '3 days',                       -- default_duration: new column. Not copied verbatim from either source (HDB/MSD = '8 days', TAT = '1 days') — set to match PT_PAP's own max_session_duration_days = 3 above, for internal consistency.
    0,                              -- max_proxy_registrations: CHANGED to follow PT_HDBMSD's actual value (0) per explicit instruction, consistent with allows_proxy_registration now false above.
    true,                           -- should_send_terms: TAT=true, ENTRAINMENT=false. Defaulted to ENTRAINMENT's value (travel/residence model). OPEN: confirm with Product/Legal.
    true,                           -- is_proforma_allowed: TAT=false, ENTRAINMENT=true. Defaulted to ENTRAINMENT's value (travel/residence model). OPEN: confirm with Finance.
    false,                          -- parental_consent_enabled: TAT=true, ENTRAINMENT=false, yet PAP has allows_minors=true like both. Defaulted to false (ENTRAINMENT's value) but this is a real OPEN decision — if minors can attend a residential program with travel, parental consent may be legally required. Needs explicit Product/Legal sign-off, not just inherited from ENTRAINMENT.
    null,                           -- parental_consent_form_content: new column, follows PT_HDBMSD (NULL) — PT_TAT actually has a large non-null consent-form HTML body here, but since parental_consent_enabled = false above, HDB/MSD's NULL is the consistent choice.
    null,                           -- parental_consent_upload_deadline: new column, HDB/MSD and TAT both NULL, no conflict.
    false,                          -- parental_consent_form_as_attachment: new column, HDB/MSD and TAT both false, no conflict.
    18.00,                          -- gst_percentage: matches both TAT and ENTRAINMENT source rows.
    9.00,                           -- cgst: new column, HDB/MSD and TAT both 9.00, no conflict.
    9.00,                           -- sgst: new column, HDB/MSD and TAT both 9.00, no conflict.
    18.00,                          -- igst: new column, HDB/MSD and TAT both 18.00, no conflict.
    'https://infinitheism-serverless.s3.ap-south-1.amazonaws.com/static-images/logo/pap-logo.png',    -- logo_url: CHANGED from the earlier HDB/MSD placeholder to PAP's actual Dev-environment logo asset, per explicit instruction. Dev bucket only (infinitheism-serverless) — QA/UAT/Prod use different asset buckets, see database/migrations/2026-08-08-01-pt-pap-logo-banner-update.sql for those environments' UPDATE statements.
    'https://infinitheism-serverless.s3.ap-south-1.amazonaws.com/static-images/banner/pap-banner.png', -- banner_url: CHANGED from the earlier HDB/MSD placeholder to PAP's actual Dev-environment banner asset, per explicit instruction. Same Dev-only caveat as logo_url above.
    'Radisson Blu Resort, Temple Bay, No.57 Covelong, East Coast Road, Mahabalipuram - 603104, Tamil Nadu.', -- venue: follows PT_HDBMSD per explicit instruction. FLAG: this is literally HDB/MSD's venue; PAP's real venue is unconfirmed and must be set before go-live.
    'Radisson Blu Resort, Temple Bay, No.57 Covelong, East Coast Road, Mahabalipuram - 603104, Tamil Nadu.', -- venue_name_in_emails: mirrors venue above, same HDB/MSD placeholder, same FLAG.
    '{"tags": ["intensive", "residential", "transformation"], "mealsIncluded": true, "accommodationType": "shared"}'::jsonb, -- meta: copied verbatim from PT_HDBMSD per explicit instruction. FLAG: tags/mealsIncluded/accommodationType describe HDB/MSD's program, not confirmed as accurate for PAP.
    0,                              -- max_capacity: follows PT_HDBMSD (0). Same convention as max_proxy_registrations (0 = unlimited per program.entity.ts comment) — OPEN: confirm PAP has no capacity cap.
    '33AACCI7694H1ZB',              -- gst_number: follows PT_TAT (not the general HDB/MSD baseline) — CONFIRMED per explicit instruction, to stay consistent with invoice_sender_address below, which is also TAT's Chennai/Tamil Nadu address. Using HDB/MSD's Telangana GSTIN here would mismatch the invoice sender's state.
    10.00,                          -- tds_percent: matches both TAT and ENTRAINMENT source rows (10.00), no HDB/MSD-vs-TAT conflict.
    'base_only',                    -- tds_applicability: matches both TAT and ENTRAINMENT source rows, no conflict.
    'infinitheism spiritual foundation private limited', -- invoice_sender_name: identical on both HDB/MSD and TAT source rows, no conflict.
    'AACCI7694H',                   -- invoice_sender_pan: identical on both HDB/MSD and TAT source rows, no conflict.
    'U74900TN2011PTC083263',        -- invoice_sender_cin: identical on both HDB/MSD and TAT source rows, no conflict.
    '3, 3rd Cross Road, R.A. Puram, Chennai 600 028, Tamil Nadu, India.', -- invoice_sender_address: follows PT_TAT per explicit instruction (differs from HDB/MSD's Secunderabad address) — paired with TAT's gst_number above so the invoice's GSTIN and sender address stay in the same state.
    'PAP',                          -- invoice_code: CONFIRMED 'PAP' per explicit instruction. NOT copied from TAT's 'TAT09' — that value is the literal prefix used to build TAT's own invoice sequence numbers (see invoice.service.ts generateInvoiceSequenceNumber, `{invoiceCode}{invoiceType}/{seq}/{year}`); reusing it verbatim would make PAP invoices share TAT's exact sequence prefix.
    '999294',                       -- services_accounting_code: now set per explicit instruction, using PT_TAT's actual value (PT_HDBMSD's own row has this NULL).
    '+919841660000',              -- helpline_number: follows PT_HDBMSD's actual literal stored format (with spaces) per explicit instruction — corrected from an earlier compact '+919841670000' entry.
    'PAP - infinitheism',    -- email_sender_name: follows PT_TAT per explicit instruction, genericized from TAT's literal "TAT Online" branding.
    'events@infinitheism.com',      -- email_sender_address: follows PT_TAT per explicit instruction.
    'PAP Team',                     -- email_bcc_name: follows PT_TAT per explicit instruction, genericized from TAT's literal "TAT Team" branding.
    'noreply@infinitheism.com',     -- email_bcc_address: follows PT_TAT per explicit instruction.
    false,                          -- seeker_can_share_experience: CHANGED to false per explicit instruction (your override) — PT_HDBMSD's own row actually has this true, PT_TAT's has false; false was chosen directly rather than following either source.
    -2,
    -2
)
ON CONFLICT (key) DO NOTHING;

-- NOT ADDED — do not exist as columns on program_type_v1 in this codebase's schema
-- (checked src/common/entities/program-type.entity.ts and every ALTER TABLE program_type_v1
-- in database/*, including database/base-script/portal-base-schema-script.sql, the base
-- schema of record): `is_controlled`, `access_group_id`. Both appeared in a program-type
-- data dump used to draft this migration's values, but that dump evidently came from a
-- schema this codebase doesn't have — inserting them here would fail with
-- "column does not exist". Flagging rather than adding; confirm with whoever owns that data
-- source before assuming these need a schema migration first.
--
-- OPEN — intentionally left at column defaults / NULL, still no signal from either source row:
--   nothing remaining in this category as of this pass (services_accounting_code above is
--   now explicitly set; access_group_id is addressed in the NOT ADDED note above).


-- ================================================
-- 2. workflow_configuration — WF_PAP_V1
-- ================================================

INSERT INTO workflow_configuration (
    workflow_key,
    workflow_name,
    program_type_key,
    program_type_id,
    description,
    workflow_version,
    lifecycle_status,
    initial_stage,
    registration_rules,
    created_by,
    updated_by,
    created_at,
    updated_at
) VALUES (
    'WF_PAP_V1',
    'PAP Registration Workflow',
    'PT_PAP',
    (SELECT id FROM program_type_v1 WHERE key = 'PT_PAP'),
    'PAP program registration workflow with 3 stages (Registration, Payment, Travel), cloned from PT_HDBMSD''s live workflow WF_HDBMSD_V8, minus the Mahatria-questions form section and the Goodies stage.',
    '1.0.0',
    'ACTIVE',
    '{"stageKey": "REGISTRATION", "stageName": "Save as Draft", "isOptional": true, "description": "Save progress and resume later"}'::jsonb,
    -- initial_stage: cloned verbatim from WF_HDBMSD_V8.
    '{"criteria": [{"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"operator": "OR", "conditions": [{"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "offline_completed", "completed"]}, {"field": "isFreeSeat", "operator": "EQUALS", "value": true}]}, {"field": "travelInfoStatus", "operator": "EQUALS", "value": "completed"}, {"field": "travelPlanStatus", "operator": "EQUALS", "value": "completed"}], "message": "Registration is completed when all criteria are fulfilled."}'::jsonb,
    -- registration_rules: cloned verbatim from WF_HDBMSD_V8 — appropriate since PT_PAP.requires_approval = true just like HDB/MSD (unlike TAT/ENTRAINMENT, which don't require approval and whose own registration_rules don't check approvalStatus).
    -2,
    -2,
    NOW(),
    NOW()
)
ON CONFLICT DO NOTHING;


-- ================================================
-- 2b. workflow_configuration_variable — link WF_PAP_V1 to the variable_master rows
-- its rule conditions reference. workflow_variable_master is a GLOBAL registry (unique
-- variable_key), so this only links existing rows — no new variable_master rows are created.
--
-- Set = WF_HDBMSD_V8's own linked variable set, verbatim, minus GOODIES_STATUS and
-- PROGRAM_HAS_GOODIES (no Goodies stage exists here — see header note). Notably this list
-- does NOT include LOGO_URL / BANNER_IMAGE_URL even though {{logoUrl}}/{{bannerImageUrl}}
-- appear throughout the stage JSON's templates below — HDB/MSD's own linking migration
-- doesn't link them either, so this preserves that same (seemingly deliberate) pattern
-- rather than introducing a PAP-specific difference.
-- Follows the same variable-linking pattern as
-- database/migrations/2026-05-13-custom-program-type-universal-workflow.sql (resolve
-- variable_master_id by variable_key in a loop — no hardcoded IDs).
-- ================================================

DO $$
DECLARE
    v_workflow_id INT;
    v_var_id      INT;
    v_order       INT := 1;
BEGIN
    SELECT id INTO v_workflow_id
    FROM workflow_configuration
    WHERE workflow_key = 'WF_PAP_V1'
    LIMIT 1;

    IF v_workflow_id IS NULL THEN
        RAISE NOTICE 'WF_PAP_V1 not found — skipping variable linking';
        RETURN;
    END IF;

    FOR v_var_id IN
        SELECT id FROM workflow_variable_master
        WHERE variable_key IN (
            'REGISTRATION_ID', 'USER_ID', 'PROGRAM_ID', 'REGISTRATION_STATUS',
            'BASIC_DETAILS_STATUS', 'APPROVAL_STATUS', 'PAYMENT_STATUS', 'PAYMENT_MODE',
            'EDIT_REQUEST_STATUS', 'TRAVEL_INFO_STATUS', 'TRAVEL_PLAN_STATUS',
            'PRO_FORMA_INVOICE_PDF_URL', 'IS_FREE_SEAT_COMPUTED', 'IS_WAITLISTED',
            'WAITLIST_POSITION',
            'INVOICE_GENERATED', 'INVOICE_PDF_URL', 'INVOICE_STATUS',
            'REGISTRATION_NUMBER', 'SEEKER_NAME', 'SEEKER_EMAIL', 'SEEKER_PHONE',
            'PROGRAM_FEE', 'PROGRAM_NAME', 'PROGRAM_START_DATE', 'PROGRAM_END_DATE',
            'PROGRAM_VENUE',
            'PROGRAM_REQUIRES_PAYMENT', 'PROGRAM_INVOLVES_TRAVEL',
            'PROGRAM_REQUIRES_APPROVAL', 'PROGRAM_ALLOWS_PROXY_REGISTRATION', 'PROGRAM_HAS_TERMS'
        )
        ORDER BY execution_order, variable_key
    LOOP
        INSERT INTO workflow_configuration_variable
            (workflow_config_id, variable_master_id, variable_order, is_required, created_by, updated_by)
        VALUES
            (v_workflow_id, v_var_id, v_order, false, -2, -2)
        ON CONFLICT DO NOTHING;
        v_order := v_order + 1;
    END LOOP;

    RAISE NOTICE 'Linked % variables to WF_PAP_V1 (ID: %)', v_order - 1, v_workflow_id;
END $$;


-- ================================================
-- 3. workflow_stage — 3 stages for WF_PAP_V1, cloned from PT_HDBMSD's live workflow
-- (WF_HDBMSD_V8, database/workflow-config-hdb-msd-insert.sql) — its REGISTRATION, PAYMENT,
-- and TRAVEL stages, verbatim except the two deviations noted on REGISTRATION below.
-- HDB/MSD's 4th stage, GOODIES, is dropped entirely (PT_PAP.has_goodies = false).
-- ================================================

-- Stage 1: REGISTRATION — cloned from WF_HDBMSD_V8's REGISTRATION stage.
-- Deviations from the source, both per explicit instruction:
--   - FS_MAHATRIAQUESTIONS section dropped from execution_rules_config — only
--     FS_BASICDETAILS is kept.
--   - SUBMIT_REGISTRATION's success-screen text genericized: HDB/MSD's literal
--     "Your request has now been placed with Mahatria." is replaced with
--     "Your request has now been placed for approval." — PAP isn't confirmed to be a
--     Mahatria-fronted program, so hardcoding that name would repeat the same mistake this
--     migration previously flagged and avoided with TAT's literal copy.
--   - SAVE_DRAFT's permission condition changed, per explicit instruction: HDB/MSD's original
--     gates the button on `allowsProxyRegistration EQUALS true` (top-level AND) plus an inner
--     OR of registrationStatus IN [draft, save_as_draft] OR basicDetailsFilled NOT_EQUALS
--     'completed'. PT_PAP has allowsProxyRegistration = false (see §1 above), so copied
--     verbatim that AND would make SAVE_DRAFT never appear at all for PAP — silently
--     contradicting program_type_v1.allow_save_as_draft = true, which this migration
--     deliberately set to true for PAP. Fixed by dropping the allowsProxyRegistration gate
--     entirely, keeping the rest of the OR (registrationStatus IN [draft, save_as_draft] OR
--     basicDetailsFilled NOT_EQUALS 'completed') exactly as HDB/MSD had it, so the button now
--     shows for PAP under the same in-progress conditions as before, just without the
--     proxy-registration requirement.
-- OPEN / FLAG (copied verbatim, not fixed): the ROLE_VIEWER prerequisite condition checks a
-- field named `basicDetailStatus` (singular "Detail") alongside `basicDetailsFilled`
-- (plural) elsewhere in the same JSON. This inconsistent naming is pre-existing in
-- WF_HDBMSD_V8 itself — preserved here for fidelity rather than silently "fixed" without
-- confirming which name the workflow engine actually reads.
INSERT INTO workflow_stage (
    workflow_config_id,
    stage_key,
    stage_name,
    stage_order,
    stage_category,
    is_optional,
    description,
    prerequisite_rules_config,
    execution_rules_config,
    action_buttons,
    completion_actions_config,
    created_by,
    updated_by,
    created_at,
    updated_at
) VALUES (
    (SELECT id FROM workflow_configuration WHERE workflow_key = 'WF_PAP_V1'),
    'REGISTRATION',
    'Registration Submission',
    1,
    'FORM',
    false,
    'Seeker fills and submits registration form',
    '{"requiresAuth": true, "requiredStages": [], "conditions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "OR", "conditions": [{"field": "approvalStatus", "operator": "EQUALS", "value": "pending"}, {"field": "approvalStatus", "operator": "IS_NULL"}, {"field": "basicDetailsFilled", "operator": "NOT_EQUALS", "value": "completed"}, {"field": "basicDetailStatus", "operator": "EQUALS", "value": "draft"}]}, "message": "Viewers can access registration when it is in draft or pending approval"}, {"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER"], "condition": {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"}, "message": "Admins can access submitted registrations"}]}'::jsonb,
    '{"sections": [{"sectionKey": "FS_BASICDETAILS", "permissions": {"create": [{"roles": ["ROLE_VIEWER"], "condition": null}], "read": [{"roles": ["ALL"], "condition": null}], "update": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "OR", "conditions": [{"field": "approvalStatus", "operator": "EQUALS", "value": "pending"}, {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "draft"}]}}, {"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER"], "condition": {"field": "basicDetailsFilled", "operator": "EQUALS", "value": "completed"}}], "delete": [{"roles": [], "condition": null}]}}]}'::jsonb,
    '[{"actionKey": "CANCEL", "label": "Cancel", "type": "secondary", "icon": "save", "apiKey": null, "permissions": [{"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "condition": null}], "onSuccess": [{"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "showToast": false, "showSuccessScreen": false}]}, {"actionKey": "SAVE_DRAFT", "label": "Save as Draft", "type": "secondary", "icon": "save", "apiKey": "SAVE_REGISTRATION_DRAFT", "permissions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "OR", "conditions": [{"field": "registrationStatus", "operator": "EQUALS", "value": "draft"}, {"field": "registrationStatus", "operator": "EQUALS", "value": "save_as_draft"}, {"field": "basicDetailsFilled", "operator": "NOT_EQUALS", "value": "completed"}]}}], "onSuccess": [{"roles": ["ROLE_VIEWER"], "showToast": true, "toast": {"message": "Draft saved successfully. You can continue later.", "type": "info"}, "showSuccessScreen": false}]}, {"actionKey": "SUBMIT_REGISTRATION", "label": "Submit", "type": "primary", "icon": "send", "apiKey": "SUBMIT_REGISTRATION", "permissions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "OR", "conditions": [{"field": "approvalStatus", "operator": "EQUALS", "value": "pending"}, {"field": "approvalStatus", "operator": "IS_NULL"}]}}, {"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER"], "condition": null}], "onSuccess": [{"roles": ["ROLE_VIEWER"], "showToast": false, "showSuccessScreen": true, "successScreenConfig": {"scenarios": [{"scenarioKey": "REGISTRATION_SUBMITTED", "condition": {"operator": "AND", "conditions": [{"field": "registrationStatus", "operator": "IN", "value": ["pending"]}, {"field": "approvalStatus", "operator": "IN", "value": ["pending", null]}]}, "screen": {"title": "{{programName}}", "message": "<div style=\"text-align:left\">Dear {{seekerName}}, we have received your details for {{programName}}.\n\nYour request will now be reviewed. If you are offered a seat, you will receive a communication with a payment link to complete your registration.\n\nPlease note: This is only an acknowledgement of your submission and does not confirm your seat.</div>", "variant": "success", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}, {"actionKey": "EDIT_REGISTRATION", "label": "edit form", "type": "secondary", "apiKey": "EDIT_REGISTRATION"}]}}], "defaultScreen": {"title": "{{programName}}", "message": "<div style=\"text-align:left\">Dear {{seekerName}}, we have received your details for {{programName}}.\n\nYour request will now be reviewed. If you are offered a seat, you will receive a communication with a payment link to complete your registration.\n\nPlease note: This is only an acknowledgement of your submission and does not confirm your seat.</div>", "variant": "success", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}, {"actionKey": "EDIT_REGISTRATION", "label": "edit form", "type": "secondary", "apiKey": "EDIT_REGISTRATION"}]}}}, {"roles": ["ROLE_ADMIN", "ROLE_SHOBA", "ROLE_RELATIONAL_MANAGER"], "showToast": false, "showSuccessScreen": false}]}]'::jsonb, -- SUBMIT_REGISTRATION success-screen genericized: "placed with Mahatria" -> "placed for approval" (see comment above)
    '{"conditional": true, "conditions": [{"when": {"field": "registrationStatus", "operator": "IN", "value": ["draft", "save_as_draft"]}, "then": {"stageStatus": "pending", "markStageComplete": false}}, {"when": {"field": "registrationStatus", "operator": "IN", "value": ["submitted", "pending"]}, "then": {"stageStatus": "completed", "markStageComplete": true}}]}'::jsonb,
    -2, -2, NOW(), NOW()
);


-- Stage 2: PAYMENT — cloned from WF_HDBMSD_V8's PAYMENT stage, verbatim. No Mahatria/TAT-
-- specific literal text in this stage's JSON — its success-screen copy is already generic
-- ("Dear infinitheist {{seekerName}}...").
INSERT INTO workflow_stage (
    workflow_config_id,
    stage_key,
    stage_name,
    stage_order,
    stage_category,
    is_optional,
    description,
    prerequisite_rules_config,
    execution_rules_config,
    action_buttons,
    completion_actions_config,
    created_by,
    updated_by,
    created_at,
    updated_at
) VALUES (
    (SELECT id FROM workflow_configuration WHERE workflow_key = 'WF_PAP_V1'),
    'PAYMENT',
    'Payment',
    2,
    'FORM',
    false,
    'Process payment (online/offline)',
    '{"requiresAuth": true, "requiredStages": ["REGISTRATION"], "conditions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [{"field": "requiresPayment", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}, {"operator": "OR", "conditions": [{"field": "paymentStatus", "operator": "IN", "value": ["failed", "online_pending"]}, {"field": "paymentStatus", "operator": "IS_NULL"}, {"operator": "AND", "conditions": [{"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"}, {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}]}]}]}, "message": "Payment required after registration approval"}, {"roles": ["ROLE_FINANCE_MANAGER", "ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER"], "condition": {"operator": "AND", "conditions": [{"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}]}, "message": "Finance team can access payment processing"}]}'::jsonb,
    '{"sections": [{"sectionKey": "FS_PAYMENTINVOICE", "permissions": {"create": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [{"field": "requiresPayment", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}, {"operator": "OR", "conditions": [{"field": "paymentStatus", "operator": "IN", "value": ["online_pending", "failed"]}, {"field": "paymentStatus", "operator": "IS_NULL"}, {"operator": "AND", "conditions": [{"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"}, {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}]}]}]}}, {"roles": ["ROLE_FINANCE_MANAGER", "ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER"], "condition": {"operator": "AND", "conditions": [{"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}]}}], "read": [{"roles": ["ALL"], "condition": null}], "update": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [{"field": "requiresPayment", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}, {"operator": "OR", "conditions": [{"field": "paymentStatus", "operator": "IN", "value": ["online_pending", "failed"]}, {"field": "paymentStatus", "operator": "IS_NULL"}, {"operator": "AND", "conditions": [{"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"}, {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}]}]}]}}, {"roles": ["ROLE_FINANCE_MANAGER", "ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER"], "condition": {"operator": "AND", "conditions": [{"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}]}}], "delete": [{"roles": [], "condition": null}]}}]}'::jsonb,
    '[{"actionKey": "CANCEL", "label": "Cancel", "type": "secondary", "icon": "close", "apiKey": null, "permissions": [{"roles": ["ROLE_ADMIN", "ROLE_FINANCE_MANAGER", "ROLE_RELATIONAL_MANAGER", "ROLE_VIEWER"], "condition": null}], "onSuccess": [{"roles": ["ROLE_VIEWER"], "showToast": false, "showSuccessScreen": false}]}, {"actionKey": "MAKE_PAYMENT", "label": "submit", "type": "primary", "icon": null, "apiKey": "MAKE_PAYMENT", "permissions": [{"roles": ["ROLE_VIEWER"], "condition": {"operator": "AND", "conditions": [{"field": "requiresPayment", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}, {"operator": "OR", "conditions": [{"field": "paymentStatus", "operator": "IN", "value": ["failed", "online_pending"]}, {"field": "paymentStatus", "operator": "IS_NULL"}, {"operator": "AND", "conditions": [{"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"}, {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}]}]}]}}], "onSuccess": [{"roles": ["ROLE_VIEWER"], "showToast": false, "showSuccessScreen": true, "successScreenConfig": {"scenarios": [{"scenarioKey": "PAYMENT_EDIT_REQUESTED", "condition": {"operator": "AND", "conditions": [{"field": "paymentMode", "operator": "EQUALS", "value": "offline"}, {"field": "paymentStatus", "operator": "EQUALS", "value": "offline_pending"}, {"field": "editRequestStatus", "operator": "EQUALS", "value": "requested"}]}, "screen": {"title": "{{programName}}", "message": "Dear infinitheist {{seekerName}},\n\nYour payment edit request for {{programName}} has been submitted.\n\nYou can edit your payment details once the request is approved.", "variant": "info", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}, {"actionKey": "UPDATE_PAYMENT", "label": "update payment", "type": "secondary", "apiKey": "UPDATE_PAYMENT_DETAILS"}]}}, {"scenarioKey": "ONLINE_PAYMENT_SUCCESS", "condition": {"operator": "AND", "conditions": [{"field": "paymentMode", "operator": "EQUALS", "value": "online"}, {"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "completed"]}]}, "screen": {"title": "{{programName}}", "message": "<div style=\"text-align:left\">Dear {{seekerName}}, congratulations on your successful registration for {{programName}}.\n\nRegistration Details:\nRegistration Number: {{registrationNumber}}\nPayment mode: {{paymentMode}}\n\nA confirmation email and WhatsApp message have been sent to your registered email address and mobile number.</div>", "variant": "success", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "DOWNLOAD_INVOICE", "label": "download invoice", "type": "secondary", "apiKey": "DOWNLOAD_INVOICE"}, {"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}]}}, {"scenarioKey": "OFFLINE_PAYMENT_CHEQUE", "condition": {"operator": "AND", "conditions": [{"field": "paymentMode", "operator": "EQUALS", "value": "offline"}, {"field": "offlinePaymentMethod", "operator": "EQUALS", "value": "Cheque"}]}, "screen": {"title": "{{programName}}", "message": "<div style=\"text-align:left\">Dear {{seekerName}}, we acknowledge your provisional registration for {{programName}}.\n\nRegistration Details:\nRegistration Number: {{registrationNumber}}\nPayment mode: {{paymentMode}}\n\nNote: Cheques are subject to realization. Seat confirmation is subject to availability thereon.\n\nAn acknowledgement email and WhatsApp message have been sent to your registered email address and mobile number.</div>", "variant": "info", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}]}}, {"scenarioKey": "OFFLINE_PAYMENT_OTHER", "condition": {"operator": "AND", "conditions": [{"field": "paymentMode", "operator": "EQUALS", "value": "offline"}, {"field": "offlinePaymentMethod", "operator": "NOT_EQUALS", "value": "Cheque"}]}, "screen": {"title": "{{programName}}", "message": "<div style=\"text-align:left\">Dear {{seekerName}}, we acknowledge your provisional registration for {{programName}}.\n\nRegistration Details:\nRegistration Number: {{registrationNumber}}\nPayment mode: {{paymentMode}}\n\nNote: Payment is subject to realization. Seat confirmation is subject to availability thereon.\n\nAn acknowledgement email and WhatsApp message have been sent to your registered email address and mobile number.</div>", "variant": "info", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}]}}, {"scenarioKey": "FREE_SEAT_REGISTRATION", "condition": {"operator": "AND", "conditions": [{"field": "isFreeSeat", "operator": "EQUALS", "value": true}, {"field": "registrationStatus", "operator": "NOT_EQUALS", "value": "cancelled"}]}, "screen": {"title": "Registration Successful!", "message": "Dear infinitheist {{seekerName}},\n\nYour registration for {{programName}} is successful.\n\nRegistration Number: {{registrationNumber}}\nProgram Date: {{programStartDate}} to {{programEndDate}}", "variant": "success", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}, {"actionKey": "VIEW_SUMMARY", "label": "summary", "type": "secondary", "apiKey": "VIEW_REGISTRATION_SUMMARY"}]}}], "defaultScreen": {"title": "Payment Submitted!", "message": "Dear infinitheist {{seekerName}},\n\nYour payment for {{programName}} has been submitted successfully.\n\nRegistration Number: {{registrationNumber}}", "variant": "success", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}]}}}]}]'::jsonb,
    '{"conditional": true, "conditions": [{"when": {"operator": "OR", "conditions": [{"field": "paymentStatus", "operator": "IN", "value": ["online_completed", "offline_completed", "completed"]}, {"field": "isFreeSeat", "operator": "EQUALS", "value": true}]}, "then": {"stageStatus": "completed", "markStageComplete": true}}, {"when": {"operator": "AND", "conditions": [{"field": "paymentStatus", "operator": "IN", "value": ["online_pending", "offline_pending", "failed"]}, {"field": "isFreeSeat", "operator": "EQUALS", "value": false}]}, "then": {"stageStatus": "pending", "markStageComplete": false}}]}'::jsonb,
    -2, -2, NOW(), NOW()
);


-- Stage 3: TRAVEL — cloned from WF_HDBMSD_V8's TRAVEL stage, verbatim.
-- FLAG (behavior differs from this migration's earlier ENTRAINMENT-derived draft): only
-- ROLE_ADMIN / ROLE_RELATIONAL_MANAGER / ROLE_SHOBA can create/update FS_TRAVELPLAN here —
-- there is no ROLE_VIEWER path, so seekers do not submit their own travel details; staff
-- enter them instead. requiredStages is also just ["REGISTRATION"] (no PAYMENT dependency),
-- and the prerequisite condition checks involvesTravel + approvalStatus only, not
-- paymentStatus. This is HDB/MSD's actual live behavior, copied verbatim per explicit
-- instruction to match HDB's workflow — confirm with Product whether PAP's seekers are
-- meant to submit their own travel details (as the earlier ENTRAINMENT-based draft had it)
-- before this goes live.
INSERT INTO workflow_stage (
    workflow_config_id,
    stage_key,
    stage_name,
    stage_order,
    stage_category,
    is_optional,
    description,
    prerequisite_rules_config,
    execution_rules_config,
    action_buttons,
    completion_actions_config,
    created_by,
    updated_by,
    created_at,
    updated_at
) VALUES (
    (SELECT id FROM workflow_configuration WHERE workflow_key = 'WF_PAP_V1'),
    'TRAVEL',
    'Travel Details',
    3,
    'FORM',
    false,
    'Complete travel information and plans',
    '{"requiresAuth": true, "requiredStages": ["REGISTRATION"], "conditions": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_SHOBA"], "condition": {"operator": "AND", "conditions": [{"field": "involvesTravel", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}]}, "message": "Registration must be approved to access travel details"}]}'::jsonb,
    '{"sections": [{"sectionKey": "FS_TRAVELPLAN", "permissions": {"create": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_SHOBA"], "condition": {"operator": "AND", "conditions": [{"field": "involvesTravel", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}]}}], "read": [{"roles": ["ALL"], "condition": null}], "update": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_SHOBA"], "condition": {"operator": "AND", "conditions": [{"field": "involvesTravel", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}]}}], "delete": [{"roles": [], "condition": null}]}}]}'::jsonb,
    '[{"actionKey": "CANCEL", "label": "Cancel", "type": "secondary", "icon": "close", "apiKey": null, "permissions": [{"roles": ["ROLE_ADMIN", "ROLE_FINANCE_MANAGER", "ROLE_RELATIONAL_MANAGER"], "condition": null}], "onSuccess": [{"roles": ["ROLE_ADMIN", "ROLE_FINANCE_MANAGER", "ROLE_RELATIONAL_MANAGER"], "showToast": false, "showSuccessScreen": false}]}, {"actionKey": "SAVE_TRAVEL", "label": "Save Travel Details", "type": "primary", "icon": "save", "apiKey": "SAVE_TRAVEL", "permissions": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_SHOBA"], "condition": {"operator": "AND", "conditions": [{"field": "involvesTravel", "operator": "EQUALS", "value": true}, {"field": "approvalStatus", "operator": "EQUALS", "value": "approved"}]}}], "onSuccess": [{"roles": ["ROLE_ADMIN", "ROLE_RELATIONAL_MANAGER", "ROLE_SHOBA"], "showToast": false, "showSuccessScreen": true, "successScreenConfig": {"scenarios": [{"scenarioKey": "TRAVEL_DETAILS_SAVED", "condition": {"operator": "AND", "conditions": [{"field": "travelInfoStatus", "operator": "EQUALS", "value": "completed"}, {"field": "travelPlanStatus", "operator": "EQUALS", "value": "completed"}]}, "screen": {"title": "Travel Details Saved!", "message": "Dear infinitheist {{seekerName}},\n\nYour travel details for {{programName}} have been saved successfully.\n\nRegistration Number: {{registrationNumber}}\nProgram Date: {{programStartDate}} to {{programEndDate}}\nVenue: {{programVenue}}\n\nYou''re all set for the program!", "variant": "success", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "VIEW_SUMMARY", "label": "summary", "type": "secondary", "apiKey": "VIEW_REGISTRATION_SUMMARY"}, {"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}]}}], "defaultScreen": {"title": "Travel Details Saved!", "message": "Dear infinitheist {{seekerName}},\n\nYour travel details have been saved successfully.\n\nRegistration Number: {{registrationNumber}}", "variant": "success", "showLogo": true, "showBanner": true, "logoUrl": "{{logoUrl}}", "bannerImageUrl": "{{bannerImageUrl}}", "actions": [{"actionKey": "HOME", "label": "home", "type": "secondary", "apiKey": null}]}}}]}]'::jsonb,
    '{"conditional": true, "conditions": [{"when": {"operator": "AND", "conditions": [{"field": "travelInfoStatus", "operator": "EQUALS", "value": "completed"}, {"field": "travelPlanStatus", "operator": "EQUALS", "value": "completed"}]}, "then": {"stageStatus": "completed", "markStageComplete": true}}, {"when": {"operator": "OR", "conditions": [{"field": "travelInfoStatus", "operator": "EQUALS", "value": "completed"}, {"field": "travelPlanStatus", "operator": "EQUALS", "value": "completed"}]}, "then": {"stageStatus": "pending", "markStageComplete": false}}]}'::jsonb,
    -2, -2, NOW(), NOW()
);

COMMIT;

-- ================================================
-- Explicitly out of scope for this migration (follow-up work):
--   program_template / template_form_section rows for PT_PAP.
--   Plan: clone PT_TAT's basic-details + payment template sections, then add/clone
--   PT_ENTRAINMENT's travel sections (FS_TRAVELINFO, FS_TRAVELPLAN), via the admin API
--   (POST /v1/program-templates, :id/clone-from-master, :id/form, :id/publish).
--   Verify the template_key int->varchar clone bug is fixed first
--   (database/migrations/2026-06-10-01-template-key-varchar.sql).
--   See docs/product-spec-docs/PT_PAP_PROGRAM_TYPE_NOTES.md §3 for full detail.
-- ================================================
