create-bw-app 0.18.6 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,106 @@
1
+ create or replace function public.process_marketing_resend_webhook(
2
+ p_provider_event_id text,
3
+ p_event_type text,
4
+ p_provider_message_id text,
5
+ p_payload jsonb,
6
+ p_occurred_at timestamptz
7
+ )
8
+ returns table (duplicate boolean, event_type text, recipient_id uuid)
9
+ language plpgsql
10
+ security definer
11
+ set search_path = public
12
+ as $$
13
+ declare
14
+ recipient public.marketing_campaign_recipients%rowtype;
15
+ inserted_event_id uuid;
16
+ suppression_reason text;
17
+ normalized_email text;
18
+ begin
19
+ if nullif(trim(p_provider_message_id), '') is not null then
20
+ select * into recipient
21
+ from public.marketing_campaign_recipients
22
+ where provider_message_id = p_provider_message_id
23
+ order by id
24
+ limit 1;
25
+ end if;
26
+
27
+ insert into public.marketing_message_events (
28
+ campaign_id,
29
+ recipient_id,
30
+ contact_id,
31
+ provider,
32
+ event_type,
33
+ provider_event_id,
34
+ payload,
35
+ occurred_at
36
+ ) values (
37
+ recipient.campaign_id,
38
+ recipient.id,
39
+ recipient.contact_id,
40
+ 'resend',
41
+ p_event_type,
42
+ nullif(trim(p_provider_event_id), ''),
43
+ p_payload,
44
+ coalesce(p_occurred_at, now())
45
+ )
46
+ on conflict (provider, provider_event_id) where provider_event_id is not null
47
+ do nothing
48
+ returning id into inserted_event_id;
49
+
50
+ if inserted_event_id is null then
51
+ return query select true, p_event_type, recipient.id;
52
+ return;
53
+ end if;
54
+
55
+ if recipient.id is not null and p_event_type in ('delivered', 'sent') then
56
+ update public.marketing_campaign_recipients
57
+ set status = 'sent',
58
+ sent_at = coalesce(p_occurred_at, now()),
59
+ error = null
60
+ where id = recipient.id;
61
+ elsif recipient.id is not null and p_event_type = 'failed' then
62
+ update public.marketing_campaign_recipients
63
+ set status = 'failed',
64
+ error = 'Resend reported delivery failure.'
65
+ where id = recipient.id;
66
+ elsif recipient.id is not null and p_event_type in ('bounced', 'complained', 'unsubscribed') then
67
+ suppression_reason := case p_event_type
68
+ when 'bounced' then 'bounced'
69
+ when 'complained' then 'complained'
70
+ else 'unsubscribed_all'
71
+ end;
72
+ normalized_email := lower(trim(recipient.email));
73
+
74
+ update public.marketing_campaign_recipients
75
+ set status = 'suppressed',
76
+ error = 'Resend reported ' || p_event_type || '.',
77
+ next_attempt_at = null
78
+ where id = recipient.id;
79
+
80
+ insert into public.marketing_suppressions (email, reason, source)
81
+ values (normalized_email, suppression_reason, 'resend_webhook')
82
+ on conflict (email) do update
83
+ set reason = excluded.reason,
84
+ source = excluded.source;
85
+
86
+ update public.marketing_campaign_recipients
87
+ set status = 'suppressed',
88
+ error = 'Email suppressed: ' || suppression_reason || '.',
89
+ next_attempt_at = null
90
+ where lower(trim(email)) = normalized_email
91
+ and status in ('queued', 'sending');
92
+
93
+ if recipient.contact_id is not null then
94
+ update public.marketing_subscriptions
95
+ set status = 'unsubscribed',
96
+ unsubscribed_at = coalesce(p_occurred_at, now())
97
+ where contact_id = recipient.contact_id;
98
+ end if;
99
+ end if;
100
+
101
+ return query select false, p_event_type, recipient.id;
102
+ end;
103
+ $$;
104
+
105
+ revoke all on function public.process_marketing_resend_webhook(text, text, text, jsonb, timestamptz) from public;
106
+ grant execute on function public.process_marketing_resend_webhook(text, text, text, jsonb, timestamptz) to service_role;