Compare commits

..

11 Commits

Author SHA1 Message Date
a3f54b2f11 reconf env.model 2023-09-06 14:23:54 +02:00
386d639151 gestion composer 1 & 2 2023-08-31 15:43:48 +02:00
a2899ee93b correctif breakday 2023-08-31 11:10:50 +02:00
efe978130c rest breakday depuis depuis début ninebadge 2023-08-25 15:43:56 +02:00
9c752523b4 rest breakday depuis depuis début ninebadge 2023-08-25 15:42:28 +02:00
afornerot
43c1b6f5ce correction feriées sur synthèse (fix #82) 2023-05-16 17:20:38 +02:00
afornerot
bfedc2f593 déblocage du max 1ETP par jour 2022-09-08 13:42:28 +02:00
afornerot
f1baf4d87e ne plus tenter de notifier (fixe #78) 2022-09-07 11:23:07 +02:00
afornerot
57220794b9 prise en compte des breakday à posteriori 2022-03-14 11:51:07 +01:00
afornerot
3edae845f0 mise en place d'un controleur REST 2022-02-14 09:59:14 +01:00
0ba36598fa ajout du l'activité et du domaine dans l'export (fixes #77) 2021-11-23 14:55:23 +01:00
27 changed files with 368 additions and 211 deletions

1
debian/compat vendored
View File

@@ -1 +0,0 @@
7

24
debian/control vendored
View File

@@ -1,24 +0,0 @@
Source: eole-schedule
Section: web
Priority: optional
Maintainer: Cadoles <contact@cadoles.com>
Build-Depends: debhelper (>= 7.0.50)
Standards-Version: 3.8.4
Homepage: https://forge.cadoles.com/Cadoles/schedule
Vcs-Git: https://forge.cadoles.com/Cadoles/schedule
Vcs-Browser: https://forge.cadoles.com/Cadoles/schedule
Package: schedule-sso
Architecture: all
Depends: ${misc:Depends}, eole-sso
Description: Filtre SSO pour schedule "EOLE".
Package: eole-schedule
Architecture: all
Depends: ${misc:Depends}, eole-envole-dependances, schedule-sso
Description: Eolisation de l'application schedule.
Package: schedule-apps
Architecture: all
Depends: ${misc:Depends}, envole-dependances-apps
Description: Sources pour schedule "EOLE".

44
debian/copyright vendored
View File

@@ -1,44 +0,0 @@
Format: http://dep.debian.net/deps/dep5
Upstream-Name: {PROJECT}
Source: {URL}
Files: *
Copyright: YEAR {UPSTREAM} {AUTHOR} <{MAIL}>
License: {UPSTREAM LICENSE}
Files: debian/*
Copyright: 2012 Équipe EOLE <eole@ac-dijon.fr>
License: CeCILL-2
License: {UPSTREAM LICENSE}
{TEXT OF THE LICENSE}
License: CeCILL-2
This software is governed by the CeCILL-2 license under French law and
abiding by the rules of distribution of free software. You can use,
modify and or redistribute the software under the terms of the CeCILL-2
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info";.
.
As a counterpart to the access to the source code and rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty and the software's author, the holder of the
economic rights, and the successive licensors have only limited
liability.
.
In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and, more generally, to use and operate it in the
same conditions as regards security.
.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL-2 license and that you accept its terms.
.
On Eole systems, the complete text of the CeCILL-2 License can be found
in '/usr/share/common-licenses/CeCILL-2-en'.

View File

@@ -1 +0,0 @@
usr/share/eole

3
debian/gbp.conf vendored
View File

@@ -1,3 +0,0 @@
# Set per distribution debian tag
[DEFAULT]
debian-tag = debian/envole/%(version)s

8
debian/rules vendored
View File

@@ -1,8 +0,0 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@

View File

@@ -1 +0,0 @@
var/www/html

View File

@@ -1 +0,0 @@
usr/share/sso

View File

@@ -1 +0,0 @@
3.0 (native)

View File

@@ -6,7 +6,9 @@
<containers> <containers>
<container name='web'> <container name='web'>
<package>schedule-apps</package> <!--
<package>schedule-apps</package>
-->
<!-- service de configuration apache --> <!-- service de configuration apache -->
<service method="apache" servicelist="schedule">schedule</service> <service method="apache" servicelist="schedule">schedule</service>

View File

@@ -51,7 +51,10 @@
"preferred-install": { "preferred-install": {
"*": "dist" "*": "dist"
}, },
"sort-packages": true "sort-packages": true,
"allow-plugins": {
"symfony/flex": true
}
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@@ -72,6 +75,9 @@
"symfony/polyfill-php56": "*" "symfony/polyfill-php56": "*"
}, },
"scripts": { "scripts": {
"pre-install-cmd": [
"php scripts/checkcomposer.php"
],
"auto-scripts": { "auto-scripts": {
"cache:clear": "symfony-cmd", "cache:clear": "symfony-cmd",
"cache:clear --env=prod": "symfony-cmd", "cache:clear --env=prod": "symfony-cmd",

View File

@@ -1,15 +1,11 @@
# Read the documentation: https://symfony.com/doc/master/bundles/FOSRestBundle/index.html # Read the documentation: https://symfony.com/doc/master/bundles/FOSRestBundle/index.html
fos_rest: null fos_rest:
# param_fetcher_listener: true param_fetcher_listener: true
# allowed_methods_listener: true body_listener: true
# routing_loader: true
# view: format_listener:
# view_response_listener: true enabled: true
# exception: rules:
# codes: - { path: '/rest', priorities: ['json', 'xml'], fallback_format: 'html' }
# App\Exception\MyException: 403 - { path: '/', fallback_format: 'html' }
# messages:
# App\Exception\MyException: Forbidden area.
# format_listener:
# rules:
# - { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json, html ] }

View File

@@ -1,9 +1,9 @@
nelmio_api_doc: nelmio_api_doc:
documentation: documentation:
info: info:
title: My App title: '%appName%'
description: This is an awesome app! description:
version: 1.0.0 version: 1.0.0
areas: # to filter documented areas areas: # to filter documented areas
path_patterns: path_patterns:
- ^/api(?!/doc$) # Accepts routes under /api except /api/doc - /rest # Accepts routes under /rest except /rest/doc

View File

@@ -1,12 +1,4 @@
# Expose your documentation as JSON swagger compliant app_swagger_ui:
app.swagger: path: /rest
path: /api/doc.json
methods: GET methods: GET
defaults: { _controller: nelmio_api_doc.controller.swagger } defaults: { _controller: nelmio_api_doc.controller.swagger_ui }
## Requires the Asset component and the Twig bundle
## $ composer require twig asset
#app.swagger_ui:
# path: /api/doc
# methods: GET
# defaults: { _controller: nelmio_api_doc.controller.swagger_ui }

View File

@@ -6,6 +6,7 @@
parameters: parameters:
appAlias: '%env(resolve:APP_ALIAS)%' appAlias: '%env(resolve:APP_ALIAS)%'
appAuth: '%env(resolve:APP_AUTH)%' appAuth: '%env(resolve:APP_AUTH)%'
appSecret: '%env(resolve:APP_SECRET)%'
appName: '%env(resolve:APP_NAME)%' appName: '%env(resolve:APP_NAME)%'
appEnv: '%env(resolve:APP_ENV)%' appEnv: '%env(resolve:APP_ENV)%'
appCron: '%env(resolve:APP_CRON)%' appCron: '%env(resolve:APP_CRON)%'
@@ -80,3 +81,6 @@ services:
public: true public: true
class: App\Service\mailService class: App\Service\mailService
arguments: ["@mailer", "@twig"] arguments: ["@mailer", "@twig"]
App\Controller\RestController:
public: true

View File

@@ -0,0 +1,13 @@
<?php
$requiredVersion = 'version 1'; // La version interdite
$composerVersion = trim(shell_exec('COMPOSER_ALLOW_SUPERUSER=1 composer --version --no-ansi'));
echo $composerVersion."\n";
if (stripos($composerVersion,$requiredVersion)===false ) {
echo "La version de Composer $requiredVersion n'est pas autorisée" . PHP_EOL;
echo "Veuillez mettre à jour Composer avec 'composer self-update --1'." . PHP_EOL;
echo "Ou executez le scripts/reconfigure.sh" . PHP_EOL;
exit(1); // Quitte avec un code d'erreur
}

View File

@@ -1,4 +1,2 @@
#!/bin/bash #!/bin/bash
# Si besoin export des valeurs de HTTP_PROXY et HTTPS_PROXY # Si besoin export des valeurs de HTTP_PROXY et HTTPS_PROXY
export HTTP_PROXY="192.168.57.160:8080"
export HTTPS_PROXY="192.168.57.160:8080"

View File

@@ -6,12 +6,13 @@ cd /var/www/html/schedule
. scripts/proxy.sh . scripts/proxy.sh
# Mise en place du fichier d'environnement model # Mise en place du fichier d'environnement model
if [ ! -f /var/www/html/schedule/.env ]; then yes 2>/dev/null | cp /var/www/html/schedule/scripts/.env.model $DIR/.env
mv /var/www/html/schedule/scripts/.env.model /var/www/html/schedule/.env
fi
# Installation des dépendances composer # Installation des dépendances composer
composer install echo COMPOSER = Install
export COMPOSER_ALLOW_SUPERUSER=1
composer self-update --1 --quiet
composer install --quiet
php bin/console app:AppInit --env=prod php bin/console app:AppInit --env=prod
php bin/console app:CronInit --env=prod php bin/console app:CronInit --env=prod

View File

@@ -174,7 +174,13 @@ class EventController extends AbstractController
// Astreinte // Astreinte
if($astreinte) { if($astreinte) {
// On regarde si une tache ne commence pas pendant une autre intervention ou qui se termine pendant une autre intervention ou qui a une intervention compris dans ses dates // Une astreinte ne peut-etre un congès
if($task->getNature()->getIsvacation()) {
$output=["return"=>"KO","error"=>"Une astreinte ne peut être de nature congès","start"=>$datestart,"end"=>$dateend,"events"=>null];
return new Response(json_encode($output));
}
// On regarde si une astreinte ne commence pas pendant une autre astreinte ou qui se termine pendant une autre astreinte ou qui a une astreinte compris dans ses dates
$penaltys = $em->createQueryBuilder('penalty') $penaltys = $em->createQueryBuilder('penalty')
->select('penalty') ->select('penalty')
->from('App:Penalty','penalty') ->from('App:Penalty','penalty')
@@ -199,6 +205,42 @@ class EventController extends AbstractController
return new Response(json_encode($output)); return new Response(json_encode($output));
} }
// On regarde si un évenement ne commence pas pendant un autre évenement ou qui se termine pendant un autre évenement ou qui a un évenement compris dans ses dates
$events = $em->createQueryBuilder('event')
->select('event')
->from('App:Event','event')
->Where('event.user=:user AND event.start<=:start AND event.end >:start')
->orWhere('event.user=:user AND event.start<:end AND event.end >=:end')
->orWhere('event.user=:user AND event.start>:start AND event.end <:end')
->setParameter('user',$iduser)
->setParameter('start',$datestart)
->setParameter('end',$dateend)
->getQuery()->getResult();
if($events) {
$tbevent=[];
$validate=false;
$holiday=false;
foreach($events as $event) {
$tmp=[
"id" => $event->getId(),
"start" => $event->getStart(),
"end" => $event->getEnd(),
];
array_push($tbevent,$tmp);
if($event->getValidate()) $validate=true;
if($event->getTask()->getNature()->getIsvacation()) $holiday=true;
}
if($validate) {
$output=["return"=>"KO","error"=>"Cet intervant a sa semaine de validé","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
elseif($holiday) {
$output=["return"=>"KO","error"=>"Cet intervant a posé des congés sur cette période","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
}
// Création de l'astreinte // Création de l'astreinte
$penalty = new Penalty(); $penalty = new Penalty();
$penalty->setStart($datestart); $penalty->setStart($datestart);
@@ -232,6 +274,8 @@ class EventController extends AbstractController
->getQuery()->getResult(); ->getQuery()->getResult();
if($events) { if($events) {
$tbevent=[]; $tbevent=[];
$validate=false;
$holiday=false;
foreach($events as $event) { foreach($events as $event) {
$tmp=[ $tmp=[
"id" => $event->getId(), "id" => $event->getId(),
@@ -239,9 +283,26 @@ class EventController extends AbstractController
"end" => $event->getEnd(), "end" => $event->getEnd(),
]; ];
array_push($tbevent,$tmp); array_push($tbevent,$tmp);
if($event->getValidate()) $validate=true;
if($event->getTask()->getNature()->getIsvacation()) $holiday=true;
}
if(!$this->isGranted('ROLE_ADMIN')&&!$this->isGranted('ROLE_MASTER')) {
$output=["return"=>"KO","error"=>"Cet intervant a déjà une tache à cette date","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
elseif($validate) {
$output=["return"=>"KO","error"=>"Cet intervant a sa semaine de validé","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
elseif($holiday) {
$output=["return"=>"KO","error"=>"Cet intervant a posé des congés sur cette période","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
elseif($task->getNature()->getIsvacation()) {
$output=["return"=>"KO","error"=>"Vous ne pouvez pas poser de congés à cette date, une intervention y est déjà plannifiée","start"=>$datestart,"end"=>$dateend,"events"=>null];
return new Response(json_encode($output));
} }
$output=["return"=>"KO","error"=>"Cet intervant a déjà une tache à cette date","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
} }
// On regarde si un jour férié ne commence pas pendant une autre intervention ou qui se termine pendant une autre intervention ou qui a une intervention compris dans ses dates // On regarde si un jour férié ne commence pas pendant une autre intervention ou qui se termine pendant une autre intervention ou qui a une intervention compris dans ses dates
@@ -288,7 +349,7 @@ class EventController extends AbstractController
$idevent=$event->getId(); $idevent=$event->getId();
//$valid_url = $this->generateUrl('app_validationholiday',[],true); //$valid_url = $this->generateUrl('app_validationholiday',[],true);
$valid_url = $this->router->generate('app_validationholiday', [], urlGeneratorInterface::ABSOLUTE_URL); $valid_url = $this->router->generate('app_validationholiday', [], urlGeneratorInterface::ABSOLUTE_URL);
$this->notificator->sendNotifAttenteValid("Congés en attente de validation", $iduser, $idevent, $valid_url); // $this->notificator->sendNotifAttenteValid("Congés en attente de validation", $iduser, $idevent, $valid_url);
} }
@@ -328,6 +389,12 @@ class EventController extends AbstractController
// Astreinte // Astreinte
if($fgastreinte) { if($fgastreinte) {
// Une astreinte ne peut-etre un congès
if($task->getNature()->getIsvacation()) {
$output=["return"=>"KO","error"=>"Une astreinte ne peut être de nature congès"];
return new Response(json_encode($output));
}
// Recherche de l'event // Recherche de l'event
$penalty = $em->getRepository("App:Penalty")->find($idevent); $penalty = $em->getRepository("App:Penalty")->find($idevent);
if(!$penalty) { if(!$penalty) {
@@ -394,6 +461,7 @@ class EventController extends AbstractController
$dateend->SetTime(17,0,0); $dateend->SetTime(17,0,0);
} }
} }
// On regarde si une tache ne commence pas pendant une autre intervention ou qui se termine pendant une autre intervention ou qui a une intervention compris dans ses dates // On regarde si une tache ne commence pas pendant une autre intervention ou qui se termine pendant une autre intervention ou qui a une intervention compris dans ses dates
$events = $em->createQueryBuilder('event') $events = $em->createQueryBuilder('event')
->select('event') ->select('event')
@@ -407,6 +475,9 @@ class EventController extends AbstractController
->getQuery()->getResult(); ->getQuery()->getResult();
if($events) { if($events) {
$tbevent=[]; $tbevent=[];
$validate=false;
$holiday=false;
foreach($events as $ev) { foreach($events as $ev) {
if ($event->getId() != $ev->getId()) { if ($event->getId() != $ev->getId()) {
$tmp=[ $tmp=[
@@ -416,11 +487,28 @@ class EventController extends AbstractController
"end" => $ev->getEnd(), "end" => $ev->getEnd(),
]; ];
array_push($tbevent,$tmp); array_push($tbevent,$tmp);
if($ev->getValidate()) $validate=true;
if($ev->getTask()->getNature()->getIsvacation()) $holiday=true;
} }
} }
if (sizeof($tbevent)>0) { if (sizeof($tbevent)>0) {
$output=["return"=>"KO","error"=>"Cet intervant a déjà une tache à cette date","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent]; if(!$this->isGranted('ROLE_ADMIN')&&!$this->isGranted('ROLE_MASTER')) {
return new Response(json_encode($output)); $output=["return"=>"KO","error"=>"Cet intervant a déjà une tache à cette date","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
elseif($validate) {
$output=["return"=>"KO","error"=>"Cet intervant a sa semaine de validé","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
elseif($holiday) {
$output=["return"=>"KO","error"=>"Cet intervant a posé des congés sur cette période","start"=>$datestart,"end"=>$dateend,"events"=>$tbevent];
return new Response(json_encode($output));
}
elseif($task->getNature()->getIsvacation()) {
$output=["return"=>"KO","error"=>"Vous ne pouvez pas poser de congés à cette date, une intervention y est déjà plannifiée","start"=>$datestart,"end"=>$dateend,"events"=>null];
return new Response(json_encode($output));
}
} }
} }

View File

@@ -262,6 +262,8 @@ class ExportController extends AbstractController
$tbproject["projectname"] = $project->getDisplayname(); $tbproject["projectname"] = $project->getDisplayname();
$tbproject["name"] = $project->getname(); $tbproject["name"] = $project->getname();
$tbproject["customer"] = $project->getCustomer()->getName(); $tbproject["customer"] = $project->getCustomer()->getName();
$tbproject["service"] = $project->getService()->getName();
$tbproject["domaine"] = $project->getDomaine()->getName();
// Somme event validé par semaine // Somme event validé par semaine
$start=new \Datetime('first day of this month'); $start=new \Datetime('first day of this month');
$start->sub(new \DateInterval('P'.$nbmonth.'M')); $start->sub(new \DateInterval('P'.$nbmonth.'M'));

View File

@@ -53,15 +53,7 @@ class ReportController extends AbstractController
$tmp["events"][$idday] = [ $tmp["events"][$idday] = [
"date"=>clone $start, "date"=>clone $start,
"allday"=>false, "events"=>[],
"colorday"=>"",
"descriptionday"=>"",
"am"=>false,
"coloram"=>"",
"descriptionam"=>"",
"ap"=>false,
"colorap"=>"",
"descriptionap"=>"",
"astreinte"=>false, "astreinte"=>false,
"colorastreinte"=>"", "colorastreinte"=>"",
"descriptionastreinte"=>"", "descriptionastreinte"=>"",
@@ -99,22 +91,16 @@ class ReportController extends AbstractController
while($st<$event->getEnd()) { while($st<$event->getEnd()) {
$idday=$st->format("Ymd"); $idday=$st->format("Ymd");
if($event->getAllday()) { if($event->getAllday()) {
$tmp["events"][$idday]["allday"]=true; $tmp["events"][$idday]["events"][$event->getId()]=["allday"=>true,"colorday"=>$event->getTask()->getColor(),"descriptionday"=>strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription()];
$tmp["events"][$idday]["colorday"]=$event->getTask()->getColor();
$tmp["events"][$idday]["descriptionday"]=strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription();
} }
else { else {
// Matin ou après-midi ? // Matin ou après-midi ?
$time=$event->getStart()->format("H"); $time=$event->getStart()->format("H");
if($time==9) { if($time==9) {
$tmp["events"][$idday]["am"]=true; $tmp["events"][$idday]["events"][$event->getId()]=["allday"=>false,"am"=>true,"ap"=>false,"coloram"=>$event->getTask()->getColor(),"descriptionam"=>strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription()];
$tmp["events"][$idday]["coloram"]=$event->getTask()->getColor();
$tmp["events"][$idday]["descriptionam"]=strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription();
} }
else { else {
$tmp["events"][$idday]["ap"]=true; $tmp["events"][$idday]["events"][$event->getId()]=["allday"=>false,"am"=>false,"ap"=>true,"colorap"=>$event->getTask()->getColor(),"descriptionap"=>strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription()];
$tmp["events"][$idday]["colorap"]=$event->getTask()->getColor();
$tmp["events"][$idday]["descriptionap"]=strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription();
} }
} }
@@ -180,18 +166,19 @@ class ReportController extends AbstractController
$st=clone $breakday->getStart(); $st=clone $breakday->getStart();
while($st<$breakday->getEnd()) { while($st<$breakday->getEnd()) {
$idday=$st->format("Ymd"); $idday=$st->format("Ymd");
$tmp["events"][$idday]["allday"]=true; $tmp["events"][$idday]["events"][-2000]["allday"]=true;
$tmp["events"][$idday]["colorday"]="#6c7a89"; $tmp["events"][$idday]["events"][-2000]["colorday"]="#6c7a89";
$tmp["events"][$idday]["descriptionday"]="Jour Férié"; $tmp["events"][$idday]["events"][-2000]["descriptionday"]="Jour Férié";
$st->add(new \DateInterval('P1D')); $st->add(new \DateInterval('P1D'));
} }
} }
array_push($tbevents,$tmp); array_push($tbevents,$tmp);
} }
} }
//dump($tbevents);
if($request->query->get('fgprint')) { if($request->query->get('fgprint')) {
$render = $this->renderView('Report/synthese.html.twig',[ $render = $this->renderView('Report/synthese.html.twig',[
"useheader" => true, "useheader" => true,

View File

@@ -0,0 +1,132 @@
<?php
namespace App\Controller;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\Annotations as FOSRest;
use Swagger\Annotations as SWG;
use App\Entity\Cache;
class RestController extends AbstractFOSRestController
{
private $output=[];
private $cpt;
/**
* Return list of maps
*
*
* @FOSRest\Post("/rest/getBreakdays")
* @SWG\Response(
* response=200,
* description="Return list of breakday events"
* )
* )
* @SWG\Parameter(
* name="key",
* in="formData",
* required=true,
* description="APIKey",
* type="string"
* )
* @SWG\Parameter(
* name="username",
* in="formData",
* required=true,
* description="username",
* type="string"
* )
*/
public function getBreakdays(Request $request) {
set_time_limit(0);
ini_set('memory_limit', '1024M');
// Initalisation Manager
$em = $this->getDoctrine()->getManager();
// Récupération des parametres
$key=$request->get("key");
$username=$request->get("username");
if($key!=$this->getParameter("appSecret")) {
$view = $this->view("API Key inconnue", 403);
return $this->handleView($view);
}
$user=$em->getRepository("App:User")->findOneBy(["username"=>$username]);
if(!$user) {
$view = $this->view("User inconnue", 403);
return $this->handleView($view);
}
// On formate le tableau de jour
$start=new \Datetime('2022-03-07 00:00');
$end=new \Datetime('00:00');
$end->modify("last day of this month");
$end->modify("next sunday");
$events = $em
->createQueryBuilder('event')
->select('event')
->from('App:Event','event')
->Where('event.user=:user AND event.start>=:start AND event.end <:end')
->setParameter('user',$user)
->setParameter('start',$start)
->setParameter('end',$end)
->getQuery()->getResult();
$output=[
"start"=>$start->format("d/m/Y"),
"end"=>$end->format("d/m/Y"),
"events"=>[],
];
$tbnature=[-200,-190,-100];
foreach($events as $event) {
if(in_array($event->getTask()->getNature()->getId(),$tbnature)) {
$tmp = [
"eventstart"=>$event->getStart(),
"eventend"=>$event->getEnd(),
"eventallday"=>$event->getAllday(),
"taskid"=>$event->getTask()->getId(),
"taskname"=>$event->getTask()->getName(),
"natureid"=>$event->getTask()->getNature()->getId(),
"naturename"=>$event->getTask()->getNature()->getName(),
];
array_push($output["events"],$tmp);
}
}
$events = $em
->createQueryBuilder('breakday')
->select('breakday')
->from('App:Breakday','breakday')
->Where('breakday.start>=:start AND breakday.end <:end')
->setParameter('start',$start)
->setParameter('end',$end)
->getQuery()->getResult();
foreach($events as $event) {
$tmp = [
"eventstart"=>$event->getStart(),
"eventend"=>$event->getEnd(),
"eventallday"=>true,
"taskid"=>null,
"taskname"=>"Jour Férié",
"natureid"=>null,
"naturename"=>"Jour Férié",
];
array_push($output["events"],$tmp);
}
$view = $this->view($output, 200);
return $this->handleView($view);
}
}

View File

@@ -101,16 +101,7 @@ class ValidationController extends AbstractController
$tmp["events"][$idday] = [ $tmp["events"][$idday] = [
"date"=>clone $start, "date"=>clone $start,
"allday"=>false, "events"=>[],
"colorday"=>"",
"descriptionday"=>"",
"am"=>false,
"coloram"=>"",
"descriptionam"=>"",
"ap"=>false,
"colorap"=>"",
"descriptionap"=>"",
"validate"=>$validate,
"astreinte"=>false, "astreinte"=>false,
"colorastreinte"=>"", "colorastreinte"=>"",
"descriptionastreinte"=>"", "descriptionastreinte"=>"",
@@ -138,22 +129,16 @@ class ValidationController extends AbstractController
while($st<$event->getEnd()) { while($st<$event->getEnd()) {
$idday=$st->format("Ymd"); $idday=$st->format("Ymd");
if($event->getAllday()) { if($event->getAllday()) {
$tmp["events"][$idday]["allday"]=true; $tmp["events"][$idday]["events"][$event->getId()]=["allday"=>true,"colorday"=>$event->getTask()->getColor(),"descriptionday"=>strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription(),"validate"=>$event->getValidate()];
$tmp["events"][$idday]["colorday"]=$event->getTask()->getColor();
$tmp["events"][$idday]["descriptionday"]=strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription();
} }
else { else {
// Matin ou après-midi ? // Matin ou après-midi ?
$time=$event->getStart()->format("H"); $time=$event->getStart()->format("H");
if($time==9) { if($time==9) {
$tmp["events"][$idday]["am"]=true; $tmp["events"][$idday]["events"][$event->getId()]=["allday"=>false,"am"=>true,"ap"=>false,"coloram"=>$event->getTask()->getColor(),"descriptionam"=>strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription(),"validate"=>$event->getValidate()];
$tmp["events"][$idday]["coloram"]=$event->getTask()->getColor();
$tmp["events"][$idday]["descriptionam"]=strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription();
} }
else { else {
$tmp["events"][$idday]["ap"]=true; $tmp["events"][$idday]["events"][$event->getId()]=["allday"=>false,"am"=>false,"ap"=>true,"colorap"=>$event->getTask()->getColor(),"descriptionap"=>strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription(),"validate"=>$event->getValidate()];
$tmp["events"][$idday]["colorap"]=$event->getTask()->getColor();
$tmp["events"][$idday]["descriptionap"]=strtoupper($event->getTask()->getDisplayname())."\n\n".$event->getDescription();
} }
} }
@@ -295,7 +280,7 @@ class ValidationController extends AbstractController
} }
} }
if($duration!= 5) { if($duration< 5) {
$output=["return"=>"KO","error"=>"Validation impossible = semaine incomplète"]; $output=["return"=>"KO","error"=>"Validation impossible = semaine incomplète"];
return new Response(json_encode($output)); return new Response(json_encode($output));
} }
@@ -500,7 +485,7 @@ class ValidationController extends AbstractController
$em->flush(); $em->flush();
$iduser=$event->getUser()->getId(); $iduser=$event->getUser()->getId();
$idevent=$event->getId(); $idevent=$event->getId();
$this->notificator->sendNotifValid("Congé validé", $iduser, $event); // $this->notificator->sendNotifValid("Congé validé", $iduser, $event);
} }
$output=[]; $output=[];

