Restructure omni services and add Chatwoot research snapshot

This commit is contained in:
Ruslan Bakiev
2026-02-21 11:11:27 +07:00
parent edea7a0034
commit b73babbbf6
7732 changed files with 978203 additions and 32 deletions

View File

@@ -0,0 +1,27 @@
json.settings resource.settings
json.created_at resource.created_at
if resource.custom_attributes.present?
json.custom_attributes do
json.plan_name resource.custom_attributes['plan_name']
json.subscribed_quantity resource.custom_attributes['subscribed_quantity']
json.subscription_status resource.custom_attributes['subscription_status']
json.subscription_ends_on resource.custom_attributes['subscription_ends_on']
json.industry resource.custom_attributes['industry'] if resource.custom_attributes['industry'].present?
json.company_size resource.custom_attributes['company_size'] if resource.custom_attributes['company_size'].present?
json.timezone resource.custom_attributes['timezone'] if resource.custom_attributes['timezone'].present?
json.logo resource.custom_attributes['logo'] if resource.custom_attributes['logo'].present?
json.onboarding_step resource.custom_attributes['onboarding_step'] if resource.custom_attributes['onboarding_step'].present?
json.marked_for_deletion_at resource.custom_attributes['marked_for_deletion_at'] if resource.custom_attributes['marked_for_deletion_at'].present?
if resource.custom_attributes['marked_for_deletion_reason'].present?
json.marked_for_deletion_reason resource.custom_attributes['marked_for_deletion_reason']
end
end
end
json.domain @account.domain
json.features @account.enabled_features
json.id @account.id
json.locale @account.locale
json.name @account.name
json.support_email @account.support_email
json.status @account.status
json.cache_keys @account.cache_keys

View File

@@ -0,0 +1,14 @@
json.id resource.id
# could be nil for a deleted agent hence the safe operator before account id
json.account_id Current.account&.id
json.availability_status resource.availability_status
json.auto_offline resource.auto_offline
json.confirmed resource.confirmed?
json.email resource.email
json.provider resource.provider
json.available_name resource.available_name
json.custom_attributes resource.custom_attributes if resource.custom_attributes.present?
json.name resource.name
json.role resource.role
json.thumbnail resource.avatar_url
json.custom_role_id resource.current_account_user&.custom_role_id if ChatwootApp.enterprise?

View File

@@ -0,0 +1,10 @@
json.id resource.id
json.name resource.name
json.description resource.description
json.thumbnail resource.avatar_url
json.outgoing_url resource.outgoing_url unless resource.system_bot?
json.bot_type resource.bot_type
json.bot_config resource.bot_config
json.account_id resource.account_id
json.access_token resource.access_token if resource.access_token.present?
json.system_bot resource.system_bot?

View File

@@ -0,0 +1,6 @@
json.id resource.id
json.name resource.name
json.description resource.description
json.thumbnail resource.avatar_url
json.outgoing_url resource.outgoing_url unless resource.system_bot?
json.bot_type resource.bot_type

View File

@@ -0,0 +1,17 @@
json.id resource.id
json.name resource.name
json.description resource.description
json.short_description resource.short_description.presence
json.enabled resource.enabled?(@current_account)
if Current.account_user&.administrator?
json.call(resource.params, *resource.params.keys)
json.action resource.action
json.button resource.action
end
json.hooks do
json.array! @current_account.hooks.where(app_id: resource.id) do |hook|
json.partial! 'api/v1/models/hook', formats: [:json], resource: hook
end
end

View File

@@ -0,0 +1,23 @@
json.id resource.display_id
json.title resource.title
json.description resource.description
json.account_id resource.account_id
json.inbox do
json.partial! 'api/v1/models/inbox', formats: [:json], resource: resource.inbox
end
json.sender do
json.partial! 'api/v1/models/agent', formats: [:json], resource: resource.sender if resource.sender.present?
end
json.message resource.message
json.template_params resource.template_params
json.campaign_status resource.campaign_status
json.enabled resource.enabled
json.campaign_type resource.campaign_type
if resource.campaign_type == 'one_off'
json.scheduled_at resource.scheduled_at.to_i
json.audience resource.audience
end
json.trigger_rules resource.trigger_rules
json.trigger_only_during_business_hours resource.trigger_only_during_business_hours
json.created_at resource.created_at
json.updated_at resource.updated_at

View File

