Skip to content

Commit

Permalink
feat(eval): export vers excel
Browse files Browse the repository at this point in the history
closes #38
  • Loading branch information
jonathanMelly committed Jun 26, 2023
1 parent 5da33c5 commit 9217503
Show file tree
Hide file tree
Showing 10 changed files with 426 additions and 176 deletions.
10 changes: 10 additions & 0 deletions app/Exports/EvaluationResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace App\Exports;

enum EvaluationResult
{
case A;
case NA;

}
132 changes: 132 additions & 0 deletions app/Exports/EvaluationSheet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

namespace App\Exports;

use App\Services\SummariesService;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Concerns\WithTitle;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class EvaluationSheet implements WithTitle,FromCollection,ShouldAutoSize,WithStyles
{

const NAME_PARTS_SEPARATOR = '|';
private Collection $data;
private string $title;

public function __construct(string $title,Collection $data)
{
$this->data=$data;
$this->title =$title;
}

public function collection()
{
$SUMMARY =0;
$PERCENTAGE=1;
$TIME_A=2;
$TIME_NA=3;

//Format is [bob][[1.1.2021,55%,...,projectName,clients]]
$projects = [
$SUMMARY=>['name'=>'bilan'],
$PERCENTAGE=>['name'=>'%'],
$TIME_A=>['name'=> 'nb pér. '.EvaluationResult::A->name],
$TIME_NA=>['name'=> 'nb pér. '. EvaluationResult::NA->name]
];

//list all projects
$this->data->each(function($studentEvaluations) use(&$projects){
foreach($studentEvaluations as $studentEvaluation){
$project = $studentEvaluation[SummariesService::PI_PROJECT];
$workload = $studentEvaluation[SummariesService::PI_ACCUMULATED_TIME];
$date = $studentEvaluation[SummariesService::PI_DATE];
$client = $studentEvaluation[SummariesService::PI_CLIENTS];
if(!in_array($project,$projects)){
$projects[]=[
'name'=>$project,
'workload'=>$workload,
'date'=>$date,
'client'=>$client];
}
}
});

//Map students / projects data for row/column format
$studentsProjectsMap = [];
foreach($this->data->keys() as $studentId){

$studentEvals = $this->data[$studentId];
$studentEval=[];

//Store result for each project
for($i=0;$i<sizeof($studentEvals);$i++)
{
$studentEval = $studentEvals[$i];

$studentsProjectsMap[$studentId][$studentEval[SummariesService::PI_PROJECT]]=
$studentEval[SummariesService::PI_SUCCESS_TIME]>0?EvaluationResult::A->name : EvaluationResult::NA->name;
}

//Compute summary for student (fake project but still using columns...)
//as data is sorted by date, last eval corresponds to latest status
$summary = $studentEval[SummariesService::PI_CURRENT_PERCENTAGE] >= SummariesService::SUCCESS_REQUIREMENT_IN_PERCENTAGE ?
EvaluationResult::A->name:
EvaluationResult::NA->name;
$studentsProjectsMap[$studentId][$projects[$SUMMARY]['name']]=$summary;

$studentsProjectsMap[$studentId][$projects[$PERCENTAGE]['name']]=
$studentEval[SummariesService::PI_CURRENT_PERCENTAGE].""; //force string for excel (0->'' wihout)

$totalSuccessTime = $studentEval[SummariesService::PI_ACCUMULATED_SUCCESS_TIME].""; //force string for excel (0->'' wihout)
$studentsProjectsMap[$studentId][$projects[$TIME_A]['name']]=$totalSuccessTime;
$studentsProjectsMap[$studentId][$projects[$TIME_NA]['name']]=
($studentEval[SummariesService::PI_ACCUMULATED_TIME]-$totalSuccessTime).""; //force string for excel (0->'' wihout)
}

//Build excel rows
$rows = [];
$header = array_merge(['prénom','nom'],collect($projects)->map(function($p) {
$label =$p['name'];
if(array_key_exists('workload',$p)){
$label .= ' (' . $p['workload'] . 'p, ' .
$p['date'] . ', ' .
$p['client'] . ')';
}
return $label;

})->all());

$rows[0]=$header;
foreach($studentsProjectsMap as $studentId=>$studentProjectsEvals){
[$firstname,$lastname] = explode(self::NAME_PARTS_SEPARATOR,$studentId);
$columns = [$firstname,$lastname];
foreach($projects as $project){
$projectName = $project['name'];
if(array_key_exists($projectName,$studentProjectsEvals)){
$columns[]=$studentProjectsEvals[$projectName];
}else{
$columns[]='';
}
}
$rows[]=$columns;
}

return collect($rows);
}

public function title(): string
{
return $this->title;
}

public function styles(Worksheet $sheet)
{
//Set style
$sheet->getStyle('A1:CC1')->getFont()->setItalic(true)->setBold(true);
$sheet->getStyle('G1:CC1')->getAlignment()->setTextRotation(90);
}
}
39 changes: 39 additions & 0 deletions app/Exports/EvaluationsExport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Exports;