View File

@@ -227,6 +227,20 @@
"phpdocumentor/type-resolver": { "phpdocumentor/type-resolver": {
"version": "1.1.0" "version": "1.1.0"
}, },
"phpunit/phpunit": {
"version": "8.5",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "4.7",
"ref": "db276258424d15e572d35a4eb834b8f815662b25"
},
"files": [
".env.test",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"psr/cache": { "psr/cache": {
"version": "1.0.1" "version": "1.0.1"
}, },

View File

@@ -1,12 +1,12 @@
{% block body %} {% block body %}
Client;Projet;Tâche;Nature;Utilisateur;Année;Semaine;Cumul; Client;Projet;Tâche;Activité;Domaine;Nature;Utilisateur;Année;Semaine;Cumul;
{% for project in projects %} {% for project in projects %}
{% if project.weeks_by_task_by_user is defined %} {% if project.weeks_by_task_by_user is defined %}
{% for year,weeks in project.weeks_by_task_by_user %} {% for year,weeks in project.weeks_by_task_by_user %}
{% for week in weeks %} {% for week in weeks %}
{% for task in week.tasks%} {% for task in week.tasks%}
{% for user in task.users%} {% for user in task.users%}
{{project.customer}};{{project.name}};{{task.taskname|replace({"&": "et"})}};{{task.nature}};{{user.displayname}};{{week.isoyear}};{{week.isoweek}};{{user.cumul|replace({".": ","})}}; {{project.customer}};{{project.name}};{{task.taskname|replace({"&": "et"})}};{{project.service}};{{project.domaine}};{{task.nature}};{{user.displayname}};{{week.isoyear}};{{week.isoweek}};{{user.cumul|replace({".": ","})}};
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}

