autopilot-core-sandbox 0.0.1

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.
Files changed (822) hide show
  1. package/README.md +53 -0
  2. package/dist/Provider.d.ts +21 -0
  3. package/dist/Provider.d.ts.map +1 -0
  4. package/dist/Provider.js +61 -0
  5. package/dist/Provider.js.map +1 -0
  6. package/dist/dist/Provider.d.ts +21 -0
  7. package/dist/dist/Provider.d.ts.map +1 -0
  8. package/dist/dist/Provider.js +61 -0
  9. package/dist/dist/Provider.js.map +1 -0
  10. package/dist/dist/index.d.ts +45 -0
  11. package/dist/dist/index.d.ts.map +1 -0
  12. package/dist/dist/index.js +61 -0
  13. package/dist/dist/index.js.map +1 -0
  14. package/dist/dist/interfaces/index.d.ts +1238 -0
  15. package/dist/dist/interfaces/index.d.ts.map +1 -0
  16. package/dist/dist/interfaces/index.js +3 -0
  17. package/dist/dist/interfaces/index.js.map +1 -0
  18. package/dist/dist/migrations/20260608222757_remote_schema.sql +5666 -0
  19. package/dist/dist/migrations/20260611174826_add_job_item_recurring_id_to_job_item.sql +7 -0
  20. package/dist/dist/migrations/20260625224612_add_dashboard_guided_tour_dismissed_to_settings_user.sql +5 -0
  21. package/dist/dist/migrations/20260627031433_support_chat_tables.sql +115 -0
  22. package/dist/dist/migrations/20260627031434_support_chat_rls.sql +37 -0
  23. package/dist/dist/migrations/20260704170209_add_estimate_scheduling.sql +121 -0
  24. package/dist/dist/migrations/20260704170210_add_estimate_scheduling_rls.sql +42 -0
  25. package/dist/dist/migrations/20260704235034_add_estimate_reminder_settings.sql +11 -0
  26. package/dist/dist/migrations/20260707003825_blocked_number_table.sql +32 -0
  27. package/dist/dist/migrations/20260707003826_blocked_number_rls.sql +22 -0
  28. package/dist/dist/migrations/20260709191055_sms_opt_out_table.sql +38 -0
  29. package/dist/dist/migrations/20260709191056_sms_opt_out_rls.sql +21 -0
  30. package/dist/dist/migrations/20260709214507_job_time_entry_table.sql +70 -0
  31. package/dist/dist/migrations/20260709214508_job_time_entry_rls.sql +21 -0
  32. package/dist/dist/migrations/20260711185956_phone_call_table.sql +99 -0
  33. package/dist/dist/migrations/20260711185957_phone_call_rls.sql +25 -0
  34. package/dist/dist/migrations/20260712014705_ai_voice_assistant_settings.sql +71 -0
  35. package/dist/dist/migrations/20260712014706_ai_voice_assistant_settings_rls.sql +14 -0
  36. package/dist/dist/migrations/20260712014707_ai_prompt_templates.sql +28 -0
  37. package/dist/dist/migrations/20260712014708_ai_prompt_templates_rls.sql +5 -0
  38. package/dist/dist/migrations/20260712014709_ai_prompt_templates_seed.sql +77 -0
  39. package/dist/dist/migrations/20260715011550_reminder_dispatch_table.sql +47 -0
  40. package/dist/dist/migrations/20260715011551_reminder_dispatch_rls.sql +22 -0
  41. package/dist/dist/migrations/20260715192923_dedup_sequence_contact_add_unique_constraint.sql +27 -0
  42. package/dist/dist/migrations/20260716194420_add_employee_location_tracking.sql +146 -0
  43. package/dist/dist/migrations/20260716194421_add_employee_location_tracking_rls.sql +154 -0
  44. package/dist/dist/migrations/20260716194422_get_client_map_last_completed_jobs.sql +28 -0
  45. package/dist/dist/migrations/20260717144535_add_blast_email_invalid_skipped_count.sql +2 -0
  46. package/dist/dist/migrations/20260717162900_create_blast_email_chunk.sql +36 -0
  47. package/dist/dist/migrations/20260717162901_add_blast_email_chunk_rls.sql +5 -0
  48. package/dist/dist/migrations/20260717162902_add_blast_email_chunk_progress_columns.sql +3 -0
  49. package/dist/dist/migrations/20260717162903_add_blast_email_bounce_tracking_columns.sql +4 -0
  50. package/dist/dist/migrations/20260717162904_create_email_hard_bounced.sql +23 -0
  51. package/dist/dist/migrations/20260717162905_add_email_hard_bounced_rls.sql +5 -0
  52. package/dist/dist/migrations/20260717164837_add_sequence_contact_sent_at.sql +19 -0
  53. package/dist/dist/migrations/20260717170920_add_sequence_contact_claim_index.sql +12 -0
  54. package/dist/dist/migrations/20260719215139_create_outbound_event.sql +59 -0
  55. package/dist/dist/migrations/20260719215140_create_outbound_event_rls.sql +16 -0
  56. package/dist/dist/migrations/20260719215141_create_webhook_delivery.sql +99 -0
  57. package/dist/dist/migrations/20260719215142_create_webhook_delivery_rls.sql +11 -0
  58. package/dist/dist/migrations/20260719215143_outbound_event_triggers.sql +219 -0
  59. package/dist/dist/migrations/20260719215144_create_api_key.sql +34 -0
  60. package/dist/dist/migrations/20260719215146_create_api_key_rls.sql +12 -0
  61. package/dist/dist/migrations/20260719215147_webhook_subscription_add_secret_active.sql +28 -0
  62. package/dist/dist/migrations/20260719215148_api_aggregate_create_functions.sql +479 -0
  63. package/dist/dist/migrations/20260721174837_webhook_subscription_generic_endpoints.sql +41 -0
  64. package/dist/dist/migrations/20260721185631_webhook_outbox_retention.sql +87 -0
  65. package/dist/dist/migrations/20260721190304_create_qb_sync_task.sql +120 -0
  66. package/dist/dist/migrations/20260721190306_qb_sync_task_rls.sql +8 -0
  67. package/dist/dist/migrations/20260721190307_qb_mapping_orphan_fks.sql +29 -0
  68. package/dist/dist/migrations/20260721190308_qb_task_retention.sql +90 -0
  69. package/dist/dist/migrations/20260721234401_create_permission_role.sql +83 -0
  70. package/dist/dist/migrations/20260721234402_permission_role_rls.sql +22 -0
  71. package/dist/dist/migrations/20260721234403_user_role_add_permission_role_id.sql +12 -0
  72. package/dist/dist/migrations/20260721234404_seed_permission_roles.sql +100 -0
  73. package/dist/dist/migrations/20260721234405_backfill_user_role_permission_role_id.sql +20 -0
  74. package/dist/dist/migrations/20260722193800_permission_role_add_manage_employees.sql +56 -0
  75. package/dist/dist/migrations/20260723025606_staging_new_employee_company_read_rls.sql +10 -0
  76. package/dist/dist/migrations/20260723134328_create_google_lsa_integration.sql +1016 -0
  77. package/dist/dist/migrations/20260723134329_google_lsa_integration_rls.sql +205 -0
  78. package/dist/dist/migrations/20260723150640_google_lsa_hardening.sql +169 -0
  79. package/dist/dist/migrations/20260723150641_google_lsa_hardening_rls.sql +12 -0
  80. package/dist/dist/migrations/20260724230721_google_lsa_facebook_exclusivity_attach.sql +104 -0
  81. package/dist/dist/migrations/20260724230722_google_lsa_facebook_exclusivity_attach_rls.sql +20 -0
  82. package/dist/dist/migrations/20260725172630_add_message_pagination_and_search.sql +265 -0
  83. package/dist/dist/migrations/20260725172631_add_message_pagination_and_search_rls.sql +72 -0
  84. package/dist/dist/migrations/20260725172632_optimize_message_thread_pagination_search.sql +245 -0
  85. package/dist/dist/migrations/20260725172633_harden_message_search_and_photo_pagination.sql +256 -0
  86. package/dist/dist/migrations/20260725172634_fix_message_thread_line_filter.sql +250 -0
  87. package/dist/dist/migrations/20260725174948_google_lsa_attach_bing_exclusivity_guard.sql +23 -0
  88. package/dist/dist/migrations/20260725200430_client_portal_settings.sql +41 -0
  89. package/dist/dist/migrations/20260725200431_client_portal_settings_rls.sql +21 -0
  90. package/dist/dist/migrations/20260725200433_client_portal_auth_tables.sql +81 -0
  91. package/dist/dist/migrations/20260725200434_client_portal_auth_rls.sql +18 -0
  92. package/dist/dist/migrations/20260725200435_portal_claim_login_attempt.sql +36 -0
  93. package/dist/dist/migrations/20260725200436_portal_appointment_request.sql +39 -0
  94. package/dist/dist/migrations/20260725200437_portal_appointment_request_rls.sql +10 -0
  95. package/dist/dist/migrations/20260725210000_google_reserve_integration.sql +85 -0
  96. package/dist/dist/migrations/20260725210001_google_reserve_integration_rls.sql +10 -0
  97. package/dist/dist/migrations/20260725220000_add_analytics_query_indexes.sql +47 -0
  98. package/dist/dist/migrations/20260725230000_onboarding_preload_data.sql +1074 -0
  99. package/dist/dist/migrations/20260725230001_onboarding_preload_data_rls.sql +40 -0
  100. package/dist/dist/migrations/20260725230002_add_pricebook_query_indexes.sql +13 -0
  101. package/dist/dist/migrations/20260726000000_facebook_ads_integration.sql +1538 -0
  102. package/dist/dist/migrations/20260726000001_facebook_ads_integration_rls.sql +356 -0
  103. package/dist/dist/migrations/20260726000002_facebook_ads_attach_lsa_exclusivity_guard.sql +25 -0
  104. package/dist/dist/migrations/20260726000003_facebook_ads_attach_bing_exclusivity_guard.sql +22 -0
  105. package/dist/dist/migrations/20260726010000_create_bing_ads_integration.sql +1112 -0
  106. package/dist/dist/migrations/20260726010001_bing_ads_integration_rls.sql +227 -0
  107. package/dist/dist/migrations/20260726220000_add_document_theme_settings.sql +11 -0
  108. package/dist/dist/migrations/20260726220001_update_document_theme_comments.sql +7 -0
  109. package/dist/dist/migrations/20260727210319_evolve_tier_for_pricing.sql +68 -0
  110. package/dist/dist/migrations/20260727210320_create_billing_addon.sql +85 -0
  111. package/dist/dist/migrations/20260727210321_create_billing_addon_rls.sql +21 -0
  112. package/dist/dist/migrations/20260728213930_create_usage_metering.sql +189 -0
  113. package/dist/dist/migrations/20260728213931_create_usage_metering_rls.sql +32 -0
  114. package/dist/dist/migrations/20260729004305_marketing_charge_txn_functions.sql +242 -0
  115. package/dist/dist/migrations/20260729004306_marketing_charge_txn_functions_rls.sql +37 -0
  116. package/dist/dist/migrations/20260729005524_update_deduct_from_balance_errcode.sql +42 -0
  117. package/dist/dist/migrations/20260730193601_fix_deduct_from_balance_lost_update.sql +46 -0
  118. package/dist/dist/migrations/20260730193602_add_blast_sms_chunk_reaper_columns.sql +27 -0
  119. package/dist/dist/migrations/20260731011415_create_google_calendar_connection.sql +84 -0
  120. package/dist/dist/migrations/20260731011416_google_calendar_connection_rls.sql +23 -0
  121. package/dist/dist/migrations/20260731011417_create_google_calendar_sync.sql +157 -0
  122. package/dist/dist/migrations/20260731011418_google_calendar_sync_rls.sql +26 -0
  123. package/dist/dist/migrations/20260731011419_event_outbound_triggers.sql +28 -0
  124. package/dist/dist/migrations/20260731011420_add_google_calendar_addon_key.sql +24 -0
  125. package/dist/dist/migrations/20260731011421_gcal_task_retention.sql +109 -0
  126. package/dist/dist/migrations/20260731234245_create_estimate_proposal.sql +157 -0
  127. package/dist/dist/migrations/20260731234247_estimate_proposal_rls.sql +46 -0
  128. package/dist/dist/migrations/20260731234248_add_proposal_estimate_settings.sql +17 -0
  129. package/dist/dist/migrations/20260731234249_add_estimate_proposals_addon_key.sql +25 -0
  130. package/dist/dist/migrations/20260731234250_approve_estimate_proposal_function.sql +133 -0
  131. package/dist/dist/migrations/20260801010609_save_estimate_proposal_function.sql +154 -0
  132. package/dist/dist/migrations/20260801173554_add_hide_autopilot_branding_setting.sql +6 -0
  133. package/dist/dist/migrations/20260806230917_add_client_billing_address_columns.sql +9 -0
  134. package/dist/dist/migrations/20260806230944_api_create_client_billing_address.sql +93 -0
  135. package/dist/dist/migrations/20260807014702_create_parent_id_company_id_keys.sql +20 -0
  136. package/dist/dist/migrations/20260807014703_create_contract_template.sql +30 -0
  137. package/dist/dist/migrations/20260807014704_create_contract.sql +233 -0
  138. package/dist/dist/migrations/20260807014705_create_contract_signature.sql +39 -0
  139. package/dist/dist/migrations/20260807014706_create_item_contract_requirement.sql +38 -0
  140. package/dist/dist/migrations/20260807014707_create_settings_contract.sql +23 -0
  141. package/dist/dist/migrations/20260807014708_contract_rls.sql +74 -0
  142. package/dist/dist/migrations/20260807014709_sign_contract_function.sql +92 -0
  143. package/dist/dist/migrations/20260807014710_create_settings_rental.sql +34 -0
  144. package/dist/dist/migrations/20260807014711_create_saved_location.sql +56 -0
  145. package/dist/dist/migrations/20260807014712_create_rental_task_option.sql +52 -0
  146. package/dist/dist/migrations/20260807014713_create_asset.sql +90 -0
  147. package/dist/dist/migrations/20260807014714_add_job_schedule_asset_fkeys.sql +39 -0
  148. package/dist/dist/migrations/20260807014715_rental_rls.sql +48 -0
  149. package/dist/dist/migrations/20260807014716_add_job_schedule_any_time.sql +7 -0
  150. package/dist/dist/migrations/20260807014717_add_job_schedule_target_location.sql +48 -0
  151. package/dist/dist/migrations/20260807014718_job_schedule_completion_guard.sql +53 -0
  152. package/dist/dist/migrations/20260807014719_add_job_schedule_list_sort_key.sql +7 -0
  153. package/dist/dist/migrations/20260807014720_add_item_duration.sql +11 -0
  154. package/dist/dist/migrations/20260807014721_add_settings_booking_enforce_rental_availability.sql +9 -0
  155. package/dist/dist/migrations/20260807014722_add_job_unsigned_rental_agreement.sql +10 -0
  156. package/dist/dist/migrations/20260807014723_add_item_size.sql +12 -0
  157. package/dist/dist/migrations/20260809193533_add_booking_path_button_labels.sql +11 -0
  158. package/dist/dist/migrations/20260809231721_add_route_distance_cache.sql +37 -0
  159. package/dist/dist/migrations/20260809231722_route_distance_cache_rls.sql +15 -0
  160. package/dist/dist/migrations/20260809231723_apply_rental_route_plan_function.sql +275 -0
  161. package/dist/dist/migrations/20260810171550_add_settings_job_default_job_types.sql +9 -0
  162. package/dist/dist/migrations/20260810212430_backfill_rental_task_option_sort_order.sql +61 -0
  163. package/dist/dist/migrations/20260811224317_add_settings_user_dnd_hint_dismissed.sql +9 -0
  164. package/dist/dist/migrations/20260813174503_repair_user_role_email_drift.sql +59 -0
  165. package/dist/dist/migrations/20260813174504_sync_user_role_email_trigger.sql +30 -0
  166. package/dist/dist/migrations/20260813175210_add_event_list_sort_key.sql +5 -0
  167. package/dist/dist/migrations/20260814172222_add_client_auto_bill_on_completion.sql +6 -0
  168. package/dist/dist/migrations/20260816160252_create_automation_rule.sql +99 -0
  169. package/dist/dist/migrations/20260816160253_automation_rule_rls.sql +19 -0
  170. package/dist/dist/migrations/20260816160254_create_settings_automation.sql +36 -0
  171. package/dist/dist/migrations/20260816160255_settings_automation_rls.sql +18 -0
  172. package/dist/dist/migrations/20260816160256_create_automation_event.sql +71 -0
  173. package/dist/dist/migrations/20260816160257_automation_event_rls.sql +12 -0
  174. package/dist/dist/migrations/20260816160258_create_automation_run.sql +129 -0
  175. package/dist/dist/migrations/20260816160259_automation_run_rls.sql +19 -0
  176. package/dist/dist/migrations/20260816160300_add_client_created_via.sql +25 -0
  177. package/dist/dist/migrations/20260816160301_add_estimate_sent_at.sql +39 -0
  178. package/dist/dist/migrations/20260816160302_add_message_automation_ref.sql +10 -0
  179. package/dist/dist/migrations/20260816160303_automation_event_triggers.sql +236 -0
  180. package/dist/dist/migrations/20260816160304_automation_retention.sql +142 -0
  181. package/dist/dist/migrations/20260816202404_add_automation_center_addon_key.sql +26 -0
  182. package/dist/dist/migrations/20260816225501_widen_automation_rule_trigger_action_checks.sql +25 -0
  183. package/dist/dist/migrations/20260816225502_widen_automation_event_type_check.sql +18 -0
  184. package/dist/dist/migrations/20260816225503_add_invoice_id_to_automation_tables.sql +18 -0
  185. package/dist/dist/migrations/20260816225504_add_job_rescheduled_capture_trigger.sql +51 -0
  186. package/dist/dist/migrations/20260816225505_add_lead_converted_capture_trigger.sql +26 -0
  187. package/dist/dist/migrations/20260816225506_fix_booking_request_import_guard.sql +27 -0
  188. package/dist/dist/migrations/20260816225507_widen_outbound_event_for_automation.sql +38 -0
  189. package/dist/dist/migrations/20260817002626_add_user_last_login_platform_columns.sql +14 -0
  190. package/dist/dist/migrations/20260817221703_create_deletion.sql +34 -0
  191. package/dist/dist/migrations/20260817221707_deletion_rls.sql +21 -0
  192. package/dist/dist/migrations/20260817221708_add_soft_delete_columns.sql +82 -0
  193. package/dist/dist/migrations/20260817221709_trash_functions.sql +434 -0
  194. package/dist/dist/migrations/20260817221710_outbound_event_soft_delete.sql +55 -0
  195. package/dist/dist/migrations/20260817221711_automation_soft_delete_events.sql +77 -0
  196. package/dist/dist/migrations/20260817221712_fix_estimate_address_cascade.sql +14 -0
  197. package/dist/dist/migrations/20260817232630_trash_batch_function.sql +67 -0
  198. package/dist/dist/migrations/20260819170204_create_email_spam_complaint.sql +23 -0
  199. package/dist/dist/migrations/20260819170205_add_email_spam_complaint_rls.sql +5 -0
  200. package/dist/dist/migrations/20260819170206_email_unsubscribed_upsert_constraints.sql +14 -0
  201. package/dist/dist/migrations/20260819180151_get_suppressed_emails_function.sql +23 -0
  202. package/dist/dist/migrations/20260819191143_is_deleted_backfill_guard.sql +29 -0
  203. package/dist/dist/migrations/20260819191144_trash_functions_no_dual_write.sql +319 -0
  204. package/dist/dist/migrations/20260819191145_client_map_jobs_deleted_at.sql +33 -0
  205. package/dist/dist/migrations/20260819191147_booking_declined_deleted_at.sql +28 -0
  206. package/dist/dist/migrations/20260819191148_onboarding_preload_no_address_is_deleted.sql +1019 -0
  207. package/dist/dist/migrations/20260820222756_add_settings_job_hide_task_timer.sql +2 -0
  208. package/dist/dist/migrations/20260824234151_add_blast_chunk_recipients.sql +13 -0
  209. package/dist/dist/migrations/20260824234152_add_blast_pause_cancel_columns.sql +10 -0
  210. package/dist/dist/migrations/20260825014725_get_job_ids_in_range.sql +42 -0
  211. package/dist/dist/migrations/20260825194452_add_failed_job_status.sql +15 -0
  212. package/dist/dist/migrations/20260825194457_remove_take_to_rental_task_options.sql +24 -0
  213. package/dist/dist/migrations/20260825194458_remove_take_to_job_schedules.sql +12 -0
  214. package/dist/dist/migrations/20260825194459_rework_apply_rental_route_plan_no_take_to.sql +168 -0
  215. package/dist/dist/migrations/20260825194500_drop_job_schedule_target_location.sql +24 -0
  216. package/dist/dist/migrations/20260825194501_add_job_schedule_size.sql +17 -0
  217. package/dist/dist/migrations/20260825233001_add_job_schedule_id_company_id_key.sql +11 -0
  218. package/dist/dist/migrations/20260825233002_create_route_plan.sql +52 -0
  219. package/dist/dist/migrations/20260825233003_create_route_plan_stop.sql +159 -0
  220. package/dist/dist/migrations/20260825233004_route_plan_rls.sql +32 -0
  221. package/dist/dist/migrations/20260825233005_apply_rental_route_plan_v2.sql +351 -0
  222. package/dist/dist/migrations/20260826150934_facebook_ads_lead_ingestion.sql +1711 -0
  223. package/dist/dist/migrations/20260826151141_facebook_ads_lead_ingestion_rls_v2.sql +43 -0
  224. package/dist/dist/migrations/20260826234722_facebook_messenger_ingestion.sql +703 -0
  225. package/dist/dist/migrations/20260826234723_facebook_messenger_ingestion_rls.sql +80 -0
  226. package/dist/dist/migrations/20260826234724_widen_automations_messenger.sql +46 -0
  227. package/dist/dist/migrations/20260827100001_add_route_plan_minutes.sql +10 -0
  228. package/dist/dist/migrations/20260827100002_add_route_plan_stop_leg_minutes.sql +9 -0
  229. package/dist/dist/migrations/20260827100003_apply_rental_route_plan_v3.sql +341 -0
  230. package/dist/dist/migrations/20260827230346_apply_rental_route_plan_v4.sql +366 -0
  231. package/dist/dist/migrations/20260829090911_create_fleet_schema.sql +3698 -0
  232. package/dist/dist/migrations/20260829090912_fleet_rls.sql +1011 -0
  233. package/dist/dist/migrations/20260831102212_add_online_booking_address_display.sql +8 -0
  234. package/dist/dist/providers/AddressProvider.d.ts +9 -0
  235. package/dist/dist/providers/AddressProvider.d.ts.map +1 -0
  236. package/dist/dist/providers/AddressProvider.js +207 -0
  237. package/dist/dist/providers/AddressProvider.js.map +1 -0
  238. package/dist/dist/providers/AutomationsProvider.d.ts +11 -0
  239. package/dist/dist/providers/AutomationsProvider.d.ts.map +1 -0
  240. package/dist/dist/providers/AutomationsProvider.js +170 -0
  241. package/dist/dist/providers/AutomationsProvider.js.map +1 -0
  242. package/dist/dist/providers/BlockedNumbersProvider.d.ts +13 -0
  243. package/dist/dist/providers/BlockedNumbersProvider.d.ts.map +1 -0
  244. package/dist/dist/providers/BlockedNumbersProvider.js +71 -0
  245. package/dist/dist/providers/BlockedNumbersProvider.js.map +1 -0
  246. package/dist/dist/providers/CategoryProvider.d.ts +8 -0
  247. package/dist/dist/providers/CategoryProvider.d.ts.map +1 -0
  248. package/dist/dist/providers/CategoryProvider.js +95 -0
  249. package/dist/dist/providers/CategoryProvider.js.map +1 -0
  250. package/dist/dist/providers/ClientProvider.d.ts +39 -0
  251. package/dist/dist/providers/ClientProvider.d.ts.map +1 -0
  252. package/dist/dist/providers/ClientProvider.js +253 -0
  253. package/dist/dist/providers/ClientProvider.js.map +1 -0
  254. package/dist/dist/providers/CompanyProvider.d.ts +7 -0
  255. package/dist/dist/providers/CompanyProvider.d.ts.map +1 -0
  256. package/dist/dist/providers/CompanyProvider.js +114 -0
  257. package/dist/dist/providers/CompanyProvider.js.map +1 -0
  258. package/dist/dist/providers/DashboardProvider.d.ts +78 -0
  259. package/dist/dist/providers/DashboardProvider.d.ts.map +1 -0
  260. package/dist/dist/providers/DashboardProvider.js +568 -0
  261. package/dist/dist/providers/DashboardProvider.js.map +1 -0
  262. package/dist/dist/providers/DiscountProvider.d.ts +8 -0
  263. package/dist/dist/providers/DiscountProvider.d.ts.map +1 -0
  264. package/dist/dist/providers/DiscountProvider.js +92 -0
  265. package/dist/dist/providers/DiscountProvider.js.map +1 -0
  266. package/dist/dist/providers/EmployeesProvider.d.ts +6 -0
  267. package/dist/dist/providers/EmployeesProvider.d.ts.map +1 -0
  268. package/dist/dist/providers/EmployeesProvider.js +185 -0
  269. package/dist/dist/providers/EmployeesProvider.js.map +1 -0
  270. package/dist/dist/providers/EstimatesProvider.d.ts +16 -0
  271. package/dist/dist/providers/EstimatesProvider.d.ts.map +1 -0
  272. package/dist/dist/providers/EstimatesProvider.js +251 -0
  273. package/dist/dist/providers/EstimatesProvider.js.map +1 -0
  274. package/dist/dist/providers/EventsProvider.d.ts +4 -0
  275. package/dist/dist/providers/EventsProvider.d.ts.map +1 -0
  276. package/dist/dist/providers/EventsProvider.js +24 -0
  277. package/dist/dist/providers/EventsProvider.js.map +1 -0
  278. package/dist/dist/providers/FilesProvider.d.ts +17 -0
  279. package/dist/dist/providers/FilesProvider.d.ts.map +1 -0
  280. package/dist/dist/providers/FilesProvider.js +201 -0
  281. package/dist/dist/providers/FilesProvider.js.map +1 -0
  282. package/dist/dist/providers/InvoicesProvider.d.ts +13 -0
  283. package/dist/dist/providers/InvoicesProvider.d.ts.map +1 -0
  284. package/dist/dist/providers/InvoicesProvider.js +207 -0
  285. package/dist/dist/providers/InvoicesProvider.js.map +1 -0
  286. package/dist/dist/providers/ItemProvider.d.ts +9 -0
  287. package/dist/dist/providers/ItemProvider.d.ts.map +1 -0
  288. package/dist/dist/providers/ItemProvider.js +201 -0
  289. package/dist/dist/providers/ItemProvider.js.map +1 -0
  290. package/dist/dist/providers/JobSourceProvider.d.ts +8 -0
  291. package/dist/dist/providers/JobSourceProvider.d.ts.map +1 -0
  292. package/dist/dist/providers/JobSourceProvider.js +75 -0
  293. package/dist/dist/providers/JobSourceProvider.js.map +1 -0
  294. package/dist/dist/providers/JobTypeProvider.d.ts +8 -0
  295. package/dist/dist/providers/JobTypeProvider.d.ts.map +1 -0
  296. package/dist/dist/providers/JobTypeProvider.js +75 -0
  297. package/dist/dist/providers/JobTypeProvider.js.map +1 -0
  298. package/dist/dist/providers/JobsProvider.d.ts +35 -0
  299. package/dist/dist/providers/JobsProvider.d.ts.map +1 -0
  300. package/dist/dist/providers/JobsProvider.js +863 -0
  301. package/dist/dist/providers/JobsProvider.js.map +1 -0
  302. package/dist/dist/providers/MessagesProvider.d.ts +33 -0
  303. package/dist/dist/providers/MessagesProvider.d.ts.map +1 -0
  304. package/dist/dist/providers/MessagesProvider.js +415 -0
  305. package/dist/dist/providers/MessagesProvider.js.map +1 -0
  306. package/dist/dist/providers/PaymentProvider.d.ts +9 -0
  307. package/dist/dist/providers/PaymentProvider.d.ts.map +1 -0
  308. package/dist/dist/providers/PaymentProvider.js +48 -0
  309. package/dist/dist/providers/PaymentProvider.js.map +1 -0
  310. package/dist/dist/providers/PermissionRolesProvider.d.ts +5 -0
  311. package/dist/dist/providers/PermissionRolesProvider.d.ts.map +1 -0
  312. package/dist/dist/providers/PermissionRolesProvider.js +30 -0
  313. package/dist/dist/providers/PermissionRolesProvider.js.map +1 -0
  314. package/dist/dist/providers/PhoneNumberProvider.d.ts +12 -0
  315. package/dist/dist/providers/PhoneNumberProvider.d.ts.map +1 -0
  316. package/dist/dist/providers/PhoneNumberProvider.js +184 -0
  317. package/dist/dist/providers/PhoneNumberProvider.js.map +1 -0
  318. package/dist/dist/providers/ProfileProvider.d.ts +6 -0
  319. package/dist/dist/providers/ProfileProvider.d.ts.map +1 -0
  320. package/dist/dist/providers/ProfileProvider.js +71 -0
  321. package/dist/dist/providers/ProfileProvider.js.map +1 -0
  322. package/dist/dist/providers/RentalsProvider.d.ts +28 -0
  323. package/dist/dist/providers/RentalsProvider.d.ts.map +1 -0
  324. package/dist/dist/providers/RentalsProvider.js +438 -0
  325. package/dist/dist/providers/RentalsProvider.js.map +1 -0
  326. package/dist/dist/providers/SettingsBookingProvider.d.ts +9 -0
  327. package/dist/dist/providers/SettingsBookingProvider.d.ts.map +1 -0
  328. package/dist/dist/providers/SettingsBookingProvider.js +163 -0
  329. package/dist/dist/providers/SettingsBookingProvider.js.map +1 -0
  330. package/dist/dist/providers/SettingsProvider.d.ts +8 -0
  331. package/dist/dist/providers/SettingsProvider.d.ts.map +1 -0
  332. package/dist/dist/providers/SettingsProvider.js +86 -0
  333. package/dist/dist/providers/SettingsProvider.js.map +1 -0
  334. package/dist/dist/providers/TagsProvider.d.ts +12 -0
  335. package/dist/dist/providers/TagsProvider.d.ts.map +1 -0
  336. package/dist/dist/providers/TagsProvider.js +210 -0
  337. package/dist/dist/providers/TagsProvider.js.map +1 -0
  338. package/dist/dist/providers/TimeCardProvider.d.ts +8 -0
  339. package/dist/dist/providers/TimeCardProvider.d.ts.map +1 -0
  340. package/dist/dist/providers/TimeCardProvider.js +93 -0
  341. package/dist/dist/providers/TimeCardProvider.js.map +1 -0
  342. package/dist/dist/providers/TrashProvider.d.ts +13 -0
  343. package/dist/dist/providers/TrashProvider.d.ts.map +1 -0
  344. package/dist/dist/providers/TrashProvider.js +98 -0
  345. package/dist/dist/providers/TrashProvider.js.map +1 -0
  346. package/dist/dist/providers/dashboardAnalytics.d.ts +9 -0
  347. package/dist/dist/providers/dashboardAnalytics.d.ts.map +1 -0
  348. package/dist/dist/providers/dashboardAnalytics.js +41 -0
  349. package/dist/dist/providers/dashboardAnalytics.js.map +1 -0
  350. package/dist/dist/providers/dashboardAnalytics.test.d.ts +2 -0
  351. package/dist/dist/providers/dashboardAnalytics.test.d.ts.map +1 -0
  352. package/dist/dist/providers/dashboardAnalytics.test.js +111 -0
  353. package/dist/dist/providers/dashboardAnalytics.test.js.map +1 -0
  354. package/dist/dist/server-safe/BlockedNumberFunctions.d.ts +11 -0
  355. package/dist/dist/server-safe/BlockedNumberFunctions.d.ts.map +1 -0
  356. package/dist/dist/server-safe/BlockedNumberFunctions.js +16 -0
  357. package/dist/dist/server-safe/BlockedNumberFunctions.js.map +1 -0
  358. package/dist/dist/server-safe/EmployeeFunctions.d.ts +14 -0
  359. package/dist/dist/server-safe/EmployeeFunctions.d.ts.map +1 -0
  360. package/dist/dist/server-safe/EmployeeFunctions.js +70 -0
  361. package/dist/dist/server-safe/EmployeeFunctions.js.map +1 -0
  362. package/dist/dist/server-safe/EmployeeLocationFunctions.d.ts +7 -0
  363. package/dist/dist/server-safe/EmployeeLocationFunctions.d.ts.map +1 -0
  364. package/dist/dist/server-safe/EmployeeLocationFunctions.js +47 -0
  365. package/dist/dist/server-safe/EmployeeLocationFunctions.js.map +1 -0
  366. package/dist/dist/server-safe/EstimateFunctions.d.ts +15 -0
  367. package/dist/dist/server-safe/EstimateFunctions.d.ts.map +1 -0
  368. package/dist/dist/server-safe/EstimateFunctions.js +34 -0
  369. package/dist/dist/server-safe/EstimateFunctions.js.map +1 -0
  370. package/dist/dist/server-safe/InvoiceFunctions.d.ts +21 -0
  371. package/dist/dist/server-safe/InvoiceFunctions.d.ts.map +1 -0
  372. package/dist/dist/server-safe/InvoiceFunctions.js +124 -0
  373. package/dist/dist/server-safe/InvoiceFunctions.js.map +1 -0
  374. package/dist/dist/server-safe/JobFunctions.d.ts +15 -0
  375. package/dist/dist/server-safe/JobFunctions.d.ts.map +1 -0
  376. package/dist/dist/server-safe/JobFunctions.js +56 -0
  377. package/dist/dist/server-safe/JobFunctions.js.map +1 -0
  378. package/dist/dist/server-safe/PaymentFunctions.d.ts +16 -0
  379. package/dist/dist/server-safe/PaymentFunctions.d.ts.map +1 -0
  380. package/dist/dist/server-safe/PaymentFunctions.js +80 -0
  381. package/dist/dist/server-safe/PaymentFunctions.js.map +1 -0
  382. package/dist/dist/server-safe/PermissionFunctions.d.ts +7 -0
  383. package/dist/dist/server-safe/PermissionFunctions.d.ts.map +1 -0
  384. package/dist/dist/server-safe/PermissionFunctions.js +39 -0
  385. package/dist/dist/server-safe/PermissionFunctions.js.map +1 -0
  386. package/dist/dist/server-safe/TagFunctions.d.ts +18 -0
  387. package/dist/dist/server-safe/TagFunctions.d.ts.map +1 -0
  388. package/dist/dist/server-safe/TagFunctions.js +52 -0
  389. package/dist/dist/server-safe/TagFunctions.js.map +1 -0
  390. package/dist/dist/server-safe/autoJobType.d.ts +16 -0
  391. package/dist/dist/server-safe/autoJobType.d.ts.map +1 -0
  392. package/dist/dist/server-safe/autoJobType.js +39 -0
  393. package/dist/dist/server-safe/autoJobType.js.map +1 -0
  394. package/dist/dist/server-safe/autoJobType.test.d.ts +2 -0
  395. package/dist/dist/server-safe/autoJobType.test.d.ts.map +1 -0
  396. package/dist/dist/server-safe/autoJobType.test.js +83 -0
  397. package/dist/dist/server-safe/autoJobType.test.js.map +1 -0
  398. package/dist/dist/server-safe/automations.d.ts +197 -0
  399. package/dist/dist/server-safe/automations.d.ts.map +1 -0
  400. package/dist/dist/server-safe/automations.js +757 -0
  401. package/dist/dist/server-safe/automations.js.map +1 -0
  402. package/dist/dist/server-safe/automations.test.d.ts +2 -0
  403. package/dist/dist/server-safe/automations.test.d.ts.map +1 -0
  404. package/dist/dist/server-safe/automations.test.js +441 -0
  405. package/dist/dist/server-safe/automations.test.js.map +1 -0
  406. package/dist/dist/server-safe/constants.d.ts +156 -0
  407. package/dist/dist/server-safe/constants.d.ts.map +1 -0
  408. package/dist/dist/server-safe/constants.js +186 -0
  409. package/dist/dist/server-safe/constants.js.map +1 -0
  410. package/dist/dist/server-safe/contracts.d.ts +3 -0
  411. package/dist/dist/server-safe/contracts.d.ts.map +1 -0
  412. package/dist/dist/server-safe/contracts.js +15 -0
  413. package/dist/dist/server-safe/contracts.js.map +1 -0
  414. package/dist/dist/server-safe/database.types.d.ts +9510 -0
  415. package/dist/dist/server-safe/database.types.d.ts.map +1 -0
  416. package/dist/dist/server-safe/database.types.js +40 -0
  417. package/dist/dist/server-safe/database.types.js.map +1 -0
  418. package/dist/dist/server-safe/entitlements.d.ts +99 -0
  419. package/dist/dist/server-safe/entitlements.d.ts.map +1 -0
  420. package/dist/dist/server-safe/entitlements.js +487 -0
  421. package/dist/dist/server-safe/entitlements.js.map +1 -0
  422. package/dist/dist/server-safe/facebookAdsLeads.d.ts +225 -0
  423. package/dist/dist/server-safe/facebookAdsLeads.d.ts.map +1 -0
  424. package/dist/dist/server-safe/facebookAdsLeads.js +376 -0
  425. package/dist/dist/server-safe/facebookAdsLeads.js.map +1 -0
  426. package/dist/dist/server-safe/facebookAdsLeads.test.d.ts +2 -0
  427. package/dist/dist/server-safe/facebookAdsLeads.test.d.ts.map +1 -0
  428. package/dist/dist/server-safe/facebookAdsLeads.test.js +189 -0
  429. package/dist/dist/server-safe/facebookAdsLeads.test.js.map +1 -0
  430. package/dist/dist/server-safe/facebookAdsLeadsSql.test.d.ts +2 -0
  431. package/dist/dist/server-safe/facebookAdsLeadsSql.test.d.ts.map +1 -0
  432. package/dist/dist/server-safe/facebookAdsLeadsSql.test.js +32 -0
  433. package/dist/dist/server-safe/facebookAdsLeadsSql.test.js.map +1 -0
  434. package/dist/dist/server-safe/facebookMessenger.d.ts +20 -0
  435. package/dist/dist/server-safe/facebookMessenger.d.ts.map +1 -0
  436. package/dist/dist/server-safe/facebookMessenger.js +63 -0
  437. package/dist/dist/server-safe/facebookMessenger.js.map +1 -0
  438. package/dist/dist/server-safe/facebookMessenger.test.d.ts +2 -0
  439. package/dist/dist/server-safe/facebookMessenger.test.d.ts.map +1 -0
  440. package/dist/dist/server-safe/facebookMessenger.test.js +51 -0
  441. package/dist/dist/server-safe/facebookMessenger.test.js.map +1 -0
  442. package/dist/dist/server-safe/helpers.d.ts +78 -0
  443. package/dist/dist/server-safe/helpers.d.ts.map +1 -0
  444. package/dist/dist/server-safe/helpers.js +569 -0
  445. package/dist/dist/server-safe/helpers.js.map +1 -0
  446. package/dist/dist/server-safe/index.d.ts +30 -0
  447. package/dist/dist/server-safe/index.d.ts.map +1 -0
  448. package/dist/dist/server-safe/index.js +46 -0
  449. package/dist/dist/server-safe/index.js.map +1 -0
  450. package/dist/dist/server-safe/permissions.d.ts +29 -0
  451. package/dist/dist/server-safe/permissions.d.ts.map +1 -0
  452. package/dist/dist/server-safe/permissions.js +180 -0
  453. package/dist/dist/server-safe/permissions.js.map +1 -0
  454. package/dist/dist/server-safe/proposals.d.ts +6 -0
  455. package/dist/dist/server-safe/proposals.d.ts.map +1 -0
  456. package/dist/dist/server-safe/proposals.js +58 -0
  457. package/dist/dist/server-safe/proposals.js.map +1 -0
  458. package/dist/dist/server-safe/rentalAvailability.d.ts +56 -0
  459. package/dist/dist/server-safe/rentalAvailability.d.ts.map +1 -0
  460. package/dist/dist/server-safe/rentalAvailability.js +124 -0
  461. package/dist/dist/server-safe/rentalAvailability.js.map +1 -0
  462. package/dist/dist/server-safe/rentalAvailability.test.d.ts +2 -0
  463. package/dist/dist/server-safe/rentalAvailability.test.d.ts.map +1 -0
  464. package/dist/dist/server-safe/rentalAvailability.test.js +290 -0
  465. package/dist/dist/server-safe/rentalAvailability.test.js.map +1 -0
  466. package/dist/dist/server-safe/rentals.d.ts +95 -0
  467. package/dist/dist/server-safe/rentals.d.ts.map +1 -0
  468. package/dist/dist/server-safe/rentals.js +432 -0
  469. package/dist/dist/server-safe/rentals.js.map +1 -0
  470. package/dist/dist/server-safe/rentals.test.d.ts +2 -0
  471. package/dist/dist/server-safe/rentals.test.d.ts.map +1 -0
  472. package/dist/dist/server-safe/rentals.test.js +1034 -0
  473. package/dist/dist/server-safe/rentals.test.js.map +1 -0
  474. package/dist/dist/server-safe/routeOptimization.d.ts +155 -0
  475. package/dist/dist/server-safe/routeOptimization.d.ts.map +1 -0
  476. package/dist/dist/server-safe/routeOptimization.js +120 -0
  477. package/dist/dist/server-safe/routeOptimization.js.map +1 -0
  478. package/dist/dist/server-safe/routeOptimization.test.d.ts +2 -0
  479. package/dist/dist/server-safe/routeOptimization.test.d.ts.map +1 -0
  480. package/dist/dist/server-safe/routeOptimization.test.js +234 -0
  481. package/dist/dist/server-safe/routeOptimization.test.js.map +1 -0
  482. package/dist/dist/server-safe/routePlanFingerprint.d.ts +13 -0
  483. package/dist/dist/server-safe/routePlanFingerprint.d.ts.map +1 -0
  484. package/dist/dist/server-safe/routePlanFingerprint.js +49 -0
  485. package/dist/dist/server-safe/routePlanFingerprint.js.map +1 -0
  486. package/dist/dist/server-safe/routePlanFingerprint.test.d.ts +2 -0
  487. package/dist/dist/server-safe/routePlanFingerprint.test.d.ts.map +1 -0
  488. package/dist/dist/server-safe/routePlanFingerprint.test.js +68 -0
  489. package/dist/dist/server-safe/routePlanFingerprint.test.js.map +1 -0
  490. package/dist/dist/server-safe/scheduleListOrder.d.ts +18 -0
  491. package/dist/dist/server-safe/scheduleListOrder.d.ts.map +1 -0
  492. package/dist/dist/server-safe/scheduleListOrder.js +92 -0
  493. package/dist/dist/server-safe/scheduleListOrder.js.map +1 -0
  494. package/dist/dist/server-safe/scheduleListOrder.test.d.ts +2 -0
  495. package/dist/dist/server-safe/scheduleListOrder.test.d.ts.map +1 -0
  496. package/dist/dist/server-safe/scheduleListOrder.test.js +260 -0
  497. package/dist/dist/server-safe/scheduleListOrder.test.js.map +1 -0
  498. package/dist/dist/server-safe/serviceMinutes.d.ts +13 -0
  499. package/dist/dist/server-safe/serviceMinutes.d.ts.map +1 -0
  500. package/dist/dist/server-safe/serviceMinutes.js +38 -0
  501. package/dist/dist/server-safe/serviceMinutes.js.map +1 -0
  502. package/dist/dist/server-safe/serviceMinutes.test.d.ts +2 -0
  503. package/dist/dist/server-safe/serviceMinutes.test.d.ts.map +1 -0
  504. package/dist/dist/server-safe/serviceMinutes.test.js +86 -0
  505. package/dist/dist/server-safe/serviceMinutes.test.js.map +1 -0
  506. package/dist/dist/server-safe/settingsSearch.d.ts +24 -0
  507. package/dist/dist/server-safe/settingsSearch.d.ts.map +1 -0
  508. package/dist/dist/server-safe/settingsSearch.js +8 -0
  509. package/dist/dist/server-safe/settingsSearch.js.map +1 -0
  510. package/dist/dist/server-safe/supportChat.d.ts +59 -0
  511. package/dist/dist/server-safe/supportChat.d.ts.map +1 -0
  512. package/dist/dist/server-safe/supportChat.js +56 -0
  513. package/dist/dist/server-safe/supportChat.js.map +1 -0
  514. package/dist/dist/server-safe/templates.d.ts +15 -0
  515. package/dist/dist/server-safe/templates.d.ts.map +1 -0
  516. package/dist/dist/server-safe/templates.js +91 -0
  517. package/dist/dist/server-safe/templates.js.map +1 -0
  518. package/dist/dist/server-safe/templates.test.d.ts +2 -0
  519. package/dist/dist/server-safe/templates.test.d.ts.map +1 -0
  520. package/dist/dist/server-safe/templates.test.js +62 -0
  521. package/dist/dist/server-safe/templates.test.js.map +1 -0
  522. package/dist/dist/server-safe/trash.d.ts +50 -0
  523. package/dist/dist/server-safe/trash.d.ts.map +1 -0
  524. package/dist/dist/server-safe/trash.js +100 -0
  525. package/dist/dist/server-safe/trash.js.map +1 -0
  526. package/dist/dist/utils/LogHandler.d.ts +3 -0
  527. package/dist/dist/utils/LogHandler.d.ts.map +1 -0
  528. package/dist/dist/utils/LogHandler.js +16 -0
  529. package/dist/dist/utils/LogHandler.js.map +1 -0
  530. package/dist/dist/utils/convertSupabaseImagesToAssets.d.ts +28 -0
  531. package/dist/dist/utils/convertSupabaseImagesToAssets.d.ts.map +1 -0
  532. package/dist/dist/utils/convertSupabaseImagesToAssets.js +14 -0
  533. package/dist/dist/utils/convertSupabaseImagesToAssets.js.map +1 -0
  534. package/dist/index.d.ts +45 -0
  535. package/dist/index.d.ts.map +1 -0
  536. package/dist/index.js +61 -0
  537. package/dist/index.js.map +1 -0
  538. package/dist/interfaces/index.d.ts +1238 -0
  539. package/dist/interfaces/index.d.ts.map +1 -0
  540. package/dist/interfaces/index.js +3 -0
  541. package/dist/interfaces/index.js.map +1 -0
  542. package/dist/providers/AddressProvider.d.ts +9 -0
  543. package/dist/providers/AddressProvider.d.ts.map +1 -0
  544. package/dist/providers/AddressProvider.js +207 -0
  545. package/dist/providers/AddressProvider.js.map +1 -0
  546. package/dist/providers/AutomationsProvider.d.ts +11 -0
  547. package/dist/providers/AutomationsProvider.d.ts.map +1 -0
  548. package/dist/providers/AutomationsProvider.js +170 -0
  549. package/dist/providers/AutomationsProvider.js.map +1 -0
  550. package/dist/providers/BlockedNumbersProvider.d.ts +7 -0
  551. package/dist/providers/BlockedNumbersProvider.d.ts.map +1 -0
  552. package/dist/providers/BlockedNumbersProvider.js +71 -0
  553. package/dist/providers/BlockedNumbersProvider.js.map +1 -0
  554. package/dist/providers/CategoryProvider.d.ts +8 -0
  555. package/dist/providers/CategoryProvider.d.ts.map +1 -0
  556. package/dist/providers/CategoryProvider.js +95 -0
  557. package/dist/providers/CategoryProvider.js.map +1 -0
  558. package/dist/providers/ClientProvider.d.ts +39 -0
  559. package/dist/providers/ClientProvider.d.ts.map +1 -0
  560. package/dist/providers/ClientProvider.js +253 -0
  561. package/dist/providers/ClientProvider.js.map +1 -0
  562. package/dist/providers/CompanyProvider.d.ts +7 -0
  563. package/dist/providers/CompanyProvider.d.ts.map +1 -0
  564. package/dist/providers/CompanyProvider.js +114 -0
  565. package/dist/providers/CompanyProvider.js.map +1 -0
  566. package/dist/providers/DashboardProvider.d.ts +78 -0
  567. package/dist/providers/DashboardProvider.d.ts.map +1 -0
  568. package/dist/providers/DashboardProvider.js +568 -0
  569. package/dist/providers/DashboardProvider.js.map +1 -0
  570. package/dist/providers/DiscountProvider.d.ts +8 -0
  571. package/dist/providers/DiscountProvider.d.ts.map +1 -0
  572. package/dist/providers/DiscountProvider.js +92 -0
  573. package/dist/providers/DiscountProvider.js.map +1 -0
  574. package/dist/providers/EmployeesProvider.d.ts +6 -0
  575. package/dist/providers/EmployeesProvider.d.ts.map +1 -0
  576. package/dist/providers/EmployeesProvider.js +185 -0
  577. package/dist/providers/EmployeesProvider.js.map +1 -0
  578. package/dist/providers/EstimatesProvider.d.ts +16 -0
  579. package/dist/providers/EstimatesProvider.d.ts.map +1 -0
  580. package/dist/providers/EstimatesProvider.js +251 -0
  581. package/dist/providers/EstimatesProvider.js.map +1 -0
  582. package/dist/providers/EventsProvider.d.ts +4 -0
  583. package/dist/providers/EventsProvider.d.ts.map +1 -0
  584. package/dist/providers/EventsProvider.js +24 -0
  585. package/dist/providers/EventsProvider.js.map +1 -0
  586. package/dist/providers/FilesProvider.d.ts +17 -0
  587. package/dist/providers/FilesProvider.d.ts.map +1 -0
  588. package/dist/providers/FilesProvider.js +201 -0
  589. package/dist/providers/FilesProvider.js.map +1 -0
  590. package/dist/providers/InvoicesProvider.d.ts +13 -0
  591. package/dist/providers/InvoicesProvider.d.ts.map +1 -0
  592. package/dist/providers/InvoicesProvider.js +207 -0
  593. package/dist/providers/InvoicesProvider.js.map +1 -0
  594. package/dist/providers/ItemProvider.d.ts +9 -0
  595. package/dist/providers/ItemProvider.d.ts.map +1 -0
  596. package/dist/providers/ItemProvider.js +201 -0
  597. package/dist/providers/ItemProvider.js.map +1 -0
  598. package/dist/providers/JobSourceProvider.d.ts +8 -0
  599. package/dist/providers/JobSourceProvider.d.ts.map +1 -0
  600. package/dist/providers/JobSourceProvider.js +75 -0
  601. package/dist/providers/JobSourceProvider.js.map +1 -0
  602. package/dist/providers/JobTypeProvider.d.ts +8 -0
  603. package/dist/providers/JobTypeProvider.d.ts.map +1 -0
  604. package/dist/providers/JobTypeProvider.js +75 -0
  605. package/dist/providers/JobTypeProvider.js.map +1 -0
  606. package/dist/providers/JobsProvider.d.ts +20 -0
  607. package/dist/providers/JobsProvider.d.ts.map +1 -0
  608. package/dist/providers/JobsProvider.js +863 -0
  609. package/dist/providers/JobsProvider.js.map +1 -0
  610. package/dist/providers/MessagesProvider.d.ts +14 -0
  611. package/dist/providers/MessagesProvider.d.ts.map +1 -0
  612. package/dist/providers/MessagesProvider.js +415 -0
  613. package/dist/providers/MessagesProvider.js.map +1 -0
  614. package/dist/providers/PaymentProvider.d.ts +9 -0
  615. package/dist/providers/PaymentProvider.d.ts.map +1 -0
  616. package/dist/providers/PaymentProvider.js +48 -0
  617. package/dist/providers/PaymentProvider.js.map +1 -0
  618. package/dist/providers/PermissionRolesProvider.d.ts +5 -0
  619. package/dist/providers/PermissionRolesProvider.d.ts.map +1 -0
  620. package/dist/providers/PermissionRolesProvider.js +30 -0
  621. package/dist/providers/PermissionRolesProvider.js.map +1 -0
  622. package/dist/providers/PhoneNumberProvider.d.ts +12 -0
  623. package/dist/providers/PhoneNumberProvider.d.ts.map +1 -0
  624. package/dist/providers/PhoneNumberProvider.js +184 -0
  625. package/dist/providers/PhoneNumberProvider.js.map +1 -0
  626. package/dist/providers/ProfileProvider.d.ts +6 -0
  627. package/dist/providers/ProfileProvider.d.ts.map +1 -0
  628. package/dist/providers/ProfileProvider.js +71 -0
  629. package/dist/providers/ProfileProvider.js.map +1 -0
  630. package/dist/providers/RentalsProvider.d.ts +28 -0
  631. package/dist/providers/RentalsProvider.d.ts.map +1 -0
  632. package/dist/providers/RentalsProvider.js +438 -0
  633. package/dist/providers/RentalsProvider.js.map +1 -0
  634. package/dist/providers/SettingsBookingProvider.d.ts +9 -0
  635. package/dist/providers/SettingsBookingProvider.d.ts.map +1 -0
  636. package/dist/providers/SettingsBookingProvider.js +163 -0
  637. package/dist/providers/SettingsBookingProvider.js.map +1 -0
  638. package/dist/providers/SettingsProvider.d.ts +8 -0
  639. package/dist/providers/SettingsProvider.d.ts.map +1 -0
  640. package/dist/providers/SettingsProvider.js +86 -0
  641. package/dist/providers/SettingsProvider.js.map +1 -0
  642. package/dist/providers/TagsProvider.d.ts +12 -0
  643. package/dist/providers/TagsProvider.d.ts.map +1 -0
  644. package/dist/providers/TagsProvider.js +210 -0
  645. package/dist/providers/TagsProvider.js.map +1 -0
  646. package/dist/providers/TimeCardProvider.d.ts +8 -0
  647. package/dist/providers/TimeCardProvider.d.ts.map +1 -0
  648. package/dist/providers/TimeCardProvider.js +93 -0
  649. package/dist/providers/TimeCardProvider.js.map +1 -0
  650. package/dist/providers/TrashProvider.d.ts +13 -0
  651. package/dist/providers/TrashProvider.d.ts.map +1 -0
  652. package/dist/providers/TrashProvider.js +98 -0
  653. package/dist/providers/TrashProvider.js.map +1 -0
  654. package/dist/providers/dashboardAnalytics.d.ts +9 -0
  655. package/dist/providers/dashboardAnalytics.d.ts.map +1 -0
  656. package/dist/providers/dashboardAnalytics.js +41 -0
  657. package/dist/providers/dashboardAnalytics.js.map +1 -0
  658. package/dist/providers/dashboardAnalytics.test.d.ts +2 -0
  659. package/dist/providers/dashboardAnalytics.test.d.ts.map +1 -0
  660. package/dist/providers/dashboardAnalytics.test.js +111 -0
  661. package/dist/providers/dashboardAnalytics.test.js.map +1 -0
  662. package/dist/server-safe/BlockedNumberFunctions.d.ts +11 -0
  663. package/dist/server-safe/BlockedNumberFunctions.d.ts.map +1 -0
  664. package/dist/server-safe/BlockedNumberFunctions.js +16 -0
  665. package/dist/server-safe/BlockedNumberFunctions.js.map +1 -0
  666. package/dist/server-safe/EmployeeFunctions.d.ts +14 -0
  667. package/dist/server-safe/EmployeeFunctions.d.ts.map +1 -0
  668. package/dist/server-safe/EmployeeFunctions.js +70 -0
  669. package/dist/server-safe/EmployeeFunctions.js.map +1 -0
  670. package/dist/server-safe/EmployeeLocationFunctions.d.ts +7 -0
  671. package/dist/server-safe/EmployeeLocationFunctions.d.ts.map +1 -0
  672. package/dist/server-safe/EmployeeLocationFunctions.js +47 -0
  673. package/dist/server-safe/EmployeeLocationFunctions.js.map +1 -0
  674. package/dist/server-safe/EstimateFunctions.d.ts +15 -0
  675. package/dist/server-safe/EstimateFunctions.d.ts.map +1 -0
  676. package/dist/server-safe/EstimateFunctions.js +34 -0
  677. package/dist/server-safe/EstimateFunctions.js.map +1 -0
  678. package/dist/server-safe/InvoiceFunctions.d.ts +21 -0
  679. package/dist/server-safe/InvoiceFunctions.d.ts.map +1 -0
  680. package/dist/server-safe/InvoiceFunctions.js +124 -0
  681. package/dist/server-safe/InvoiceFunctions.js.map +1 -0
  682. package/dist/server-safe/JobFunctions.d.ts +15 -0
  683. package/dist/server-safe/JobFunctions.d.ts.map +1 -0
  684. package/dist/server-safe/JobFunctions.js +56 -0
  685. package/dist/server-safe/JobFunctions.js.map +1 -0
  686. package/dist/server-safe/PaymentFunctions.d.ts +16 -0
  687. package/dist/server-safe/PaymentFunctions.d.ts.map +1 -0
  688. package/dist/server-safe/PaymentFunctions.js +80 -0
  689. package/dist/server-safe/PaymentFunctions.js.map +1 -0
  690. package/dist/server-safe/PermissionFunctions.d.ts +7 -0
  691. package/dist/server-safe/PermissionFunctions.d.ts.map +1 -0
  692. package/dist/server-safe/PermissionFunctions.js +39 -0
  693. package/dist/server-safe/PermissionFunctions.js.map +1 -0
  694. package/dist/server-safe/TagFunctions.d.ts +18 -0
  695. package/dist/server-safe/TagFunctions.d.ts.map +1 -0
  696. package/dist/server-safe/TagFunctions.js +52 -0
  697. package/dist/server-safe/TagFunctions.js.map +1 -0
  698. package/dist/server-safe/autoJobType.d.ts +16 -0
  699. package/dist/server-safe/autoJobType.d.ts.map +1 -0
  700. package/dist/server-safe/autoJobType.js +39 -0
  701. package/dist/server-safe/autoJobType.js.map +1 -0
  702. package/dist/server-safe/autoJobType.test.d.ts +2 -0
  703. package/dist/server-safe/autoJobType.test.d.ts.map +1 -0
  704. package/dist/server-safe/autoJobType.test.js +83 -0
  705. package/dist/server-safe/autoJobType.test.js.map +1 -0
  706. package/dist/server-safe/automations.d.ts +197 -0
  707. package/dist/server-safe/automations.d.ts.map +1 -0
  708. package/dist/server-safe/automations.js +757 -0
  709. package/dist/server-safe/automations.js.map +1 -0
  710. package/dist/server-safe/automations.test.d.ts +2 -0
  711. package/dist/server-safe/automations.test.d.ts.map +1 -0
  712. package/dist/server-safe/automations.test.js +441 -0
  713. package/dist/server-safe/automations.test.js.map +1 -0
  714. package/dist/server-safe/constants.d.ts +156 -0
  715. package/dist/server-safe/constants.d.ts.map +1 -0
  716. package/dist/server-safe/constants.js +186 -0
  717. package/dist/server-safe/constants.js.map +1 -0
  718. package/dist/server-safe/contracts.d.ts +3 -0
  719. package/dist/server-safe/contracts.d.ts.map +1 -0
  720. package/dist/server-safe/contracts.js +15 -0
  721. package/dist/server-safe/contracts.js.map +1 -0
  722. package/dist/server-safe/database.types.d.ts +9510 -0
  723. package/dist/server-safe/database.types.d.ts.map +1 -0
  724. package/dist/server-safe/database.types.js +40 -0
  725. package/dist/server-safe/database.types.js.map +1 -0
  726. package/dist/server-safe/entitlements.d.ts +99 -0
  727. package/dist/server-safe/entitlements.d.ts.map +1 -0
  728. package/dist/server-safe/entitlements.js +487 -0
  729. package/dist/server-safe/entitlements.js.map +1 -0
  730. package/dist/server-safe/helpers.d.ts +78 -0
  731. package/dist/server-safe/helpers.d.ts.map +1 -0
  732. package/dist/server-safe/helpers.js +569 -0
  733. package/dist/server-safe/helpers.js.map +1 -0
  734. package/dist/server-safe/index.d.ts +30 -0
  735. package/dist/server-safe/index.d.ts.map +1 -0
  736. package/dist/server-safe/index.js +46 -0
  737. package/dist/server-safe/index.js.map +1 -0
  738. package/dist/server-safe/permissions.d.ts +29 -0
  739. package/dist/server-safe/permissions.d.ts.map +1 -0
  740. package/dist/server-safe/permissions.js +180 -0
  741. package/dist/server-safe/permissions.js.map +1 -0
  742. package/dist/server-safe/proposals.d.ts +6 -0
  743. package/dist/server-safe/proposals.d.ts.map +1 -0
  744. package/dist/server-safe/proposals.js +58 -0
  745. package/dist/server-safe/proposals.js.map +1 -0
  746. package/dist/server-safe/rentalAvailability.d.ts +56 -0
  747. package/dist/server-safe/rentalAvailability.d.ts.map +1 -0
  748. package/dist/server-safe/rentalAvailability.js +124 -0
  749. package/dist/server-safe/rentalAvailability.js.map +1 -0
  750. package/dist/server-safe/rentalAvailability.test.d.ts +2 -0
  751. package/dist/server-safe/rentalAvailability.test.d.ts.map +1 -0
  752. package/dist/server-safe/rentalAvailability.test.js +290 -0
  753. package/dist/server-safe/rentalAvailability.test.js.map +1 -0
  754. package/dist/server-safe/rentals.d.ts +95 -0
  755. package/dist/server-safe/rentals.d.ts.map +1 -0
  756. package/dist/server-safe/rentals.js +432 -0
  757. package/dist/server-safe/rentals.js.map +1 -0
  758. package/dist/server-safe/rentals.test.d.ts +2 -0
  759. package/dist/server-safe/rentals.test.d.ts.map +1 -0
  760. package/dist/server-safe/rentals.test.js +1034 -0
  761. package/dist/server-safe/rentals.test.js.map +1 -0
  762. package/dist/server-safe/routeOptimization.d.ts +155 -0
  763. package/dist/server-safe/routeOptimization.d.ts.map +1 -0
  764. package/dist/server-safe/routeOptimization.js +120 -0
  765. package/dist/server-safe/routeOptimization.js.map +1 -0
  766. package/dist/server-safe/routeOptimization.test.d.ts +2 -0
  767. package/dist/server-safe/routeOptimization.test.d.ts.map +1 -0
  768. package/dist/server-safe/routeOptimization.test.js +234 -0
  769. package/dist/server-safe/routeOptimization.test.js.map +1 -0
  770. package/dist/server-safe/routePlanFingerprint.d.ts +13 -0
  771. package/dist/server-safe/routePlanFingerprint.d.ts.map +1 -0
  772. package/dist/server-safe/routePlanFingerprint.js +49 -0
  773. package/dist/server-safe/routePlanFingerprint.js.map +1 -0
  774. package/dist/server-safe/routePlanFingerprint.test.d.ts +2 -0
  775. package/dist/server-safe/routePlanFingerprint.test.d.ts.map +1 -0
  776. package/dist/server-safe/routePlanFingerprint.test.js +68 -0
  777. package/dist/server-safe/routePlanFingerprint.test.js.map +1 -0
  778. package/dist/server-safe/scheduleListOrder.d.ts +18 -0
  779. package/dist/server-safe/scheduleListOrder.d.ts.map +1 -0
  780. package/dist/server-safe/scheduleListOrder.js +92 -0
  781. package/dist/server-safe/scheduleListOrder.js.map +1 -0
  782. package/dist/server-safe/scheduleListOrder.test.d.ts +2 -0
  783. package/dist/server-safe/scheduleListOrder.test.d.ts.map +1 -0
  784. package/dist/server-safe/scheduleListOrder.test.js +260 -0
  785. package/dist/server-safe/scheduleListOrder.test.js.map +1 -0
  786. package/dist/server-safe/serviceMinutes.d.ts +13 -0
  787. package/dist/server-safe/serviceMinutes.d.ts.map +1 -0
  788. package/dist/server-safe/serviceMinutes.js +38 -0
  789. package/dist/server-safe/serviceMinutes.js.map +1 -0
  790. package/dist/server-safe/serviceMinutes.test.d.ts +2 -0
  791. package/dist/server-safe/serviceMinutes.test.d.ts.map +1 -0
  792. package/dist/server-safe/serviceMinutes.test.js +86 -0
  793. package/dist/server-safe/serviceMinutes.test.js.map +1 -0
  794. package/dist/server-safe/settingsSearch.d.ts +24 -0
  795. package/dist/server-safe/settingsSearch.d.ts.map +1 -0
  796. package/dist/server-safe/settingsSearch.js +8 -0
  797. package/dist/server-safe/settingsSearch.js.map +1 -0
  798. package/dist/server-safe/supportChat.d.ts +59 -0
  799. package/dist/server-safe/supportChat.d.ts.map +1 -0
  800. package/dist/server-safe/supportChat.js +56 -0
  801. package/dist/server-safe/supportChat.js.map +1 -0
  802. package/dist/server-safe/templates.d.ts +15 -0
  803. package/dist/server-safe/templates.d.ts.map +1 -0
  804. package/dist/server-safe/templates.js +91 -0
  805. package/dist/server-safe/templates.js.map +1 -0
  806. package/dist/server-safe/templates.test.d.ts +2 -0
  807. package/dist/server-safe/templates.test.d.ts.map +1 -0
  808. package/dist/server-safe/templates.test.js +62 -0
  809. package/dist/server-safe/templates.test.js.map +1 -0
  810. package/dist/server-safe/trash.d.ts +50 -0
  811. package/dist/server-safe/trash.d.ts.map +1 -0
  812. package/dist/server-safe/trash.js +100 -0
  813. package/dist/server-safe/trash.js.map +1 -0
  814. package/dist/utils/LogHandler.d.ts +3 -0
  815. package/dist/utils/LogHandler.d.ts.map +1 -0
  816. package/dist/utils/LogHandler.js +16 -0
  817. package/dist/utils/LogHandler.js.map +1 -0
  818. package/dist/utils/convertSupabaseImagesToAssets.d.ts +28 -0
  819. package/dist/utils/convertSupabaseImagesToAssets.d.ts.map +1 -0
  820. package/dist/utils/convertSupabaseImagesToAssets.js +14 -0
  821. package/dist/utils/convertSupabaseImagesToAssets.js.map +1 -0
  822. package/package.json +37 -0