@@ -0,0 +1,20 @@
json.additional_attributes resource.additional_attributes
json.availability_status resource.availability_status
json.email resource.email
json.id resource.id
json.name resource.name
json.phone_number resource.phone_number
json.blocked resource.blocked
json.identifier resource.identifier
json.thumbnail resource.avatar_url
json.custom_attributes resource.custom_attributes
json.last_activity_at resource.last_activity_at.to_i if resource[:last_activity_at].present?
json.created_at resource.created_at.to_i if resource[:created_at].present?
# we only want to output contact inbox when its /contacts endpoints
if defined?(with_contact_inboxes) && with_contact_inboxes.present?
json.contact_inboxes do
json.array! resource.contact_inboxes do |contact_inbox|
json.partial! 'api/v1/models/contact_inbox', formats: [:json], resource: contact_inbox
end
end
end

View File

@@ -0,0 +1,4 @@
json.source_id resource.source_id
json.inbox do
json.partial! 'api/v1/models/inbox_slim', formats: [:json], resource: resource.inbox
end

View File

@@ -0,0 +1,24 @@
# This file is used to render conversation data search API response.
json.id conversation.display_id
json.uuid conversation.uuid
json.created_at conversation.created_at.to_i
json.contact do
json.id conversation.contact.id
json.name conversation.contact.name
end
json.inbox do
json.id conversation.inbox.id
json.name conversation.inbox.name
json.channel_type conversation.inbox.channel_type
end
json.messages do
json.array! conversation.messages do |message|
json.content message.content
json.id message.id
json.sender_name message.sender.name if message.sender
json.message_type message.message_type_before_type_cast
json.created_at message.created_at.to_i
end
end
json.account_id conversation.account_id

View File

@@ -0,0 +1,25 @@
json.id resource.id
json.rating resource.rating
json.feedback_message resource.feedback_message
json.csat_review_notes resource.csat_review_notes
json.review_notes_updated_at resource.review_notes_updated_at&.to_i
if resource.review_notes_updated_by
json.review_notes_updated_by do
json.id resource.review_notes_updated_by.id
json.name resource.review_notes_updated_by.name
end
end
json.account_id resource.account_id
json.message_id resource.message_id
if resource.contact
json.contact do
json.partial! 'api/v1/models/contact', formats: [:json], resource: resource.contact
end
end
json.conversation_id resource.conversation.display_id
if resource.assigned_agent
json.assigned_agent do
json.partial! 'api/v1/models/agent', formats: [:json], resource: resource.assigned_agent
end
end
json.created_at resource.created_at.to_i

View File

@@ -0,0 +1,12 @@
json.id resource.id
json.attribute_display_name resource.attribute_display_name
json.attribute_display_type resource.attribute_display_type
json.attribute_description resource.attribute_description
json.attribute_key resource.attribute_key
json.regex_pattern resource.regex_pattern
json.regex_cue resource.regex_cue
json.attribute_values resource.attribute_values
json.attribute_model resource.attribute_model
json.default_value resource.default_value
json.created_at resource.created_at
json.updated_at resource.updated_at

View File

@@ -0,0 +1,6 @@
json.id resource.id
json.name resource.name
json.filter_type resource.filter_type
json.query resource.query
json.created_at resource.created_at
json.updated_at resource.updated_at

View File

@@ -0,0 +1,4 @@
json.id resource.id
json.title resource.title
json.content resource.content
json.created_at resource.created_at

View File

@@ -0,0 +1,9 @@
json.id resource.id
json.app_id resource.app_id
json.status resource.enabled?
json.inbox resource.inbox&.slice(:id, :name)
json.account_id resource.account_id
json.hook_type resource.hook_type
json.settings resource.settings if Current.account_user&.administrator?
json.reference_id resource.reference_id if Current.account_user&.administrator?

View File

