# دليل المطور - نظام إدارة مهام الموظفين

## مقدمة

هذا الدليل مخصص للمطورين الذين سيعملون على تطوير وصيانة نظام إدارة مهام الموظفين في Elevators ERP. يوفر هذا الدليل معلومات تفصيلية عن هيكل النظام وكيفية توسيعه وتطويره.

## هيكل قاعدة البيانات

### جدول المهام (tasks)

```
- id (primary key)
- title (string) - عنوان المهمة
- description (text) - وصف المهمة
- status (enum) - حالة المهمة: pending, in_progress, completed, cancelled
- priority (enum) - أولوية المهمة: low, medium, high, urgent
- start_date (date) - تاريخ بدء المهمة
- due_date (date) - تاريخ استحقاق المهمة
- progress (integer) - نسبة الإنجاز (0-100)
- created_by (foreign key) - معرف المستخدم الذي أنشأ المهمة
- completed_at (timestamp) - تاريخ إكمال المهمة
- created_at (timestamp)
- updated_at (timestamp)
```

### جدول تعيين المهام (task_assignees)

```
- id (primary key)
- task_id (foreign key) - معرف المهمة
- employee_id (foreign key) - معرف الموظف
- assigned_by (foreign key) - معرف المستخدم الذي قام بالتعيين
- created_at (timestamp)
- updated_at (timestamp)
```

### جدول تعليقات المهام (task_comments)

```
- id (primary key)
- task_id (foreign key) - معرف المهمة
- user_id (foreign key) - معرف المستخدم
- comment (text) - نص التعليق
- created_at (timestamp)
- updated_at (timestamp)
```

### جدول مرفقات المهام (task_attachments)

```
- id (primary key)
- task_id (foreign key) - معرف المهمة
- user_id (foreign key) - معرف المستخدم
- file_name (string) - اسم الملف
- file_path (string) - مسار الملف
- file_size (integer) - حجم الملف
- file_type (string) - نوع الملف
- description (string) - وصف المرفق
- created_at (timestamp)
- updated_at (timestamp)
```

## النماذج (Models)

### Task.php

```php
<?php

namespace App\Models\HRM;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\User;
use App\Models\HRM\Employee;

class Task extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'title', 'description', 'status', 'priority',
        'start_date', 'due_date', 'progress', 'created_by',
        'completed_at'
    ];

    protected $dates = [
        'start_date', 'due_date', 'completed_at'
    ];

    protected $casts = [
        'progress' => 'integer',
    ];

    // العلاقات
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function assignees()
    {
        return $this->hasMany(TaskAssignee::class);
    }

    public function comments()
    {
        return $this->hasMany(TaskComment::class);
    }

    public function attachments()
    {
        return $this->hasMany(TaskAttachment::class);
    }

    // الخصائص المحسوبة
    public function getDaysRemainingAttribute()
    {
        if (!$this->due_date) {
            return null;
        }

        return now()->diffInDays($this->due_date, false);
    }

    public function getIsOverdueAttribute()
    {
        if (!$this->due_date || $this->status === 'completed' || $this->status === 'cancelled') {
            return false;
        }

        return now()->gt($this->due_date);
    }

    public function getStatusLabelAttribute()
    {
        $labels = [
            'pending' => 'قيد الانتظار',
            'in_progress' => 'قيد التنفيذ',
            'completed' => 'مكتملة',
            'cancelled' => 'ملغية'
        ];

        return $labels[$this->status] ?? $this->status;
    }

    public function getStatusColorAttribute()
    {
        $colors = [
            'pending' => 'secondary',
            'in_progress' => 'primary',
            'completed' => 'success',
            'cancelled' => 'danger'
        ];

        return $colors[$this->status] ?? 'secondary';
    }

    public function getPriorityLabelAttribute()
    {
        $labels = [
            'low' => 'منخفضة',
            'medium' => 'متوسطة',
            'high' => 'عالية',
            'urgent' => 'عاجلة'
        ];

        return $labels[$this->priority] ?? $this->priority;
    }

    public function getPriorityColorAttribute()
    {
        $colors = [
            'low' => 'success',
            'medium' => 'info',
            'high' => 'warning',
            'urgent' => 'danger'
        ];

        return $colors[$this->priority] ?? 'secondary';
    }

    // النطاقات (Scopes)
    public function scopePending($query)
    {
        return $query->where('status', 'pending');
    }

    public function scopeInProgress($query)
    {
        return $query->where('status', 'in_progress');
    }

    public function scopeCompleted($query)
    {
        return $query->where('status', 'completed');
    }

    public function scopeCancelled($query)
    {
        return $query->where('status', 'cancelled');
    }

    public function scopeOverdue($query)
    {
        return $query->where('due_date', '<', now())
            ->whereNotIn('status', ['completed', 'cancelled']);
    }

    public function scopeUpcoming($query, $days = 7)
    {
        return $query->where('due_date', '>=', now())
            ->where('due_date', '<=', now()->addDays($days))
            ->whereNotIn('status', ['completed', 'cancelled']);
    }

    public function scopeForEmployee($query, $employeeId)
    {
        return $query->whereHas('assignees', function ($q) use ($employeeId) {
            $q->where('employee_id', $employeeId);
        });
    }
}
```

