merge code
This commit is contained in:
		
						commit
						14fcbd9224
					
				| 
						 | 
				
			
			@ -28,18 +28,39 @@ class ProfileController extends Controller
 | 
			
		|||
        $this->jiraService = $jiraService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getProfilesData()
 | 
			
		||||
    public function getProfilesData(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $user = auth('admins')->user();
 | 
			
		||||
 | 
			
		||||
        $userEmail = $user->email;
 | 
			
		||||
        $projects = $this->jiraService->getAllProjects();
 | 
			
		||||
 | 
			
		||||
        $userCriterias = UserCriteria::with([
 | 
			
		||||
            'sprint',   // Join với bảng sprint
 | 
			
		||||
            'criteria', // Join với bảng criteria
 | 
			
		||||
        ])->where('user_email', $userEmail)->get();
 | 
			
		||||
        $startDate = $request->input('fromDate');
 | 
			
		||||
        $endDate = $request->input('toDate');
 | 
			
		||||
 | 
			
		||||
        $userCriterias = UserCriteria::with([
 | 
			
		||||
            'sprint' => function ($query) use ($startDate, $endDate) {
 | 
			
		||||
                if ($startDate && $endDate) {
 | 
			
		||||
                    $query->whereBetween('complete_date', [$startDate, $endDate]);
 | 
			
		||||
                } elseif ($startDate) {
 | 
			
		||||
                    $query->where('complete_date', '>=', $startDate);
 | 
			
		||||
                } elseif ($endDate) {
 | 
			
		||||
                    $query->where('complete_date', '<=', $endDate);
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            'criteria',
 | 
			
		||||
        ])->where('user_email', $userEmail)
 | 
			
		||||
            ->whereHas('sprint', function ($query) use ($startDate, $endDate) {
 | 
			
		||||
                if ($startDate && $endDate) {
 | 
			
		||||
                    $query->whereBetween('complete_date', [$startDate, $endDate]);
 | 
			
		||||
                } elseif ($startDate) {
 | 
			
		||||
                    $query->where('complete_date', '>=', $startDate);
 | 
			
		||||
                } elseif ($endDate) {
 | 
			
		||||
                    $query->where('complete_date', '<=', $endDate);
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            ->get();
 | 
			
		||||
        // dd($userCriterias);
 | 
			
		||||
        // Xử lý dữ liệu thành cấu trúc mong muốn
 | 
			
		||||
        $projectsData = $userCriterias->groupBy('sprint.project_id')->map(function ($userCriteriasByProject, $projectId) use ($projects) {
 | 
			
		||||
            $result = self::getProjectById($projects, $projectId);
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +70,7 @@ class ProfileController extends Controller
 | 
			
		|||
                    $sprint = $userCriteriasBySprint->first()->sprint;
 | 
			
		||||
                    return [
 | 
			
		||||
                        'name' => $sprint->name,
 | 
			
		||||
                        'complete_date' => $sprint->complete_date ?? '',
 | 
			
		||||
                        'criterias' => $userCriteriasBySprint->map(function ($userCriteria) {
 | 
			
		||||
                            $criteria = $userCriteria->criteria;
 | 
			
		||||
                            return [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,180 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Modules\Admin\app\Http\Controllers;
 | 
			
		||||
 | 
			
		||||
use App\Http\Controllers\Controller;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Modules\Admin\app\Models\Technical;
 | 
			
		||||
use Modules\Admin\app\Models\TechnicalUser;
 | 
			
		||||
use App\Traits\AnalyzeData;
 | 
			
		||||
use App\Traits\HasFilterRequest;
 | 
			
		||||
use App\Traits\HasOrderByRequest;
 | 
			
		||||
use App\Traits\HasSearchRequest;
 | 
			
		||||
use Modules\Admin\app\Models\Admin;
 | 
			
		||||
 | 
			
		||||
class TechnicalController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    use HasOrderByRequest;
 | 
			
		||||
    use HasFilterRequest;
 | 
			
		||||
    use HasSearchRequest;
 | 
			
		||||
    use AnalyzeData;
 | 
			
		||||
 | 
			
		||||
    public function getAllUsers()
 | 
			
		||||
    {
 | 
			
		||||
        $users = Admin::where('permission', 'like', '%staff%')->get()->toArray();
 | 
			
		||||
        return AbstractController::ResultSuccess($users);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllTechnical(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $technicals = new Technical;
 | 
			
		||||
 | 
			
		||||
        // Order by
 | 
			
		||||
        $this->orderByRequest($technicals, $request);
 | 
			
		||||
 | 
			
		||||
        $technicals->orderBy('name', 'asc');
 | 
			
		||||
        // Filter
 | 
			
		||||
        $this->filterRequest(
 | 
			
		||||
            builder: $technicals,
 | 
			
		||||
            request: $request,
 | 
			
		||||
            filterKeys: [
 | 
			
		||||
                'name' => self::F_TEXT,
 | 
			
		||||
                'level' => self::F_TEXT,
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $this->searchRequest(
 | 
			
		||||
            builder: $technicals,
 | 
			
		||||
            value: $request->get('search'),
 | 
			
		||||
            fields: [
 | 
			
		||||
                'name',
 | 
			
		||||
                'level'
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $responseData = $technicals->get();
 | 
			
		||||
 | 
			
		||||
        return AbstractController::ResultSuccess($responseData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function createTechnical(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $request->validate([
 | 
			
		||||
            'name' => 'required|string|max:255',
 | 
			
		||||
            'level' => 'nullable|integer|min:1|max:3',
 | 
			
		||||
        ]);
 | 
			
		||||
        $technical = Technical::create([
 | 
			
		||||
            'name' => $request->name,
 | 
			
		||||
            'level' => $request->level,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        return AbstractController::ResultSuccess($technical, "Technical created successfully!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function deleteTechnical(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $id = $request->input('id');
 | 
			
		||||
        $technical = Technical::find($id);
 | 
			
		||||
        if (!$technical) {
 | 
			
		||||
            return AbstractController::ResultError("Technical not found");
 | 
			
		||||
        }
 | 
			
		||||
        $technical->delete();
 | 
			
		||||
        return AbstractController::ResultSuccess("Technical deleted successfully!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTechnicalsByUserId($userId)
 | 
			
		||||
    {
 | 
			
		||||
        $technicals = TechnicalUser::with('technical')
 | 
			
		||||
            ->where('user_id', $userId)
 | 
			
		||||
            ->get();
 | 
			
		||||
 | 
			
		||||
        if ($technicals->isEmpty()) {
 | 
			
		||||
            return AbstractController::ResultError("No technicals found for this user.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Chuẩn bị dữ liệu để trả về
 | 
			
		||||
        $technicalData = $technicals->map(function ($technicalUser) {
 | 
			
		||||
            return [
 | 
			
		||||
                'id' => $technicalUser->technical->id,
 | 
			
		||||
                'name' => $technicalUser->technical->name,
 | 
			
		||||
                'level' => $technicalUser->technical->level,
 | 
			
		||||
                'point' => $technicalUser->point,
 | 
			
		||||
                'updated_at' => $technicalUser->updated_at
 | 
			
		||||
            ];
 | 
			
		||||
        });
 | 
			
		||||
        return AbstractController::ResultSuccess($technicalData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTechnicalsOfUser()
 | 
			
		||||
    {
 | 
			
		||||
        $userInfo = auth('admins')->user();
 | 
			
		||||
        $userId = $userInfo->id;
 | 
			
		||||
        $technicals = TechnicalUser::with('technical')
 | 
			
		||||
            ->where('user_id', $userId)
 | 
			
		||||
            ->get();
 | 
			
		||||
 | 
			
		||||
        if ($technicals->isEmpty()) {
 | 
			
		||||
            return AbstractController::ResultError("No technicals found for this user.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Chuẩn bị dữ liệu để trả về
 | 
			
		||||
        $technicalData = $technicals->map(function ($technicalUser) {
 | 
			
		||||
            return [
 | 
			
		||||
                'id' => $technicalUser->technical->id,
 | 
			
		||||
                'name' => $technicalUser->technical->name,
 | 
			
		||||
                'level' => $technicalUser->technical->level,
 | 
			
		||||
                'point' => $technicalUser->point,
 | 
			
		||||
                'updated_at' => $technicalUser->updated_at
 | 
			
		||||
            ];
 | 
			
		||||
        });
 | 
			
		||||
        return AbstractController::ResultSuccess($technicalData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getListUserByTechnicalId($technicalId)
 | 
			
		||||
    {
 | 
			
		||||
        $users = TechnicalUser::with('user')
 | 
			
		||||
            ->where('technical_id', $technicalId)
 | 
			
		||||
            ->get();
 | 
			
		||||
 | 
			
		||||
        if ($users->isEmpty()) {
 | 
			
		||||
            return AbstractController::ResultError("No users found for this technical.");
 | 
			
		||||
        }
 | 
			
		||||
        $userData = $users->map(function ($technicalUser) {
 | 
			
		||||
            if ($technicalUser->user) {
 | 
			
		||||
                return [
 | 
			
		||||
                    'user_id' => $technicalUser->user->id ?? "",
 | 
			
		||||
                    'name' => $technicalUser->user->name,
 | 
			
		||||
                    'email' => $technicalUser->user->email,
 | 
			
		||||
                    'point' => $technicalUser->point
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return AbstractController::ResultSuccess($userData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function updateTechnicalsUser(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $userInfo = auth('admins')->user();
 | 
			
		||||
 | 
			
		||||
        $validatedData = $request->validate([
 | 
			
		||||
            'technicals' => 'required|array',
 | 
			
		||||
            'technicals.*.technical_id' => 'required|exists:technicals,id', // Phải tồn tại trong bảng technicals
 | 
			
		||||
            'technicals.*.point' => 'required|integer|min:0|max:3', // Điểm trong khoảng [0-3]
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        // Xóa hết các bản ghi hiện có của user trong bảng technical_users
 | 
			
		||||
        TechnicalUser::where('user_id', $userInfo->id)->delete();
 | 
			
		||||
 | 
			
		||||
        // Duyệt qua mảng technicals và thêm mới dữ liệu
 | 
			
		||||
        foreach ($validatedData['technicals'] as $technical) {
 | 
			
		||||
            TechnicalUser::create([
 | 
			
		||||
                'user_id' => $userInfo->id,
 | 
			
		||||
                'technical_id' => $technical['technical_id'],
 | 
			
		||||
                'point' => $technical['point']
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return AbstractController::ResultSuccess('Technicals for user updated successfully.');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,9 +2,12 @@
 | 
			
		|||
 | 
			
		||||
namespace Modules\Admin\app\Models;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
 | 
			
		||||
use Illuminate\Database\Eloquent\Model;
 | 
			
		||||
 | 
			
		||||
class Technical extends Model
 | 
			
		||||
{
 | 
			
		||||
    use HasFactory;
 | 
			
		||||
 | 
			
		||||
    protected $fillable = ['name', 'level'];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,20 +2,31 @@
 | 
			
		|||
 | 
			
		||||
namespace Modules\Admin\app\Models;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
 | 
			
		||||
use Illuminate\Database\Eloquent\Model;
 | 
			
		||||
 | 
			
		||||
class TechnicalUser extends Model
 | 
			
		||||
{
 | 
			
		||||
    protected $table = 'technicals_users';
 | 
			
		||||
    protected $fillable = ['user_id', 'technical_id', 'point'];
 | 
			
		||||
    use HasFactory;
 | 
			
		||||
 | 
			
		||||
    protected $table = 'technicals_users';
 | 
			
		||||
 | 
			
		||||
    // Các trường có thể được fill
 | 
			
		||||
    protected $fillable = [
 | 
			
		||||
        'user_id',
 | 
			
		||||
        'technical_id',
 | 
			
		||||
        'point',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    // Quan hệ với bảng users
 | 
			
		||||
    public function user()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->belongsTo(User::class, 'user_id', 'id');
 | 
			
		||||
        return $this->belongsTo(User::class, 'user_id');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Quan hệ với bảng technicals
 | 
			
		||||
    public function technical()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->belongsTo(Technical::class, 'technical_id', 'id');
 | 
			
		||||
        return $this->belongsTo(Technical::class, 'technical_id');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ use Modules\Admin\app\Http\Controllers\TrackingController;
 | 
			
		|||
use Modules\Admin\app\Http\Controllers\CriteriasController;
 | 
			
		||||
use Modules\Admin\app\Http\Controllers\EvaluationController;
 | 
			
		||||
use Modules\Admin\app\Http\Controllers\ProfileController;
 | 
			
		||||
use Modules\Admin\app\Http\Controllers\TechnicalController;
 | 
			
		||||
use Modules\Admin\app\Http\Controllers\TestCaseForSprintController;
 | 
			
		||||
use Modules\Admin\app\Http\Middleware\AdminMiddleware;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -182,6 +183,19 @@ Route::middleware('api')
 | 
			
		|||
                Route::get('/technical', [EvaluationController::class, 'technical'])->middleware('check.permission:admin');
 | 
			
		||||
                Route::get('/report', [EvaluationController::class, 'report'])->middleware('check.permission:admin');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            Route::group([
 | 
			
		||||
                'prefix' => 'technical',
 | 
			
		||||
            ], function () {
 | 
			
		||||
                Route::get('/get-all-user', [TechnicalController::class, 'getAllUsers'])->middleware('check.permission:admin');
 | 
			
		||||
                Route::get('/get-all', [TechnicalController::class, 'getAllTechnical']);
 | 
			
		||||
                Route::post('/create', [TechnicalController::class, 'createTechnical'])->middleware('check.permission:admin');
 | 
			
		||||
                Route::get('/delete', [TechnicalController::class, 'deleteTechnical'])->middleware('check.permission:admin');
 | 
			
		||||
                Route::get('/get-tech-of-user', [TechnicalController::class, 'getTechnicalsOfUser']);
 | 
			
		||||
                Route::get('/get-tech-by-user-id/{userId}', [TechnicalController::class, 'getTechnicalsByUserId'])->middleware('check.permission:admin');
 | 
			
		||||
                Route::get('/get-list-user-by-tech-id/{technicalId}', [TechnicalController::class, 'getListUserByTechnicalId'])->middleware('check.permission:admin');
 | 
			
		||||
                Route::post('/technicals-user/update', [TechnicalController::class, 'updateTechnicalsUser']);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -74,3 +74,6 @@ export const createTestCase = API_URL + 'v1/admin/criterias/test-cases'
 | 
			
		|||
//Profile
 | 
			
		||||
export const getProfilesData = API_URL + 'v1/admin/criterias/profiles-data'
 | 
			
		||||
export const updateProfilesData = API_URL + 'v1/admin/criterias/profiles-data/update'
 | 
			
		||||
 | 
			
		||||
export const evaluation = API_URL + 'v1/admin/evaluation/report'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import { getProfilesData } from '@/api/Admin'
 | 
			
		||||
import { evaluation, getProfilesData } from '@/api/Admin'
 | 
			
		||||
import DataTableAll from '@/components/DataTable/DataTable'
 | 
			
		||||
import ProjectInvolvement from '@/components/ProjectInvolvement/ProjectInvolvement'
 | 
			
		||||
import { get } from '@/rtk/helpers/apiService'
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import { notifications } from '@mantine/notifications'
 | 
			
		|||
import moment from 'moment'
 | 
			
		||||
import { useEffect, useState } from 'react'
 | 
			
		||||
import classes from './StaffEvaluation.module.css'
 | 
			
		||||
import axios from 'axios'
 | 
			
		||||
 | 
			
		||||
interface User {
 | 
			
		||||
  id: number
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +82,37 @@ const StaffEvaluation = () => {
 | 
			
		|||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const downloadFile = async () => {
 | 
			
		||||
    await axios({
 | 
			
		||||
      url: evaluation,
 | 
			
		||||
      method: 'GET',
 | 
			
		||||
      responseType: 'blob',
 | 
			
		||||
      headers: {
 | 
			
		||||
        'Content-Type': 'application/json',
 | 
			
		||||
        Authorization: `Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzI2ODE3ODU3LCJleHAiOjE3MjY5MDQyNTcsIm5iZiI6MTcyNjgxNzg1NywianRpIjoid0kzeXM5SGZiV21wS3pONSIsInN1YiI6IjE2IiwicHJ2IjoiZDJmZjI5MzM5YThhM2U4MmMzNTgyYTVhOGU3MzlkZjE3ODliYjEyZiJ9.oEHW0cIlQkawYQMVZnz5TZ5twzY18301eLmXjC55LfY`,
 | 
			
		||||
      },
 | 
			
		||||
      params: {
 | 
			
		||||
        ...filter,
 | 
			
		||||
        userID: 3,
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
      .then((response) => {
 | 
			
		||||
        const fileURL = window.URL.createObjectURL(new Blob([response.data]))
 | 
			
		||||
        const fileLink = document.createElement('a')
 | 
			
		||||
 | 
			
		||||
        fileLink.href = fileURL
 | 
			
		||||
        fileLink.setAttribute('download', 'RENAME_WORD_FILE.docx') // -------------> RENAME_WORD_FILE
 | 
			
		||||
        document.body.appendChild(fileLink)
 | 
			
		||||
 | 
			
		||||
        fileLink.click()
 | 
			
		||||
 | 
			
		||||
        fileLink.remove()
 | 
			
		||||
      })
 | 
			
		||||
      .catch((error) => {
 | 
			
		||||
        console.error('Error downloading the file:', error)
 | 
			
		||||
      })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const fetchData = async () => {
 | 
			
		||||
      const result = await getListProfilesData()
 | 
			
		||||
| 
						 | 
				
			
			@ -193,10 +225,7 @@ const StaffEvaluation = () => {
 | 
			
		|||
        >
 | 
			
		||||
          <Button
 | 
			
		||||
            // m={5}
 | 
			
		||||
            onClick={() => {
 | 
			
		||||
              // setAction('add')
 | 
			
		||||
              // form.reset()
 | 
			
		||||
            }}
 | 
			
		||||
            onClick={() => downloadFile()}
 | 
			
		||||
          >
 | 
			
		||||
            Export
 | 
			
		||||
          </Button>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,4 +3,6 @@ openpyxl
 | 
			
		|||
pyzbar
 | 
			
		||||
opencv-python
 | 
			
		||||
qrcode
 | 
			
		||||
pyautogui
 | 
			
		||||
pyautogui
 | 
			
		||||
requests
 | 
			
		||||
pillow
 | 
			
		||||
		Loading…
	
		Reference in New Issue