160 lines
No EOL
5.8 KiB
PL/PgSQL
160 lines
No EOL
5.8 KiB
PL/PgSQL
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; |