### TaskAssignee.php

```php
<?php

namespace App\Models\HRM;

use Illuminate\Database\Eloquent\Model;
use App\Models\User;

class TaskAssignee extends Model
{
    protected $fillable = [
        'task_id', 'employee_id', 'assigned_by'
    ];

    public function task()
    {
        return $this->belongsTo(Task::class);
    }

    public function employee()
    {
        return $this->belongsTo(Employee::class);
    }

    public function assigner()
    {
        return $this->belongsTo(User::class, 'assigned_by');
    }
}
```

### TaskComment.php

```php
<?php

namespace App\Models\HRM;

use Illuminate\Database\Eloquent\Model;
use App\Models\User;

class TaskComment extends Model
{
    protected $fillable = [
        'task_id', 'user_id', 'comment'
    ];

    public function task()
    {
        return $this->belongsTo(Task::class);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
```

### TaskAttachment.php

```php
<?php

namespace App\Models\HRM;

use Illuminate\Database\Eloquent\Model;
use App\Models\User;

class TaskAttachment extends Model
{
    protected $fillable = [
        'task_id', 'user_id', 'file_name', 'file_path',
        'file_size', 'file_type', 'description'
    ];

    public function task()
    {
        return $this->belongsTo(Task::class);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function getFileSizeForHumansAttribute()
    {
        $bytes = $this->file_size;
        $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
        
        for ($i = 0; $bytes > 1024; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, 2) . ' ' . $units[$i];
    }

    public function getFileIconAttribute()
    {
        $icons = [
            'image' => 'fas fa-file-image',
            'pdf' => 'fas fa-file-pdf',
            'word' => 'fas fa-file-word',
            'excel' => 'fas fa-file-excel',
            'powerpoint' => 'fas fa-file-powerpoint',
            'archive' => 'fas fa-file-archive',
            'audio' => 'fas fa-file-audio',
            'video' => 'fas fa-file-video',
            'code' => 'fas fa-file-code',
            'text' => 'fas fa-file-alt',
        ];

        $type = explode('/', $this->file_type)[0];
        $extension = pathinfo($this->file_name, PATHINFO_EXTENSION);

        if ($type === 'image') {
            return $icons['image'];
        } elseif ($extension === 'pdf') {
            return $icons['pdf'];
        } elseif (in_array($extension, ['doc', 'docx'])) {
            return $icons['word'];
        } elseif (in_array($extension, ['xls', 'xlsx', 'csv'])) {
            return $icons['excel'];
        } elseif (in_array($extension, ['ppt', 'pptx'])) {
            return $icons['powerpoint'];
        } elseif (in_array($extension, ['zip', 'rar', '7z'])) {
            return $icons['archive'];
        } elseif ($type === 'audio') {
            return $icons['audio'];
        } elseif ($type === 'video') {
            return $icons['video'];
        } elseif (in_array($extension, ['html', 'css', 'js', 'php', 'java', 'py'])) {
            return $icons['code'];
        } else {
            return $icons['text'];
        }
    }
}
```

## المتحكمات (Controllers)

### TaskController.php

المتحكم الرئيسي لإدارة المهام. يتضمن الوظائف التالية:

