CRM/backend/app/Http/Controllers/Api/CalendarController.php

83 خطوط
3.6 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\FollowUp;
use App\Models\Task;
use App\Support\AccessControl;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class CalendarController extends Controller
{
public function index(Request $request): JsonResponse
{
$validated = $request->validate([
'from' => 'required|date',
'to' => 'required|date|after_or_equal:from',
'type' => 'nullable|string|in:task,follow_up',
]);
$from = Carbon::parse($validated['from'])->startOfDay();
$to = Carbon::parse($validated['to'])->endOfDay();
abort_if($from->diffInDays($to) > 370, 422, 'بازه تقویم نمی‌تواند بیشتر از یک سال باشد.');
$events = collect();
$type = $validated['type'] ?? null;
if ((! $type || $type === 'task') && Gate::allows('viewAny', Task::class)) {
$tasks = Task::query()
->with(['assignee:id,name', 'taskable'])
->whereNotNull('due_at')
->whereBetween('due_at', [$from, $to]);
AccessControl::scopeTasks($tasks, $request->user());
$events->push(...$tasks->get()->map(fn (Task $task) => [
'id' => "task-{$task->id}",
'entity_id' => $task->id,
'type' => 'task',
'title' => $task->subject,
'starts_at' => $task->due_at,
'status' => is_object($task->status) ? $task->status->value : $task->status,
'priority' => is_object($task->priority) ? $task->priority->value : $task->priority,
'assignee' => $task->assignee?->only(['id', 'name']),
'related' => $task->taskable ? [
'type' => class_basename($task->taskable_type),
'id' => $task->taskable_id,
'label' => $task->taskable->name ?? $task->taskable->title ?? $task->taskable->company ?? null,
] : null,
'url' => "/tasks?task={$task->id}",
]));
}
if ((! $type || $type === 'follow_up') && Gate::allows('viewAny', FollowUp::class)) {
$followUps = FollowUp::query()
->with(['lead:id,first_name,last_name,company', 'user:id,name'])
->whereBetween('scheduled_at', [$from, $to]);
AccessControl::scopeFollowUps($followUps, $request->user());
$events->push(...$followUps->get()->map(fn (FollowUp $followUp) => [
'id' => "follow-up-{$followUp->id}",
'entity_id' => $followUp->id,
'type' => 'follow_up',
'title' => $followUp->notes ?: 'پیگیری لید',
'starts_at' => $followUp->scheduled_at,
'status' => $followUp->status,
'priority' => null,
'assignee' => $followUp->user?->only(['id', 'name']),
'related' => $followUp->lead ? [
'type' => 'Lead',
'id' => $followUp->lead_id,
'label' => $followUp->lead->company ?: trim("{$followUp->lead->first_name} {$followUp->lead->last_name}"),
] : null,
'url' => "/follow-ups?follow_up={$followUp->id}",
]));
}
abort_if($events->isEmpty() && ! Gate::allows('viewAny', Task::class) && ! Gate::allows('viewAny', FollowUp::class), 403);
return response()->json(['events' => $events->sortBy('starts_at')->values()]);
}
}