create or replace function public.update_profile_subscription_status() returns trigger as $$ declare v_user_id uuid; v_plan subscription_plan; v_customer_id text; v_old_plan subscription_plan; v_has_trialing boolean; v_has_active boolean; v_subscription_status text; v_period_end timestamp; begin raise notice '==================== TRIGGER START ===================='; raise notice 'Table: %, Operation: %, Time: %', TG_TABLE_NAME, TG_OP, now(); -- Get customer ID based on which table triggered this if TG_TABLE_NAME = 'subscriptions' then v_customer_id := new.customer; v_subscription_status := new.status::text; raise notice 'Source: subscriptions table'; raise notice ' - Subscription ID: %', new.id; raise notice ' - Customer ID: %', v_customer_id; raise notice ' - Status: %', v_subscription_status; raise notice ' - Cancel at period end: %', new.cancel_at_period_end; elsif TG_TABLE_NAME = 'subscription_items' then -- Get customer ID from the subscription select customer, status::text into v_customer_id, v_subscription_status from stripe.subscriptions where id = new.subscription; raise notice 'Source: subscription_items table'; raise notice ' - Subscription Item ID: %', new.id; raise notice ' - Subscription ID: %', new.subscription; raise notice ' - Customer ID: %', v_customer_id; raise notice ' - Price ID: %', new.price; raise notice ' - Period Start: %', to_timestamp(new.current_period_start); raise notice ' - Period End: %', to_timestamp(new.current_period_end); else raise notice 'Unknown table: %, skipping', TG_TABLE_NAME; return new; end if; -- Skip if no customer_id found if v_customer_id is null then raise notice 'SKIP: No customer_id found'; raise notice '==================== TRIGGER END (SKIPPED) ===================='; return new; end if; -- Extract user_id from customer metadata select (metadata->>'user_id')::uuid into v_user_id from stripe.customers where id = v_customer_id; raise notice 'Customer metadata lookup:'; raise notice ' - User ID: %', v_user_id; -- Skip if no user_id found if v_user_id is null then raise notice 'SKIP: No user_id in customer metadata'; raise notice '==================== TRIGGER END (SKIPPED) ===================='; return new; end if; -- Get current plan from profile select plan into v_old_plan from public.profiles where id = v_user_id; raise notice 'Profile lookup:'; raise notice ' - Current plan: %', v_old_plan; -- Check for trialing subscription with detailed logging raise notice 'Checking for TRIALING subscription...'; select exists( select 1 from stripe.subscriptions s inner join stripe.customers c on c.id = s.customer inner join stripe.subscription_items si on si.subscription = s.id where (c.metadata->>'user_id')::uuid = v_user_id and s.status::text = 'trialing' and si.current_period_end is not null and to_timestamp(si.current_period_end) > now() ) into v_has_trialing; raise notice ' - Has trialing: %', v_has_trialing; -- Check for active/past_due subscription with detailed logging raise notice 'Checking for ACTIVE/PAST_DUE subscription...'; select exists( select 1 from stripe.subscriptions s inner join stripe.customers c on c.id = s.customer inner join stripe.subscription_items si on si.subscription = s.id where (c.metadata->>'user_id')::uuid = v_user_id and s.status::text in ('active', 'past_due') and si.current_period_end is not null and to_timestamp(si.current_period_end) > now() ) into v_has_active; raise notice ' - Has active/past_due: %', v_has_active; -- Show what subscriptions exist for this user raise notice 'All subscriptions for user %:', v_user_id; for v_subscription_status, v_period_end in select s.status::text, to_timestamp(si.current_period_end) from stripe.subscriptions s inner join stripe.customers c on c.id = s.customer left join stripe.subscription_items si on si.subscription = s.id where (c.metadata->>'user_id')::uuid = v_user_id loop raise notice ' - Status: %, Period End: %', v_subscription_status, v_period_end; end loop; -- Determine the user's current plan raise notice 'Calculating new plan...'; select case when exists( select 1 from stripe.subscriptions s inner join stripe.customers c on c.id = s.customer inner join stripe.subscription_items si on si.subscription = s.id where (c.metadata->>'user_id')::uuid = v_user_id and s.status::text = 'trialing' and si.current_period_end is not null and to_timestamp(si.current_period_end) > now() ) then 'trial'::subscription_plan when exists( select 1 from stripe.subscriptions s inner join stripe.customers c on c.id = s.customer inner join stripe.subscription_items si on si.subscription = s.id where (c.metadata->>'user_id')::uuid = v_user_id and s.status::text in ('active', 'past_due') and si.current_period_end is not null and to_timestamp(si.current_period_end) > now() ) then 'standard'::subscription_plan else 'none'::subscription_plan end into v_plan; raise notice ' - Calculated plan: %', v_plan; raise notice ' - Plan change: % → %', v_old_plan, v_plan; -- Update the user's profile if v_old_plan is distinct from v_plan then raise notice 'UPDATING profile...'; update public.profiles set plan = v_plan where id = v_user_id; raise notice 'Profile UPDATED successfully'; else raise notice 'No plan change needed, skipping update'; end if; raise notice '==================== TRIGGER END (SUCCESS) ===================='; return new; end; $$ language plpgsql security definer;