@@ -0,0 +1,1711 @@
1
+ -- Meta Lead Ads ingestion: Page/Form configuration, durable webhook receipt,
2
+ -- consent evidence, atomic lead creation, and agent-first call attempts.
3
+ --
4
+ -- Everything in this migration is additive and fail-closed. Lead sync and
5
+ -- auto-dial are disabled for every existing company until a server route
6
+ -- validates and enables the configuration through
7
+ -- set_facebook_ads_lead_settings(). The companion RLS migration keeps every
8
+ -- credential, PII, evidence, and queue table service-role only.
9
+
10
+ -- ============================================================
11
+ -- Shared normalized-array checks
12
+ -- ============================================================
13
+
14
+ create or replace function "public"."facebook_ads_text_array_is_normalized"(
15
+ "p_values" text[]
16
+ )
17
+ returns boolean
18
+ language sql
19
+ immutable
20
+ parallel safe
21
+ set search_path = ''
22
+ as $$
23
+ select case
24
+ when cardinality("p_values") = 0 then true
25
+ when coalesce(array_ndims("p_values"), 0) <> 1 then false
26
+ when exists (
27
+ select 1
28
+ from unnest("p_values") as "item"("value")
29
+ where "item"."value" is null
30
+ or nullif(btrim("item"."value"), '') is null
31
+ ) then false
32
+ else "p_values" = array(
33
+ select distinct "item"."value"
34
+ from unnest("p_values") as "item"("value")
35
+ order by "item"."value"
36
+ )
37
+ end;
38
+ $$;
39
+
40
+ alter function "public"."facebook_ads_text_array_is_normalized"(text[])
41
+ owner to "postgres";
42
+
43
+ create or replace function "public"."facebook_ads_call_days_are_normalized"(
44
+ "p_days" smallint[]
45
+ )
46
+ returns boolean
47
+ language sql
48
+ immutable
49
+ parallel safe
50
+ set search_path = ''
51
+ as $$
52
+ select case
53
+ when cardinality("p_days") = 0 then false
54
+ when coalesce(array_ndims("p_days"), 0) <> 1 then false
55
+ when exists (
56
+ select 1
57
+ from unnest("p_days") as "day_row"("value")
58
+ where "day_row"."value" is null
59
+ or "day_row"."value" not between 1 and 7
60
+ ) then false
61
+ else "p_days" = array(
62
+ select distinct "day_row"."value"
63
+ from unnest("p_days") as "day_row"("value")
64
+ order by "day_row"."value"
65
+ )::smallint[]
66
+ end;
67
+ $$;
68
+
69
+ alter function "public"."facebook_ads_call_days_are_normalized"(smallint[])
70
+ owner to "postgres";
71
+
72
+ -- ============================================================
73
+ -- Existing-table additions
74
+ -- ============================================================
75
+
76
+ alter table "public"."client"
77
+ add column if not exists "is_do_not_marketing_email" boolean
78
+ default false not null;
79
+
80
+ alter table "public"."facebook_ads_connection"
81
+ add column if not exists "granted_scopes" text[]
82
+ default '{}'::text[] not null;
83
+
84
+ alter table "public"."facebook_ads_connection"
85
+ add constraint "facebook_ads_connection_granted_scopes_check"
86
+ check (
87
+ "public"."facebook_ads_text_array_is_normalized"("granted_scopes")
88
+ );
89
+
90
+ alter table "public"."settings_facebook_ads"
91
+ add column if not exists "lead_sync_enabled" boolean default false not null,
92
+ add column if not exists "lead_tag_id" uuid,
93
+ add column if not exists "lead_sms_rule_id" uuid,
94
+ add column if not exists "lead_email_rule_id" uuid,
95
+ -- The customer attests that the company service timezone governs calling
96
+ -- every lead delivered by its selected Meta Forms. This is deliberately
97
+ -- separate from enabling the feature so the legal assumption is explicit.
98
+ add column if not exists "lead_auto_dial_timezone_attested" boolean
99
+ default false not null,
100
+ add column if not exists "lead_auto_dial_enabled" boolean default false not null,
101
+ add column if not exists "lead_auto_dial_phone_number_id" uuid,
102
+ add column if not exists "lead_auto_dial_user_id" uuid,
103
+ add column if not exists "lead_auto_dial_delay_seconds" integer default 0 not null,
104
+ add column if not exists "lead_auto_dial_window_start" time without time zone
105
+ default '08:00:00'::time without time zone not null,
106
+ add column if not exists "lead_auto_dial_window_end" time without time zone
107
+ default '20:00:00'::time without time zone not null,
108
+ -- ISO weekdays: Monday=1 through Sunday=7.
109
+ add column if not exists "lead_auto_dial_window_days" smallint[]
110
+ default array[1, 2, 3, 4, 5, 6, 7]::smallint[] not null;
111
+
112
+ alter table "public"."settings_facebook_ads"
113
+ add constraint "settings_facebook_ads_lead_tag_id_fkey"
114
+ foreign key ("lead_tag_id") references "public"."client_tag"("id")
115
+ on delete set null,
116
+ add constraint "settings_facebook_ads_lead_sms_rule_id_fkey"
117
+ foreign key ("lead_sms_rule_id") references "public"."automation_rule"("id")
118
+ on delete set null,
119
+ add constraint "settings_facebook_ads_lead_email_rule_id_fkey"
120
+ foreign key ("lead_email_rule_id") references "public"."automation_rule"("id")
121
+ on delete set null,
122
+ add constraint "settings_facebook_ads_lead_auto_dial_phone_number_id_fkey"
123
+ foreign key ("lead_auto_dial_phone_number_id")
124
+ references "public"."phone_number"("id") on delete set null,
125
+ add constraint "settings_facebook_ads_lead_auto_dial_user_id_fkey"
126
+ foreign key ("lead_auto_dial_user_id") references "public"."user"("id")
127
+ on delete set null,
128
+ add constraint "settings_facebook_ads_lead_sync_source_check"
129
+ check (not "lead_sync_enabled" or "source_id" is not null),
130
+ add constraint "settings_facebook_ads_lead_rule_distinct_check"
131
+ check (
132
+ "lead_sms_rule_id" is null
133
+ or "lead_email_rule_id" is null
134
+ or "lead_sms_rule_id" <> "lead_email_rule_id"
135
+ ),
136
+ add constraint "settings_facebook_ads_lead_auto_dial_config_check"
137
+ check (
138
+ not "lead_auto_dial_enabled"
139
+ or (
140
+ "lead_auto_dial_timezone_attested"
141
+ and
142
+ "lead_auto_dial_phone_number_id" is not null
143
+ and "lead_auto_dial_user_id" is not null
144
+ )
145
+ ),
146
+ add constraint "settings_facebook_ads_lead_auto_dial_delay_check"
147
+ check ("lead_auto_dial_delay_seconds" between 0 and 86400),
148
+ add constraint "settings_facebook_ads_lead_auto_dial_window_check"
149
+ check ("lead_auto_dial_window_start" < "lead_auto_dial_window_end"),
150
+ add constraint "settings_facebook_ads_lead_auto_dial_days_check"
151
+ check (
152
+ "public"."facebook_ads_call_days_are_normalized"(
153
+ "lead_auto_dial_window_days"
154
+ )
155
+ );
156
+
157
+ -- Facebook lead response rules are selected explicitly in settings rather
158
+ -- than discovered from every company-wide lead_created rule. Snapshot that
159
+ -- selection on the automation event created by the existing client trigger:
160
+ -- downstream fanout can then require both provenance and rule-id inclusion.
161
+ -- The non-Facebook branch deliberately preserves the old INSERT shape, so its
162
+ -- payload remains the automation_event default '{}'::jsonb.
163
+ create or replace function "public"."capture_automation_lead_created"()
164
+ returns trigger
165
+ language plpgsql
166
+ security definer
167
+ set search_path = ''
168
+ as $$
169
+ declare
170
+ "v_rule_ids" jsonb;
171
+ begin
172
+ if new."created_via" = 'facebook_lead_ads' then
173
+ select to_jsonb(array_remove(array[
174
+ "settings"."lead_sms_rule_id",
175
+ "settings"."lead_email_rule_id"
176
+ ], null::uuid))
177
+ into "v_rule_ids"
178
+ from "public"."settings_facebook_ads" as "settings"
179
+ where "settings"."company_id" = new."company_id";
180
+
181
+ insert into "public"."automation_event" (
182
+ "company_id", "event_type", "client_id", "payload"
183
+ ) values (
184
+ new."company_id",
185
+ 'lead_created',
186
+ new."id",
187
+ jsonb_build_object(
188
+ 'created_via', 'facebook_lead_ads',
189
+ 'rule_ids', coalesce("v_rule_ids", '[]'::jsonb)
190
+ )
191
+ );
192
+ else
193
+ insert into "public"."automation_event" (
194
+ "company_id", "event_type", "client_id"
195
+ ) values (new."company_id", 'lead_created', new."id");
196
+ end if;
197
+
198
+ return null;
199
+ end;
200
+ $$;
201
+
202
+ alter function "public"."capture_automation_lead_created"()
203
+ owner to "postgres";
204
+
205
+ -- ============================================================
206
+ -- Page and Form configuration
207
+ -- ============================================================
208
+
209
+ create table if not exists "public"."facebook_ads_lead_page" (
210
+ "id" uuid default gen_random_uuid() not null,
211
+ "created_at" timestamp with time zone default now() not null,
212
+ "updated_at" timestamp with time zone default now() not null,
213
+ "company_id" uuid not null,
214
+ "connection_id" uuid not null,
215
+ "meta_page_id" text not null,
216
+ "page_name" text not null,
217
+ -- Ciphertext produced by autopilot-web's Facebook token encryption.
218
+ "encrypted_page_access_token" text not null,
219
+ "token_expires_at" timestamp with time zone,
220
+ "is_enabled" boolean default false not null,
221
+ "subscription_status" text default 'pending' not null,
222
+ "subscribed_at" timestamp with time zone,
223
+ "last_subscription_attempt_at" timestamp with time zone,
224
+ "last_subscription_error" text,
225
+ -- selected is fail-closed: no Form is accepted until explicitly saved.
226
+ "form_selection_mode" text default 'selected' not null,
227
+ constraint "facebook_ads_lead_page_pkey" primary key ("id"),
228
+ constraint "facebook_ads_lead_page_company_id_id_key"
229
+ unique ("company_id", "id"),
230
+ constraint "facebook_ads_lead_page_meta_page_id_key" unique ("meta_page_id"),
231
+ constraint "facebook_ads_lead_page_company_id_fkey"
232
+ foreign key ("company_id") references "public"."company"("id")
233
+ on delete cascade,
234
+ constraint "facebook_ads_lead_page_company_connection_fkey"
235
+ foreign key ("company_id", "connection_id")
236
+ references "public"."facebook_ads_connection"("company_id", "id")
237
+ on delete cascade,
238
+ constraint "facebook_ads_lead_page_meta_page_id_check"
239
+ check ("meta_page_id" ~ '^[0-9]+$'),
240
+ constraint "facebook_ads_lead_page_page_name_check"
241
+ check (nullif(btrim("page_name"), '') is not null),
242
+ constraint "facebook_ads_lead_page_token_check"
243
+ check (nullif(btrim("encrypted_page_access_token"), '') is not null),
244
+ constraint "facebook_ads_lead_page_subscription_status_check"
245
+ check (
246
+ "subscription_status" in (
247
+ 'pending', 'subscribed', 'error', 'disconnected'
248
+ )
249
+ ),
250
+ constraint "facebook_ads_lead_page_form_selection_mode_check"
251
+ check ("form_selection_mode" in ('all', 'selected')),
252
+ constraint "facebook_ads_lead_page_enabled_subscription_check"
253
+ check (not "is_enabled" or "subscription_status" = 'subscribed')
254
+ );
255
+
256
+ alter table "public"."facebook_ads_lead_page" owner to "postgres";
257
+
258
+ create index if not exists "facebook_ads_lead_page_company_enabled_idx"
259
+ on "public"."facebook_ads_lead_page" ("company_id", "is_enabled");
260
+
261
+ create table if not exists "public"."facebook_ads_lead_form" (
262
+ "id" uuid default gen_random_uuid() not null,
263
+ "created_at" timestamp with time zone default now() not null,
264
+ "updated_at" timestamp with time zone default now() not null,
265
+ "company_id" uuid not null,
266
+ "page_id" uuid not null,
267
+ "meta_form_id" text not null,
268
+ "form_name" text not null,
269
+ "is_enabled" boolean default false not null,
270
+ -- Successful reconciliation advances this cursor. Workers overlap their
271
+ -- next Graph scan slightly so delayed Meta writes are still observed.
272
+ "last_reconciled_at" timestamp with time zone,
273
+ -- Maps Meta field names to first_name/last_name/email/phone. The exact
274
+ -- JSON shape is validated by the server-safe module added with this PR.
275
+ "field_mapping" jsonb default '{}'::jsonb not null,
276
+ -- A company must explicitly attest each channel and save the disclosure
277
+ -- shown on the Meta Form. A missing attestation/disclosure can never be
278
+ -- normalized to granted consent during finalization.
279
+ "sms_consent_attested" boolean default false not null,
280
+ "sms_consent_disclosure" text,
281
+ "email_consent_attested" boolean default false not null,
282
+ "email_consent_disclosure" text,
283
+ "voice_consent_attested" boolean default false not null,
284
+ "voice_consent_disclosure" text,
285
+ constraint "facebook_ads_lead_form_pkey" primary key ("id"),
286
+ constraint "facebook_ads_lead_form_company_id_id_key"
287
+ unique ("company_id", "id"),
288
+ constraint "facebook_ads_lead_form_page_form_key"
289
+ unique ("page_id", "meta_form_id"),
290
+ constraint "facebook_ads_lead_form_company_id_fkey"
291
+ foreign key ("company_id") references "public"."company"("id")
292
+ on delete cascade,
293
+ constraint "facebook_ads_lead_form_company_page_fkey"
294
+ foreign key ("company_id", "page_id")
295
+ references "public"."facebook_ads_lead_page"("company_id", "id")
296
+ on delete cascade,
297
+ constraint "facebook_ads_lead_form_meta_form_id_check"
298
+ check ("meta_form_id" ~ '^[0-9]+$'),
299
+ constraint "facebook_ads_lead_form_name_check"
300
+ check (nullif(btrim("form_name"), '') is not null),
301
+ constraint "facebook_ads_lead_form_field_mapping_check"
302
+ check (jsonb_typeof("field_mapping") = 'object'),
303
+ constraint "facebook_ads_lead_form_sms_consent_check"
304
+ check (
305
+ not "sms_consent_attested"
306
+ or nullif(btrim("sms_consent_disclosure"), '') is not null
307
+ ),
308
+ constraint "facebook_ads_lead_form_email_consent_check"
309
+ check (
310
+ not "email_consent_attested"
311
+ or nullif(btrim("email_consent_disclosure"), '') is not null
312
+ ),
313
+ constraint "facebook_ads_lead_form_voice_consent_check"
314
+ check (
315
+ not "voice_consent_attested"
316
+ or nullif(btrim("voice_consent_disclosure"), '') is not null
317
+ )
318
+ );
319
+
320
+ alter table "public"."facebook_ads_lead_form" owner to "postgres";
321
+
322
+ create index if not exists "facebook_ads_lead_form_company_page_enabled_idx"
323
+ on "public"."facebook_ads_lead_form" (
324
+ "company_id", "page_id", "is_enabled"
325
+ );
326
+
327
+ create or replace trigger "set_facebook_ads_lead_page_updated_at_trigger"
328
+ before update on "public"."facebook_ads_lead_page"
329
+ for each row execute function "public"."set_facebook_ads_updated_at"();
330
+
331
+ create or replace trigger "set_facebook_ads_lead_form_updated_at_trigger"
332
+ before update on "public"."facebook_ads_lead_form"
333
+ for each row execute function "public"."set_facebook_ads_updated_at"();
334
+
335
+ -- ============================================================
336
+ -- Durable receipt and consent evidence
337
+ -- ============================================================
338
+
339
+ create table if not exists "public"."facebook_ads_lead_event" (
340
+ "id" uuid default gen_random_uuid() not null,
341
+ "created_at" timestamp with time zone default now() not null,
342
+ "updated_at" timestamp with time zone default now() not null,
343
+ "company_id" uuid not null,
344
+ -- Nullable specifically so disconnecting a Page can erase its token and
345
+ -- configuration without erasing historical submission/consent evidence.
346
+ "page_id" uuid,
347
+ "meta_page_id" text not null,
348
+ "meta_leadgen_id" text not null,
349
+ "meta_form_id" text not null,
350
+ "meta_created_at" timestamp with time zone not null,
351
+ "meta_ad_id" text,
352
+ "meta_adset_id" text,
353
+ "meta_campaign_id" text,
354
+ "source_id" uuid,
355
+ "client_id" uuid,
356
+ "webhook_payload" jsonb not null,
357
+ "lead_payload" jsonb,
358
+ -- Immutable snapshot of mapping + channel attestations/disclosures at
359
+ -- receipt time. Form/Page deletion cannot destroy compliance evidence.
360
+ "form_configuration_snapshot" jsonb default '{}'::jsonb not null,
361
+ "status" text default 'pending' not null,
362
+ "skip_reason" text,
363
+ "received_count" integer default 1 not null,
364
+ "replay_count" integer default 0 not null,
365
+ "last_received_at" timestamp with time zone default now() not null,
366
+ "attempt_count" integer default 0 not null,
367
+ "next_attempt_at" timestamp with time zone default now() not null,
368
+ "last_attempt_at" timestamp with time zone,
369
+ "fetched_at" timestamp with time zone,
370
+ "processed_at" timestamp with time zone,
371
+ "last_error" text,
372
+ constraint "facebook_ads_lead_event_pkey" primary key ("id"),
373
+ constraint "facebook_ads_lead_event_company_id_id_key"
374
+ unique ("company_id", "id"),
375
+ constraint "facebook_ads_lead_event_meta_submission_key"
376
+ unique ("meta_page_id", "meta_leadgen_id"),
377
+ constraint "facebook_ads_lead_event_company_id_fkey"
378
+ foreign key ("company_id") references "public"."company"("id")
379
+ on delete cascade,
380
+ constraint "facebook_ads_lead_event_company_page_fkey"
381
+ foreign key ("company_id", "page_id")
382
+ references "public"."facebook_ads_lead_page"("company_id", "id")
383
+ on delete set null ("page_id"),
384
+ constraint "facebook_ads_lead_event_source_id_fkey"
385
+ foreign key ("source_id") references "public"."job_source"("id")
386
+ on delete set null,
387
+ constraint "facebook_ads_lead_event_client_id_fkey"
388
+ foreign key ("client_id") references "public"."client"("id")
389
+ on delete set null,
390
+ constraint "facebook_ads_lead_event_meta_page_id_check"
391
+ check ("meta_page_id" ~ '^[0-9]+$'),
392
+ constraint "facebook_ads_lead_event_meta_leadgen_id_check"
393
+ check ("meta_leadgen_id" ~ '^[0-9]+$'),
394
+ constraint "facebook_ads_lead_event_meta_form_id_check"
395
+ check ("meta_form_id" ~ '^[0-9]+$'),
396
+ constraint "facebook_ads_lead_event_meta_ad_id_check"
397
+ check ("meta_ad_id" is null or "meta_ad_id" ~ '^[0-9]+$'),
398
+ constraint "facebook_ads_lead_event_meta_adset_id_check"
399
+ check ("meta_adset_id" is null or "meta_adset_id" ~ '^[0-9]+$'),
400
+ constraint "facebook_ads_lead_event_meta_campaign_id_check"
401
+ check ("meta_campaign_id" is null or "meta_campaign_id" ~ '^[0-9]+$'),
402
+ constraint "facebook_ads_lead_event_webhook_payload_check"
403
+ check (jsonb_typeof("webhook_payload") = 'object'),
404
+ constraint "facebook_ads_lead_event_lead_payload_check"
405
+ check ("lead_payload" is null or jsonb_typeof("lead_payload") = 'object'),
406
+ constraint "facebook_ads_lead_event_form_snapshot_check"
407
+ check (jsonb_typeof("form_configuration_snapshot") = 'object'),
408
+ constraint "facebook_ads_lead_event_status_check"
409
+ check ("status" in ('pending', 'processing', 'processed', 'skipped', 'dead')),
410
+ constraint "facebook_ads_lead_event_received_count_check"
411
+ check ("received_count" > 0),
412
+ constraint "facebook_ads_lead_event_replay_count_check"
413
+ check ("replay_count" >= 0),
414
+ constraint "facebook_ads_lead_event_attempt_count_check"
415
+ check ("attempt_count" >= 0),
416
+ constraint "facebook_ads_lead_event_processed_at_check"
417
+ check ("status" <> 'processed' or "processed_at" is not null)
418
+ );
419
+
420
+ alter table "public"."facebook_ads_lead_event" owner to "postgres";
421
+
422
+ create index if not exists "facebook_ads_lead_event_due_idx"
423
+ on "public"."facebook_ads_lead_event" ("next_attempt_at", "created_at")
424
+ where "status" = 'pending';
425
+
426
+ create index if not exists "facebook_ads_lead_event_company_history_idx"
427
+ on "public"."facebook_ads_lead_event" ("company_id", "created_at" desc);
428
+
429
+ create index if not exists "facebook_ads_lead_event_client_idx"
430
+ on "public"."facebook_ads_lead_event" ("client_id")
431
+ where "client_id" is not null;
432
+
433
+ create table if not exists "public"."facebook_ads_lead_consent" (
434
+ "id" uuid default gen_random_uuid() not null,
435
+ "created_at" timestamp with time zone default now() not null,
436
+ "company_id" uuid not null,
437
+ "lead_event_id" uuid not null,
438
+ "channel" text not null,
439
+ "status" text default 'unknown' not null,
440
+ "captured_at" timestamp with time zone,
441
+ "disclosure_text" text,
442
+ "response_value" text,
443
+ "evidence" jsonb default '{}'::jsonb not null,
444
+ constraint "facebook_ads_lead_consent_pkey" primary key ("id"),
445
+ constraint "facebook_ads_lead_consent_company_id_id_key"
446
+ unique ("company_id", "id"),
447
+ constraint "facebook_ads_lead_consent_event_channel_key"
448
+ unique ("lead_event_id", "channel"),
449
+ constraint "facebook_ads_lead_consent_company_id_fkey"
450
+ foreign key ("company_id") references "public"."company"("id")
451
+ on delete cascade,
452
+ constraint "facebook_ads_lead_consent_company_event_fkey"
453
+ foreign key ("company_id", "lead_event_id")
454
+ references "public"."facebook_ads_lead_event"("company_id", "id")
455
+ on delete cascade,
456
+ constraint "facebook_ads_lead_consent_channel_check"
457
+ check ("channel" in ('email', 'sms', 'voice')),
458
+ constraint "facebook_ads_lead_consent_status_check"
459
+ check ("status" in ('granted', 'denied', 'unknown')),
460
+ constraint "facebook_ads_lead_consent_evidence_check"
461
+ check (jsonb_typeof("evidence") = 'object'),
462
+ constraint "facebook_ads_lead_consent_granted_evidence_check"
463
+ check (
464
+ "status" <> 'granted'
465
+ or (
466
+ "captured_at" is not null
467
+ and nullif(btrim("disclosure_text"), '') is not null
468
+ )
469
+ )
470
+ );
471
+
472
+ alter table "public"."facebook_ads_lead_consent" owner to "postgres";
473
+
474
+ create index if not exists "facebook_ads_lead_consent_company_event_idx"
475
+ on "public"."facebook_ads_lead_consent" ("company_id", "lead_event_id");
476
+
477
+ -- ============================================================
478
+ -- Agent-first auto-dial queue
479
+ -- ============================================================
480
+
481
+ create table if not exists "public"."facebook_ads_lead_call_attempt" (
482
+ "id" uuid default gen_random_uuid() not null,
483
+ "created_at" timestamp with time zone default now() not null,
484
+ "updated_at" timestamp with time zone default now() not null,
485
+ "company_id" uuid not null,
486
+ "lead_event_id" uuid not null,
487
+ "client_id" uuid,
488
+ "consent_id" uuid not null,
489
+ "from_phone_number_id" uuid,
490
+ "target_user_id" uuid,
491
+ "answered_by_user_id" uuid,
492
+ -- Immutable snapshots keep the audit useful after a number/user changes.
493
+ "from_phone_number" text not null,
494
+ "destination_phone_number" text not null,
495
+ "routing_snapshot" jsonb default '{}'::jsonb not null,
496
+ "status" text default 'pending' not null,
497
+ -- quiet-hours/business-window holds return a claimed row to pending with
498
+ -- a future next_attempt_at; workers never need a direct table update.
499
+ "held_reason" text,
500
+ "attempt_count" integer default 0 not null,
501
+ "next_attempt_at" timestamp with time zone default now() not null,
502
+ "last_attempt_at" timestamp with time zone,
503
+ "twilio_agent_call_sid" text,
504
+ "twilio_lead_call_sid" text,
505
+ "twilio_conference_sid" text,
506
+ "started_at" timestamp with time zone,
507
+ "connected_at" timestamp with time zone,
508
+ "completed_at" timestamp with time zone,
509
+ "skip_reason" text,
510
+ "last_error" text,
511
+ constraint "facebook_ads_lead_call_attempt_pkey" primary key ("id"),
512
+ constraint "facebook_ads_lead_call_attempt_company_id_id_key"
513
+ unique ("company_id", "id"),
514
+ constraint "facebook_ads_lead_call_attempt_lead_event_id_key"
515
+ unique ("lead_event_id"),
516
+ constraint "facebook_ads_lead_call_attempt_company_id_fkey"
517
+ foreign key ("company_id") references "public"."company"("id")
518
+ on delete cascade,
519
+ constraint "facebook_ads_lead_call_attempt_company_event_fkey"
520
+ foreign key ("company_id", "lead_event_id")
521
+ references "public"."facebook_ads_lead_event"("company_id", "id")
522
+ on delete cascade,
523
+ constraint "facebook_ads_lead_call_attempt_client_id_fkey"
524
+ foreign key ("client_id") references "public"."client"("id")
525
+ on delete set null,
526
+ constraint "facebook_ads_lead_call_attempt_company_consent_fkey"
527
+ foreign key ("company_id", "consent_id")
528
+ references "public"."facebook_ads_lead_consent"("company_id", "id")
529
+ on delete cascade,
530
+ constraint "facebook_ads_lead_call_attempt_from_phone_number_id_fkey"
531
+ foreign key ("from_phone_number_id")
532
+ references "public"."phone_number"("id") on delete set null,
533
+ constraint "facebook_ads_lead_call_attempt_target_user_id_fkey"
534
+ foreign key ("target_user_id") references "public"."user"("id")
535
+ on delete set null,
536
+ constraint "facebook_ads_lead_call_attempt_answered_by_user_id_fkey"
537
+ foreign key ("answered_by_user_id") references "public"."user"("id")
538
+ on delete set null,
539
+ constraint "facebook_ads_lead_call_attempt_status_check"
540
+ check (
541
+ "status" in (
542
+ 'pending', 'processing', 'agent_ringing', 'lead_ringing',
543
+ 'connected', 'completed', 'skipped', 'failed', 'dead'
544
+ )
545
+ ),
546
+ constraint "facebook_ads_lead_call_attempt_count_check"
547
+ check ("attempt_count" >= 0),
548
+ constraint "facebook_ads_lead_call_attempt_from_phone_check"
549
+ check (nullif(btrim("from_phone_number"), '') is not null),
550
+ constraint "facebook_ads_lead_call_attempt_destination_phone_check"
551
+ check (nullif(btrim("destination_phone_number"), '') is not null),
552
+ constraint "facebook_ads_lead_call_attempt_routing_snapshot_check"
553
+ check (jsonb_typeof("routing_snapshot") = 'object')
554
+ );
555
+
556
+ alter table "public"."facebook_ads_lead_call_attempt" owner to "postgres";
557
+
558
+ create index if not exists "facebook_ads_lead_call_attempt_due_idx"
559
+ on "public"."facebook_ads_lead_call_attempt" (
560
+ "next_attempt_at", "created_at"
561
+ ) where "status" = 'pending';
562
+
563
+ create index if not exists "facebook_ads_lead_call_attempt_company_history_idx"
564
+ on "public"."facebook_ads_lead_call_attempt" (
565
+ "company_id", "created_at" desc
566
+ );
567
+
568
+ create unique index if not exists "facebook_ads_lead_call_attempt_agent_sid_key"
569
+ on "public"."facebook_ads_lead_call_attempt" ("twilio_agent_call_sid")
570
+ where "twilio_agent_call_sid" is not null;
571
+
572
+ create unique index if not exists "facebook_ads_lead_call_attempt_lead_sid_key"
573
+ on "public"."facebook_ads_lead_call_attempt" ("twilio_lead_call_sid")
574
+ where "twilio_lead_call_sid" is not null;
575
+
576
+ create unique index if not exists "facebook_ads_lead_call_attempt_conference_sid_key"
577
+ on "public"."facebook_ads_lead_call_attempt" ("twilio_conference_sid")
578
+ where "twilio_conference_sid" is not null;
579
+
580
+ create or replace trigger "set_facebook_ads_lead_event_updated_at_trigger"
581
+ before update on "public"."facebook_ads_lead_event"
582
+ for each row execute function "public"."set_facebook_ads_updated_at"();
583
+
584
+ create or replace trigger "set_facebook_ads_lead_call_attempt_updated_at_trigger"
585
+ before update on "public"."facebook_ads_lead_call_attempt"
586
+ for each row execute function "public"."set_facebook_ads_updated_at"();
587
+
588
+ -- ============================================================
589
+ -- Lead settings RPC
590
+ -- ============================================================
591
+
592
+ create or replace function "public"."set_facebook_ads_lead_settings"("p" jsonb)
593
+ returns void
594
+ language plpgsql
595
+ security definer
596
+ set search_path = ''
597
+ as $$
598
+ declare
599
+ "v_company_id" uuid := ("p" ->> 'company_id')::uuid;
600
+ "v_current" "public"."settings_facebook_ads"%rowtype;
601
+ "v_sync_enabled" boolean;
602
+ "v_tag_id" uuid;
603
+ "v_sms_rule_id" uuid;
604
+ "v_email_rule_id" uuid;
605
+ "v_timezone_attested" boolean;
606
+ "v_auto_dial_enabled" boolean;
607
+ "v_phone_number_id" uuid;
608
+ "v_user_id" uuid;
609
+ "v_delay_seconds" integer;
610
+ "v_window_start" time without time zone;
611
+ "v_window_end" time without time zone;
612
+ "v_window_days" smallint[];
613
+ begin
614
+ if jsonb_typeof("p") <> 'object' or "v_company_id" is null then
615
+ raise exception 'company_id and an object payload are required'
616
+ using errcode = '22023';
617
+ end if;
618
+
619
+ if not exists (
620
+ select 1 from "public"."company" where "id" = "v_company_id"
621
+ ) then
622
+ raise exception 'Company does not exist' using errcode = '23503';
623
+ end if;
624
+
625
+ insert into "public"."settings_facebook_ads" ("company_id")
626
+ values ("v_company_id")
627
+ on conflict ("company_id") do nothing;
628
+
629
+ select * into "v_current"
630
+ from "public"."settings_facebook_ads"
631
+ where "company_id" = "v_company_id"
632
+ for update;
633
+
634
+ "v_sync_enabled" := case when "p" ? 'lead_sync_enabled'
635
+ then coalesce(("p" ->> 'lead_sync_enabled')::boolean, false)
636
+ else "v_current"."lead_sync_enabled" end;
637
+ "v_tag_id" := case when "p" ? 'lead_tag_id'
638
+ then ("p" ->> 'lead_tag_id')::uuid
639
+ else "v_current"."lead_tag_id" end;
640
+ "v_sms_rule_id" := case when "p" ? 'lead_sms_rule_id'
641
+ then ("p" ->> 'lead_sms_rule_id')::uuid
642
+ else "v_current"."lead_sms_rule_id" end;
643
+ "v_email_rule_id" := case when "p" ? 'lead_email_rule_id'
644
+ then ("p" ->> 'lead_email_rule_id')::uuid
645
+ else "v_current"."lead_email_rule_id" end;
646
+ "v_timezone_attested" := case
647
+ when "p" ? 'lead_auto_dial_timezone_attested'
648
+ then coalesce(
649
+ ("p" ->> 'lead_auto_dial_timezone_attested')::boolean,
650
+ false
651
+ )
652
+ else "v_current"."lead_auto_dial_timezone_attested" end;
653
+ "v_auto_dial_enabled" := case when "p" ? 'lead_auto_dial_enabled'
654
+ then coalesce(("p" ->> 'lead_auto_dial_enabled')::boolean, false)
655
+ else "v_current"."lead_auto_dial_enabled" end;
656
+ "v_phone_number_id" := case when "p" ? 'lead_auto_dial_phone_number_id'
657
+ then ("p" ->> 'lead_auto_dial_phone_number_id')::uuid
658
+ else "v_current"."lead_auto_dial_phone_number_id" end;
659
+ "v_user_id" := case when "p" ? 'lead_auto_dial_user_id'
660
+ then ("p" ->> 'lead_auto_dial_user_id')::uuid
661
+ else "v_current"."lead_auto_dial_user_id" end;
662
+ "v_delay_seconds" := case when "p" ? 'lead_auto_dial_delay_seconds'
663
+ then coalesce(("p" ->> 'lead_auto_dial_delay_seconds')::integer, 0)
664
+ else "v_current"."lead_auto_dial_delay_seconds" end;
665
+ "v_window_start" := case when "p" ? 'lead_auto_dial_window_start'
666
+ then ("p" ->> 'lead_auto_dial_window_start')::time without time zone
667
+ else "v_current"."lead_auto_dial_window_start" end;
668
+ "v_window_end" := case when "p" ? 'lead_auto_dial_window_end'
669
+ then ("p" ->> 'lead_auto_dial_window_end')::time without time zone
670
+ else "v_current"."lead_auto_dial_window_end" end;
671
+
672
+ if "p" ? 'lead_auto_dial_window_days' then
673
+ if jsonb_typeof("p" -> 'lead_auto_dial_window_days') <> 'array' then
674
+ raise exception 'lead_auto_dial_window_days must be an array'
675
+ using errcode = '22023';
676
+ end if;
677
+ select coalesce(
678
+ array_agg("day_row"."value"::smallint order by "day_row"."value"::smallint),
679
+ '{}'::smallint[]
680
+ ) into "v_window_days"
681
+ from jsonb_array_elements_text(
682
+ "p" -> 'lead_auto_dial_window_days'
683
+ ) as "day_row"("value");
684
+ else
685
+ "v_window_days" := "v_current"."lead_auto_dial_window_days";
686
+ end if;
687
+
688
+ if "v_sync_enabled" and "v_current"."source_id" is null then
689
+ raise exception 'A Facebook Ads lead source is required before enabling lead sync'
690
+ using errcode = '23514';
691
+ end if;
692
+
693
+ if "v_tag_id" is not null and not exists (
694
+ select 1 from "public"."client_tag"
695
+ where "id" = "v_tag_id" and "company_id" = "v_company_id"
696
+ ) then
697
+ raise exception 'Lead tag does not belong to this company'
698
+ using errcode = '23503';
699
+ end if;
700
+
701
+ -- Facebook follow-up is marketing by definition. Requiring both trusted
702
+ -- Facebook provenance and explicit marketing classification prevents a
703
+ -- generic lead rule from being repurposed and keeps the executor's
704
+ -- per-channel DNM gates in the path for every selected rule.
705
+ if "v_sms_rule_id" is not null and not exists (
706
+ select 1 from "public"."automation_rule"
707
+ where "id" = "v_sms_rule_id"
708
+ and "company_id" = "v_company_id"
709
+ and "trigger_type" = 'lead_created'
710
+ and "trigger_config" ->> 'created_via' = 'facebook_lead_ads'
711
+ and "action_type" = 'sms_client'
712
+ and "action_config" ->> 'communication_type' = 'marketing'
713
+ ) then
714
+ raise exception 'SMS rule must be this company''s Facebook lead-created marketing SMS rule'
715
+ using errcode = '23503';
716
+ end if;
717
+
718
+ if "v_email_rule_id" is not null and not exists (
719
+ select 1 from "public"."automation_rule"
720
+ where "id" = "v_email_rule_id"
721
+ and "company_id" = "v_company_id"
722
+ and "trigger_type" = 'lead_created'
723
+ and "trigger_config" ->> 'created_via' = 'facebook_lead_ads'
724
+ and "action_type" = 'email_client'
725
+ and "action_config" ->> 'communication_type' = 'marketing'
726
+ ) then
727
+ raise exception 'Email rule must be this company''s Facebook lead-created marketing email rule'
728
+ using errcode = '23503';
729
+ end if;
730
+
731
+ if "v_sms_rule_id" is not null
732
+ and "v_sms_rule_id" = "v_email_rule_id" then
733
+ raise exception 'SMS and email rules must be different'
734
+ using errcode = '23514';
735
+ end if;
736
+
737
+ if "v_delay_seconds" not between 0 and 86400
738
+ or "v_window_start" is null
739
+ or "v_window_end" is null
740
+ or "v_window_start" >= "v_window_end"
741
+ or not "public"."facebook_ads_call_days_are_normalized"("v_window_days")
742
+ then
743
+ raise exception 'Auto-dial delay or call window is invalid'
744
+ using errcode = '23514';
745
+ end if;
746
+
747
+ if "v_auto_dial_enabled" then
748
+ if not "v_timezone_attested" then
749
+ raise exception 'Auto-dial requires company service timezone attestation'
750
+ using errcode = '23514';
751
+ end if;
752
+
753
+ if "v_phone_number_id" is null or "v_user_id" is null then
754
+ raise exception 'Auto-dial requires a phone number and user'
755
+ using errcode = '23514';
756
+ end if;
757
+
758
+ if not exists (
759
+ select 1 from "public"."phone_number"
760
+ where "id" = "v_phone_number_id"
761
+ and "company_id" = "v_company_id"
762
+ and "twilio" = true
763
+ and "client_id" is null
764
+ and "phone_sid" is not null
765
+ ) then
766
+ raise exception 'Auto-dial phone number is not an active company Twilio number'
767
+ using errcode = '23503';
768
+ end if;
769
+
770
+ if not exists (
771
+ select 1 from "public"."user"
772
+ where "id" = "v_user_id"
773
+ and "company_id" = "v_company_id"
774
+ and "is_current_employee" = true
775
+ ) then
776
+ raise exception 'Auto-dial user is not a current company employee'
777
+ using errcode = '23503';
778
+ end if;
779
+
780
+ if not exists (
781
+ select 1 from "public"."phone_number_user_link"
782
+ where "company_id" = "v_company_id"
783
+ and "phone_number_id" = "v_phone_number_id"
784
+ and "user_id" = "v_user_id"
785
+ ) then
786
+ raise exception 'Auto-dial user is not linked to the selected number'
787
+ using errcode = '23514';
788
+ end if;
789
+ end if;
790
+
791
+ update "public"."settings_facebook_ads"
792
+ set
793
+ "lead_sync_enabled" = "v_sync_enabled",
794
+ "lead_tag_id" = "v_tag_id",
795
+ "lead_sms_rule_id" = "v_sms_rule_id",
796
+ "lead_email_rule_id" = "v_email_rule_id",
797
+ "lead_auto_dial_timezone_attested" = "v_timezone_attested",
798
+ "lead_auto_dial_enabled" = "v_auto_dial_enabled",
799
+ "lead_auto_dial_phone_number_id" = "v_phone_number_id",
800
+ "lead_auto_dial_user_id" = "v_user_id",
801
+ "lead_auto_dial_delay_seconds" = "v_delay_seconds",
802
+ "lead_auto_dial_window_start" = "v_window_start",
803
+ "lead_auto_dial_window_end" = "v_window_end",
804
+ "lead_auto_dial_window_days" = "v_window_days"
805
+ where "company_id" = "v_company_id";
806
+ end;
807
+ $$;
808
+
809
+ alter function "public"."set_facebook_ads_lead_settings"(jsonb)
810
+ owner to "postgres";
811
+
812
+ -- ============================================================
813
+ -- Receipt, claim, replay, and finalization RPCs
814
+ -- ============================================================
815
+
816
+ create or replace function "public"."enqueue_facebook_ads_lead_event"("p" jsonb)
817
+ returns jsonb
818
+ language plpgsql
819
+ security definer
820
+ set search_path = ''
821
+ as $$
822
+ declare
823
+ "v_page" "public"."facebook_ads_lead_page"%rowtype;
824
+ "v_form" "public"."facebook_ads_lead_form"%rowtype;
825
+ "v_settings" "public"."settings_facebook_ads"%rowtype;
826
+ "v_form_found" boolean := false;
827
+ "v_form_selected" boolean := false;
828
+ "v_accepted" boolean := false;
829
+ "v_reason" text;
830
+ "v_snapshot" jsonb := '{}'::jsonb;
831
+ "v_event_id" uuid;
832
+ "v_received_count" integer;
833
+ "v_status" text;
834
+ "v_return_reason" text;
835
+ "v_webhook_payload" jsonb := coalesce("p" -> 'webhook_payload', '{}'::jsonb);
836
+ begin
837
+ if jsonb_typeof("p") <> 'object'
838
+ or jsonb_typeof("v_webhook_payload") <> 'object'
839
+ or coalesce("p" ->> 'meta_page_id', '') !~ '^[0-9]+$'
840
+ or coalesce("p" ->> 'meta_leadgen_id', '') !~ '^[0-9]+$'
841
+ or coalesce("p" ->> 'meta_form_id', '') !~ '^[0-9]+$'
842
+ or "p" ->> 'meta_created_at' is null
843
+ then
844
+ raise exception 'Valid Meta Page, lead, Form, created time, and payload are required'
845
+ using errcode = '22023';
846
+ end if;
847
+
848
+ select * into "v_page"
849
+ from "public"."facebook_ads_lead_page"
850
+ where "meta_page_id" = "p" ->> 'meta_page_id';
851
+
852
+ if not found then
853
+ return jsonb_build_object(
854
+ 'event_id', null,
855
+ 'accepted', false,
856
+ 'duplicate', false,
857
+ 'reason', 'page_not_configured'
858
+ );
859
+ end if;
860
+
861
+ select * into "v_settings"
862
+ from "public"."settings_facebook_ads"
863
+ where "company_id" = "v_page"."company_id";
864
+
865
+ select * into "v_form"
866
+ from "public"."facebook_ads_lead_form"
867
+ where "company_id" = "v_page"."company_id"
868
+ and "page_id" = "v_page"."id"
869
+ and "meta_form_id" = "p" ->> 'meta_form_id';
870
+ "v_form_found" := found;
871
+
872
+ if "v_form_found" then
873
+ "v_snapshot" := jsonb_build_object(
874
+ 'form_id', "v_form"."id",
875
+ 'form_name', "v_form"."form_name",
876
+ 'is_enabled', "v_form"."is_enabled",
877
+ 'field_mapping', "v_form"."field_mapping",
878
+ 'sms', jsonb_build_object(
879
+ 'attested', "v_form"."sms_consent_attested",
880
+ 'disclosure', "v_form"."sms_consent_disclosure"
881
+ ),
882
+ 'email', jsonb_build_object(
883
+ 'attested', "v_form"."email_consent_attested",
884
+ 'disclosure', "v_form"."email_consent_disclosure"
885
+ ),
886
+ 'voice', jsonb_build_object(
887
+ 'attested', "v_form"."voice_consent_attested",
888
+ 'disclosure', "v_form"."voice_consent_disclosure"
889
+ )
890
+ );
891
+ end if;
892
+
893
+ "v_form_selected" := "v_page"."form_selection_mode" = 'all'
894
+ or ("v_form_found" and "v_form"."is_enabled");
895
+ "v_accepted" := "v_page"."is_enabled"
896
+ and "v_page"."subscription_status" = 'subscribed'
897
+ and coalesce("v_settings"."lead_sync_enabled", false)
898
+ and "v_settings"."source_id" is not null
899
+ and "v_form_selected";
900
+
901
+ "v_reason" := case
902
+ when not "v_page"."is_enabled"
903
+ and "v_page"."subscription_status" = 'pending'
904
+ then 'page_activation_pending'
905
+ when not "v_page"."is_enabled" then 'page_disabled'
906
+ when "v_page"."subscription_status" <> 'subscribed' then 'page_not_subscribed'
907
+ when not coalesce("v_settings"."lead_sync_enabled", false) then 'lead_sync_disabled'
908
+ when "v_settings"."source_id" is null then 'source_not_configured'
909
+ when not "v_form_selected" then 'form_not_selected'
910
+ else null
911
+ end;
912
+
913
+ insert into "public"."facebook_ads_lead_event" (
914
+ "company_id", "page_id", "meta_page_id", "meta_leadgen_id",
915
+ "meta_form_id", "meta_created_at", "source_id", "webhook_payload",
916
+ "form_configuration_snapshot", "status", "skip_reason"
917
+ ) values (
918
+ "v_page"."company_id",
919
+ "v_page"."id",
920
+ "p" ->> 'meta_page_id',
921
+ "p" ->> 'meta_leadgen_id',
922
+ "p" ->> 'meta_form_id',
923
+ ("p" ->> 'meta_created_at')::timestamp with time zone,
924
+ "v_settings"."source_id",
925
+ "v_webhook_payload",
926
+ "v_snapshot",
927
+ case when "v_accepted" then 'pending' else 'skipped' end,
928
+ "v_reason"
929
+ )
930
+ on conflict ("meta_page_id", "meta_leadgen_id") do update
931
+ set
932
+ "received_count" = "facebook_ads_lead_event"."received_count" + 1,
933
+ "last_received_at" = now()
934
+ returning "id", "received_count", "status", "skip_reason"
935
+ into "v_event_id", "v_received_count", "v_status", "v_return_reason";
936
+
937
+ return jsonb_build_object(
938
+ 'event_id', "v_event_id",
939
+ 'accepted', "v_status" <> 'skipped',
940
+ 'duplicate', "v_received_count" > 1,
941
+ 'reason', "v_return_reason"
942
+ );
943
+ end;
944
+ $$;
945
+
946
+ alter function "public"."enqueue_facebook_ads_lead_event"(jsonb)
947
+ owner to "postgres";
948
+
949
+ create or replace function "public"."claim_facebook_ads_lead_events"(
950
+ "batch_size" integer
951
+ )
952
+ returns setof "public"."facebook_ads_lead_event"
953
+ language sql
954
+ security definer
955
+ set search_path = ''
956
+ as $$
957
+ update "public"."facebook_ads_lead_event"
958
+ set
959
+ "status" = 'processing',
960
+ "attempt_count" = "attempt_count" + 1,
961
+ "last_attempt_at" = now()
962
+ where "id" in (
963
+ select "id"
964
+ from "public"."facebook_ads_lead_event"
965
+ where "status" = 'pending' and "next_attempt_at" <= now()
966
+ order by "next_attempt_at", "created_at"
967
+ limit least(greatest(coalesce("batch_size", 0), 0), 100)
968
+ for update skip locked
969
+ )
970
+ returning *;
971
+ $$;
972
+
973
+ alter function "public"."claim_facebook_ads_lead_events"(integer)
974
+ owner to "postgres";
975
+
976
+ create or replace function "public"."replay_facebook_ads_lead_event"(
977
+ "p_company_id" uuid,
978
+ "p_event_id" uuid
979
+ )
980
+ returns boolean
981
+ language plpgsql
982
+ security definer
983
+ set search_path = ''
984
+ as $$
985
+ declare
986
+ "v_updated" uuid;
987
+ begin
988
+ update "public"."facebook_ads_lead_event" as "event_row"
989
+ set
990
+ "status" = 'pending',
991
+ "skip_reason" = null,
992
+ "attempt_count" = 0,
993
+ "replay_count" = "event_row"."replay_count" + 1,
994
+ "next_attempt_at" = now(),
995
+ "last_attempt_at" = null,
996
+ "processed_at" = null,
997
+ "last_error" = null
998
+ from "public"."settings_facebook_ads" as "settings",
999
+ "public"."facebook_ads_lead_page" as "page"
1000
+ where "event_row"."id" = "p_event_id"
1001
+ and "event_row"."company_id" = "p_company_id"
1002
+ and "event_row"."status" in ('skipped', 'dead')
1003
+ and "event_row"."client_id" is null
1004
+ and "event_row"."page_id" = "page"."id"
1005
+ and "page"."company_id" = "p_company_id"
1006
+ and "page"."is_enabled"
1007
+ and "page"."subscription_status" = 'subscribed'
1008
+ -- Replay must respect the Page's current Form-selection policy. The
1009
+ -- receipt-time form_configuration_snapshot remains untouched below so
1010
+ -- consent evidence cannot be upgraded by later Form edits.
1011
+ and (
1012
+ "page"."form_selection_mode" = 'all'
1013
+ or (
1014
+ "page"."form_selection_mode" = 'selected'
1015
+ and exists (
1016
+ select 1
1017
+ from "public"."facebook_ads_lead_form" as "form"
1018
+ where "form"."company_id" = "p_company_id"
1019
+ and "form"."page_id" = "page"."id"
1020
+ and "form"."meta_form_id" = "event_row"."meta_form_id"
1021
+ and "form"."is_enabled"
1022
+ )
1023
+ )
1024
+ )
1025
+ and "settings"."company_id" = "p_company_id"
1026
+ and "settings"."lead_sync_enabled"
1027
+ and "settings"."source_id" is not null
1028
+ returning "event_row"."id" into "v_updated";
1029
+
1030
+ return "v_updated" is not null;
1031
+ end;
1032
+ $$;
1033
+
1034
+ alter function "public"."replay_facebook_ads_lead_event"(uuid, uuid)
1035
+ owner to "postgres";
1036
+
1037
+ create or replace function "public"."promote_facebook_ads_activation_gap_events"(
1038
+ "p_company_id" uuid,
1039
+ "p_page_id" uuid
1040
+ )
1041
+ returns table ("event_id" uuid)
1042
+ language plpgsql
1043
+ security definer
1044
+ set search_path = ''
1045
+ as $$
1046
+ begin
1047
+ if "p_company_id" is null or "p_page_id" is null then
1048
+ raise exception 'company_id and page_id are required'
1049
+ using errcode = '22023';
1050
+ end if;
1051
+
1052
+ return query
1053
+ update "public"."facebook_ads_lead_event" as "event_row"
1054
+ set
1055
+ "status" = 'pending',
1056
+ "skip_reason" = null,
1057
+ "attempt_count" = 0,
1058
+ "replay_count" = "event_row"."replay_count" + 1,
1059
+ "next_attempt_at" = now(),
1060
+ "last_attempt_at" = null,
1061
+ "processed_at" = null,
1062
+ "last_error" = null
1063
+ from "public"."settings_facebook_ads" as "settings",
1064
+ "public"."facebook_ads_lead_page" as "page"
1065
+ where "event_row"."company_id" = "p_company_id"
1066
+ and "event_row"."page_id" = "p_page_id"
1067
+ and "event_row"."status" = 'skipped'
1068
+ and "event_row"."skip_reason" = 'page_activation_pending'
1069
+ and "event_row"."client_id" is null
1070
+ and "page"."company_id" = "p_company_id"
1071
+ and "page"."id" = "p_page_id"
1072
+ and "page"."is_enabled"
1073
+ and "page"."subscription_status" = 'subscribed'
1074
+ and "settings"."company_id" = "p_company_id"
1075
+ and "settings"."lead_sync_enabled"
1076
+ and "settings"."source_id" is not null
1077
+ and nullif(btrim(
1078
+ "event_row"."form_configuration_snapshot" ->> 'form_id'
1079
+ ), '') is not null
1080
+ and "event_row"."form_configuration_snapshot" -> 'is_enabled'
1081
+ = 'true'::jsonb
1082
+ and exists (
1083
+ select 1
1084
+ from (values ('sms'), ('email'), ('voice')) as "channel_row"("name")
1085
+ where "event_row"."form_configuration_snapshot"
1086
+ -> "channel_row"."name" -> 'attested' = 'true'::jsonb
1087
+ and nullif(btrim(
1088
+ "event_row"."form_configuration_snapshot"
1089
+ -> "channel_row"."name" ->> 'disclosure'
1090
+ ), '') is not null
1091
+ )
1092
+ returning "event_row"."id";
1093
+ end;
1094
+ $$;
1095
+
1096
+ alter function "public"."promote_facebook_ads_activation_gap_events"(uuid, uuid)
1097
+ owner to "postgres";
1098
+
1099
+ create or replace function "public"."finalize_facebook_ads_lead_event"("p" jsonb)
1100
+ returns table (
1101
+ "event_id" uuid,
1102
+ "client_id" uuid,
1103
+ "client_created" boolean,
1104
+ "call_attempt_id" uuid
1105
+ )
1106
+ language plpgsql
1107
+ security definer
1108
+ set search_path = ''
1109
+ as $$
1110
+ declare
1111
+ "v_event" "public"."facebook_ads_lead_event"%rowtype;
1112
+ "v_page" "public"."facebook_ads_lead_page"%rowtype;
1113
+ "v_settings" "public"."settings_facebook_ads"%rowtype;
1114
+ "v_client_id" uuid;
1115
+ "v_call_attempt_id" uuid;
1116
+ "v_voice_consent_id" uuid;
1117
+ "v_inserted_consent_id" uuid;
1118
+ "v_phone" text := nullif(btrim("p" ->> 'primary_phone_number'), '');
1119
+ "v_email" text := nullif(btrim("p" ->> 'email'), '');
1120
+ "v_consents" jsonb := coalesce("p" -> 'consents', '[]'::jsonb);
1121
+ "v_consent" jsonb;
1122
+ "v_channel" text;
1123
+ "v_status" text;
1124
+ "v_disclosure" text;
1125
+ "v_attested" boolean;
1126
+ "v_sms_granted" boolean := false;
1127
+ "v_email_granted" boolean := false;
1128
+ "v_voice_granted" boolean := false;
1129
+ "v_from_phone" text;
1130
+ "v_company_timezone" text;
1131
+ begin
1132
+ if jsonb_typeof("p") <> 'object'
1133
+ or "p" ->> 'event_id' is null
1134
+ or jsonb_typeof(coalesce("p" -> 'lead_payload', '{}'::jsonb)) <> 'object'
1135
+ or jsonb_typeof("v_consents") <> 'array'
1136
+ then
1137
+ raise exception 'event_id, lead payload, and a consent array are required'
1138
+ using errcode = '22023';
1139
+ end if;
1140
+
1141
+ select * into "v_event"
1142
+ from "public"."facebook_ads_lead_event"
1143
+ where "id" = ("p" ->> 'event_id')::uuid
1144
+ for update;
1145
+
1146
+ if not found then
1147
+ raise exception 'Facebook lead event does not exist'
1148
+ using errcode = 'P0002';
1149
+ end if;
1150
+
1151
+ if "v_event"."status" = 'processed' and "v_event"."client_id" is not null then
1152
+ return query select "v_event"."id", "v_event"."client_id", false, (
1153
+ select "id" from "public"."facebook_ads_lead_call_attempt"
1154
+ where "lead_event_id" = "v_event"."id"
1155
+ );
1156
+ return;
1157
+ end if;
1158
+
1159
+ if "v_event"."status" <> 'processing' or "v_event"."client_id" is not null then
1160
+ raise exception 'Facebook lead event is not claimable for finalization'
1161
+ using errcode = '55000';
1162
+ end if;
1163
+
1164
+ select * into "v_settings"
1165
+ from "public"."settings_facebook_ads"
1166
+ where "company_id" = "v_event"."company_id"
1167
+ for share;
1168
+
1169
+ if not found
1170
+ or not "v_settings"."lead_sync_enabled"
1171
+ or "v_settings"."source_id" is null
1172
+ then
1173
+ update "public"."facebook_ads_lead_event"
1174
+ set "status" = 'skipped', "skip_reason" = 'lead_sync_disabled'
1175
+ where "id" = "v_event"."id";
1176
+ return query select "v_event"."id", null::uuid, false, null::uuid;
1177
+ return;
1178
+ end if;
1179
+
1180
+ -- Graph retrieval happens outside this transaction. Re-lock the current
1181
+ -- Page before any client/automation side effect so a disconnect that
1182
+ -- completed in that interval fails closed. Holding the Page row through
1183
+ -- commit also prevents it from being disabled after this check but before
1184
+ -- the client INSERT below.
1185
+ select * into "v_page"
1186
+ from "public"."facebook_ads_lead_page"
1187
+ where "id" = "v_event"."page_id"
1188
+ and "company_id" = "v_event"."company_id"
1189
+ for share;
1190
+
1191
+ if not found or not "v_page"."is_enabled" then
1192
+ update "public"."facebook_ads_lead_event"
1193
+ set "status" = 'skipped', "skip_reason" = 'page_disabled'
1194
+ where "id" = "v_event"."id";
1195
+ return query select "v_event"."id", null::uuid, false, null::uuid;
1196
+ return;
1197
+ end if;
1198
+
1199
+ if "v_page"."subscription_status" <> 'subscribed' then
1200
+ update "public"."facebook_ads_lead_event"
1201
+ set "status" = 'skipped', "skip_reason" = 'page_not_subscribed'
1202
+ where "id" = "v_event"."id";
1203
+ return query select "v_event"."id", null::uuid, false, null::uuid;
1204
+ return;
1205
+ end if;
1206
+
1207
+ if not exists (
1208
+ select 1 from "public"."job_source"
1209
+ where "id" = "v_settings"."source_id"
1210
+ and "company_id" = "v_event"."company_id"
1211
+ ) then
1212
+ raise exception 'Configured Facebook lead source is invalid'
1213
+ using errcode = '23503';
1214
+ end if;
1215
+
1216
+ if nullif(btrim("p" ->> 'first_name'), '') is null
1217
+ and nullif(btrim("p" ->> 'last_name'), '') is null
1218
+ and "v_email" is null
1219
+ and "v_phone" is null
1220
+ then
1221
+ raise exception 'A lead must include at least one contact field'
1222
+ using errcode = '23514';
1223
+ end if;
1224
+
1225
+ if (
1226
+ select count(*) <> count(distinct "consent_row"."value" ->> 'channel')
1227
+ from jsonb_array_elements("v_consents") as "consent_row"("value")
1228
+ ) then
1229
+ raise exception 'Consent channels must be unique'
1230
+ using errcode = '23505';
1231
+ end if;
1232
+
1233
+ -- Normalize consent before inserting the client. This is a critical
1234
+ -- fail-closed invariant: the lead_created automation trigger fires on
1235
+ -- the client INSERT, so its marketing DND flags must already reflect
1236
+ -- explicit channel consent at that exact statement.
1237
+ for "v_consent" in
1238
+ select "consent_row"."value"
1239
+ from jsonb_array_elements("v_consents") as "consent_row"("value")
1240
+ loop
1241
+ "v_channel" := "v_consent" ->> 'channel';
1242
+ "v_status" := "v_consent" ->> 'status';
1243
+
1244
+ if "v_channel" is null
1245
+ or "v_channel" not in ('email', 'sms', 'voice')
1246
+ or "v_status" is null
1247
+ or "v_status" not in ('granted', 'denied', 'unknown')
1248
+ or jsonb_typeof(coalesce("v_consent" -> 'evidence', '{}'::jsonb)) <> 'object'
1249
+ then
1250
+ raise exception 'Consent channel, status, or evidence is invalid'
1251
+ using errcode = '22023';
1252
+ end if;
1253
+
1254
+ "v_attested" := coalesce((
1255
+ "v_event"."form_configuration_snapshot"
1256
+ -> "v_channel" ->> 'attested'
1257
+ )::boolean, false);
1258
+ "v_disclosure" := nullif(btrim(
1259
+ "v_event"."form_configuration_snapshot"
1260
+ -> "v_channel" ->> 'disclosure'
1261
+ ), '');
1262
+
1263
+ if "v_status" = 'granted' and (
1264
+ not "v_attested"
1265
+ or "v_disclosure" is null
1266
+ or "v_consent" ->> 'captured_at' is null
1267
+ ) then
1268
+ raise exception 'Granted consent requires an attested Form disclosure and capture time'
1269
+ using errcode = '23514';
1270
+ end if;
1271
+
1272
+ if "v_status" = 'granted' and "v_channel" = 'sms' then
1273
+ "v_sms_granted" := true;
1274
+ elsif "v_status" = 'granted' and "v_channel" = 'email' then
1275
+ "v_email_granted" := true;
1276
+ elsif "v_status" = 'granted' and "v_channel" = 'voice' then
1277
+ "v_voice_granted" := true;
1278
+ end if;
1279
+ end loop;
1280
+
1281
+ insert into "public"."client" (
1282
+ "company_id", "email", "first_name", "last_name",
1283
+ "client_or_lead", "primary_phone_number", "source_id",
1284
+ "created_via", "is_do_not_marketing_sms",
1285
+ "is_do_not_marketing_email"
1286
+ ) values (
1287
+ "v_event"."company_id",
1288
+ "v_email",
1289
+ nullif(btrim("p" ->> 'first_name'), ''),
1290
+ nullif(btrim("p" ->> 'last_name'), ''),
1291
+ 'lead'::"public"."client_or_lead_enum",
1292
+ "v_phone",
1293
+ "v_settings"."source_id",
1294
+ 'facebook_lead_ads',
1295
+ not "v_sms_granted",
1296
+ not "v_email_granted"
1297
+ ) returning "id" into "v_client_id";
1298
+
1299
+ if "v_phone" is not null then
1300
+ insert into "public"."phone_number" (
1301
+ "company_id", "client_id", "twilio", "phone_number", "label"
1302
+ ) values (
1303
+ "v_event"."company_id", "v_client_id", false, "v_phone", 'Primary'
1304
+ );
1305
+ end if;
1306
+
1307
+ if "v_settings"."lead_tag_id" is not null then
1308
+ if not exists (
1309
+ select 1 from "public"."client_tag"
1310
+ where "id" = "v_settings"."lead_tag_id"
1311
+ and "company_id" = "v_event"."company_id"
1312
+ ) then
1313
+ raise exception 'Configured Facebook lead tag is invalid'
1314
+ using errcode = '23503';
1315
+ end if;
1316
+ insert into "public"."client_tag_link" (
1317
+ "company_id", "client_id", "client_tag_id"
1318
+ ) values (
1319
+ "v_event"."company_id", "v_client_id", "v_settings"."lead_tag_id"
1320
+ );
1321
+ end if;
1322
+
1323
+ for "v_consent" in
1324
+ select "consent_row"."value"
1325
+ from jsonb_array_elements("v_consents") as "consent_row"("value")
1326
+ loop
1327
+ "v_channel" := "v_consent" ->> 'channel';
1328
+ "v_status" := "v_consent" ->> 'status';
1329
+ "v_disclosure" := nullif(btrim(
1330
+ "v_event"."form_configuration_snapshot"
1331
+ -> "v_channel" ->> 'disclosure'
1332
+ ), '');
1333
+
1334
+ insert into "public"."facebook_ads_lead_consent" (
1335
+ "company_id", "lead_event_id", "channel", "status",
1336
+ "captured_at", "disclosure_text", "response_value", "evidence"
1337
+ ) values (
1338
+ "v_event"."company_id",
1339
+ "v_event"."id",
1340
+ "v_channel",
1341
+ "v_status",
1342
+ ("v_consent" ->> 'captured_at')::timestamp with time zone,
1343
+ "v_disclosure",
1344
+ "v_consent" ->> 'response_value',
1345
+ coalesce("v_consent" -> 'evidence', '{}'::jsonb)
1346
+ ) returning "id" into "v_inserted_consent_id";
1347
+
1348
+ if "v_channel" = 'voice' and "v_status" = 'granted' then
1349
+ "v_voice_consent_id" := "v_inserted_consent_id";
1350
+ end if;
1351
+ end loop;
1352
+
1353
+ update "public"."facebook_ads_lead_event"
1354
+ set
1355
+ "source_id" = "v_settings"."source_id",
1356
+ "client_id" = "v_client_id",
1357
+ "lead_payload" = coalesce("p" -> 'lead_payload', '{}'::jsonb),
1358
+ "meta_ad_id" = nullif("p" ->> 'meta_ad_id', ''),
1359
+ "meta_adset_id" = nullif("p" ->> 'meta_adset_id', ''),
1360
+ "meta_campaign_id" = nullif("p" ->> 'meta_campaign_id', ''),
1361
+ "fetched_at" = now(),
1362
+ "processed_at" = now(),
1363
+ "status" = 'processed',
1364
+ "skip_reason" = null,
1365
+ "last_error" = null
1366
+ where "id" = "v_event"."id";
1367
+
1368
+ -- Voice is stricter than record creation: no explicit, attested voice
1369
+ -- grant means no call-attempt row exists for a worker to accidentally
1370
+ -- claim. Settings and current number/user linkage are revalidated here.
1371
+ if "v_voice_granted"
1372
+ and "v_voice_consent_id" is not null
1373
+ and "v_phone" is not null
1374
+ and "v_settings"."lead_auto_dial_enabled"
1375
+ and "v_settings"."lead_auto_dial_phone_number_id" is not null
1376
+ and "v_settings"."lead_auto_dial_user_id" is not null
1377
+ then
1378
+ select "phone"."phone_number", "company"."time_zone"
1379
+ into "v_from_phone", "v_company_timezone"
1380
+ from "public"."phone_number" as "phone"
1381
+ inner join "public"."company" as "company"
1382
+ on "company"."id" = "phone"."company_id"
1383
+ inner join "public"."user" as "user_row"
1384
+ on "user_row"."id" = "v_settings"."lead_auto_dial_user_id"
1385
+ and "user_row"."company_id" = "phone"."company_id"
1386
+ and "user_row"."is_current_employee" = true
1387
+ inner join "public"."phone_number_user_link" as "link"
1388
+ on "link"."company_id" = "phone"."company_id"
1389
+ and "link"."phone_number_id" = "phone"."id"
1390
+ and "link"."user_id" = "user_row"."id"
1391
+ where "phone"."id" = "v_settings"."lead_auto_dial_phone_number_id"
1392
+ and "phone"."company_id" = "v_event"."company_id"
1393
+ and "phone"."twilio" = true
1394
+ and "phone"."client_id" is null
1395
+ and "phone"."phone_sid" is not null;
1396
+
1397
+ if found then
1398
+ insert into "public"."facebook_ads_lead_call_attempt" (
1399
+ "company_id", "lead_event_id", "client_id", "consent_id",
1400
+ "from_phone_number_id", "target_user_id",
1401
+ "from_phone_number", "destination_phone_number",
1402
+ "routing_snapshot", "next_attempt_at"
1403
+ ) values (
1404
+ "v_event"."company_id",
1405
+ "v_event"."id",
1406
+ "v_client_id",
1407
+ "v_voice_consent_id",
1408
+ "v_settings"."lead_auto_dial_phone_number_id",
1409
+ "v_settings"."lead_auto_dial_user_id",
1410
+ "v_from_phone",
1411
+ "v_phone",
1412
+ jsonb_build_object(
1413
+ 'time_zone', "v_company_timezone",
1414
+ 'window_start', "v_settings"."lead_auto_dial_window_start",
1415
+ 'window_end', "v_settings"."lead_auto_dial_window_end",
1416
+ 'window_days', "v_settings"."lead_auto_dial_window_days",
1417
+ 'delay_seconds', "v_settings"."lead_auto_dial_delay_seconds"
1418
+ ),
1419
+ now() + make_interval(
1420
+ secs => "v_settings"."lead_auto_dial_delay_seconds"
1421
+ )
1422
+ ) returning "id" into "v_call_attempt_id";
1423
+ end if;
1424
+ end if;
1425
+
1426
+ return query select "v_event"."id", "v_client_id", true, "v_call_attempt_id";
1427
+ end;
1428
+ $$;
1429
+
1430
+ alter function "public"."finalize_facebook_ads_lead_event"(jsonb)
1431
+ owner to "postgres";
1432
+
1433
+ -- ============================================================
1434
+ -- Call claim and state-transition RPCs
1435
+ -- ============================================================
1436
+
1437
+ create or replace function "public"."claim_facebook_ads_lead_call_attempts"(
1438
+ "batch_size" integer
1439
+ )
1440
+ returns setof "public"."facebook_ads_lead_call_attempt"
1441
+ language sql
1442
+ security definer
1443
+ set search_path = ''
1444
+ as $$
1445
+ update "public"."facebook_ads_lead_call_attempt"
1446
+ set
1447
+ "status" = 'processing',
1448
+ "held_reason" = null,
1449
+ "attempt_count" = "attempt_count" + 1,
1450
+ "last_attempt_at" = now(),
1451
+ "started_at" = coalesce("started_at", now())
1452
+ where "id" in (
1453
+ select "id"
1454
+ from "public"."facebook_ads_lead_call_attempt"
1455
+ where "status" = 'pending' and "next_attempt_at" <= now()
1456
+ order by "next_attempt_at", "created_at"
1457
+ limit least(greatest(coalesce("batch_size", 0), 0), 100)
1458
+ for update skip locked
1459
+ )
1460
+ returning *;
1461
+ $$;
1462
+
1463
+ alter function "public"."claim_facebook_ads_lead_call_attempts"(integer)
1464
+ owner to "postgres";
1465
+
1466
+ create or replace function "public"."update_facebook_ads_lead_call_state"(
1467
+ "p" jsonb
1468
+ )
1469
+ returns boolean
1470
+ language plpgsql
1471
+ security definer
1472
+ set search_path = ''
1473
+ as $$
1474
+ declare
1475
+ "v_company_id" uuid := ("p" ->> 'company_id')::uuid;
1476
+ "v_attempt_id" uuid := ("p" ->> 'attempt_id')::uuid;
1477
+ "v_new_status" text := "p" ->> 'status';
1478
+ "v_expected_status" text := "p" ->> 'expected_status';
1479
+ "v_attempt" "public"."facebook_ads_lead_call_attempt"%rowtype;
1480
+ "v_old_rank" integer;
1481
+ "v_new_rank" integer;
1482
+ "v_terminal" boolean;
1483
+ "v_answered_by" uuid := ("p" ->> 'answered_by_user_id')::uuid;
1484
+ "v_next_attempt_at" timestamp with time zone :=
1485
+ ("p" ->> 'next_attempt_at')::timestamp with time zone;
1486
+ "v_expected_updated_at" timestamp with time zone :=
1487
+ ("p" ->> 'expected_updated_at')::timestamp with time zone;
1488
+ "v_is_retry_hold" boolean;
1489
+ begin
1490
+ if jsonb_typeof("p") <> 'object'
1491
+ or "v_company_id" is null
1492
+ or "v_attempt_id" is null
1493
+ or "v_new_status" is null
1494
+ or ("p" ? 'next_attempt_at' and "v_next_attempt_at" is null)
1495
+ or (
1496
+ "p" ? 'expected_updated_at'
1497
+ and "v_expected_updated_at" is null
1498
+ )
1499
+ or (
1500
+ "p" ? 'expected_status'
1501
+ and (
1502
+ "v_expected_status" is null
1503
+ or "v_expected_status" not in (
1504
+ 'pending', 'processing', 'agent_ringing', 'lead_ringing',
1505
+ 'connected', 'completed', 'skipped', 'failed', 'dead'
1506
+ )
1507
+ )
1508
+ )
1509
+ or "v_new_status" not in (
1510
+ 'pending', 'processing', 'agent_ringing', 'lead_ringing',
1511
+ 'connected', 'completed', 'skipped', 'failed', 'dead'
1512
+ )
1513
+ then
1514
+ raise exception 'Valid company, attempt, and call status are required'
1515
+ using errcode = '22023';
1516
+ end if;
1517
+
1518
+ select * into "v_attempt"
1519
+ from "public"."facebook_ads_lead_call_attempt"
1520
+ where "id" = "v_attempt_id" and "company_id" = "v_company_id"
1521
+ for update;
1522
+
1523
+ if not found then
1524
+ return false;
1525
+ end if;
1526
+
1527
+ -- Optional compare-and-set guards let sweepers inspect provider state,
1528
+ -- then safely dead-letter only if no callback advanced the row while the
1529
+ -- provider request was in flight. Existing callers can omit both keys.
1530
+ if ("p" ? 'expected_status'
1531
+ and "v_attempt"."status" <> "v_expected_status")
1532
+ or ("p" ? 'expected_updated_at'
1533
+ and "v_attempt"."updated_at" is distinct from "v_expected_updated_at")
1534
+ then
1535
+ return false;
1536
+ end if;
1537
+
1538
+ "v_terminal" := "v_attempt"."status" in (
1539
+ 'completed', 'skipped', 'failed', 'dead'
1540
+ );
1541
+ "v_old_rank" := case "v_attempt"."status"
1542
+ when 'pending' then 0
1543
+ when 'processing' then 1
1544
+ when 'agent_ringing' then 2
1545
+ when 'lead_ringing' then 3
1546
+ when 'connected' then 4
1547
+ else 5
1548
+ end;
1549
+ "v_new_rank" := case "v_new_status"
1550
+ when 'pending' then 0
1551
+ when 'processing' then 1
1552
+ when 'agent_ringing' then 2
1553
+ when 'lead_ringing' then 3
1554
+ when 'connected' then 4
1555
+ else 5
1556
+ end;
1557
+ -- A hold is the sole permitted backward transition. Before provider work
1558
+ -- it releases a processing claim; after the agent answers it lets a
1559
+ -- transient entitlement/configuration check defer safely once the web
1560
+ -- worker has ended the current conference. CAS guards remain available so
1561
+ -- a concurrent callback always wins.
1562
+ "v_is_retry_hold" := "v_attempt"."status" in ('processing', 'agent_ringing')
1563
+ and "v_new_status" = 'pending'
1564
+ and "v_next_attempt_at" is not null
1565
+ and "v_next_attempt_at" > now()
1566
+ and nullif(btrim("p" ->> 'held_reason'), '') is not null;
1567
+
1568
+ if ("v_terminal" and "v_new_status" <> "v_attempt"."status")
1569
+ or (
1570
+ not "v_terminal"
1571
+ and "v_new_rank" < "v_old_rank"
1572
+ and not "v_is_retry_hold"
1573
+ )
1574
+ then
1575
+ raise exception 'Call state cannot transition backward or leave a terminal state'
1576
+ using errcode = '23514';
1577
+ end if;
1578
+
1579
+ if "v_answered_by" is not null and not exists (
1580
+ select 1 from "public"."user"
1581
+ where "id" = "v_answered_by" and "company_id" = "v_company_id"
1582
+ ) then
1583
+ raise exception 'Answered-by user does not belong to this company'
1584
+ using errcode = '23503';
1585
+ end if;
1586
+
1587
+ update "public"."facebook_ads_lead_call_attempt"
1588
+ set
1589
+ "status" = "v_new_status",
1590
+ "held_reason" = case
1591
+ when "p" ? 'held_reason' then "p" ->> 'held_reason'
1592
+ when "v_new_status" <> 'pending' then null
1593
+ else "v_attempt"."held_reason" end,
1594
+ "next_attempt_at" = case
1595
+ when "p" ? 'next_attempt_at' then "v_next_attempt_at"
1596
+ else "v_attempt"."next_attempt_at" end,
1597
+ "twilio_agent_call_sid" = case
1598
+ when "p" ? 'twilio_agent_call_sid'
1599
+ then nullif("p" ->> 'twilio_agent_call_sid', '')
1600
+ else "v_attempt"."twilio_agent_call_sid" end,
1601
+ "twilio_lead_call_sid" = case
1602
+ when "p" ? 'twilio_lead_call_sid'
1603
+ then nullif("p" ->> 'twilio_lead_call_sid', '')
1604
+ else "v_attempt"."twilio_lead_call_sid" end,
1605
+ "twilio_conference_sid" = case
1606
+ when "p" ? 'twilio_conference_sid'
1607
+ then nullif("p" ->> 'twilio_conference_sid', '')
1608
+ else "v_attempt"."twilio_conference_sid" end,
1609
+ "answered_by_user_id" = case
1610
+ when "p" ? 'answered_by_user_id' then "v_answered_by"
1611
+ else "v_attempt"."answered_by_user_id" end,
1612
+ "started_at" = case
1613
+ when "p" ? 'started_at'
1614
+ then ("p" ->> 'started_at')::timestamp with time zone
1615
+ else "v_attempt"."started_at" end,
1616
+ "connected_at" = case
1617
+ when "p" ? 'connected_at'
1618
+ then ("p" ->> 'connected_at')::timestamp with time zone
1619
+ when "v_new_status" = 'connected'
1620
+ then coalesce("v_attempt"."connected_at", now())
1621
+ else "v_attempt"."connected_at" end,
1622
+ "completed_at" = case
1623
+ when "p" ? 'completed_at'
1624
+ then ("p" ->> 'completed_at')::timestamp with time zone
1625
+ when "v_new_status" in ('completed', 'skipped', 'failed', 'dead')
1626
+ then coalesce("v_attempt"."completed_at", now())
1627
+ else "v_attempt"."completed_at" end,
1628
+ "skip_reason" = case
1629
+ when "p" ? 'skip_reason' then "p" ->> 'skip_reason'
1630
+ else "v_attempt"."skip_reason" end,
1631
+ "last_error" = case
1632
+ when "p" ? 'last_error' then "p" ->> 'last_error'
1633
+ else "v_attempt"."last_error" end
1634
+ where "id" = "v_attempt_id";
1635
+
1636
+ return true;
1637
+ end;
1638
+ $$;
1639
+
1640
+ alter function "public"."update_facebook_ads_lead_call_state"(jsonb)
1641
+ owner to "postgres";
1642
+
1643
+ -- ============================================================
1644
+ -- Function permissions (tables are handled in the RLS migration)
1645
+ -- ============================================================
1646
+
1647
+ revoke all on function "public"."facebook_ads_text_array_is_normalized"(text[])
1648
+ from public;
1649
+ revoke all on function "public"."facebook_ads_text_array_is_normalized"(text[])
1650
+ from "anon";
1651
+ revoke all on function "public"."facebook_ads_text_array_is_normalized"(text[])
1652
+ from "authenticated";
1653
+ grant execute on function "public"."facebook_ads_text_array_is_normalized"(text[])
1654
+ to "service_role";
1655
+
1656
+ revoke all on function "public"."facebook_ads_call_days_are_normalized"(smallint[])
1657
+ from public;
1658
+ revoke all on function "public"."facebook_ads_call_days_are_normalized"(smallint[])
1659
+ from "anon";
1660
+ revoke all on function "public"."facebook_ads_call_days_are_normalized"(smallint[])
1661
+ from "authenticated";
1662
+ grant execute on function "public"."facebook_ads_call_days_are_normalized"(smallint[])
1663
+ to "service_role";
1664
+
1665
+ revoke all on function "public"."set_facebook_ads_lead_settings"(jsonb) from public;
1666
+ revoke all on function "public"."set_facebook_ads_lead_settings"(jsonb) from "anon";
1667
+ revoke all on function "public"."set_facebook_ads_lead_settings"(jsonb) from "authenticated";
1668
+ grant execute on function "public"."set_facebook_ads_lead_settings"(jsonb) to "service_role";
1669
+
1670
+ revoke all on function "public"."enqueue_facebook_ads_lead_event"(jsonb) from public;
1671
+ revoke all on function "public"."enqueue_facebook_ads_lead_event"(jsonb) from "anon";
1672
+ revoke all on function "public"."enqueue_facebook_ads_lead_event"(jsonb) from "authenticated";
1673
+ grant execute on function "public"."enqueue_facebook_ads_lead_event"(jsonb) to "service_role";
1674
+
1675
+ revoke all on function "public"."claim_facebook_ads_lead_events"(integer) from public;
1676
+ revoke all on function "public"."claim_facebook_ads_lead_events"(integer) from "anon";
1677
+ revoke all on function "public"."claim_facebook_ads_lead_events"(integer) from "authenticated";
1678
+ grant execute on function "public"."claim_facebook_ads_lead_events"(integer) to "service_role";
1679
+
1680
+ revoke all on function "public"."replay_facebook_ads_lead_event"(uuid, uuid) from public;
1681
+ revoke all on function "public"."replay_facebook_ads_lead_event"(uuid, uuid) from "anon";
1682
+ revoke all on function "public"."replay_facebook_ads_lead_event"(uuid, uuid) from "authenticated";
1683
+ grant execute on function "public"."replay_facebook_ads_lead_event"(uuid, uuid) to "service_role";
1684
+
1685
+ revoke all on function "public"."promote_facebook_ads_activation_gap_events"(uuid, uuid) from public;
1686
+ revoke all on function "public"."promote_facebook_ads_activation_gap_events"(uuid, uuid) from "anon";
1687
+ revoke all on function "public"."promote_facebook_ads_activation_gap_events"(uuid, uuid) from "authenticated";
1688
+ grant execute on function "public"."promote_facebook_ads_activation_gap_events"(uuid, uuid) to "service_role";
1689
+
1690
+ revoke all on function "public"."finalize_facebook_ads_lead_event"(jsonb) from public;
1691
+ revoke all on function "public"."finalize_facebook_ads_lead_event"(jsonb) from "anon";
1692
+ revoke all on function "public"."finalize_facebook_ads_lead_event"(jsonb) from "authenticated";
1693
+ grant execute on function "public"."finalize_facebook_ads_lead_event"(jsonb) to "service_role";
1694
+
1695
+ revoke all on function "public"."claim_facebook_ads_lead_call_attempts"(integer)
1696
+ from public;
1697
+ revoke all on function "public"."claim_facebook_ads_lead_call_attempts"(integer)
1698
+ from "anon";
1699
+ revoke all on function "public"."claim_facebook_ads_lead_call_attempts"(integer)
1700
+ from "authenticated";
1701
+ grant execute on function "public"."claim_facebook_ads_lead_call_attempts"(integer)
1702
+ to "service_role";
1703
+
1704
+ revoke all on function "public"."update_facebook_ads_lead_call_state"(jsonb)
1705
+ from public;
1706
+ revoke all on function "public"."update_facebook_ads_lead_call_state"(jsonb)
1707
+ from "anon";
1708
+ revoke all on function "public"."update_facebook_ads_lead_call_state"(jsonb)
1709
+ from "authenticated";
1710
+ grant execute on function "public"."update_facebook_ads_lead_call_state"(jsonb)
1711
+ to "service_role";