use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;

class EvaluationsExport implements FromCollection,WithMultipleSheets,ShouldAutoSize
{

private Collection $data;

public function __construct(Collection $data)
{
$this->data=$data;
}

public function collection()
{
return $this->data;
}

public function sheets(): array
{
$sheets = [];

//Format is [cin1b][bob][[1.1.2021,55%,...,projectName,clients]]
$this->data->each(
function ($groupEvaluations,$groupName) use (&$sheets){
$sheets[]=new EvaluationSheet($groupName,collect($groupEvaluations));;
}
);

return $sheets;
}

}
34 changes: 34 additions & 0 deletions app/Http/Controllers/EvaluationExportController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\Http\Controllers;

use App\Exports\EvaluationsExport;
use App\Services\SummariesService;
use App\SwissFrenchDateFormat;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;

class EvaluationExportController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request, SummariesService $summariesService)
{
/* @var $evalData Collection*/
$evalData = $summariesService->getEvaluationsSummary(
Auth::user(),
$request->get("academicPeriodId"),
$request->get("timeUnit"),
json:false
);

return Excel::download(new EvaluationsExport($evalData),
'inf-prat-'.now()->format(SwissFrenchDateFormat::DATE_TIME_FS).'.xlsx');
}
}
64 changes: 42 additions & 22 deletions app/Services/SummariesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@
use App\Models\Contract;
use App\Models\User;
use App\Models\WorkerContract;
use Illuminate\Support\Collection;
use LaravelIdea\Helper\App\Models\_IH_WorkerContract_C;

