NASER change task orders and make daily report and end task when emploee exit
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Carbon\CarbonInterval;
|
||||
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
|
||||
use function PHPUnit\Framework\throwException;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
@@ -10,6 +11,7 @@ use Illuminate\Support\Facades\Http;
|
||||
use App\Models\AttendanceBreak;
|
||||
use Morilog\Jalali\Jalalian;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\TaskDuration;
|
||||
use App\Models\Pivot_Tasks;
|
||||
use App\Models\Attendance;
|
||||
use App\Models\Tasks;
|
||||
@@ -98,7 +100,7 @@ class AttendanceController extends Controller
|
||||
|
||||
}
|
||||
$user->tasks = Tasks::where('created_by', $user->id)
|
||||
->orWhereJsonContains('assignees', (string) $user->id)
|
||||
->orWhereJsonContains('assignees', (string)$user->id)
|
||||
->orderBy('target_date', 'desc')
|
||||
->get();
|
||||
//dd($user->tasks);
|
||||
@@ -169,8 +171,6 @@ class AttendanceController extends Controller
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
public function ai()
|
||||
{
|
||||
$response = Http::withHeaders([
|
||||
@@ -223,7 +223,7 @@ class AttendanceController extends Controller
|
||||
|
||||
if ($user->is_admin == 1) {
|
||||
setcookie('ad', '1', time() + (60 * 60 * 24 * 365 * 5), "/");
|
||||
}elseif ($user->is_admin == 2){
|
||||
} elseif ($user->is_admin == 2) {
|
||||
setcookie('ad', '2', time() + (60 * 60 * 24 * 365 * 5), "/");
|
||||
}
|
||||
|
||||
@@ -286,13 +286,18 @@ class AttendanceController extends Controller
|
||||
// خروج
|
||||
//end task
|
||||
if (!empty($user->active_task)) {
|
||||
$task = Tasks::where('name', $user->active_task)->first();
|
||||
|
||||
if ($p_task = Pivot_Tasks::where('user_id', $user->plain_id)->where('task_id', $task->task_id)->whereNull('ended_at')->latest('started_at')->first()) {
|
||||
$p_task->duration = $attendance->duration(Carbon::parse($p_task->started_at)->format('H:i:s'), Carbon::now()->format('H:i:s'));
|
||||
$p_task->ended_at = Carbon::now();
|
||||
$p_task->save();
|
||||
|
||||
$taskDu = TaskDuration::where('user_id', $user->id)->whereNull('end')->whereNull('duration')->get();
|
||||
if ($taskDu) {
|
||||
foreach ($taskDu as $item) {
|
||||
$fakeRequest = Request::create(
|
||||
'/active_task', // مسیر فرضی (مهم نیست)
|
||||
'POST',
|
||||
['task_id' => $item->task_id] // شناسه تسک
|
||||
);
|
||||
if ($item->end == null) {
|
||||
(new TaskController())->activeTask($fakeRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
$user->active_task = null;
|
||||
$user->save();
|
||||
@@ -324,7 +329,7 @@ class AttendanceController extends Controller
|
||||
$attendance->save();
|
||||
|
||||
$this->send($user->name, $attendance, 'attendance');
|
||||
|
||||
$this->dailyReport($user->id, $user->name);
|
||||
return redirect()->back()->with('message', [
|
||||
'color' => '#3b82f6',
|
||||
'text' => 'خروج با موفقیت ثبت شد.'
|
||||
@@ -645,6 +650,48 @@ class AttendanceController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
private function dailyReport($userId, $userName)
|
||||
{
|
||||
$tasks = Tasks::with(['duration'])->where('created_by', $userId)->orWhereJsonContains('assignees', $userId)->get();
|
||||
$message = " *" . Jalalian::now()->format('j F') . "* "
|
||||
. "\n * _{$userName}_ * ";
|
||||
foreach ($tasks as $task) {
|
||||
switch ($task->priority) {
|
||||
case 'none':
|
||||
$message .= "\n⚪";
|
||||
break;
|
||||
case 'low':
|
||||
$message .= "\n🟢";
|
||||
break;
|
||||
case 'medium':
|
||||
$message .= "\n🟡";
|
||||
break;
|
||||
case 'high':
|
||||
$message .= "\n🟠";
|
||||
break;
|
||||
case 'urgent':
|
||||
$message .= "\n🔴";
|
||||
break;
|
||||
}
|
||||
$message .= "$task->title";
|
||||
$today = now()->format('Y-m-d 00:00:00');
|
||||
$totalSeconds = 0;
|
||||
foreach ($task->duration as $item) {
|
||||
if (($userId == $item->user_id && $item->duration !== null) && $item->start > $today) {
|
||||
$totalSeconds += CarbonInterval::createFromFormat('H:i:s', $item->duration)->totalSeconds;
|
||||
}
|
||||
}
|
||||
$task->totalDuration = CarbonInterval::seconds($totalSeconds)->cascade()->format('%H:%I');
|
||||
$message .= " $task->totalDuration";
|
||||
}
|
||||
Http::withoutVerifying()->post('https://tapi.bale.ai/1482838710:sYbLzby0tuLRzHvP4d3LsbcNwg2sjSDLTAU/sendMessage', [
|
||||
"chat_id" => '985309723',
|
||||
'text' => $message,
|
||||
]);
|
||||
// $this->send_level1_admins($message);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,9 @@ class TaskController extends Controller
|
||||
if ($user) {
|
||||
if ($user->is_admin == 1) {
|
||||
$tasks = Tasks::with(['duration', 'comments.user', 'appName'])
|
||||
->orderBy('target_date', 'desc')
|
||||
->orderByRaw('target_date IS NULL')
|
||||
->orderBy('target_date', 'asc')
|
||||
->orderBy('updated_at', 'desc')
|
||||
->get();
|
||||
// dd($tasks);
|
||||
foreach ($tasks as $task) {
|
||||
@@ -157,8 +159,11 @@ class TaskController extends Controller
|
||||
} else {
|
||||
$tasks = Tasks::with(['duration', 'comments.user'])->where('created_by', $user->id)
|
||||
->orWhereJsonContains('assignees', (string)$user->id)
|
||||
->orderBy('target_date', 'desc')
|
||||
->orderByRaw('target_date IS NULL') // تسکهای دارای مهلت اول بیایند (NULL آخر)
|
||||
->orderBy('target_date', 'asc') // نزدیکترین مهلت اول
|
||||
->orderBy('updated_at', 'desc') // در صورت یکسان بودن مهلت، آخرین تغییر اول
|
||||
->get();
|
||||
|
||||
// dd($tasks);
|
||||
foreach ($tasks as $task) {
|
||||
$totalSeconds = 0;
|
||||
|
||||
@@ -35,6 +35,7 @@ class User extends Authenticatable
|
||||
'plain_id',
|
||||
'break',
|
||||
'req_counts',
|
||||
'active_task'
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -136,9 +136,9 @@ $state = [
|
||||
$actionType = $ended_at ? 'start' : ($started_at ? 'end' : 'start');
|
||||
$p_id = $lastDuration?->id ?? '';
|
||||
@endphp
|
||||
{{--@if($_COOKIE['user_identity'] == 'naser_me') {{dump($task)}} @endif--}}
|
||||
{{--@if($_COOKIE['user_identity'] == 'naser_me') {{dump($task)}} @endif--}}
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-2 py-2">
|
||||
<td class="px-2 py-2 {{ $task->active ? 'border-s-4 border-cyan-400 ' : '' }}">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="inline-flex items-center justify-center w-5 h-5">{!! $stateIcon !!}</span>
|
||||
<div>
|
||||
@@ -336,7 +336,7 @@ $state = [
|
||||
ویرایش کامل
|
||||
</button>
|
||||
<button id="modalDeleteTaskBtn" type="button"
|
||||
class="px-4 py-2 rounded-lg font-medium text-gray-700 bg-red-100 hover:bg-gray-200 transition" >
|
||||
class="px-4 py-2 rounded-lg font-medium text-gray-700 bg-red-100 hover:bg-gray-200 transition">
|
||||
حذف
|
||||
</button>
|
||||
</div>
|
||||
@@ -659,7 +659,7 @@ $state = [
|
||||
if (at > 0 && /\S/.test(before[at - 1])) return null; // باید ابتدای کلمه باشد
|
||||
const query = before.slice(at + 1);
|
||||
if (/\s/.test(query)) return null;
|
||||
return { atIndex: at, query };
|
||||
return {atIndex: at, query};
|
||||
}
|
||||
|
||||
function insertMention(textarea, atIndex, username) {
|
||||
@@ -679,7 +679,7 @@ $state = [
|
||||
const dropdown = document.getElementById('mentionDropdown');
|
||||
if (!textarea || !dropdown) return;
|
||||
|
||||
let state = { open: false, atIndex: -1, query: '' };
|
||||
let state = {open: false, atIndex: -1, query: ''};
|
||||
|
||||
function close() {
|
||||
dropdown.classList.add('hidden');
|
||||
@@ -688,7 +688,7 @@ $state = [
|
||||
}
|
||||
|
||||
function open(items, atIndex, query) {
|
||||
state = { open: true, atIndex, query };
|
||||
state = {open: true, atIndex, query};
|
||||
dropdown.innerHTML = items.map(u => {
|
||||
const name = escapeHtml(u.name);
|
||||
const uname = escapeHtml(u.user_name);
|
||||
@@ -751,7 +751,7 @@ $state = [
|
||||
|
||||
// اپ
|
||||
const appNameEl = document.getElementById('modalTaskAppName');
|
||||
const appTypes = {1:'خانگی', 2:'همکار'};
|
||||
const appTypes = {1: 'خانگی', 2: 'همکار'};
|
||||
if (appNameEl) {
|
||||
const app = (appsList || []).find(a => String(a.id) === String(task.app));
|
||||
appNameEl.textContent = app ? `${app.name_fa} (${appTypes[app.type]})` : '-';
|
||||
@@ -803,7 +803,7 @@ $state = [
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
body: JSON.stringify({ task_id: task.id })
|
||||
body: JSON.stringify({task_id: task.id})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
@@ -963,7 +963,10 @@ $state = [
|
||||
const tdEdit = $('#modalTaskTargetDateEdit');
|
||||
|
||||
if (sdEdit.length) {
|
||||
try { sdEdit.persianDatepicker('destroy'); } catch (e) {}
|
||||
try {
|
||||
sdEdit.persianDatepicker('destroy');
|
||||
} catch (e) {
|
||||
}
|
||||
sdEdit.persianDatepicker({
|
||||
format: 'YYYY/MM/DD',
|
||||
autoClose: true,
|
||||
@@ -981,7 +984,10 @@ $state = [
|
||||
}
|
||||
|
||||
if (tdEdit.length) {
|
||||
try { tdEdit.persianDatepicker('destroy'); } catch (e) {}
|
||||
try {
|
||||
tdEdit.persianDatepicker('destroy');
|
||||
} catch (e) {
|
||||
}
|
||||
tdEdit.persianDatepicker({
|
||||
format: 'YYYY/MM/DD',
|
||||
autoClose: true,
|
||||
@@ -1024,7 +1030,7 @@ $state = [
|
||||
fd.append('target_date', tdGreg?.value || '');
|
||||
|
||||
saveBtn.disabled = true;
|
||||
fetch('{{ route('task.edit') }}', { method: 'POST', body: fd })
|
||||
fetch('{{ route('task.edit') }}', {method: 'POST', body: fd})
|
||||
.then(() => {
|
||||
// backend redirect میدهد، ما فقط UI را آپدیت میکنیم
|
||||
currentTaskDetails.priority = prEdit?.value || 'none';
|
||||
@@ -1038,7 +1044,12 @@ $state = [
|
||||
if (tdView) tdView.textContent = currentTaskDetails.target_date ? formatJalaliDate(currentTaskDetails.target_date) : '-';
|
||||
|
||||
// priority view
|
||||
const priorityLabels = {'urgent': 'فوری', 'high': 'بالا', 'medium': 'متوسط', 'low': 'پایین'};
|
||||
const priorityLabels = {
|
||||
'urgent': 'فوری',
|
||||
'high': 'بالا',
|
||||
'medium': 'متوسط',
|
||||
'low': 'پایین'
|
||||
};
|
||||
const priorityColors = {
|
||||
'urgent': 'bg-red-100 text-red-800',
|
||||
'high': 'bg-orange-100 text-orange-800',
|
||||
@@ -1069,7 +1080,9 @@ $state = [
|
||||
setQuickEditMode(false);
|
||||
})
|
||||
.catch(() => alert('خطا در ذخیره تغییرات'))
|
||||
.finally(() => { saveBtn.disabled = false; });
|
||||
.finally(() => {
|
||||
saveBtn.disabled = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -1099,6 +1112,6 @@ $state = [
|
||||
|
||||
// NOTE: مدیریت زمان از مودال جزئیات حذف شده و فقط در تب "زمانها" انجام میشود.
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
|
||||
Reference in New Issue
Block a user