561 lines
21 KiB
PHP
Executable File
561 lines
21 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\App;
|
|
use App\Models\TaskComment;
|
|
use App\Models\TaskDuration;
|
|
use http\Env\Response;
|
|
use http\Message;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Http\Request;
|
|
use App\Models\Pivot_Tasks;
|
|
use App\Models\Attendance;
|
|
use GuzzleHttp\Client;
|
|
use App\Models\Tasks;
|
|
use App\Models\User;
|
|
use Carbon\Carbon;
|
|
use Morilog\Jalali\Jalalian;
|
|
use Carbon\CarbonInterval;
|
|
|
|
|
|
class TaskController extends Controller
|
|
{
|
|
private function taskChangeMessage(Tasks $task, array $before, array $after, ?User $actor): string
|
|
{
|
|
$lines = [];
|
|
$actorName = $actor?->name ?? 'نامشخص';
|
|
|
|
$titleBefore = (string)($before['title'] ?? '');
|
|
$titleAfter = (string)($after['title'] ?? $task->title ?? '');
|
|
|
|
$lines[] = "ویرایش تسک: «{$titleAfter}»";
|
|
$lines[] = "توسط: {$actorName}";
|
|
|
|
$appBefore = $before['app'] ?? null;
|
|
$appAfter = $after['app'] ?? $task->app ?? null;
|
|
$a1 = App::find($appBefore)?->name_fa ?? ($appBefore ?? '-');
|
|
$a2 = App::find($appAfter)?->name_fa ?? ($appAfter ?? '-');
|
|
$lines[] = ($appBefore != $appAfter) ? "اپ: {$a1} ← {$a2}" : "اپ: {$a2}";
|
|
|
|
$lines[] = (($before['title'] ?? null) !== ($after['title'] ?? null))
|
|
? "عنوان: {$titleBefore} ← {$titleAfter}"
|
|
: "عنوان: {$titleAfter}";
|
|
|
|
$priorityFa = [
|
|
'none' => 'ندارد',
|
|
'low' => 'کم',
|
|
'medium' => 'عادی',
|
|
'high' => 'زیاد',
|
|
'urgent' => 'فوری',
|
|
];
|
|
$p1 = $before['priority'] ?? null;
|
|
$p2 = $after['priority'] ?? null;
|
|
$lines[] = ($p1 !== $p2)
|
|
? "اولویت: " . ($priorityFa[$p1] ?? ($p1 ?? '-')) . " ← " . ($priorityFa[$p2] ?? ($p2 ?? '-'))
|
|
: "اولویت: " . ($priorityFa[$p2] ?? ($p2 ?? '-'));
|
|
|
|
$stateFa = [
|
|
1 => 'انباشته',
|
|
2 => 'برای انجام',
|
|
3 => 'درحال انجام',
|
|
4 => 'پایان یافته',
|
|
];
|
|
$s1 = (int)($before['state'] ?? 0);
|
|
$s2 = (int)($after['state'] ?? 0);
|
|
$lines[] = ($s1 !== $s2 && $s2)
|
|
? "وضعیت: " . ($stateFa[$s1] ?? ($before['state'] ?? '-')) . " ← " . ($stateFa[$s2] ?? ($after['state'] ?? '-'))
|
|
: "وضعیت: " . ($stateFa[$s2] ?? ($after['state'] ?? '-'));
|
|
|
|
$d1 = $before['start_date'] ?? null;
|
|
$d2 = $after['start_date'] ?? null;
|
|
$lines[] = ($d1 !== $d2)
|
|
? "شروع: " . ($d1 ?: '-') . " ← " . ($d2 ?: '-')
|
|
: "شروع: " . ($d2 ?: '-');
|
|
|
|
$t1 = $before['target_date'] ?? null;
|
|
$t2 = $after['target_date'] ?? null;
|
|
$lines[] = ($t1 !== $t2)
|
|
? "ددلاین: " . ($t1 ?: '-') . " ← " . ($t2 ?: '-')
|
|
: "ددلاین: " . ($t2 ?: '-');
|
|
|
|
$desc1 = trim((string)($before['description'] ?? ''));
|
|
$desc2 = trim((string)($after['description'] ?? ''));
|
|
$lines[] = ($desc1 !== $desc2)
|
|
? "توضیحات: " . (!empty($desc2) ? 'تغییر کرد' : 'پاک شد')
|
|
: "توضیحات: بدون تغییر";
|
|
|
|
$aBefore = $before['assignees'] ?? null;
|
|
$aAfter = $after['assignees'] ?? null;
|
|
$arr1 = is_string($aBefore) ? json_decode($aBefore, true) : $aBefore;
|
|
$arr2 = is_string($aAfter) ? json_decode($aAfter, true) : $aAfter;
|
|
$arr1 = is_array($arr1) ? array_map('strval', $arr1) : [];
|
|
$arr2 = is_array($arr2) ? array_map('strval', $arr2) : [];
|
|
sort($arr1);
|
|
sort($arr2);
|
|
$names1 = User::whereIn('id', $arr1)->pluck('name')->all();
|
|
$names2 = User::whereIn('id', $arr2)->pluck('name')->all();
|
|
$lines[] = ($arr1 !== $arr2)
|
|
? "مسئولین: " . (!empty($names1) ? implode('، ', $names1) : '-') . " ← " . (!empty($names2) ? implode('، ', $names2) : '-')
|
|
: "مسئولین: " . (!empty($names2) ? implode('، ', $names2) : '-');
|
|
|
|
return implode("\n", $lines);
|
|
}
|
|
// public function tasks()
|
|
// {
|
|
// $user = User::where('user_name', $_COOKIE['user_identity'])->first();
|
|
// $tasks = $user->tasks;
|
|
// $users = User::get();
|
|
//
|
|
// $state_order = [
|
|
// "c73c2044-ea14-42cb-b08d-cecf3d1fdfb5",
|
|
// "a9ce312f-cfca-491e-8e3d-1975aa6ebc10",
|
|
// "dea1fb57-a281-4fe7-8f3e-ee5567637e35",
|
|
// "770fbe42-99f6-41db-9b9e-773d9cced1a5",
|
|
// "b0e464e1-34eb-41ea-b2f7-3ef7483bc9f0",
|
|
// "d61d14a3-72f7-4f44-894b-efe8b2a75be1",
|
|
// ];
|
|
//
|
|
// $work_item = $tasks->whereNull('parent')->sortBy(fn($t) => array_search($t->state, $state_order));
|
|
// $sub_work_items = $tasks->whereNotNull('parent')->sortBy(fn($t) => array_search($t->state, $state_order));
|
|
//
|
|
// foreach ($work_item as $w) {
|
|
// foreach ($sub_work_items as $t) {
|
|
// foreach ($users as $u) {
|
|
// if ($t->created_by == $u->plain_id)
|
|
// $t->created_by = $u->name;
|
|
// if ($w->created_by == $u->plain_id)
|
|
// $w->created_by = $u->name;
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// return view('tasks.tasks', compact('tasks', 'work_item', 'sub_work_items'));
|
|
// }
|
|
|
|
public function tasks()
|
|
{
|
|
$user = User::where('user_name', $_COOKIE['user_identity'])->first();
|
|
if ($user) {
|
|
if ($user->is_admin == 1) {
|
|
$tasks = Tasks::with(['duration', 'comments.user', 'appName'])
|
|
->orderByRaw('target_date IS NULL')
|
|
->orderBy('target_date', 'asc')
|
|
->orderBy('updated_at', 'desc')
|
|
->get();
|
|
// dd($tasks);
|
|
foreach ($tasks as $task) {
|
|
$totalSeconds = 0;
|
|
foreach ($task->duration as $item) {
|
|
if ($item->duration !== null) {
|
|
$totalSeconds += CarbonInterval::createFromFormat('H:i:s', $item->duration)->totalSeconds;
|
|
}
|
|
}
|
|
|
|
$task->totalDuration = CarbonInterval::seconds($totalSeconds)->cascade()->format('%H:%I:%S');
|
|
$active_task = TaskDuration::where('task_id', $task->id)->orderBy('start', 'desc')->first();
|
|
$task->active = !empty($active_task) && $active_task->end == null;
|
|
}
|
|
} else {
|
|
$tasks = Tasks::with(['duration', 'comments.user'])->where('created_by', $user->id)
|
|
->orWhereJsonContains('assignees', (string)$user->id)
|
|
->orderByRaw('target_date IS NULL') // تسکهای دارای مهلت اول بیایند (NULL آخر)
|
|
->orderBy('target_date', 'asc') // نزدیکترین مهلت اول
|
|
->orderBy('updated_at', 'desc') // در صورت یکسان بودن مهلت، آخرین تغییر اول
|
|
->get();
|
|
|
|
// dd($tasks);
|
|
foreach ($tasks as $task) {
|
|
$totalSeconds = 0;
|
|
foreach ($task->duration as $item) {
|
|
if ($user->id == $item->user_id && $item->duration !== null) {
|
|
$totalSeconds += CarbonInterval::createFromFormat('H:i:s', $item->duration)->totalSeconds;
|
|
}
|
|
}
|
|
|
|
$task->totalDuration = CarbonInterval::seconds($totalSeconds)->cascade()->format('%H:%I:%S');
|
|
$active_task = TaskDuration::where('task_id', $task->id)->where('user_id', $user->id)->orderBy('start', 'desc')->first();
|
|
$task->active = !empty($active_task) && $active_task->end == null;
|
|
}
|
|
}
|
|
|
|
$count = count($tasks);
|
|
|
|
// dd((new Tasks())->filterByState($tasks)['backlog'][0], 'count ='.$count);
|
|
|
|
return view('tasks.tasks', [
|
|
'tasks' => (new Tasks())->filterByState($tasks),
|
|
'count' => $count,
|
|
'user_id' => $user->id,
|
|
'isAdminLevel1' => $user->is_admin == 1,
|
|
'mentionUsers' => User::select('id', 'name', 'user_name')->get(),
|
|
'appsList' => App::select('id', 'name_fa')->get(),
|
|
'priorityLabels' => [
|
|
'urgent' => 'فوری',
|
|
'high' => 'بالا',
|
|
'medium' => 'متوسط',
|
|
'low' => 'پایین'
|
|
],
|
|
'priorityColors' => [
|
|
'urgent' => 'bg-red-100 text-red-800',
|
|
'high' => 'bg-orange-100 text-orange-800',
|
|
'medium' => 'bg-yellow-100 text-yellow-800',
|
|
'low' => 'bg-green-100 text-green-800'
|
|
],
|
|
|
|
]);
|
|
} else {
|
|
return back()->with('message', [
|
|
'color' => 'red',
|
|
'text' => 'کاربر یافت نشد!'
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function showTask($id)
|
|
{
|
|
|
|
$task = Tasks::with(['comments.user'])->find($id ?? null);
|
|
return view('tasks.create', ['task' => $task]);
|
|
|
|
}
|
|
|
|
public function editTask(Request $request)
|
|
{
|
|
// dd($request->all());
|
|
if (!isset($_COOKIE['user_identity'])) {
|
|
return back()->with('message', [
|
|
'color' => 'red',
|
|
'text' => 'ابتدا باید وارد شوید!'
|
|
]);
|
|
}
|
|
$actor = User::where('user_name', $_COOKIE['user_identity'])->first();
|
|
|
|
$data = $request->all();
|
|
$task = Tasks::find($data['id'] ?? null);
|
|
if (!$task) {
|
|
return back()->with('message', [
|
|
'color' => 'red',
|
|
'text' => 'وظیفه یافت نشد!'
|
|
]);
|
|
}
|
|
|
|
$before = $task->toArray();
|
|
|
|
$data['updated_by'] = $actor?->id;
|
|
if (array_key_exists('assignees', $data)) {
|
|
$data['assignees'] = !empty($data['assignees']) ? json_encode($data['assignees']) : null;
|
|
} else {
|
|
unset($data['assignees']);
|
|
}
|
|
unset($data['_token'], $data['id'], $data['start_date_display'], $data['target_date_display']);
|
|
|
|
$task->update($data);
|
|
$after = $task->toArray();
|
|
|
|
$title = $task->title;
|
|
$message = "تسک «{$title}» برای شما بهروزرسانی شد.";
|
|
$message_admin = $this->taskChangeMessage($task, $before, $after, $actor);
|
|
|
|
if (!empty($request->assignees)) {
|
|
foreach ($request->assignees as $assignee) {
|
|
$assigneeUser = User::where('id', $assignee)->first();
|
|
if ($assigneeUser && $assigneeUser->bale !== null) {
|
|
$this->send_bale($assigneeUser->bale, $message);
|
|
}
|
|
}
|
|
}
|
|
// dd($data, $message, $message_admin);
|
|
$this->send_level1_admins($message_admin);
|
|
|
|
return back()->with('message', [
|
|
'color' => 'green',
|
|
'text' => $message
|
|
]);
|
|
}
|
|
|
|
public function createTask()
|
|
{
|
|
return view('tasks.create');
|
|
}
|
|
|
|
public function deleteTask($id)
|
|
{
|
|
Tasks::destroy($id);
|
|
|
|
return response()->json([
|
|
"success" => true,
|
|
"message" => "Task deleted successfully.",
|
|
"task_id" => 45
|
|
]);
|
|
}
|
|
|
|
public function storeTask(Request $request)
|
|
{
|
|
// dd($request->all());
|
|
if (!isset($_COOKIE['user_identity'])) {
|
|
return back()->with('message', [
|
|
'color' => 'red',
|
|
'text' => 'ابتدا باید وارد شوید!'
|
|
]);
|
|
}
|
|
$user = User::where('user_name', $_COOKIE['user_identity'])->first();
|
|
|
|
$data = $request->all();
|
|
$data['created_by'] = $user->id;
|
|
$data['assignees'] = !empty($data['assignees']) ? json_encode($data['assignees']) : null;
|
|
|
|
$task = Tasks::create($data);
|
|
|
|
$message = "تسک جدیدی با عنوان {$data['title']} برای شما ایجاد شد.";
|
|
$deadline = !empty($data['target_date']) ? Jalalian::fromCarbon(Carbon::parse($data['target_date']))->format('Y-m-d') : null;
|
|
$app = App::find($data['app']);
|
|
$message_admin = "ایجاد تسک: «{$data['title']}»";
|
|
$message_admin .= !empty($app) ? "\nاپ {$app->name_fa}" : null;
|
|
$message_admin .= !empty($deadline) ? "\nددلاین {$deadline}" : null;
|
|
$message_admin .= !empty($data['start_date']) ? "\nتاریخ شروع {$data['start_date']}" : null;
|
|
$message_admin .= !empty($data['state_fa']) ? "\nوضعیت: {$data['state_fa']}" : null;
|
|
$message_admin .= !empty($data['description']) ? "\nبا توضیحات:\n" . $data['description'] : null;
|
|
$message_admin .= !empty($data['assignees']) ? "\nتوسط " . $user->name . " ساخته شد و به" : null;
|
|
|
|
if (!empty($data['assignees'])) {
|
|
foreach ($request->assignees as $assignee) {
|
|
$user = User::where('id', $assignee)->first();
|
|
$message_admin .= "\n$user->name";
|
|
if ($user && $user->bale !== null) {
|
|
$this->send_bale($user->bale, $message);
|
|
}
|
|
}
|
|
$message_admin .= "\nاختصاص یافت.";
|
|
} else {
|
|
$message_admin .= "\nتوسط " . $user->name . " ساخته شد";
|
|
}
|
|
// dd($data, $message, $message_admin);
|
|
$this->send_level1_admins($message_admin);
|
|
|
|
return back()->with('message', [
|
|
'color' => 'green',
|
|
'text' => $message
|
|
]);
|
|
}
|
|
|
|
public function activeTask(Request $request)
|
|
{
|
|
// dd($request);
|
|
$user = User::where('user_name', $_COOKIE['user_identity'])->first();
|
|
$task = Tasks::find($request->task_id);
|
|
if (!$task) {
|
|
return response()->json([
|
|
'action' => 'not_found',
|
|
'status' => false
|
|
]);
|
|
}
|
|
|
|
$taskDU = TaskDuration::where('user_id', $user->id)
|
|
->where('task_id', $request->task_id)
|
|
->orderBy('id', 'desc')
|
|
->first();
|
|
|
|
// اگر رکورد باز داریم => پایان
|
|
if (!empty($taskDU) && ($taskDU->start !== null && $taskDU->end == null)) {
|
|
// dd('in if');
|
|
|
|
$attendance = new Attendance();
|
|
$s = Carbon::parse($taskDU->start)->format('H:i:s');
|
|
$e = Carbon::parse(now())->format('H:i:s');
|
|
$duration = $taskDU->duration;
|
|
if ($e > $s) {
|
|
$diff = $attendance->duration($s, $e);
|
|
if ($duration !== null) {
|
|
[$h1, $m1, $s1] = explode(':', $duration);
|
|
$durationSeconds = $h1 * 3600 + $m1 * 60 + $s1;
|
|
|
|
[$h2, $m2, $s2] = explode(':', $diff);
|
|
$diffSeconds = $h2 * 3600 + $m2 * 60 + $s2;
|
|
|
|
$totalSeconds = $durationSeconds + $diffSeconds;
|
|
|
|
$hours = floor($totalSeconds / 3600);
|
|
$minutes = floor(($totalSeconds % 3600) / 60);
|
|
$seconds = $totalSeconds % 60;
|
|
|
|
$duration = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
|
|
} else {
|
|
$duration = $diff;
|
|
}
|
|
$taskDU->end = now();
|
|
$taskDU->duration = $duration;
|
|
$user->active_task = null;
|
|
$taskDU->save();
|
|
$user->save();
|
|
$this->send_level1_admins("پایان تسک: «{$task->title}»\nتوسط: {$user->name}\nمدت این نوبت: {$duration}");
|
|
return response()->json([
|
|
'action' => 'ended',
|
|
'status' => true,
|
|
'duration' => $duration,
|
|
'start' => $taskDU->start,
|
|
'end' => $taskDU->end,
|
|
]);
|
|
} else
|
|
return response()->json([
|
|
'action' => 'end',
|
|
'status' => false
|
|
]);
|
|
} else {
|
|
// شروع => همیشه یک رکورد جدید بساز
|
|
$new_task_duration = TaskDuration::create([
|
|
'task_id' => $task->id,
|
|
'user_id' => $user->id,
|
|
'start' => now(),
|
|
'end' => null,
|
|
]);
|
|
$user->active_task = $task->title;
|
|
$user->save();
|
|
$this->send_level1_admins("شروع تسک: «{$task->title}»\nتوسط: {$user->name}");
|
|
return response()->json([
|
|
'action' => 'start',
|
|
'status' => true,
|
|
'start' => $new_task_duration->start,
|
|
'id' => $new_task_duration->id,
|
|
]);
|
|
}
|
|
return back()->with('message', ['color' => 'red',
|
|
'text' => 'وظیفه یافت نشد✖️']);
|
|
|
|
}
|
|
|
|
|
|
public function addTask(Request $request)
|
|
{
|
|
if (isset($_COOKIE['user_identity'])) {
|
|
$user = User::where('user_name', $_COOKIE['user_identity'])->first();
|
|
} else {
|
|
return back()->with('message', [
|
|
'color' => 'red',
|
|
'text' => 'auth failed!'
|
|
]);
|
|
}
|
|
$request->validate([
|
|
'title' => 'required',
|
|
'description' => 'required',
|
|
'assignees' => 'required',
|
|
'start_date' => 'required',
|
|
'target_date' => 'required',
|
|
'priority' => 'required',
|
|
'description_html' => 'required',
|
|
'completed_at' => 'required',
|
|
'state' => 'required',
|
|
'created_at' => 'required',
|
|
'updated_at' => 'required',
|
|
'app' => 'required',
|
|
'task_type' => 'required',
|
|
]);
|
|
$data = $request->all();
|
|
$data['user_id'] = $user->id;
|
|
|
|
Tasks::create([$data]);
|
|
return back()->with('message', [
|
|
'color' => 'green',
|
|
'text' => 'وظیفه ایجاد شد.'
|
|
]);
|
|
}
|
|
|
|
public function storeComment(Request $request, $id)
|
|
{
|
|
if (!isset($_COOKIE['user_identity'])) {
|
|
return back()->with('message', [
|
|
'color' => 'red',
|
|
'text' => 'ابتدا باید وارد شوید!'
|
|
]);
|
|
}
|
|
|
|
$actor = User::where('user_name', $_COOKIE['user_identity'])->first();
|
|
$task = Tasks::find($id ?? null);
|
|
if (!$task) {
|
|
return back()->with('message', [
|
|
'color' => 'red',
|
|
'text' => 'وظیفه یافت نشد!'
|
|
]);
|
|
}
|
|
|
|
$request->validate([
|
|
'body' => 'required|string',
|
|
]);
|
|
|
|
$body = trim((string)$request->input('body'));
|
|
|
|
preg_match_all('/@([\p{L}\p{N}_.-]+)/u', $body, $matches);
|
|
$usernames = array_values(array_unique($matches[1] ?? []));
|
|
|
|
$mentionedUsers = !empty($usernames)
|
|
? User::whereIn('user_name', $usernames)->get()
|
|
: collect();
|
|
|
|
$mentionedIds = $mentionedUsers->pluck('id')->values()->all();
|
|
|
|
TaskComment::create([
|
|
'task_id' => $task->id,
|
|
'user_id' => $actor->id,
|
|
'body' => $body,
|
|
'mentioned_user_ids' => !empty($mentionedIds) ? $mentionedIds : null,
|
|
]);
|
|
|
|
$text = "کامنت جدید روی تسک «{$task->title}»\n"
|
|
. "توسط: {$actor->name}\n\n"
|
|
. $body;
|
|
|
|
foreach ($mentionedUsers as $mu) {
|
|
if ($mu->id === $actor->id) {
|
|
continue;
|
|
}
|
|
if ($mu->bale) {
|
|
$this->send_bale($mu->bale, $text);
|
|
}
|
|
}
|
|
|
|
$this->send_level1_admins($text);
|
|
|
|
return back()->with('message', [
|
|
'color' => 'green',
|
|
'text' => 'کامنت ثبت شد.'
|
|
]);
|
|
}
|
|
|
|
|
|
public function webhookPlane(Request $request)
|
|
{
|
|
$d = $request->all();
|
|
|
|
// فقط وقتی تغییر state هست
|
|
if (isset($d['event'], $d['action'], $d['data']['name'], $d['data']['state']['name'])) {
|
|
$msg = "Event: {$d['event']}\nAction: {$d['action']}\nName: {$d['data']['name']}\nNew Status: {$d['data']['state']['name']}";
|
|
|
|
// ارسال به تلگرام
|
|
Http::get("https://api.wwwapp.ir/telegran_send.php", [
|
|
'botToken' => "7467099619:AAF2V6yYcbAb8oSIRSCyH5i2GKfdWVO3a7k",
|
|
'chatId' => "-4742642674",
|
|
'message' => $msg,
|
|
]);
|
|
}
|
|
|
|
// اگر خواستی ثبت در دیتابیس هم اضافه کنی
|
|
// DB::table('tst')->insert([
|
|
// 'data' => json_encode($d, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE),
|
|
// ]);
|
|
|
|
return response()->json(['status' => 'ok'], 200);
|
|
}
|
|
|
|
|
|
private function send_bale($chat_id, $message)
|
|
{
|
|
try {
|
|
Http::withoutVerifying()->post('https://tapi.bale.ai/1482838710:sYbLzby0tuLRzHvP4d3LsbcNwg2sjSDLTAU/sendMessage', [
|
|
"chat_id" => $chat_id,
|
|
'text' => $message,
|
|
]);
|
|
} catch (\Exception $e) {
|
|
}
|
|
}
|
|
}
|