83 خطوط
3.6 KiB
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()]);
|
|
}
|
|
}
|