class SummariesService
{
const SUCCESS_REQUIREMENT=80/100;
const SUCCESS_REQUIREMENT_IN_PERCENTAGE = self::SUCCESS_REQUIREMENT*100;

const PI_DATE=0;
const PI_PERCENTAGE=1;
const PI_CURRENT_PERCENTAGE=1;
const PI_SUCCESS_TIME=2;
const PI_TIME=3;
const PI_ACCUMULATED_SUCCESS_TIME=4;
const PI_ACCUMULATED_TIME=5;
const PI_PROJECT=6;
const PI_CLIENTS=7;

public function getEvaluationsSummary(User $user,int $academicPeriodId,int $_timeUnit):string{
/**
* @param User $user
* @param int $academicPeriodId
* @param int $_timeUnit
* @param bool $json
* @return string | Collection data for chart OR raw collection
*/
public function getEvaluationsSummary(User $user, int $academicPeriodId, int $_timeUnit, bool $json=true):string | Collection{

$seriesData=[];
$timeUnit = RequiredTimeUnit::from($_timeUnit);
Expand Down Expand Up @@ -63,14 +73,15 @@ public function getEvaluationsSummary(User $user,int $academicPeriodId,int $_tim
$wContracts = $wContractsBaseQuery
->with('contract.jobDefinition')


->orderByPowerJoins('groupMember.group.groupName.year')
->orderByPowerJoins('groupMember.group.groupName.name')
->orderByPowerJoins('groupMember.user.lastname')
->orderByPowerJoins('groupMember.user.firstname')
->orderBy('success_date')

->get();

$seriesData = array_merge($seriesData, $this->buildSeriesData($wContracts, $timeUnit));
$seriesData = array_merge($seriesData, $this->buildSeriesData($wContracts, $timeUnit,!$json));
}

$period = AcademicPeriod::whereId($academicPeriodId)->firstOrFail();
Expand Down Expand Up @@ -151,32 +162,39 @@ public function getEvaluationsSummary(User $user,int $academicPeriodId,int $_tim
//collect($data)->flatten(2)->groupBy(fn($eval)=>$eval[2])->map(fn($project)=>$project->reduce(fn($carry,$eval2)=>$carry+$eval2[1],0))

//collect($data)->flatten(2)->groupBy(fn($eval)=>$eval[2])->map(fn($project)=>$project->reduce(fn($carry,$eval2)=>[$carry[0]+$eval2[1],'bob'.$carry[1]],[0,'max']))
if(sizeof($seriesData)>0){
return json_encode([
'evaluations'=>$seriesData,
'summaries'=>$summaries,
'datesWindow'=>[
$period->start->format(DateFormat::ECHARTS_FORMAT),
$period->end->format(DateFormat::ECHARTS_FORMAT),
$startZoom->format(DateFormat::ECHARTS_FORMAT),
now()->addDay(5)->format(DateFormat::ECHARTS_FORMAT)
],
'groupsCount'=>count($seriesData)
]);
if($json){
if(sizeof($seriesData)>0){
return json_encode([
'evaluations'=>$seriesData,
'summaries'=>$summaries,
'datesWindow'=>[
$period->start->format(DateFormat::ECHARTS_FORMAT),
$period->end->format(DateFormat::ECHARTS_FORMAT),
$startZoom->format(DateFormat::ECHARTS_FORMAT),
now()->addDay(5)->format(DateFormat::ECHARTS_FORMAT)
],
'groupsCount'=>count($seriesData)
]);
}
return "{}";
}else{
return collect($seriesData);
}
return "{}";



}

/**
* @param \LaravelIdea\Helper\App\Models\_IH_WorkerContract_C|\Illuminate\Database\Eloquent\Collection|array $wContracts
* Format is [cin1b][bob][[1.1.2021,55%,...,projectName,clients]]
*
* @param _IH_WorkerContract_C|\Illuminate\Database\Eloquent\Collection|array $wContracts
* @param RequiredTimeUnit $timeUnit
* @param array $seriesData
* @return array
*/
public function buildSeriesData(\LaravelIdea\Helper\App\Models\_IH_WorkerContract_C|\Illuminate\Database\Eloquent\Collection|array $wContracts, RequiredTimeUnit $timeUnit): array
public function buildSeriesData(_IH_WorkerContract_C|\Illuminate\Database\Eloquent\Collection|array $wContracts,
RequiredTimeUnit $timeUnit,
bool $fullName=false): array
{
$seriesData=[];
$accumulatedTime = 0;
Expand All @@ -191,7 +209,9 @@ public function buildSeriesData(\LaravelIdea\Helper\App\Models\_IH_WorkerContrac

$groupMember = $wContract->groupMember;
$worker = $groupMember->user;
$workerName = $worker->getFirstnameL();
$workerName = $fullName ?
$worker->firstname.'|'.$worker->lastname:
$worker->getFirstnameL();
//Worker switch, reset accumulators
//[for perf reasons, all data is fetched with 1 request with all contracts sorted by userid...]
if($workerName!=$previousWorkerName){
Expand Down Expand Up @@ -219,7 +239,7 @@ public function buildSeriesData(\LaravelIdea\Helper\App\Models\_IH_WorkerContrac
//ATTENTION: for echarts series format (as currently used), first 2 infos are X and Y ...
$seriesData[$group][$workerName][] = [
self::PI_DATE=> $formattedDate,
self::PI_PERCENTAGE=> $percentage,
self::PI_CURRENT_PERCENTAGE=> $percentage,
self::PI_SUCCESS_TIME => $successTime,
self::PI_TIME=> $time,
self::PI_ACCUMULATED_SUCCESS_TIME=> $accumulatedSuccessTime,
Expand Down
1 change: 1 addition & 0 deletions app/SwissFrenchDateFormat.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class SwissFrenchDateFormat
{
public const DATE = 'd.m.Y';
public const DATE_TIME = 'd.m.Y H:i:s';
public const DATE_TIME_FS = 'd.m.Y-H_i_s';


}
4 changes: 3 additions & 1 deletion lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,5 +307,7 @@
"Evaluation summary": "Bilan d’évaluation",
"Evolution": "Évolution",
"Success rate": "Taux de réussite",
"Current summary": "Bilan à cette date"
"Current summary": "Bilan à cette date",
"Download": "Télécharger",
"Export": "Exporter"
}
Loading

0 comments on commit 9217503

Please sign in to comment.