@@ -0,0 +1,137 @@
json.id resource.id
json.avatar_url resource.try(:avatar_url)
json.channel_id resource.channel_id
json.name resource.name
json.channel_type resource.channel_type
json.greeting_enabled resource.greeting_enabled
json.greeting_message resource.greeting_message
json.working_hours_enabled resource.working_hours_enabled
json.enable_email_collect resource.enable_email_collect
json.csat_survey_enabled resource.csat_survey_enabled
json.csat_config resource.csat_config
json.enable_auto_assignment resource.enable_auto_assignment
json.auto_assignment_config resource.auto_assignment_config
json.out_of_office_message resource.out_of_office_message
json.working_hours resource.weekly_schedule
json.timezone resource.timezone
json.callback_webhook_url resource.callback_webhook_url
json.allow_messages_after_resolved resource.allow_messages_after_resolved
json.lock_to_single_conversation resource.lock_to_single_conversation
json.sender_name_type resource.sender_name_type
json.business_name resource.business_name
if resource.portal.present?
json.help_center do
json.name resource.portal.name
json.slug resource.portal.slug
end
end
## Channel specific settings
## TODO : Clean up and move the attributes into channel sub section
json.tweets_enabled resource.channel.try(:tweets_enabled) if resource.twitter?
## WebWidget Attributes
json.allowed_domains resource.channel.try(:allowed_domains)
json.widget_color resource.channel.try(:widget_color)
json.website_url resource.channel.try(:website_url)
json.hmac_mandatory resource.channel.try(:hmac_mandatory)
json.welcome_title resource.channel.try(:welcome_title)
json.welcome_tagline resource.channel.try(:welcome_tagline)
json.web_widget_script resource.channel.try(:web_widget_script)
json.website_token resource.channel.try(:website_token)
json.selected_feature_flags resource.channel.try(:selected_feature_flags)
json.reply_time resource.channel.try(:reply_time)
if resource.web_widget?
json.hmac_token resource.channel.try(:hmac_token) if Current.account_user&.administrator?
json.pre_chat_form_enabled resource.channel.try(:pre_chat_form_enabled)
json.pre_chat_form_options resource.channel.try(:pre_chat_form_options)
json.continuity_via_email resource.channel.try(:continuity_via_email)
end
## Facebook Attributes
if resource.facebook?
json.page_id resource.channel.try(:page_id)
json.reauthorization_required resource.channel.try(:reauthorization_required?)
end
## Instagram Attributes
json.reauthorization_required resource.channel.try(:reauthorization_required?) if resource.instagram?
json.instagram_id resource.channel.try(:instagram_id) if resource.instagram?
## Tiktok Attributes
json.reauthorization_required resource.channel.try(:reauthorization_required?) if resource.tiktok?
## Twilio Attributes
json.messaging_service_sid resource.channel.try(:messaging_service_sid)
json.phone_number resource.channel.try(:phone_number)
json.medium resource.channel.try(:medium) if resource.twilio?
if resource.twilio?
json.content_templates resource.channel.try(:content_templates)
if Current.account_user&.administrator?
json.auth_token resource.channel.try(:auth_token)
json.account_sid resource.channel.try(:account_sid)
end
end
if resource.email?
## Email Channel Attributes
json.email resource.channel.try(:email)
json.forwarding_enabled ENV.fetch('MAILER_INBOUND_EMAIL_DOMAIN', '').present?
json.forward_to_email resource.channel.try(:forward_to_email) if ENV.fetch('MAILER_INBOUND_EMAIL_DOMAIN', '').present?
## IMAP
if Current.account_user&.administrator?
json.imap_login resource.channel.try(:imap_login)
json.imap_password resource.channel.try(:imap_password)
json.imap_address resource.channel.try(:imap_address)
json.imap_port resource.channel.try(:imap_port)
json.imap_enabled resource.channel.try(:imap_enabled)
json.imap_enable_ssl resource.channel.try(:imap_enable_ssl)
if resource.channel.try(:microsoft?) || resource.channel.try(:google?) || resource.channel.try(:legacy_google?)
json.reauthorization_required resource.channel.try(:provider_config).empty? || resource.channel.try(:reauthorization_required?)
end
end
## SMTP
if Current.account_user&.administrator?
json.smtp_login resource.channel.try(:smtp_login)
json.smtp_password resource.channel.try(:smtp_password)
json.smtp_address resource.channel.try(:smtp_address)
json.smtp_port resource.channel.try(:smtp_port)
json.smtp_enabled resource.channel.try(:smtp_enabled)
json.smtp_domain resource.channel.try(:smtp_domain)
json.smtp_enable_ssl_tls resource.channel.try(:smtp_enable_ssl_tls)
json.smtp_enable_starttls_auto resource.channel.try(:smtp_enable_starttls_auto)
json.smtp_openssl_verify_mode resource.channel.try(:smtp_openssl_verify_mode)
json.smtp_authentication resource.channel.try(:smtp_authentication)
end
end
## API Channel Attributes
if resource.api?
json.hmac_token resource.channel.try(:hmac_token) if Current.account_user&.administrator?
json.webhook_url resource.channel.try(:webhook_url)
json.inbox_identifier resource.channel.try(:identifier)
json.additional_attributes resource.channel.try(:additional_attributes)
end
json.provider resource.channel.try(:provider)
## Telegram Attributes
json.bot_name resource.channel.try(:bot_name) if resource.telegram?
### WhatsApp Channel
if resource.whatsapp?
json.message_templates resource.channel.try(:message_templates)
json.provider_config resource.channel.try(:provider_config) if Current.account_user&.administrator?
json.reauthorization_required resource.channel.try(:reauthorization_required?)
end
## Voice Channel Attributes
if resource.channel_type == 'Channel::Voice'
json.voice_call_webhook_url resource.channel.try(:voice_call_webhook_url)
json.voice_status_webhook_url resource.channel.try(:voice_status_webhook_url)
end

