<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Process\Process;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\Patch;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Request\ParamFetcher;
use Symfony\Component\HttpFoundation\StreamedResponse;
use App\Exyzt\JwtAuthentificationBundle\Lib\Util;
use App\Exyzt\JwtAuthentificationBundle\Services\TokenService;
use App\Service\FPS\CouchConnectionService as couchDB;
use App\Service\FPS\PlateValidatorService;
use App\Service\FPS\CalculFpsService;
use App\Service\FPS\FpsService;
use App\Service\FPS\FpsCsvService;
use App\Entity\Fps;
use App\Entity\ActivityFPS;
use App\Entity\Payment;
use App\Entity\Claim;
use App\Entity\FpsComment;
use JsonSchema\Validator;
use JsonSchema\Constraints\Constraint;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use App\Exyzt\RESTBundle\Controller\AbstractRESTController;
use App\Repository\FpsRepository;
use App\Repository\ClaimRepository;
use App\Log\CustomLogger;
use Doctrine\Persistence\ManagerRegistry;
class FpsController extends AbstractRESTController
{
/**
* Calcul le montant du FPS en POST
* @Post("/api/{cityId}/fine-values/v1")
* @Security("is_granted('ROLE_PDA_FPS')")
*
*/
public function postCalculFPSAction(Request $request, couchDB $couchDB, CalculFpsService $calculFPS, PlateValidatorService $plateValidator, FpsService $serviceFps){
$logFile = 'FPS-FINE-VALUES-' . $request->get('cityId') . '.log';
$logger = new CustomLogger('fine-values');
$logger->setFileOptions($logFile, 30);
$data = Util::getDataRequest($request);
$logger->info("*** CALCUL DE PRIX ", $data);
$user = $this->getUser();
if($user->getCodeVille() != $request->get('cityId')){
$logger->error("Invalid cityId", ["Request=".$request->get('cityId'), "UserToken=".$user->getCodeVille()]);
$logger->info("* FIN DU CALCUL");
$errors[0]=array("code"=>"401","type"=>"Unauthorized");
return new JsonResponse(array("errors"=>$errors), Response::HTTP_UNAUTHORIZED,array(),false);
}
$client = $couchDB->getClient("city_".$request->get('cityId')."_ref_fps_metadata");
if(isset($data['zoneId'])){
$docName = 'ZONE_'.$data['zoneId'];
}
elseif(isset($data['parkId'])){
$docName = 'PARK_'.$data['parkId'];
}
try {
$doc = $client->getDoc($docName);
}
catch(\Exception $e){
$logger->error("Zone tarifaire ou parc inconnu", [$e]);
$logger->info("* FIN DU CALCUL");
$errors[0] = array("code"=>"1004","type"=>"Zone tarifaire inconnue");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if(substr($docName,0,4) === "ZONE" && property_exists($doc, 'error')){
$logger->error("Zone tarifaire inconnue", json_decode($doc->error, true));
$logger->info("* FIN DU CALCUL");
$errors[0]=array("code"=>"1004","type"=>"Zone tarifaire inconnue");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if(substr($docName,0,4) === "PARK" && property_exists($doc, 'error')){
$logger->error("Parc inconnu", json_decode($doc->error, true));
$logger->info("* FIN DU CALCUL");
$errors[0]=array("code"=>"1014","type"=>"Parc inconnu");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
$prices = json_decode(json_encode($doc->prices), true);
$timeReduced = property_exists($doc, 'timeReduced') ? json_decode(json_encode($doc->timeReduced), true): null;
$timeValidity = json_decode(json_encode($doc->timeValidity), true);
$timeZone = property_exists($doc, 'timeZone') ? json_decode(json_encode($doc->timeZone), true): 'Europe/Paris';
date_default_timezone_set($timeZone);
$freeDay = json_decode(json_encode($doc->freeDay), true);
$week = json_decode(json_encode($doc->week), true);
$gracePeriod = property_exists($doc, 'gracePeriod') ? json_decode(json_encode($doc->gracePeriod), true): 0.00;
$gracePeriodMax = property_exists($doc, 'gracePeriodMax') ? json_decode(json_encode($doc->gracePeriodMax), true): 0;
$dataForSchema = json_decode(json_encode($data), FALSE);
$schema = $serviceFps->getSchema(realpath(__DIR__.'/../Schemas/calculFps.json'));
$validator = new Validator;
$validator->coerce($dataForSchema, $schema);
if ($validator->isValid()) {
if($data['licensePlate']['plateCountry'] === 'FR'){
$plateValid = $plateValidator->analysePlate($data['licensePlate']);
if (sizeof($plateValid['error']) > 0) {
$logger->error("Erreur lors de la validation de plaque d'immatriculation", $plateValid['error']);
$logger->info("* FIN DU CALCUL");
return new JsonResponse(array("errors"=>$plateValid['error']), 422, array(), false);
} else {
$data['licensePlate'] = $plateValid['licensePlate'];
}
}
else{
$data['licensePlate']['plate'] = strtoupper(str_replace(array(' ','-'), '', $data['licensePlate']['plate']));
}
$statementDatetimeString=$data['statementDatetime'];
$statementDatetime=new \DateTime($statementDatetimeString);
$statementDatetime2 = clone $statementDatetime;
if($statementDatetime2->sub(new \DateInterval('PT10M')) > new \DateTime('now')){
$logger->error("Date de constatation invalide", [$data['statementDatetime']]);
$logger->info("* FIN DU CALCUL");
$errors[0]=array("code"=>"1005","type"=>"Date de constatation invalide");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
$response = $calculFPS->getCalculFps($client, $data, $week, $timeValidity, $timeZone, $freeDay, $prices, $timeReduced, $gracePeriod, $gracePeriodMax);
$logger->info("RESPONSE OK", $response);
$logger->info("* FIN DU CALCUL");
return new JsonResponse($response,Response::HTTP_OK,array(),false);
}
else {
$logger->error("Echec de validation des champs fournis", $validator->getErrors());
$logger->info("* FIN DU CALCUL");
$errors[0]=array("code"=>"1001","type"=>"Structure de la requête invalide");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
}
/**
* Créer un FPS
* @View()
* @Post("/api/{cityId}/fines/v1")
* @Security("is_granted('ROLE_PDA_FPS') or is_granted('ROLE_RAPO_UPDATE') or is_granted('ROLE_SVC_FPS_CREATE')")
*
*/
public function postFPSAction(Request $request, $cityId, TokenService $token, PlateValidatorService $plateValidator, FPSservice $serviceFps, ManagerRegistry $registry){
$user = $this->getUser();
if ( $user->getCodeVille() != $request->get('cityId')){
$errors[0] = array("code"=>"401","type"=>"Unauthorized");
return new JsonResponse(array("errors"=>$errors), Response::HTTP_UNAUTHORIZED,array(),false);
}
$data = Util::getDataRequest($request);
if (substr($data['fineLegalId'],0,14) !== $request->get('cityId') ){
$errors[0] = array("code"=>"401","type"=>"Unauthorized");
return new JsonResponse(array("errors"=>$errors), Response::HTTP_UNAUTHORIZED,array(),false);
}
if ($data['type']==='INITIAL'){
// INITIAL should not have 'claims', 'surcharge' should not be gretter than 0, 'finePrice' should not be 0 (== instead of === in case of value is passed as string)
if ( isset($data['claims']) || (isset( $data['surcharge'] ) && $data['surcharge'] > 0) || $data['finePrice'] == 0) {
$errors[0] = array( "code" => "1001", "type" => "Structure de la requête invalide" );
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
}
if ( intval($data['finePrice']) < 0) {
$errors[0] = array( "code" => "1001", "type" => "Structure de la requête invalide" );
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
$dataForSchema = json_decode(json_encode($data), FALSE);
$schema = $serviceFps->getSchema(realpath(__DIR__.'/../Schemas/fpsCreate.json'));
$validator = new Validator;
$validator->validate($dataForSchema, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
if ($validator->isValid()) {
$em = $registry->getManager( self::_PREFIX_EM.$cityId);
/** @var FpsRepository $repository*/
$repository = $registry->getRepository('App:Fps', self::_PREFIX_EM.$cityId);
$fpsEntity = $repository->findOneBy( ["fineLegalId" => $data['fineLegalId']] );
if ( $fpsEntity ){
$errors[0] = array("code" => "1003","type" => "Numéro de FPS déjà existant");
return new JsonResponse( array("errors"=>$errors ), 422 ,array(),false);
}
if ( strlen( $data['fineLegalId']) != 26 ){
$errors[0] = array("code" => "1002","type" => "Numéro de FPS invalide" );
return new JsonResponse( array("errors"=>$errors ), 422 ,array(),false);
}
if ( isset( $data['fineShortId'] ) ){
$exist = $repository->fineShortIdAvailable( $data['fineShortId'], $data['cityId']);
if ( $exist){
$errors[0] = array("code"=>"1101","type"=>"Numéro de FineShortId non valide");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
}
$conn = $registry->getConnection(self::_PREFIX_CONNECT.$cityId);
$conn->beginTransaction(); // suspend auto-commit
try {
$fps = new Fps;
$fps->setOriginalFpsJson( $request->getContent() );
$fps->setFineLegalId( $data['fineLegalId'] );
$dateModified = new \DateTime('now');
$dateModifiedRCF3339 = $dateModified->format(\DateTime::ATOM);
$fps->setDateModified( new \DateTime( $dateModifiedRCF3339 ) );
$fps->setType($data['type']);
$fps->setParent(array_key_exists('parent',$data) ? $data['parent'] : null);
$fps->setRootFineLegalId(array_key_exists('rootFineLegalId',$data) ? $data['rootFineLegalId'] : null);
$fps->setAuthId($data['authId']);
$fps->setAgentId($data['agent']['agentId']);
$fps->setCityId($request->get('cityId'));
$fps->setZoneId(array_key_exists('zoneId',$data) ? $data['zoneId'] : null);
$fps->setParkId(array_key_exists('parkId',$data) ? $data['parkId'] : null);
$fps->setNotificationAuthority($data['notificationAuthority']);
$fps->setPaymentStatus($data['paymentStatus']);
$fps->setName($data['agent']['name']);
$fps->setStatementDatetime(new \DateTime($data['statementDatetime']));
$fps->setTerminalId($data['terminalId']);
if($data['licensePlate']['plateCountry'] === 'FR'){
$plateValid = $plateValidator->analysePlate( $data['licensePlate'] );
if (sizeof($plateValid['error']) > 0) {
return new JsonResponse(array("errors"=>$plateValid['error']), 422, array(), false);
} else {
$data['licensePlate'] = $plateValid['licensePlate'];
}
}
else{
$data['licensePlate']['plate'] = strtoupper(str_replace(array(' ','-'), '', $data['licensePlate']['plate']));
}
$fps->setPlate( $data['licensePlate']['plate'] );
$fps->setPlateCountry( $data['licensePlate']['plateCountry'] );
$fps->setBrand($data['vehicle']['brand']);
$fps->setModel(array_key_exists('model',$data['vehicle']) ? $data['vehicle']['model'] : null);
$fps->setFinePrice($data['finePrice']);
$fps->setValidityDatetime(new \DateTime($data['validityDatetime']));
$fps->setReducedFinePrice(array_key_exists('reducedFinePrice',$data) ? $data['reducedFinePrice'] : null);
$fps->setReducedDatetime(array_key_exists('reducedDatetime',$data) ? new \DateTime($data['reducedDatetime']) : null);
$fps->setAuthTransfertDateTime(array_key_exists('authTransfertDateTime',$data) ? new \DateTime($data['authTransfertDateTime']) : null);
$fps->setNotificationDatetime(array_key_exists('notificationDatetime',$data) ? new \DateTime($data['notificationDatetime']) : null);
$fps->setPricingCategory(array_key_exists('pricingCategory',$data['licensePlate']) ? $data['licensePlate']['pricingCategory'] : null);
$fps->setVehiculeCategory(array_key_exists('vehiculeCategory',$data['vehicle']) ? $data['vehicle']['vehiculeCategory'] : null);
$fps->setOffender(array_key_exists('offender',$data) ? $data['offender'] : null);
$fps->setSurcharge(array_key_exists('surcharge',$data) ? $data['surcharge'] : null);
$fps->setTerminalType(array_key_exists('terminalType', $data) ? $data['terminalType'] : null);
if(array_key_exists('claims',$data)){
foreach($data['claims'] as $c){
$claim = new Claim;
$claim->setClaimStatus($c['claimStatus']);
$claim->setClaimType($c['claimType']);
if(isset($c['claimReason'])){
$claim->setClaimReason($c['claimReason']);
}
$claim->setDateModified(new \DateTime($c['dateModified']));
$claim->setFps($fps);
$fps->addClaim($claim);
$em->persist($claim);
}
}
if(!empty($data['comments'])) {
foreach($data['comments'] as $com) {
// Create comment
$comment = new FpsComment;
$comment->setAgentId($com['agent']['agentId']);
$comment->setName($com['agent']['name']);
$comment->setText(trim($com['text']));
$comment->setCreationDatetime(new \Datetime($com['creationDatetime']));
$comment->setFineId($fps);
// Add comment to FPS
$fps->addComment($comment);
// Persist comment
$em->persist($comment);
}
}
if ($fps->getType() === 'CORRECTION' ){
$fpsParent = $repository->findOneBy(['fineLegalId' => $fps->getParent() ]);
if ($fpsParent == null){
$errors[0] = array( "code" => "1001", "type" => "Structure de la requête invalide" );
return new JsonResponse( array( "errors"=>$errors ), 422 , array(), false );
}
else {
$fpsParent->setDateModified(new \Datetime('now'));
$em->persist($fpsParent);
}
}
$idUser = $token->getUserId( $request );
$activity = new ActivityFPS;
$activity->setIdUser( $idUser );
$activity->setMethod('POST');
$activity->setBody( $request->getContent() );
$activity->setFps( $fps );
$em->persist( $activity );
$em->persist( $fps );
$em->flush();
$fineId = $fps->getFineId();
if ( isset( $data['fineShortId']) ){
$fineShortId = $data['fineShortId'];
}else {
$fineShortId = $serviceFps->createShortId($fineId);
}
$fps->setFineShortId( $fineShortId );
$em->persist( $fps );
$em->flush();
$em->refresh( $fps );
$conn->commit();
} catch (\Throwable $t) {
$conn->rollBack();
$errorInfo = array_values(array_filter( $t->getPrevious()->errorInfo, fn($value, $key) => str_contains($value, 'ERROR'), ARRAY_FILTER_USE_BOTH));
$message = array_values(array_filter(explode("\n", $errorInfo[0]), fn($value, $key) => str_contains($value, 'ERROR'), ARRAY_FILTER_USE_BOTH));
$errors[0] = array("code" => "1003", "type" => "Numéro de FPS déjà existant", "message" => count($message) > 0 ? $message[0] : "Une erreur est survenue lors de l'enregistrement du FPS");
return new JsonResponse( array("errors"=>$errors ), 422 ,array(),false);
}
try {
$fpsCree = $fps->getFormat();
$codeWorkSpace = $request->get('cityId');
$links = Util::serialize( $fps, $codeWorkSpace, array('self'), true, $expand = "");
$jsonResponse = new JsonResponse( json_encode( $fpsCree ), Response::HTTP_CREATED, array( "Location" => json_decode( $links)->{'_links'}->self->href ), true );
$process = new Process(['sh', $_ENV['APP_DIR'].'/scripts/FPS/send-fps.sh']);
$process->start();
return $jsonResponse;
} catch (\Exception $e) {
return $e->getMessage();
}
}
else {
$errors[0] = array( "code" => "1001", "type" => "Structure de la requête invalide" );
return new JsonResponse( array( "errors"=>$errors ), 422 , array(), false );
}
}
/**
* Récupère une liste de FPS en fonction de criteres en POST
* @Post("/api/{cityId}/fines-search/v1")
* @Security("is_granted('ROLE_PC_FPS') or is_granted('ROLE_SVC_FPS_READ')")
*/
public function postFPSListAction(Request $request, $cityId, FPSService $serviceFps){
$maxRecordsDefault = 25;
$pageDefault = 1;
// get and json decode request
$search = empty(Util::getDataRequest($request)) ? ["maxRecords" => $maxRecordsDefault] : Util::getDataRequest($request);
$user = $this->getUser();
$verifications = $serviceFps->verificationsAuthorizationPlateFormatAndFormatJson($user->getCodeVille(),$cityId,$search );
if ( sizeof($verifications['error']) > 0) {
return new JsonResponse($verifications['error'], 422 ,array(),false);
}
else {
//replace search by search after verifications
$search = $verifications['search'];
// integral true for a complete FPS json
$integral = ($user->hasRole('ROLE_FPS_COMPLETE') && $request->get('integral') != null) ? 'complete' : false ;
// find FPSList - filter by search
/** @var FpsRepository $repositoryFPS */
$repositoryFPS = $this->getDoctrine()->getRepository('App:Fps', self::_PREFIX_EM.$cityId);
$fpsResultSearch = $repositoryFPS->getFpsFromSearch($search, $cityId, $integral);
// for each FPS found, clean and push as json in matches table
$matches = $serviceFps->cleanFpsList($fpsResultSearch);
// informations pages, total ...
$currentPage = isset($search['page']) ? intval($search['page']) : $pageDefault;
$limit = (isset($search['maxRecords']) && $search['maxRecords'] > 0) ? intval($search['maxRecords']) : $maxRecordsDefault;
// count false if return total is not required
$count = $request->get('count') != null ? $request->get('count') : true ;
$total_records = ( !$count ) ? 0 : $repositoryFPS->getCountFps( $search, 'count');
$total_pages = intval( ceil( $total_records / $limit ));
if ( $currentPage > $total_pages ) {
$res = array();
} else {
$res = array( "previousPage" => $currentPage - 1, "nextPage" => $currentPage + 1, "matches" => $matches, "total" => $total_records);
if ( $currentPage === 1 ) {
unset( $res['previousPage'] );
}
if ($currentPage === $total_pages || $total_pages === 0) {
unset( $res['nextPage'] );
}
}
return new JsonResponse($res, (sizeof($matches) === 0) ? Response::HTTP_NO_CONTENT : Response::HTTP_OK, array(), false);
}
}
/**
* Récupère un FPS en fonction de son fineId
* @Get("/api/{cityId}/fines/v1/{fineId}", requirements = {"fineId": "[0-9]+"})
* @Security("is_granted('ROLE_PC_FPS') or is_granted('ROLE_SVC_FPS_READ')")
*/
public function getFPSAction(Request $request, $cityId, $fineId, FPSService $serviceFps){
// User vérifications authorizations
$user = $this->getUser();
if($user->getCodeVille() != $request->get('cityId') ){
$errors[0] = array("code"=>"401","type"=>"Unauthorized");
return new JsonResponse(array("errors"=>$errors), Response::HTTP_UNAUTHORIZED,array(),false);
}
// fineId format verifications
if(!is_int((int) $fineId)){
$errors[0]=['code' => '1','type' => 'Fine Id doit être un entier valide'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
// integral true for a complete FPS json
$integral = ($user->hasRole('ROLE_FPS_COMPLETE') && $request->get('integral') != null) ? 'complete' : null ;
// find FPS by fineId
/** @var FpsRepository $repositoryFPS */
$repositoryFPS = $this->getDoctrine()->getRepository('App:Fps', self::_PREFIX_EM.$cityId);
$fps = $repositoryFPS->getFpsFormatedByfineId($fineId, $cityId, $integral);
if(empty($fps) ){
$errors[0] = ['code' => Response::HTTP_NOT_FOUND,'type' => 'Aucun FPS n’a été trouvé'];
return new JsonResponse(array("errors"=>$errors), Response::HTTP_NOT_FOUND,array(),false);
}
if ($fps['cityId'] != $request->get('cityId')){
$errors[0] = ['code' => Response::HTTP_NOT_FOUND,'type' => 'La ville du FPS ne correspond pas'];
return new JsonResponse(array("errors"=>$errors), Response::HTTP_NOT_FOUND,array(),false);
}
// clean null value
$fps = $serviceFps->cleanFps($fps);
$response = new JsonResponse(json_encode($fps), Response::HTTP_OK, array(), true);
$response->setEtag(md5($response->getContent()));
$response->headers->set('Access-Control-Expose-Headers', 'ETag');
return $response;
}
/**
* Modifie un FPS
* @Patch("/api/{cityId}/fines/v1/{fineId}",
* requirements = {
* "fineId": "[0-9]+"
* })
* @Security("is_granted('ROLE_PC_FPS') or is_granted('ROLE_PDA_FPS') or is_granted('ROLE_SVC_FPS_UPDATE')")
*
*/
public function patchFPSAction(Request $request, $cityId,$fineId, TokenService $token, FPSservice $serviceFps){
/////////////////// header verifications
$user = $this->getUser();
if ( $user->getCodeVille() != $request->get('cityId') ) {
$errors[0] = array( "code" => "401", "type" => "Unauthorized");
return new JsonResponse( array( "errors" => $errors ), Response::HTTP_UNAUTHORIZED, array(), false);
}
if ( ! is_int((int) $fineId)){
$errors[0] = [ 'code' => '1', 'type' => 'Fine Id doit être un entier valide' ];
return new JsonResponse( array( "errors" => $errors ), 422 , array(), false);
}
$ifMatch = $request->headers->get('If-Match');
$datas = Util::getDataRequest($request);
$dataForSchema = json_decode(json_encode($datas), FALSE);
$schema = $serviceFps->getSchema( realpath(__DIR__.'/../Schemas/updateFps.json') );
$validator = new Validator;
$validator->coerce($dataForSchema, $schema);
if ( ! $validator->isValid()) {
$errors[0] = array( "code" => "1001", "type" => "Structure de la requête invalide" );
return new JsonResponse( array("errors" => $errors, "validation" => $validator->getErrors()), 422 , array(), false);
}
else {
///////////////// connected entity manager
$em = $this->getDoctrine()->getManager(self::_PREFIX_EM.$cityId);
/** @var FpsRepository $repositoryFPS */
$repositoryFPS = $this->getDoctrine()->getRepository('App:Fps', self::_PREFIX_EM.$cityId);
///////////////// find FPS by fineId for verifications - same format than the last format return for stade
$fps = $repositoryFPS->getFpsFormatedByfineId($fineId, $cityId, null);
if(empty($fps) ){
$errors[0] = ['code' => Response::HTTP_NOT_FOUND,'type' => 'Aucun FPS n’a été trouvé'];
return new JsonResponse(array("errors"=>$errors), Response::HTTP_NOT_FOUND,array(),false);
}
if ($fps['cityId'] != $request->get('cityId')){
$errors[0] = ['code' => Response::HTTP_NOT_FOUND,'type' => 'La ville du FPS ne correspond pas'];
return new JsonResponse(array("errors"=>$errors), Response::HTTP_NOT_FOUND,array(),false);
}
// clean null value
$fps = $serviceFps->cleanFps($fps);
////////////Vérification if is the same FPS, with no modification /////////////////
if(substr($ifMatch,1,strlen($ifMatch)-2) !== md5(json_encode($fps))){
return new JsonResponse(null, Response::HTTP_PRECONDITION_FAILED,array(),false);
}
////////////// end verifications
/////////// begin traitment//////////////
//// find FPS for modifications //////////
$fpsEntity = $repositoryFPS->find($fineId);
foreach ($datas as $data){
if ( substr( $data['path'], 0, 7 ) !=="/claims" &&
$data['path'] !=="/cancelDatetime" &&
$data['path'] !=="/debtCollectionDatetime" &&
$data['path'] !=="/paymentStatus" &&
substr( $data['path'], 0, 9 ) !== "/payments" &&
$data['path'] !=="/notificationDatetime" &&
$data['path'] !=="/offender" &&
$data['path'] !=="/comments/-" ) {
$errors[0] = ['code' => '1012', 'type' => 'Champs non autorisés à être modifié'];
return new JsonResponse( array( "errors" => $errors), 422 , array(), false);
}
//si claims replace
if ( substr( $data['path'], 0, 7 ) === "/claims" && $data['op'] === "replace" ){
//check si claims existe$
/** @var ClaimRepository $repository */
$repository = $this->getDoctrine()->getRepository('App:Claim', self::_PREFIX_EM.$cityId);
$claims = $repository->findBy( ["fps" => $fpsEntity] );
if ( !$claims ){
$errors[0] = ['code' => '1013', 'type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse( array( "errors" => $errors), 422 , array(), false);
}
if(substr( $data['path'], 8) !== false && array_key_exists(substr( $data['path'], 8), $claims)){
$claim = $fpsEntity->getClaims()[substr( $data['path'], 8)];
}
else{
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
foreach($data['value'] as $c){
if(is_array($c)){
if(isset($c['claimStatus'])){
$claim->setClaimStatus($c['claimStatus']);
if($c['claimStatus'] === "ACCEPTED" || $c['claimStatus'] === "TRANSFERRED"){
$fpsEntity->setType("CANCELLED");
}
}
if(isset($c['dateModified'])){
$claim->setDateModified(new \DateTime($c['dateModified']));
$fpsEntity->setDateModified(new \DateTime('now'));
}
if(isset($c['claimReason'])){
$claim->setClaimReason($c['claimReason']);
}
$em->persist($claim);
}
else{
if(isset($data['value']['claimStatus'])){
$claim->setClaimStatus($data['value']['claimStatus']);
if($data['value']['claimStatus'] === "ACCEPTED" || $data['value']['claimStatus'] === "TRANSFERRED"){
$fpsEntity->setType("CANCELLED");
}
}
if(isset($data['value']['dateModified'])){
$claim->setDateModified(new \DateTime($data['value']['dateModified']));
$fpsEntity->setDateModified(new \DateTime('now'));
}
if(isset($data['value']['claimReason'])){
$claim->setClaimReason($data['value']['claimReason']);
}
$em->persist($claim);
break;
}
}
}
if(substr( $data['path'], 0, 7 ) === "/claims" && $data['op'] === 'add' ){
foreach($data['value'] as $c){
if(is_array($c)){
if($c['claimStatus'] !== "FILLED"){
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if(count($fpsEntity->getClaims())>0 && $fpsEntity->getClaims()[0]->getClaimType() === "PRELIMINARY" && $c['claimType'] ==='PRELIMINARY'){
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
//si claims add
if(!isset($c['claimType']) || ($c['claimType'] !== 'PRELIMINARY' && $c['claimType'] !== 'REGULATORY')){
$errors[0]=array("code"=>"1001","type"=>"Structure de la requête invalide");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if(count($fpsEntity->getClaims())>0 && $fpsEntity->getClaims()[count($fpsEntity->getClaims())-1]->getClaimType() === "REGULATORY" && $c['claimType'] ==='REGULATORY'){
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
$claim = new Claim;
$claim->setClaimStatus($c['claimStatus']);
$claim->setClaimType($c['claimType']);
if(isset($c['claimReason'])){
$claim->setClaimReason($c['claimReason']);
}
$claim->setDateModified(new \DateTime($c['dateModified']));
$fpsEntity->setDateModified(new \DateTime('now'));
$claim->setFps($fpsEntity);
$fpsEntity->addClaim($claim);
$em->persist($claim);
}
else{
if($data['value']['claimStatus'] !== "FILLED"){
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if(count($fpsEntity->getClaims())>0 && $fpsEntity->getClaims()[0]->getClaimType() === "PRELIMINARY" && $data['value']['claimType'] ==='PRELIMINARY'){
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
//si claims add
if(!isset($data['value']['claimType']) || ($data['value']['claimType'] !== 'PRELIMINARY' && $data['value']['claimType'] !== 'REGULATORY')){
$errors[0]=array("code"=>"1001","type"=>"Structure de la requête invalide");
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if(count($fpsEntity->getClaims())>0 && $fpsEntity->getClaims()[count($fpsEntity->getClaims())-1]->getClaimType() === "REGULATORY" && $data['value']['claimType'] === 'REGULATORY'){
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
$claim = new Claim;
$claim->setClaimStatus($data['value']['claimStatus']);
$claim->setClaimType($data['value']['claimType']);
if(isset($data['value']['claimReason'])){
$claim->setClaimReason($data['value']['claimReason']);
}
$claim->setDateModified(new \DateTime($data['value']['dateModified']));
$fpsEntity->setDateModified(new \DateTime('now'));
$claim->setFps($fpsEntity);
$fpsEntity->addClaim($claim);
$em->persist($claim);
break;
}
}
}
if($data['path'] ==="/cancelDatetime" && $data['op'] === 'add'){
if($fpsEntity->getCancelDateTime() != null && $fpsEntity->getType() === "CANCELLED"){
$errors[0]=['code' => '1012','type' => 'Champs non autorisés à être modifié'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
$fpsEntity->setCancelDatetime(new \DateTime($data['value']));
$fpsEntity->setDateModified(new \DateTime('now'));
$fpsEntity->setType("CANCELLED");
}
if($data['path'] ==="/cancelDatetime" && $data['op'] === 'replace'){
$errors[0]=['code' => '1012','type' => 'Champs non autorisés à être modifié'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if($data['path'] ==="/debtCollectionDatetime"){
$fpsEntity->setDebtCollectionDatetime(new \DateTime($data['value']));
$fpsEntity->setDateModified(new \DateTime('now'));
}
if($data['path'] ==="/paymentStatus" ){
if($fpsEntity->getPaymentStatus() === "PENDING" && ($data['value']==="PAID" || $data['value']==="OVERPAID")){
if($data['path'] ==="/paymentStatus" ){
$fpsEntity->setPaymentStatus($data['value']);
$fpsEntity->setDateModified(new \DateTime('now'));
}
}
else{
$errors[0]=['code' => '1013','type' => 'Incohérence des modifications par rapport au cycle de vie du FPS'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
}
if(substr($data['path'], 0, 9) === "/payments" && $data['op'] === 'add'){
foreach($data['value'] as $p){
if(is_array($p)){
$paymentType = !empty($p['paymentType']) ? $p['paymentType'] : null;
$payment= new Payment;
$payment->setPaymentDatetime(new \DateTime($p['paymentDatetime']));
$payment->setPaymentChannel($p['paymentChannel']);
$payment->setPaymentAmount($p['paymentAmount']);
$payment->setPaymentType($paymentType);
$payment->setFps($fpsEntity);
$fpsEntity->addPayment($payment);
$fpsEntity->setDateModified(new \DateTime('now'));
$em->persist($payment);
}
else{
$paymentType = (
isset($data['value']['paymentType']) && !empty($data['value']['paymentType'])
) ? $data['value']['paymentType'] : null;
$payment= new Payment;
$payment->setPaymentDatetime(new \DateTime($data['value']['paymentDatetime']));
$payment->setPaymentChannel($data['value']['paymentChannel']);
$payment->setPaymentAmount($data['value']['paymentAmount']);
$payment->setPaymentType($paymentType);
$payment->setFps($fpsEntity);
$fpsEntity->addPayment($payment);
$fpsEntity->setDateModified(new \DateTime('now'));
$em->persist($payment);
break;
}
}
}
if(substr($data['path'], 0, 9) === "/payments" && $data['op'] === 'replace'){
$errors[0]=['code' => '1012','type' => 'Champs non autorisés à être modifié'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if($data['path'] ==="/notificationDatetime" ){
$fpsEntity->setNotificationDatetime(new \DateTime($data['value']));
$fpsEntity->setDateModified(new \DateTime('now'));
}
if($data['path'] ==="/offender" && $data['op'] === 'add'){
if($fpsEntity->getOffender() != null){
$errors[0]=['code' => '1012','type' => 'Champs non autorisés à être modifié'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
$fpsEntity->setOffender($data['value']);
$fpsEntity->setDateModified(new \DateTime('now'));
}
if($data['path'] ==="/offender" && $data['op'] === 'replace'){
$errors[0]=['code' => '1012','type' => 'Champs non autorisés à être modifié'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
if ($data['path'] === "/comments/-") {
if ($data['op'] === 'replace') {
$errors[0]=['code' => '1012','type' => 'Champs non autorisés à être modifié'];
return new JsonResponse(array("errors"=>$errors), 422 ,array(),false);
}
// Create comment
$comment = new FpsComment;
$comment->setAgentId($data['value']['agent']['agentId']);
$comment->setName($data['value']['agent']['name']);
$comment->setText(trim($data['value']['text']));
$comment->setCreationDatetime(new \Datetime($data['value']['creationDatetime']));
$comment->setFineId($fpsEntity);
// Add comment to FPS
$fpsEntity->addComment($comment);
// Persist comment
$em->persist($comment);
}
}
try {
$idUser = $token->getUserId($request);
$activity = new ActivityFPS;
$activity->setIdUser($idUser);
$activity->setMethod('PATCH');
$activity->setBody($request->getContent());
$activity->setFps($fpsEntity);
$em->persist($activity);
$em->persist($fpsEntity);
$em->flush();
$em->refresh($fpsEntity);
if(isset($claim)){
$em->refresh($claim);
}
if(isset($payment)){
$em->refresh($payment);
}
$fpsUpdate=$fpsEntity->getFormat();
$jsonResponse= new JsonResponse(json_encode($fpsUpdate), Response::HTTP_OK, array(), true);
return $jsonResponse;
} catch (\Exception $e) {
return $e->getMessage();
}
}
}
/**
* Récupère une liste de FPS en fonction de criteres en GET - csv export
* @Get("/api/v1/{cityId}/fines-export")
* @Security("is_granted('ROLE_PC_FPS') or is_granted('ROLE_SVC_FPS_READ')")
*
*/
public function exportFPSListAction(Request $request, $cityId, FpsService $fpsService, FpsCsvService $fpsCsvService){
$maxRecordsDefault = 0;
$pageDefault = "1";
$search = json_decode($request->get('search'), true);
$user = $this->getUser();
$integral = $request->get('integral') != null ? $request->get('integral') === 'true' : false ;
$verifications = $fpsService->verificationsAuthorizationPlateFormatAndFormatJson($user->getCodeVille(),$request->get('cityId'),$search );
if ( sizeof($verifications['error']) > 0) {
return new JsonResponse($verifications['error'], 422 ,array(),false);
}
else {
if (!isset($search['maxRecords'])) {
$search['maxRecords'] = $maxRecordsDefault;
}
if( !isset($search['page'])){
$search['page'] = $pageDefault;
}
if( !isset($search['orderBy']) || count($search['orderBy']) === 0){
$search['orderBy'] = [array("field" => "fps.fineId", "sort" => "ASC")];
}
$complete = $user->hasRole('ROLE_FPS_COMPLETE') && $integral === true ? 'complete' : false;
// find FPSList - filter by search
/** @var FpsRepository $repositoryFPS */
$repositoryFPS = $this->getDoctrine()->getRepository('App:Fps', self::_PREFIX_EM.$cityId);
$fpsQuery = $repositoryFPS->getFpsFromSearch($search, $cityId, $complete, 'csv');
return $fpsCsvService->generateCsv($fpsQuery, $cityId);
}
}
/**
* Récupère une liste de FPS en fonction de criteres en GET - csv export
* @Get("/api/v1/{cityId}/fpsm")
* @Security("is_granted('ROLE_PC_FPS') or is_granted('ROLE_SVC_FPS_READ')")
*
*/
public function exportFPSMAction(Request $request, $cityId, FpsCsvService $fpsCsvService, ManagerRegistry $registry){
$month = explode(",", $request->get('months'));
$year = $request->get('year');
$user = $this->getUser();
// User vérifications authorizations
if ($user->getCodeVille() != $cityId) {
return ['error' => ["code" => "401", "type" => "Unauthorized"]];
}
else {
// find FPSList - filter by search
/** @var FpsRepository $repositoryFPS */
$repositoryFPS = $registry->getRepository('App:Fps', self::_PREFIX_EM.$cityId);
$fpsQuery = $repositoryFPS->getFpsM($month, $year);
return $fpsCsvService->generateCsv($fpsQuery, $cityId);
}
}
/**
* @Get("/api/{cityId}/last-fine")
* @QueryParam(name="agentId", nullable=false, description="agentId")
* @QueryParam(name="date", nullable=false, description="date")
*
*/
public function getLastFPSIdAction(Request $request, ParamFetcher $paramFetcher){
/** @var FpsRepository $repositoryFPS*/
$repositoryFPS = $this->getDoctrine()->getRepository('App:Fps', self::_PREFIX_EM.$request->get('cityId'));
$resId = $repositoryFPS->getLastFPSId($request->get('cityId'), $paramFetcher->get('agentId'), $paramFetcher->get('date'));
$res = ["last" => $resId];
return new JsonResponse(json_encode($res), Response::HTTP_OK, array(), true);
}
}