View File

@@ -35,6 +35,7 @@
float:left; float:left;
width:100%; width:100%;
height: 18px; height: 18px;
flex: 0 0 auto;
} }
.am, .ap { .am, .ap {
@@ -42,6 +43,7 @@
float:left; float:left;
width:50%; width:50%;
height: 18px; height: 18px;
flex: 0 0 auto;
} }
.astreinte { .astreinte {
@@ -83,27 +85,30 @@
{% endif %} {% endif %}
<td> <td>
<div class="date">{{ event.date | date("d/m") }}</div> <div class="date">{{ event.date | date("d/m") }}</div>
{% if event.allday %} <div class="d-flex flex-wrap">
<div class='allday' style='background-color:{{ event.colorday }};' title='{{ event.descriptionday }}'>1</div> {% set haveam=false %}
{% else %} {% for detail in event.events %}
{%if event.am %} {% if detail.allday %}
<div class='am' style='background-color:{{ event.coloram }};' title='{{ event.descriptionam }}'>0.5</div> <div class='allday' style='background-color:{{ detail.colorday }};' title='{{ detail.descriptionday }}'>1</div>
{% else %} {% else %}
<div class='am'></div> {%if detail.am %}
{% endif %} {% set haveam=true %}
<div class='am' style='background-color:{{ detail.coloram }};' title='{{ detail.descriptionam }}'>0.5</div>
{% endif %}
{%if event.ap %} {%if detail.ap %}
<div class='ap' style='background-color:{{ event.colorap }};' title='{{ event.descriptionap }}'>0.5</div> {% if not haveam %}<div class='am'></div>{%endif%}
{% else %} <div class='ap ml-auto' style='background-color:{{ detail.colorap }};' title='{{ detail.descriptionap }}'>0.5</div>
<div class='ap'></div> {% endif %}
{% endif %} {% endif %}
{% endif %} {% endfor %}
{% if event.astreinte %} {% if event.astreinte %}
<div class='astreinte' style='background-color:{{ event.colorastreinte }};' title='{{ event.descriptionastreinte }}'>*</div> <div class='astreinte' style='background-color:{{ event.colorastreinte }};' title='{{ event.descriptionastreinte }}'>*</div>
{% else %} {% else %}
<div class='astreinte'></div> <div class='astreinte'></div>
{% endif %} {% endif %}
</div>
</td> </td>
{% set nbday=nbday+1 %} {% set nbday=nbday+1 %}
@@ -126,4 +131,14 @@
function myprint() { function myprint() {
document.location.href="{{path(app.request.attributes.get('_route'),{fgprint:true})}}"; document.location.href="{{path(app.request.attributes.get('_route'),{fgprint:true})}}";
} }
$(document).ready(function() {
maxheight=0;
$( ".card" ).each(function( index ) {
if($(this).height()>maxheight)
maxheight=$(this).height();
});
$( ".card" ).height(maxheight);
});
{% endblock %} {% endblock %}

View File

@@ -35,6 +35,7 @@
float:left; float:left;
width:100%; width:100%;
height: 18px; height: 18px;
flex: 0 0 auto;
} }
.am, .ap { .am, .ap {
@@ -42,6 +43,7 @@
float:left; float:left;
width:50%; width:50%;
height: 18px; height: 18px;
flex: 0 0 auto;
} }
.astreinte { .astreinte {
@@ -83,7 +85,8 @@
{% if nbday==1 %} {% if nbday==1 %}
<tr id="{{user.user.id}}-{{event.date|date("Ymd")}}"}"> <tr id="{{user.user.id}}-{{event.date|date("Ymd")}}"}">
<td class="no-print" style="vertical-align:middle"> <td class="no-print" style="vertical-align:middle">
{% if event.validate %} {% set first=event.events|first %}
{% if first and first.validate %}
<i class="fa fa-thumbs-down devalidate-{{user.user.id}}" onClick="devalidate({{user.user.id}},'{{event.date|date("Ymd")}}','{{event.date|date("m/d/Y")}}')" style="cursor:pointer; color:red;"></i> <i class="fa fa-thumbs-down devalidate-{{user.user.id}}" onClick="devalidate({{user.user.id}},'{{event.date|date("Ymd")}}','{{event.date|date("m/d/Y")}}')" style="cursor:pointer; color:red;"></i>
{%else%} {%else%}
<i class="fa fa-thumbs-up validate-{{user.user.id}}" onClick="validate({{user.user.id}},'{{event.date|date("Ymd")}}','{{event.date|date("m/d/Y")}}')" style="cursor:pointer; color:green;{% if btnvalidate %}display:none{% endif %}"></i> <i class="fa fa-thumbs-up validate-{{user.user.id}}" onClick="validate({{user.user.id}},'{{event.date|date("Ymd")}}','{{event.date|date("m/d/Y")}}')" style="cursor:pointer; color:green;{% if btnvalidate %}display:none{% endif %}"></i>
@@ -95,21 +98,24 @@
<td> <td>
<div class="date">{{ event.date | date("d/m") }}</div> <div class="date">{{ event.date | date("d/m") }}</div>
{% if event.allday %} <div class="d-flex flex-wrap">
<div class='allday' style='background-color:{{ event.colorday }};' title='{{ event.descriptionday }}'>1</div> {% set haveam=false %}
{% else %} {% for detail in event.events %}
{%if event.am %} {% if detail.allday %}
<div class='am' style='background-color:{{ event.coloram }};' title='{{ event.descriptionam }}'>0.5</div> <div class='allday' style='background-color:{{ detail.colorday }};' title='{{ detail.descriptionday }}'>1</div>
{% else %} {% else %}
<div class='am'></div> {%if detail.am %}
{% endif %} {% set haveam=true %}
<div class='am' style='background-color:{{ detail.coloram }};' title='{{ detail.descriptionam }}'>0.5</div>
{% endif %}
{%if event.ap %} {%if detail.ap %}
<div class='ap' style='background-color:{{ event.colorap }};' title='{{ event.descriptionap }}'>0.5</div> {% if not haveam %}<div class='am'></div>{%endif%}
{% else %} <div class='ap' style='background-color:{{ detail.colorap }};' title='{{ detail.descriptionap }}'>0.5</div>
<div class='ap'></div> {% endif %}
{% endif %} {% endif %}
{% endif %} {% endfor %}
</div>
{% if event.astreinte %} {% if event.astreinte %}
<div class='astreinte' style='background-color:{{ event.colorastreinte }};' title='{{ event.descriptionastreinte }}'>*</div> <div class='astreinte' style='background-color:{{ event.colorastreinte }};' title='{{ event.descriptionastreinte }}'>*</div>