* feat(scheduled-messages): add recurring scheduled messages
Implements the recurring scheduled messages feature allowing agents to
configure recurrence rules when scheduling messages, with automatic
creation of subsequent scheduled messages after each send.
Backend:
- RecurringScheduledMessage model with JSONB recurrence_rule validation
- RecurrenceCalculatorService for next occurrence date calculation
- RecurrenceDescriptionService for human-readable rule descriptions
- CreateNextOccurrenceService for auto-creating child ScheduledMessages
- RecurringScheduledMessagesController with CRUD operations
- RecurringScheduledMessagePolicy for authorization
- Modified SendScheduledMessageJob to handle recurrence after send
- Updated due_for_sending scope to exclude resolved conversations
- ActionCable events for real-time updates
- Activity message i18n (en + pt-BR)
Frontend:
- RecurrenceDropdown.vue with contextual shortcut options
- RecurrenceCustomModal.vue for custom recurrence configuration
- RecurringScheduledMessageItem.vue for sidebar display
- Integration into ScheduledMessageModal.vue
- Updated ScheduledMessages.vue with recurrence section and filtering
- Vuex store module for recurring scheduled messages
- API client for CRUD operations
- WebSocket handlers in actionCable.js
- recurrenceHelpers.js utility functions
- i18n keys for en and pt-BR
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): fix creation and edit visibility
- Fix API payload key mismatch (snake_case vs camelCase) in modal submit
- Add status: 'active' to recurring creation payload
- Fix strong params to permit recurrence_rule array fields (week_days)
- Cast string values from strong params to integers for JSONB validation
- Show RecurrenceDropdown when editing (remove isEditing gate)
- Populate recurrenceRule from scheduled message's recurring parent
- Include recurring_scheduled_message_id and recurrence_rule in
scheduled message jbuilder response
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): fix dropdown toggle and locale tag errors
- Use DropdownItem :click prop instead of @click to use the injected
closeMenu from DropdownContainer context (default slot doesn't
expose toggle)
- Normalize locale from pt_BR to pt-BR for Intl.DateTimeFormat
compatibility in RecurringScheduledMessageItem
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(recurring-messages): add separator line and expandable history
- Add border separator between recurring messages section and
pending/draft messages, matching the history section separator
- Replace static 'N enviadas' counter with clickable toggle that
expands to show individual sent/failed child messages with
status badges and formatted timestamps
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(recurring-messages): add click-to-navigate on sent children
Make sent child messages in recurring message history clickable.
Clicking navigates to the actual message in the conversation using
the messageId query param, same pattern as ScheduledMessageItem.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(recurring-messages): allow editing recurring messages
- Add edit button to RecurringScheduledMessageItem (active only)
- Transform recurring message into scheduledMessage-compatible shape
with recurring_scheduled_message_id set, so the modal reuses
the existing update path
- Handle edge case of removing recurrence from a recurring message
(cancels series without trying to update a non-existent standalone)
- Sent history is preserved by the backend update action
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): show recurrence field without date selection
Remove v-if="scheduledDate" gate so the recurrence dropdown is
always visible in the modal. Falls back to today's date for
contextual shortcut labels when no date is selected yet.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): ensure recurrence visible on edit and add pending_scheduled_message to API
- Add pending_scheduled_message to recurring_scheduled_message jbuilder
so REST API data matches WebSocket push_event_data
- Add fallback in openEditRecurringModal to find pending child from
scheduled_messages array when pending_scheduled_message is absent
- Add same fallback in nextSendLabel computed
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(scheduled-messages): add sections for Drafts and Pending messages in the UI
* refactor(scheduled-messages): merge RecurringScheduledMessageItem into ScheduledMessageItem
Consolidate the recurring message card into the existing
ScheduledMessageItem component instead of maintaining a separate
component. The unified component detects recurring messages via
recurrence_rule and conditionally shows:
- Recurrence description header with repeat icon
- Next send time label
- Expandable sent/failed children history with click-to-navigate
- Stop button (replaces delete) with confirmation modal
- Active/completed/cancelled status badges
Delete the now-unused RecurringScheduledMessageItem.vue.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(scheduled-messages): use blue badge for active, keep green for sent
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(scheduled-messages): remove draft and pending sections from UI and update recurrence title
* fix(recurring-messages): use Teleport for recurrence dropdown
Replace DropdownContainer with Teleport-based floating dropdown so
options render outside the modal. Fixes:
- Dropdown no longer enlarges the modal or causes scrolling
- Dropdown closes before Custom modal opens (no overlap)
- Auto-detects available space and opens above/below trigger
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): recalculate next date when recurrence rule changes
When editing a recurring message and changing the recurrence rule,
the pending occurrence date is now validated against the new rule.
If the user-provided date doesn't match (e.g. Thursday removed from
weekly days), the system computes the next valid date using
RecurrenceCalculatorService instead of blindly using the old date.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(scheduled-messages): resolve deprecated onClose and disabled type warnings
- Replace :on-close prop with @close event on woot-modal components
- Cast hasTemplate computed to boolean to fix disabled prop type check
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(scheduled-messages): replace remaining deprecated on-close props
- ScheduledMessages.vue delete confirm modal
- RecurrenceCustomModal.vue modal
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): address review feedback on PR #240
- Fix v-if/v-else bug hiding message list behind resolved warning
- Fix occurrences_sent incrementing on failed sends (skip_increment flag)
- Fix compute_next_valid_date using .min instead of .max
- Fix Vuex delete action to update state on cancel (not remove)
- Use atomic update_counters for occurrences_sent increment
- Add safe Date.iso8601 parsing with rescue in should_complete?
- Add null: false to occurrences_sent migration column
- Fix pt-BR accent: Recorrencia → Recorrências
- Use I18n.with_locale(account.locale) for all activity messages
- Fix N+1 in jbuilder partials (Ruby filtering + eager loading)
- Add interval >= 1 validation to RecurrenceCustomModal isValid
- Validate recurrence_rule presence when status is active
- Add ISO8601 date format validation for end_date
- Add unknown_agent i18n key for fallback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): wrap create/update in transactions, clean pending on deactivation
- Wrap create and update flows in ActiveRecord transactions
- Move attachment purge after save! to prevent data loss on validation failure
- Destroy pending children when status transitions to non-active
- Fixes critical bug where stopping recurrence could leave armed pending messages
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): prevent monthly/yearly day-of-month drift
Store the original intended day in recurrence_rule JSONB as month_day
(for monthly) and year_day/year_month (for yearly). The calculator
now uses these stored values instead of @last_date.day, preventing
drift after short months cap the day (e.g., Jan 31 → Feb 28 → all
subsequent months stuck on 28).
Backend:
- RecurrenceCalculatorService: use rule[:month_day] for monthly and
rule[:year_day]/rule[:year_month] for yearly calculations
- Controller: permit and cast the new integer keys
Frontend:
- recurrenceHelpers: yearly shortcuts include year_day/year_month
- RecurrenceCustomModal: emit month_day for monthly day_of_month
rules and year_day/year_month for yearly rules
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): i18n description services, align due_for_sending scope
Backend:
- RecurrenceDescriptionService: replace hardcoded English with I18n.t()
calls; accept locale parameter and use I18n.with_locale
- RecurringScheduledMessage model: pass account locale to description service
- ScheduledMessage: align due_for_sending? instance method with scope by
checking conversation status (open/pending)
Frontend:
- buildRecurrenceDescription: use t() i18n function instead of manual
isPt locale branching
- Add DESCRIPTION i18n keys to en/conversation.json and pt_BR/conversation.json
- Update RecurrenceDropdown and ScheduledMessageItem callers to pass t
i18n:
- Add recurring_scheduled_messages.description.* keys to en.yml and pt_BR.yml
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): keep pending child when deactivating recurrence
When editing a recurring message to disable recurrence while setting a
future send date, the pending child message is now preserved instead of
being destroyed. This allows a 'final send' without creating new
recurrences (the send job already guards with recurring&.active?).
Backend:
- Add update_pending_on_deactivation: updates pending child's
scheduled_at or creates a final pending occurrence
- Replace destroy_all in update's non-active branch
Frontend:
- activeRecurringMessages now includes non-active recurring messages
that still have a pending child (pending_scheduled_message)
- Stop button hidden for already-cancelled recurring messages
- inactiveRecurringMessages excludes messages with pending children
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): prevent removing recurrence from existing recurring message
Once a scheduled message has recurrence, the 'Does not repeat' option is
hidden from the RecurrenceDropdown when editing. This avoids edge cases
where deactivating recurrence leaves the message in an ambiguous display
state.
- RecurrenceDropdown: add hideNoRepeat prop, filter NO_REPEAT from shortcuts
- ScheduledMessageModal: pass hideNoRepeat when isEditingRecurring
- Revert update_pending_on_deactivation (no longer reachable from UI)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): address CodeRabbit review feedback
- ScheduledMessage#push_event_data: expose recurring_scheduled_message_id
in ActionCable payloads so frontend correctly classifies children
- RecurringScheduledMessagePolicy: add agent_bot? check for parity with
ScheduledMessagePolicy
- RecurrenceCalculatorService: guard against nil/empty week_days
- Factory: bind inbox and account to conversation to prevent cross-account
flakiness in specs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(recurring-messages): update schema to enforce non-null constraint on occurrences_sent
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
## PR#1: Reporting events rollup — model and write path
Reporting queries currently hit the `reporting_events` table directly.
This works, but the table grows linearly with event volume, and
aggregation queries (counts, averages over date ranges) get
progressively slower as accounts age.
This PR introduces a pre-aggregated `reporting_events_rollups` table
that stores daily per-metric, per-dimension (account/agent/inbox)
totals. The write path is intentionally decoupled from the read path —
rollup rows are written inline from the event listener via upsert, and a
backfill service exists to rebuild historical data from raw events.
Nothing reads from this table yet.
The write path activates when an account has a `reporting_timezone` set
(new account setting). The `reporting_events_rollup` feature flag
controls only the future read path, not writes — so rollup data
accumulates silently once timezone is configured. A `MetricRegistry`
maps raw event names to rollup column semantics in one place, keeping
the write and (future) read paths aligned.
### What changed
- Migration for `reporting_events_rollups` with a unique composite index
for upsert
- `ReportingEventsRollup` model
- `reporting_timezone` account setting with IANA timezone validation
- `MetricRegistry` — single source of truth for event-to-metric mappings
- `RollupService` — real-time upsert from event listener
- `BackfillService` — rebuilds rollups for a given account + date from
raw events
- Rake tasks for interactive backfill and timezone setup
- `reporting_events_rollup` feature flag (disabled by default)
### How to test
1. Set a `reporting_timezone` on an account
(`Account.first.update!(reporting_timezone: 'Asia/Kolkata')`)
2. Resolve a conversation or trigger a first response
3. Check `ReportingEventsRollup.where(account_id: ...)` — rows should
appear
4. Run backfill: `bundle exec rake reporting_events_rollup:backfill` and
verify historical data populates
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
# Pull Request Template
## Description
Add account setting and store_accessor for
`captain_force_legacy_auto_resolve`.
Enterprise job now skips LLM evaluation when this flag is true and falls
back to legacy time-based resolution. Add spec to cover the fallback.
## Type of change
We recently rolled out Captain deciding if a conversation is resolved or
not. While it is an improvement for majority of customers, some still
prefer the old way of auto-resolving based on inactivity. This PR adds a
check.
## How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.
legacy_auto_resolve = true
<img width="1282" height="848" alt="CleanShot 2026-03-13 at 19 55 55@2x"
src="https://github.com/user-attachments/assets/dfdcc5d5-6d21-462b-87a6-a5e1b1290a8b"
/>
legacy_auto_resolve = false
<img width="1268" height="864" alt="CleanShot 2026-03-13 at 20 00 50@2x"
src="https://github.com/user-attachments/assets/f4719ec6-922a-4c3b-bc45-7b29eaced565"
/>
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
Add a temporary `captain_disable_auto_resolve` boolean setting on
accounts to prevent Captain from resolving conversations. Guards both
the scheduled resolution job and the assistant's resolve tool.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Adds an account-level setting `keep_pending_on_bot_failure` to control
whether conversations should move from pending to open when agent bot
webhooks fail.
Some users experience occasional message drops and don't want
conversations to automatically reopen due to transient bot failures.
This setting gives accounts control over that behavior. This is a
temporary setting which will be removed in future once a proper fix for
it is done, so it is not added in the UI.
* feat: Adds model for scheduling messages
* feat: Implement scheduled message handling and processing jobs
* feat: Add ScheduledMessagesController and associated specs for managing scheduled messages
* refactor: Simplify scheduled message job specs and improve metadata handling
* feat: Add ScheduledMessagePolicy for managing access to scheduled messages
* feat: Add routes for managing scheduled messages
* feat: Add scheduled message event handling and broadcasting
* feat: Add JSON views for scheduled messages creation, destruction, updating, and indexing
* feat: Update scheduled message status and dispatch update event after message creation
* feat: Ensure scheduled message updates trigger dispatch event
* feat: Add mutation types for managing scheduled messages
* feat: Add additionalAttributes prop to Message component and provider
* feat: Implement scheduled message handling in ActionCable and Vuex store
* feat: Add unit tests for scheduled messages actions and mutations
* feat: implement scheduled messages functionality
- Added support for scheduling messages in the conversation dashboard.
- Introduced new components: ScheduledMessageModal and ScheduledMessages for managing scheduled messages.
- Enhanced ReplyBottomPanel to include scheduling options.
- Updated Base.vue to handle scheduled message styling.
- Integrated Vuex store module for managing scheduled messages state.
- Added necessary translations for scheduled messages in English and Portuguese.
* feat: add pagination to scheduled messages index and update tests accordingly
* chore: update scheduled messages specs for future time validation and response status
* chore: enhance scheduled messages API with pagination and add skeleton loader component
* feat: add create_scheduled_message action to automation rule attributes
* feat: implement create_scheduled_message action and enhance attachment handling
* feat: add scheduled message functionality with UI components and localization
* test: enhance scheduledMessages mutations tests with meta handling and structure
* chore: update label to display file name upon successful upload in AutomationFileInput component
* feat: add initialAttachment prop to ScheduledMessageModal and update ReplyBox to pass attachment
* chore: prepend_mod_with to ScheduledMessagesController for better module handling
* fix: attachment visibility in ScheduledMessageItem component
* chore: enhance ScheduledMessage model with validations and reduce controller load
* refactor: simplify ScheduledMessagesAPI methods by removing unnecessary instance variable
* chore: update event emission for scheduled message creation in ReplyBox and ScheduledMessageModal
* refactor: update status configuration to use label keys
* chore: update date formatting in ScheduledMessageItem component
* refactor: collapse logic to checkOverflow and update related functionality
* chore: add author indication for current user in scheduled messages
* chore: enhance scheduled message metadata with author information and localization
* fix: send message shortcut
* chore: handle errors in scheduled message submission
* chore: update scheduled message modal to use combined date and time input
* chore: refactor scheduled messages handling to remove pagination and update related tests
* fix: ensure scheduled messages update status and dispatch on failure
* fix: update scheduled message due date logic and simplify sending checks
* refactor: rename build_message method for send_message
* fix: update scheduled message creation time and improve test reliability
* chore: ignore unnecessary check
* chore: add scheduled message metadata handling in message builder, add scheduled message factorie and update specs
* refactor: use scheduled message factorie creation in specs
* chore: streamline error handling in scheduled message job and remove dispatch logic
* fix: change scheduled_messages association to destroy dependent records
* refactor: remove unused attributes from scheduled message payload builder
* chore: update scheduled message retrieval to use conversation association
* chore: correct cron format for scheduled messages job
* chore: remove migration for author_type in scheduled_messages
* feat: enhance scheduled messages management with delete confirmation and error handling
* chore: set cron poll interval to 10 seconds for improved scheduling precision
* feat: include additional_attributes in message JSON response
* feat: enhance scheduled message validation and localization support
* chore: update scheduled message display
* Merge branch 'main' into Cayo-Oliveira/CU-86aenh268/Mensagens-agendadas
* feat: add scheduled message indicators and validation for message length
* fix: remove unnecessary condition from line-clamp class binding
* feat: update scheduled messages localization and enhance content validation
* feat: update scheduled messages order, enhance scheduledAt computation, and add message association
* fix: reorder condition for Facebook channel message length computation
* fix: change detection for attachments in scheduled messages
* fix: remove unnecessary colon from close-on-backdrop-click prop in ScheduledMessageModal
* chore: add error handling for scheduled message deletion and update localization for delete failure
* fix: enforce minimum delay of 1 minute for scheduled messages and update validation
* fix: remove unused private property and improve locale formatting for scheduled messages
* fix: adjust positioning of DropdownBody in ReplyBottomPanel and clean up schema foreign keys
* docs: add scheduled messages management APIs and payload definitions
---------
Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
We are expanding Chatwoot’s automation capabilities by
introducing **Conversation Workflows**, a dedicated section in settings
where teams can configure rules that govern how conversations are closed
and what information agents must fill before resolving. This feature
helps teams enforce data consistency, collect structured resolution
information, and ensure downstream reporting is accurate.
Instead of having auto‑resolution buried inside Account Settings, we
introduced a new sidebar item:
- Auto‑resolve conversations (existing behaviour)
- Required attributes on resolution (new)
This groups all conversation‑closing logic into a single place.
#### Required Attributes on Resolve
Admins can now pick which custom conversation attributes must be filled
before an agent can resolve a conversation.
**How it works**
- Admin selects one or more attributes from the list of existing
conversation level custom attributes.
- These selected attributes become mandatory during resolution.
- List all the attributes configured via Required Attributes (Text,
Number, Link, Date, List, Checkbox)
- When an agent clicks Resolve Conversation:
If attributes already have values → the conversation resolves normally.
If attributes are missing → a modal appears prompting the agent to fill
them.
<img width="1554" height="1282" alt="CleanShot 2025-12-10 at 11 42
23@2x"
src="https://github.com/user-attachments/assets/4cd5d6e1-abe8-4999-accd-d4a08913b373"
/>
#### Custom Attributes Integration
On the Custom Attributes page, we will surfaced indicators showing how
each attribute is being used.
Each attribute will show badges such as:
- Resolution → used in the required‑on‑resolve workflow
- Pre‑chat form → already existing
<img width="2390" height="1822" alt="CleanShot 2025-12-10 at 11 43
42@2x"
src="https://github.com/user-attachments/assets/b92a6eb7-7f6c-40e6-bf23-6a5310f2d9c5"
/>
#### Admin Flow
- Navigate to Settings → Conversation Workflows.
- Under Required attributes on resolve, click Add Required Attribute.
- Pick from the dropdown list of conversation attributes.
- Save changes.
Agents will now be prompted automatically whenever they resolve.
<img width="2434" height="872" alt="CleanShot 2025-12-10 at 11 44 42@2x"
src="https://github.com/user-attachments/assets/632fc0e5-767c-4a1c-8cf4-ffe3d058d319"
/>
#### NOTES
- The Required Attributes on Resolve modal should only appear when
values are missing.
- Required attributes must block the resolution action until satisfied.
- Bulk‑resolve actions should follow the same rules — any conversation
missing attributes cannot be bulk‑resolved, rest will be resolved, show
a notification that the resolution cannot be done.
- API resolution does not respect the attributes.
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
fixes: #11834
This pull request introduces TikTok channel integration, enabling users
to connect and manage TikTok business accounts similarly to other
supported social channels. The changes span backend API endpoints,
authentication helpers, webhook handling, configuration, and frontend
components to support TikTok as a first-class channel.
**Key Notes**
* This integration is only compatible with TikTok Business Accounts
* Special permissions are required to access the TikTok [Business
Messaging
API](https://business-api.tiktok.com/portal/docs?id=1832183871604753).
* The Business Messaging API is region-restricted and is currently
unavailable to users in the EU.
* Only TEXT, IMAGE, and POST_SHARE messages are currently supported due
to limitations in the TikTok Business Messaging API
* A message will be successfully sent only if it contains text alone or
one image attachment. Messages with multiple attachments or those
combining text and attachments will fail and receive a descriptive error
status.
* Messages sent directly from the TikTok App will be synced into the
system
* Initiating a new conversation from the system is not permitted due to
limitations from the TikTok Business Messaging API.
**Backend: TikTok Channel Integration**
* Added `Api::V1::Accounts::Tiktok::AuthorizationsController` to handle
TikTok OAuth authorization initiation, returning the TikTok
authorization URL.
* Implemented `Tiktok::CallbacksController` to handle TikTok OAuth
callback, process authorization results, create or update channel/inbox,
and handle errors or denied scopes.
* Added `Webhooks::TiktokController` to receive and verify TikTok
webhook events, including signature verification and event dispatching.
* Created `Tiktok::IntegrationHelper` module for JWT-based token
generation and verification for secure TikTok OAuth state management.
**Configuration and Feature Flags**
* Added TikTok app credentials (`TIKTOK_APP_ID`, `TIKTOK_APP_SECRET`) to
allowed configs and app config, and registered TikTok as a feature in
the super admin features YAML.
[[1]](diffhunk://#diff-5e46e1d248631a1147521477d84a54f8ba6846ea21c61eca5f70042d960467f4R43)
[[2]](diffhunk://#diff-8bf37a019cab1dedea458c437bd93e34af1d6e22b1672b1d43ef6eaa4dcb7732R69)
[[3]](diffhunk://#diff-123164bea29f3c096b0d018702b090d5ae670760c729141bd4169a36f5f5c1caR74-R79)
**Frontend: TikTok Channel UI and Messaging Support**
* Added `TiktokChannel` API client for frontend TikTok authorization
requests.
* Updated channel icon mappings and tests to include TikTok
(`Channel::Tiktok`).
[[1]](diffhunk://#diff-b852739ed45def61218d581d0de1ba73f213f55570aa5eec52aaa08f380d0e16R16)
[[2]](diffhunk://#diff-3cd3ae32e94ef85f1f2c4435abf0775cc0614fb37ee25d97945cd51573ef199eR64-R69)
* Enabled TikTok as a supported channel in contact forms, channel
widgets, and feature toggles.
[[1]](diffhunk://#diff-ec59c85e1403aaed1a7de35971fe16b7033d5cd763be590903ebf8f1ca25a010R47)
[[2]](diffhunk://#diff-ec59c85e1403aaed1a7de35971fe16b7033d5cd763be590903ebf8f1ca25a010R69)
[[3]](diffhunk://#diff-725b90ca7e3a6837ec8291e9f57094f6a46b3ee00e598d16564f77f32cf354b0R26-R29)
[[4]](diffhunk://#diff-725b90ca7e3a6837ec8291e9f57094f6a46b3ee00e598d16564f77f32cf354b0R51-R54)
[[5]](diffhunk://#diff-725b90ca7e3a6837ec8291e9f57094f6a46b3ee00e598d16564f77f32cf354b0R68)
* Updated message meta logic to support TikTok-specific message statuses
(sent, delivered, read).
[[1]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696R23)
[[2]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696L63-R65)
[[3]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696L81-R84)
[[4]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696L103-R107)
* Added support for embedded message attachments (e.g., TikTok embeds)
with a new `EmbedBubble` component and updated message rendering logic.
[[1]](diffhunk://#diff-c3d701caf27d9c31e200c6143c11a11b9d8826f78aa2ce5aa107470e6fdb9d7fR31)
[[2]](diffhunk://#diff-047859f9368a46d6d20177df7d6d623768488ecc38a5b1e284f958fad49add68R1-R19)
[[3]](diffhunk://#diff-c3d701caf27d9c31e200c6143c11a11b9d8826f78aa2ce5aa107470e6fdb9d7fR316)
[[4]](diffhunk://#diff-cbc85e7c4c8d56f2a847d0b01cd48ef36e5f87b43023bff0520fdfc707283085R52)
* Adjusted reply policy and UI messaging for TikTok's 48-hour reply
window.
[[1]](diffhunk://#diff-0d691f6a983bd89502f91253ecf22e871314545d1e3d3b106fbfc76bf6d8e1c7R208-R210)
[[2]](diffhunk://#diff-0d691f6a983bd89502f91253ecf22e871314545d1e3d3b106fbfc76bf6d8e1c7R224-R226)
These changes collectively enable end-to-end TikTok channel support,
from configuration and OAuth flow to webhook processing and frontend
message handling.
------------
# TikTok App Setup & Configuration
1. Grant access to the Business Messaging API
([Documentation](https://business-api.tiktok.com/portal/docs?id=1832184145137922))
2. Set the app authorization redirect URL to
`https://FRONTEND_URL/tiktok/callback`
3. Update the installation config with TikTok App ID and Secret
4. Create a Business Messaging Webhook configuration and set the
callback url to `https://FRONTEND_URL/webhooks/tiktok`
([Documentation](https://business-api.tiktok.com/portal/docs?id=1832190670631937))
. You can do this by calling
`Tiktok::AuthClient.update_webhook_callback` from rails console once you
finish Tiktok channel configuration in super admin ( will be automated
in future )
5. Enable TikTok channel feature in an account
---------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Extracted the backend changes from
https://github.com/chatwoot/chatwoot/pull/13040
- Added the support for saving `conversation_required_attributes` in
account
- Delete `conversation_required_attributes` if custom attribute deleted.
Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
## Description
When a user tries creating a new account through the Super Admin
dashboard, and they forget to fill in the account name, they're faced
with an ugly error (generic "Something went wrong" on production).
This PR simply adds the `validates :name, presence: true` model
validation on `Account` model, which is translated as a proper error
message on the Super Admin UI.
## Linear reference:
https://linear.app/chatwoot/issue/CW-4649/re-imagine-assignments
## Description
This PR introduces the foundation for Assignment V2 system by
implementing assignment policies and their association with inboxes.
Assignment policies allow configuring how conversations are distributed
among agents, with support for different assignment orders (round_robin
in community, balanced in enterprise) and conversation prioritization
strategies
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
## How Has This Been Tested?
Test Coverage:
- Controller specs for assignment policies CRUD operations
- Enterprise-specific specs for balanced assignment order
- Model specs for community/enterprise separation
Manual Testing:
1. Create assignment policy: POST
/api/v1/accounts/{id}/assignment_policies
2. List policies: GET /api/v1/accounts/{id}/assignment_policies
3. Assign policy to inbox: POST
/api/v1/accounts/{id}/assignment_policies/{id}/inboxes
4. View inbox policy: GET
/api/v1/accounts/{id}/inboxes/{id}/assignment_policy
5. Verify community edition ignores "balanced" assignment order
6. Verify enterprise edition supports both "round_robin" and "balanced"
- testing the flows after enterprise folder deletion
## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Pranav <pranavrajs@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
### Summary
- Converts conversation auto-resolution duration from days to minutes
for more
granular control
- Updates validation to allow values from 10 minutes (minimum) to 999
days (maximum)
- Implements smart messaging to show appropriate time units in activity
messages
### Changes
- Created migration to convert existing durations from days to minutes
(x1440)
- Updated conversation resolver to use minutes instead of days
- Added dynamic translation key selection based on duration value
- Updated related specs and documentation
- Added support for displaying durations in days, hours, or minutes
based on value
### Test plan
- Verify account validation accepts new minute-based ranges
- Confirm existing account settings are correctly migrated
- Test auto-resolution works properly with minute values
- Ensure proper time unit display in activity messages
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
- Removes the portal_members table and all associated records
- Updates policies to use custom roles with knowledge_base_manage
permission
- Updates controllers, models, and views to work without portal
membership
- Adds tests for the new permission model
## Description
Add account delete option in the user account settings.
Fixes#1555
## Type of change
- [ ] New feature (non-breaking change which adds functionality)


## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Sojan Jose <sojan.official@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This PR implements the following features
- FAQs from conversations will be generated in account language
- Contact notes will be generated in account language
- Copilot chat will respond in user language, unless the agent asks the
question in a different language
## Changes
### Copilot Chat
- Update the prompt to include an instruction for the language, the bot
will reply in asked language, but will default to account language
- Update the `ChatService` class to include pass the language to
`SystemPromptsService`
### FAQ and Contact note generation
- Update contact note generator and conversation generator to include
account locale
- Pass the account locale to `SystemPromptsService`
<details><summary>Screenshots</summary>
#### FAQs being generated in system langauge

#### Copilot responding in system language

</details>
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
This PR adds service to automate account abuse detection. Currently
based on the signup name and URL, could potentially add more context
such as usage analysis, message metadata etc.
This PR addresses several items listed in our rubocop_todo by implementing the necessary corrections and enhancements. As a result, we are now able to remove the rubocop_todo file entirely, streamlining our codebase and ensuring adherence to our coding standards.
fixes: https://linear.app/chatwoot/issue/CW-1806/chore-rubocop-audit
This commit introduces the ability to associate response sources to an inbox, allowing external webpages to be parsed by Chatwoot. The parsed data is converted into embeddings for use with GPT models when managing customer queries.
The implementation relies on the `pgvector` extension for PostgreSQL. Database migrations related to this feature are handled separately by `Features::ResponseBotService`. A future update will integrate these migrations into the default rails migrations, once compatibility with Postgres extensions across all self-hosted installation options is confirmed.
Additionally, a new GitHub action has been added to the CI pipeline to ensure the execution of specs related to this feature.
Conversation and campaign sequences persist in the database even after the related account is deleted. This PR adds an after_desttory callback on the account model that will delete the associated sequences.
Fixes: #4252