NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Tickets for Laravel

Merging tickets

When two tickets turn out to be the same problem, merge the duplicate into the one that stays:

$result = Tickets::for('TCK-9')->by($agent)->mergeInto('TCK-12', reason: 'Same printer');
// MergeResult { source, target, comments: 4, attachments: 1 }

What a merge does

In one transaction, both tickets locked in primary-key order:

  • Every comment of the source moves to the target (comments’ transfer()).
  • A system internal note goes on the target (TCK-9 merged into this ticket) and a system public reply on the source (Merged into TCK-12), which stays there.
  • The target gains the source’s watchers, and the source’s requester as a watcher when it differs — both requesters see the combined public thread, never the internal notes.
  • The target gains the source’s tags (those its project may carry) and — with tickets.merge.move_attachments — the source’s attachments.
  • A duplicates link source → target is added, the source records merged_into_id, and its guest links are revoked (GuestAccessRevoked).
  • The Merged automation dismisses the source (merged:TCK-12), which locks its conversation and cancels a pending auto-close.
  • merged / merged_from activities are written, then TicketMerged fires and the merged notification goes to the source’s requester. The public entries count only the messages the requester side may read and carry no reason; an internal entry holds both when they differ.

Refused with InvalidMergeException: the same ticket; a Closed or already merged source or target (the error names where the merge chain ends); a cross-project merge with tickets.merge.cross_project off; an actor the merge ability does not allow, or whom the agent scope keeps off either ticket (the system may merge). Custom field values are not merged. Reading a merged source still works, and API resources carry merged_into.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.