- `index()`: عرض قائمة المهام مع خيارات التصفية
- `create()`: عرض نموذج إنشاء مهمة جديدة
- `store()`: حفظ مهمة جديدة
- `show()`: عرض تفاصيل المهمة
- `edit()`: عرض نموذج تعديل المهمة
- `update()`: تحديث المهمة
- `destroy()`: حذف المهمة
- `updateStatus()`: تحديث حالة المهمة
- `updateProgress()`: تحديث نسبة إنجاز المهمة

### TaskAssigneeController.php

متحكم لإدارة تعيين المهام للموظفين. يتضمن الوظائف التالية:

- `store()`: إضافة موظف للمهمة
- `destroy()`: إزالة موظف من المهمة

### TaskCommentController.php

متحكم لإدارة تعليقات المهام. يتضمن الوظائف التالية:

- `store()`: إضافة تعليق جديد
- `update()`: تعديل تعليق
- `destroy()`: حذف تعليق

### TaskAttachmentController.php

متحكم لإدارة مرفقات المهام. يتضمن الوظائف التالية:

- `store()`: رفع مرفق جديد
- `destroy()`: حذف مرفق
- `download()`: تنزيل مرفق

### TaskDashboardController.php

متحكم لعرض لوحة معلومات المهام. يتضمن الوظائف التالية:

- `index()`: عرض لوحة المعلومات مع الإحصائيات والرسوم البيانية

## المسارات (Routes)

جميع مسارات نظام إدارة المهام موجودة في ملف `routes/hrm.php`:

```php
// مسارات إدارة المهام
Route::group(['prefix' => 'tasks', 'as' => 'tasks.'], function () {
    Route::get('/', 'TaskController@index')->name('index');
    Route::get('/create', 'TaskController@create')->name('create');
    Route::post('/', 'TaskController@store')->name('store');
    Route::get('/{task}', 'TaskController@show')->name('show');
    Route::get('/{task}/edit', 'TaskController@edit')->name('edit');
    Route::put('/{task}', 'TaskController@update')->name('update');
    Route::delete('/{task}', 'TaskController@destroy')->name('destroy');
    
    // تحديث حالة المهمة
    Route::patch('/{task}/status', 'TaskController@updateStatus')->name('update-status');
    
    // تحديث نسبة الإنجاز
    Route::patch('/{task}/progress', 'TaskController@updateProgress')->name('update-progress');
    
    // لوحة المعلومات
    Route::get('/dashboard/view', 'TaskDashboardController@index')->name('dashboard');
    
    // مهام الموظف
    Route::get('/employee/{employee}', 'TaskController@employeeTasks')->name('employee');
    
    // تعيين المهام
    Route::post('/{task}/assignees', 'TaskAssigneeController@store')->name('assignees.store');
    Route::delete('/{task}/assignees/{assignee}', 'TaskAssigneeController@destroy')->name('assignees.destroy');
    
    // تعليقات المهام
    Route::post('/{task}/comments', 'TaskCommentController@store')->name('comments.store');
    Route::put('/{task}/comments/{comment}', 'TaskCommentController@update')->name('comments.update');
    Route::delete('/{task}/comments/{comment}', 'TaskCommentController@destroy')->name('comments.destroy');
    
    // مرفقات المهام
    Route::post('/{task}/attachments', 'TaskAttachmentController@store')->name('attachments.store');
    Route::delete('/{task}/attachments/{attachment}', 'TaskAttachmentController@destroy')->name('attachments.destroy');
    Route::get('/{task}/attachments/{attachment}/download', 'TaskAttachmentController@download')->name('attachments.download');
});
```

## الإشعارات (Notifications)

### TaskAssignedNotification.php

إشعار يتم إرساله للموظف عند تعيينه لمهمة جديدة.

### TaskStatusUpdatedNotification.php

إشعار يتم إرساله للموظفين المكلفين بالمهمة عند تحديث حالة المهمة.

### TaskCommentAddedNotification.php

إشعار يتم إرساله للموظفين المكلفين بالمهمة عند إضافة تعليق جديد.

## الوظائف المستقبلية

### 1. نظام تذكير للمهام المتأخرة

يمكن إضافة وظيفة لإرسال تذكيرات للموظفين عن المهام المتأخرة أو التي على وشك الاستحقاق. يمكن تنفيذ ذلك باستخدام Laravel Task Scheduling:

```php
// في app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    // إرسال تذكير يومي للمهام المتأخرة
    $schedule->command('tasks:send-overdue-reminders')->dailyAt('09:00');
    
    // إرسال تذكير للمهام التي تستحق خلال 24 ساعة
    $schedule->command('tasks:send-due-soon-reminders')->dailyAt('15:00');
}
```

### 2. المهام المتكررة

يمكن إضافة وظيفة لإنشاء مهام متكررة بشكل دوري (يومي، أسبوعي، شهري). سيتطلب ذلك إضافة جدول جديد `recurring_tasks` وتعديل نموذج `Task`:

```php
// في app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    // إنشاء المهام المتكررة
    $schedule->command('tasks:create-recurring')->dailyAt('00:01');
}
```

### 3. ربط المهام بالمشاريع

يمكن توسيع النظام لربط المهام بمشاريع التركيب أو الصيانة. سيتطلب ذلك إضافة حقل `project_id` إلى جدول `tasks` وإنشاء علاقة مع نموذج `Project`.

### 4. تقارير متقدمة

يمكن إضافة تقارير متقدمة لتحليل أداء الموظفين وإنجاز المهام، مثل:

- تقرير الوقت المستغرق لإكمال المهام
- تقرير المهام المتأخرة حسب الموظف
- تقرير توزيع المهام حسب القسم
- تقرير الإنتاجية الشهرية

## نصائح للتطوير

1. **استخدام الصلاحيات**: تأكد دائماً من التحقق من صلاحيات المستخدم قبل تنفيذ أي إجراء:

```php
if (!auth()->user()->hasPermission('create_employee_task')) {
    abort(403, 'غير مصرح لك بإنشاء مهام جديدة');
}
```

2. **التحقق من المدخلات**: استخدم طلبات التحقق (Form Requests) للتحقق من صحة المدخلات:

```php
// في app/Http/Requests/StoreTaskRequest.php
public function rules()
{
    return [
        'title' => 'required|string|max:255',
        'description' => 'nullable|string',
        'status' => 'required|in:pending,in_progress,completed,cancelled',
        'priority' => 'required|in:low,medium,high,urgent',
        'start_date' => 'required|date',
        'due_date' => 'required|date|after_or_equal:start_date',
        'assignees' => 'required|array|min:1',
        'assignees.*' => 'exists:employees,id',
    ];
}
```

3. **استخدام المعاملات (Transactions)**: استخدم المعاملات عند إجراء عمليات متعددة على قاعدة البيانات:

```php
DB::beginTransaction();
try {
    // إنشاء المهمة
    $task = Task::create($validatedData);
    
    // تعيين الموظفين
    foreach ($request->assignees as $employeeId) {
        TaskAssignee::create([
            'task_id' => $task->id,
            'employee_id' => $employeeId,
            'assigned_by' => auth()->id(),
        ]);
    }
    
    DB::commit();
} catch (\Exception $e) {
    DB::rollBack();
    return back()->with('error', 'حدث خطأ أثناء إنشاء المهمة: ' . $e->getMessage());
}
```

4. **تحسين الأداء**: استخدم التحميل المسبق (Eager Loading) لتحسين أداء الاستعلامات:

```php
// بدلاً من
$tasks = Task::all();

// استخدم
$tasks = Task::with(['assignees.employee', 'creator'])->get();
```

5. **الاختبارات**: قم بكتابة اختبارات وحدة وتكامل للتأكد من عمل النظام بشكل صحيح:

```php
// في tests/Feature/TaskManagementTest.php
public function test_user_can_create_task()
{
    $user = User::factory()->create();
    $user->givePermissionTo('create_employee_task');
    
    $employee = Employee::factory()->create();
    
    $response = $this->actingAs($user)->post(route('hrm.tasks.store'), [
        'title' => 'مهمة اختبار',
        'description' => 'وصف المهمة',
        'status' => 'pending',
        'priority' => 'medium',
        'start_date' => now()->format('Y-m-d'),
        'due_date' => now()->addDays(7)->format('Y-m-d'),
        'assignees' => [$employee->id],
    ]);
    
    $response->assertRedirect(route('hrm.tasks.index'));
    $this->assertDatabaseHas('tasks', ['title' => 'مهمة اختبار']);
}
```