Add email integration for ticket system and IMAP inbound support
Email integration: IMAP polling via webklex/php-imap (M365/Zoho/MIAB
compatible), TicketEmailProcessor with 3-strategy ticket matching
(In-Reply-To, References, subject line [EZSCALE-{id}]), signature and
quote stripping, scheduled command every 2min.
Outbound: 4 notification classes (TicketCreated, CustomerReply,
StaffReply, StatusChanged) with email threading headers via
withSymfonyMessage(). Staff replies set Reply-To: support@ezscale.cloud.
Frontend: ticket reference chips on all pages, "Via Email" badges on
email-originated replies. 12 new tests (163 total, 816 assertions).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -15,6 +16,8 @@ class SupportTicket extends Model
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'ticket_reference',
|
||||
'customer_email',
|
||||
'subject',
|
||||
'status',
|
||||
'priority',
|
||||
@@ -30,6 +33,25 @@ class SupportTicket extends Model
|
||||
];
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::created(function (SupportTicket $ticket): void {
|
||||
if (empty($ticket->ticket_reference)) {
|
||||
$ticket->updateQuietly([
|
||||
'ticket_reference' => sprintf(
|
||||
config('tickets.ticket_reference_format'),
|
||||
$ticket->id
|
||||
),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeByReference(Builder $query, string $reference): Builder
|
||||
{
|
||||
return $query->where('ticket_reference', $reference);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
||||
@@ -17,6 +17,9 @@ class TicketReply extends Model
|
||||
'user_id',
|
||||
'body',
|
||||
'is_staff_reply',
|
||||
'message_id',
|
||||
'from_email',
|
||||
'via_email',
|
||||
];
|
||||
|
||||
/** @return array<string, string> */
|
||||
@@ -24,6 +27,7 @@ class TicketReply extends Model
|
||||
{
|
||||
return [
|
||||
'is_staff_reply' => 'boolean',
|
||||
'via_email' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user