View File

@@ -0,0 +1,6 @@
json.id resource.id
json.avatar_url resource.try(:avatar_url)
json.channel_id resource.channel_id
json.name resource.name
json.channel_type resource.channel_type
json.provider resource.channel.try(:provider)

View File

@@ -0,0 +1,19 @@
json.id macro.id
json.name macro.name
json.visibility macro.visibility
if macro.created_by.present?
json.created_by do
json.partial! 'api/v1/models/agent', formats: [:json], resource: macro.created_by
end
end
if macro.updated_by.present?
json.updated_by do
json.partial! 'api/v1/models/agent', formats: [:json], resource: macro.updated_by
end
end
json.account_id macro.account_id
json.actions macro.actions
json.files macro.file_base_data if macro.files.any?

View File

@@ -0,0 +1,14 @@
json.id message.id
json.content message.content
json.inbox_id message.inbox_id
json.echo_id message.echo_id if message.echo_id
json.conversation_id message.conversation.display_id
json.message_type message.message_type_before_type_cast
json.content_type message.content_type
json.status message.status
json.content_attributes message.content_attributes
json.created_at message.created_at.to_i
json.private message.private
json.source_id message.source_id
json.sender message.sender.push_event_data if message.sender
json.attachments message.attachments.map(&:push_event_data) if message.attachments.present?

View File

@@ -0,0 +1,11 @@
json.id resource.id
json.content resource.content
json.account_id json.account_id
json.contact_id json.contact_id
if resource.user.present?
json.user do
json.partial! 'api/v1/models/agent', formats: [:json], resource: resource.user
end
end
json.created_at resource.created_at.to_i
json.updated_at resource.updated_at.to_i

View File

@@ -0,0 +1,3 @@
json.code locale
json.articles_count portal.articles.search({ locale: locale }).size
json.categories_count portal.categories.search_by_locale(locale).size

View File

@@ -0,0 +1,6 @@
json.id resource.id
json.name resource.name
json.description resource.description
json.allow_auto_assign resource.allow_auto_assign
json.account_id resource.account_id
json.is_member Current.user.teams.include?(resource)

View File

@@ -0,0 +1,35 @@
json.access_token resource.access_token.token
json.account_id resource.active_account_user&.account_id
json.available_name resource.available_name
json.avatar_url resource.avatar_url
json.confirmed resource.confirmed?
json.display_name resource.display_name
json.message_signature resource.message_signature
json.email resource.email
json.hmac_identifier resource.hmac_identifier if GlobalConfig.get('CHATWOOT_INBOX_HMAC_KEY')['CHATWOOT_INBOX_HMAC_KEY'].present?
json.id resource.id
json.inviter_id resource.active_account_user&.inviter_id
json.name resource.name
json.provider resource.provider
json.pubsub_token resource.pubsub_token
json.custom_attributes resource.custom_attributes if resource.custom_attributes.present?
json.role resource.active_account_user&.role
json.ui_settings resource.ui_settings
json.uid resource.uid
json.type resource.type
json.accounts do
json.array! resource.account_users do |account_user|
json.id account_user.account_id
json.name account_user.account.name
json.status account_user.account.status
json.active_at account_user.active_at
json.role account_user.role
json.permissions account_user.permissions
# the actual availability user has configured
json.availability account_user.availability
# availability derived from presence
json.availability_status account_user.availability_status
json.auto_offline account_user.auto_offline
json.partial! 'api/v1/models/account_user', account_user: account_user if ChatwootApp.enterprise?
end
end

View File

@@ -0,0 +1,9 @@
json.id resource.id
json.content resource.content
json.message_type resource.message_type_before_type_cast
json.content_type resource.content_type
json.content_attributes resource.content_attributes
json.created_at resource.created_at.to_i
json.conversation_id resource.conversation.display_id
json.attachments resource.attachments.map(&:push_event_data) if resource.attachments.present?
json.sender resource.sender.push_event_data if resource.sender