Deprecated : Constant E_STRICT is deprecated in /home/pastorz/old-espace-client/vendor/symfony/error-handler/ErrorHandler.php on line 58
Deprecated : Constant E_STRICT is deprecated in /home/pastorz/old-espace-client/vendor/symfony/error-handler/ErrorHandler.php on line 76
Symfony Profiler
<?php
namespace App\Service ;
use App\Entity\Batch ;
use App\Entity\Carrier ;
use App\Entity\CarrierInsurancePriceRange ;
use App\Entity\DeliveryNote ;
use App\Entity\EstimationRequest ;
use App\Entity\SupportRequest ;
use App\Twig\FormatExtension ;
use Com\Tecnick\Color\Exception ;
use Doctrine\Common\Collections\Collection ;
use Doctrine\ORM\EntityManagerInterface ;
use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException ;
use setasign\Fpdi\PdfParser\Filter\FilterException ;
use setasign\Fpdi\PdfParser\PdfParserException ;
use setasign\Fpdi\PdfParser\Type\PdfTypeException ;
use setasign\Fpdi\PdfReader\PdfReaderException ;
use setasign\Fpdi\Tcpdf\Fpdi ;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface ;
use Symfony\Component\HttpFoundation\Response ;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface ;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface ;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface ;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface ;
use Symfony\Contracts\HttpClient\HttpClientInterface ;
use Symfony\Contracts\HttpClient\ResponseInterface ;
use Throwable ;
class ColissimoService
{
private const BASE_URL = 'https://ws.colissimo.fr' ;
private const ENDPOINTS = array(
'getToken' => '/widget-colissimo/rest/authenticate.rest' ,
'generateLabel' => '/sls-ws/SlsServiceWSRest/2.0/generateLabel' ,
'checkGenerateLabel' => '/sls-ws/SlsServiceWSRest/2.0/checkGenerateLabel' ,
);
public function __construct (
private ParameterBagInterface $parameterBag ,
private BrandService $brandService ,
private HttpClientInterface $httpClient ,
private EntityManagerInterface $em ,
private PdfGenerationService $pdfGenerationService ,
private LabelService $labelService
)
{
}
public function getBaseUrl (): string
{
return self :: BASE_URL ;
}
/**
* @return array|null
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
*/
public function getToken (): ?array
{
$response = $this -> call ( 'POST' , self :: ENDPOINTS [ __FUNCTION__ ], array( 'login' => $this -> parameterBag -> get ( "colissimo.login" ), 'password' => $this -> parameterBag -> get ( "colissimo.password" )));
return json_decode ( $response -> getContent (), true );
}
/**
* @param string $method
* @param string $endpoint
* @param array|null $bodyParams
* @param array $queryParams
* @return ResponseInterface
* @throws TransportExceptionInterface
*/
private function call ( string $method , string $endpoint , array $bodyParams = null , array $queryParams = array(), array $batchesIds = null ): ResponseInterface
{
$params = array(
'json' => $bodyParams
);
if (isset($bodyParams [ 'letter' ])) {
$params [ 'user_data' ] = [
'productCode' => $bodyParams [ 'letter' ][ 'service' ][ 'productCode' ],
'batchesIds' => $batchesIds
];
}
return $this -> httpClient -> request ( $method , self :: BASE_URL . $endpoint . '?' . http_build_query ( $queryParams ), $params );
}
/**
* @param DeliveryNote|null $note
* @param bool|null $generateOneOnly
* @param Collection|null $batches
* @param bool|null $isReturnLabel
* @return Response
* @throws ClientExceptionInterface
* @throws CrossReferenceException
* @throws Exception
* @throws FilterException
* @throws PdfParserException
* @throws PdfReaderException
* @throws PdfTypeException
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
*/
public function generateLabel (? DeliveryNote $note = null , ? bool $generateOneOnly = false , ? Collection $batches = null , ? bool $isReturnLabel = false , ? bool $debug = false ): Response
{
if (!$note && ! $batches ) throw new Exception ( "DeliveryNote null, Batches null" );
//Has to generate labels for each batch, and then merge them together
$allParcels = $this -> getAllParcelParams ( $note ?-> getBatches () ?? $batches , $isReturnLabel );
if ($generateOneOnly ) {
$allParcels = array_slice ( $allParcels , 0 , 1 );
$allParcels [ 0 ][ 'letter' ][ 'parcel' ][ 'weight' ] = 1 ;
}else if(!$isReturnLabel ){
($note ?? $batches -> first ()-> getDeliveryNote ())-> getShipment ()-> setTrackingNumbers ([]);
}
if ($debug ) return $this -> checkGenerateLabel ( $allParcels [ 0 ]);
//Download and merge all parcel labels
return $this -> concurrentMergeDownloads ( $allParcels , $note );
}
/**
* @param mixed $batches
* @param bool|null $isReturnLabel
* @return array|null
*/
private function getAllParcelParams ( mixed $batches , ? bool $isReturnLabel = false ): array| null
{
if ($batches -> isEmpty ()) return null ;
$parcels = [ 'combinedParcels' => []];
foreach ($batches as $key => $batch ) {
if ($batch -> isIndividualShipment ()) $parcels [ $key ] = [ $batch ];
else $parcels [ 'combinedParcels' ][] = $batch ;
}
$parcelParams = [];
foreach ($parcels as $key => $parcel ) {
if ($parcel ) $parcelParams [] = $this -> getParcelParams ( $parcel , $isReturnLabel );
}
return $parcelParams ;
}
/**
* @param array $parcel
* @param bool|null $isReturnLabel
* @return array
*/
private function getParcelParams (array $parcel , ? bool $isReturnLabel = false ): array
{
/** @var DeliveryNote $note */
$note = $parcel [ 0 ]-> getDeliveryNote ();
if ($isReturnLabel ) $productCode = 'CORE' ;
else if (isset($note -> getShipment ()-> getDeliveryAddress ()[ 'productCode' ])) {
$productCode = $note -> getShipment ()-> getDeliveryAddress ()[ 'productCode' ];
} else {
$productCode = $note -> getShipment ()-> isDeliveryAgainstSignature () || $note -> getShipment ()-> isInsurance () ? 'DOS' : 'DOM' ;
}
if (in_array ( strtoupper ( $productCode ), [ 'ACP' , 'CDI' ])) $productCode = 'BPR' ;
$brandAddress = $isReturnLabel ? $this -> brandService -> getBrand ()-> getWarehouseAddress () : $this -> brandService -> getBrand ()-> getAddress ();
$senderAddress = [
"companyName" => $this -> brandService -> getBrand ()-> getCompanyName (),
"line2" => $brandAddress -> getAddress (),
"countryCode" => $brandAddress -> getCountry ()-> getCode (),
"city" => $brandAddress -> getCity (),
"zipCode" => preg_replace ( '/\s/' , '' , $brandAddress -> getZipcode ())
];
$addresseeFirstname = trim ( $note -> getShipment () ? $note -> getShipment ()-> getDeliveryAddress ()[ 'firstname' ] : $note -> getUser ()-> getLastname ());
$addresseeLastname = trim ( $note -> getShipment () ? $note -> getShipment ()-> getDeliveryAddress ()[ 'lastname' ] : $note -> getUser ()-> getLastname ());
$countryCode = isset( $note -> getShipment ()?-> getDeliveryAddress ()[ 'countryCode' ]) ? $note -> getShipment ()?-> getDeliveryAddress ()[ 'countryCode' ] : 'FR' ;
$zipcode = preg_replace ( '/\s/' , '' , $note -> getShipment () ? $note -> getShipment ()-> getDeliveryAddress ()[ 'zipcode' ] : $note -> getUser ()-> getFallbackAddress ()-> getZipcode ());
if ($countryCode === 'FR' ) $zipcode = FormatExtension :: formatZipCode ( $zipcode );
$addresseeAddress = [
"lastName" => strlen ( $addresseeFirstname ) ? $addresseeFirstname : '.' ,
"firstName" => strlen ( $addresseeLastname ) ? $addresseeLastname : '.' ,
"line0" => $note -> getShipment () ? $note -> getShipment ()-> getDeliveryAddress ()[ 'address_line2' ] ?? '' : $note -> getUser ()-> getFallbackAddress ()-> getAddressLine2 (),
"line1" => $note -> getShipment () ? $note -> getShipment ()-> getDeliveryAddress ()[ 'address_line1' ] ?? '' : $note -> getUser ()-> getFallbackAddress ()-> getAddressLine1 (),
"line2" => $note -> getShipment () ? $note -> getShipment ()-> getDeliveryAddress ()[ 'address' ] : $note -> getUser ()-> getFallbackAddress ()-> getAddress (),
"countryCode" => $countryCode ,
"city" => $note -> getShipment () ? $note -> getShipment ()-> getDeliveryAddress ()[ 'city' ] : $note -> getUser ()-> getFallbackAddress ()-> getCity (),
"zipCode" => $zipcode ,
"mobileNumber" => $note -> getUser ()-> getPhone (),
"email" => $note -> getUser ()-> getEmail ()
];
$weight = array_sum ( array_map (fn( Batch $b ) => $b -> getWeight (), $parcel ));
if(!$isReturnLabel ){
$maxInsuranceValue = max ( $note -> getShipment ()-> getCarrier ()-> getInsurancePriceRanges ()-> map (fn( CarrierInsurancePriceRange $priceRange ) => $priceRange -> getInsuranceValue ())-> toArray ());
}
$data = array(
"contractNumber" => $this -> parameterBag -> get ( 'colissimo.login' ),
"password" => $this -> parameterBag -> get ( 'colissimo.password' ),
"outputFormat" => [
"x" => 0 ,
"y" => 0 ,
"outputPrintingType" => "PDF_10x15_300dpi"
],
"letter" => [
"service" => [
"productCode" => $productCode ,
"depositDate" => (new \DateTime ())-> format ( 'Y-m-d' ),
"orderNumber" => $note -> getId (),
"commercialName" => $this -> brandService -> getBrand ()-> getName ()
],
"parcel" => [
"insuranceValue" => ! $isReturnLabel && $note -> getShipment ()-> isInsurance () ? intval ( min ( $maxInsuranceValue , $note -> getShipment ()-> getInsuredValue () ?? array_sum ( array_map (fn( Batch $batch ) => $batch -> getTotalAmount (), $note -> getBatches ()-> toArray ()))) * 100 ) : "0" ,
"weight" => $weight ?: 1 ,
],
"sender" => [
"senderParcelRef" => ( $isReturnLabel ? "SAV_" : "" ) . $note -> getCode (),
"address" => $isReturnLabel ? $addresseeAddress : $senderAddress
],
"addressee" => [
"addresseeParcelRef" => ( $isReturnLabel ? "SAV_" : "" ) . $note -> getCode (),
"address" => $isReturnLabel ? $senderAddress : $addresseeAddress
]
]
);
if (!$isReturnLabel && $note -> getShipment ()-> getCarrier ()-> getIsServicePoint ()) {
$data [ 'letter' ][ 'parcel' ][ 'pickupLocationId' ] = $note -> getShipment ()-> getDeliveryAddress ()[ 'pickupLocationId' ];
}
return ['data' => $data , 'batchesIds' => array_map (fn( Batch $b ) => $b -> getId (), $parcel )];
}
/**
* @param array $parcel
* @return Response
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
*/
private function checkGenerateLabel (array $parcel ): Response
{
return new Response ( $this -> call ( 'POST' , endpoint : self :: ENDPOINTS [ __FUNCTION__ ], bodyParams : $parcel [ 'data' ], batchesIds : $parcel [ 'batchesIds' ])-> getContent ());
}
/**
* @param array $parcels
* @param DeliveryNote|null $note
* @return Response
* @throws ClientExceptionInterface
* @throws CrossReferenceException
* @throws Exception
* @throws FilterException
* @throws PdfParserException
* @throws PdfReaderException
* @throws PdfTypeException
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
* @throws \Exception
*/
public function concurrentMergeDownloads (array $parcels , ? DeliveryNote $note = null ): Response
{
$outPut = new Fpdi ();
$outPut -> setPrintFooter ( false );
$outPut -> setPrintHeader ( false );
//Send all requests
$responses = [];
foreach ($parcels as $parcel ) {
$responses [] = $this -> call ( 'POST' , endpoint : self :: ENDPOINTS [ 'generateLabel' ], bodyParams : $parcel [ 'data' ], batchesIds : $parcel [ 'batchesIds' ]);
}
//Asynchronously handle them
foreach ( $this -> httpClient -> stream ( $responses ) as $response => $chunk ) {
if ($chunk -> isLast ()) {
$isBiggerLabel = in_array ( $response -> getInfo ( 'user_data' )[ 'productCode' ], [ 'A2P' ]);
$isReturnLabel = in_array ( $response -> getInfo ( 'user_data' )[ 'productCode' ], [ 'CORE' ]);
$batchesIds = $response -> getInfo ( 'user_data' )[ 'batchesIds' ];
$raw = $response -> getContent ();
$content = $this -> getResponseSlicedToPDF ( $raw );
$fileName = uniqid () . "_label.pdf" ;
file_put_contents ( ConstantsService :: TMP_PDFS_DIR . $fileName , $content );
$outPut -> AddPage ( format : [ 100 , 150 ]);
$outPut -> setSourceFile ( ConstantsService :: TMP_PDFS_DIR . $fileName );
$tplId = $outPut -> importPage ( 1 );
$outPut -> Rect ( 0 , 0 , 100 , 150 , style : 'F' , fill_color : [ 255 , 255 , 255 ]);
if ($isReturnLabel ) $yOffset = 3 ;
else $yOffset = $isBiggerLabel ? 5 : 15 ;
$outPut -> useTemplate ( $tplId , x : $isBiggerLabel ? 0 : 3 , y : $yOffset , height : 140 );
if (!$isReturnLabel ) {
foreach ($batchesIds as $key => $value ) {
$batch = $this -> em -> getRepository ( Batch ::class)-> find ( $value );
$trackingNumber = $this -> getTrackingNumber ( $raw );
$batch -> getDeliveryNote ()-> getShipment ()-> addTrackingNumber ( $trackingNumber );
$this -> labelService -> generateLabel ( $batch -> getDeliveryNote ()-> getShipment (), $trackingNumber );
$this -> em -> persist ( $batch );
$this -> em -> persist ( $batch -> getDeliveryNote ()-> getShipment ());
}
}
unlink ( ConstantsService :: TMP_PDFS_DIR . $fileName );
}
}
$result = $outPut -> Output ( dest : "S" );
$this -> em -> flush ();
return new Response ( $result , Response :: HTTP_OK , [
'Content-Type' => 'application/pdf' ,
'Content-Disposition' => 'inline; filename=label' . ( $note ? '_' . $note -> getCode () : '' ) . '.pdf'
]);
}
private function getResponseSlicedToPDF ( string $input ): string | Response
{
$start_tag = "%PDF-1.3" ;
$end_tag = "%%EOF" ;
$output = "" ;
$start_pos = strpos ( $input , $start_tag );
$end_pos = strpos ( $input , $end_tag );
if ($start_pos !== false && $end_pos !== false ) {
$end_pos += strlen ( $end_tag );
$output = substr ( $input , $start_pos , $end_pos - $start_pos );
}
return $output ;
}
private function getTrackingNumber ( string $input ): string
{
preg_match ( '/\{"messages".*"pdfUrl":.*}}/' , $input , $matches );
if (!$matches ) throw new Exception ( "Error while parsing tracking number." );
$json = json_decode ( $matches [ 0 ]);
if (!isset($json -> labelV2Response ) || !isset( $json -> labelV2Response -> parcelNumber )) throw new Exception ( "No tracking number found." );
return $json -> labelV2Response -> parcelNumber ;
}
/**
* @param EstimationRequest $estimationRequest
* @return array
* @throws Exception
*/
public function generateEstimationLabels ( EstimationRequest $estimationRequest ): array
{
try {
$trackingNumbers = [];
$pdfs = [];
for ($i = 0 ; $i < $estimationRequest -> getLabelQuantity (); $i ++) {
['pdf' => $pdf , 'trackingNumber' => $trackingNumber ] = $this -> generateEstimationLabel ( $estimationRequest );
$pdfs [] = $pdf ;
$trackingNumbers [] = $trackingNumber ;
}
$pdf = $this -> pdfGenerationService -> mergePdfs ( $pdfs );
return ['pdf' => $pdf , 'trackingNumbers' => $trackingNumbers ];
} catch (Throwable ) {
throw new Exception ( 'Erreur lors de la génération des étiquettes' );
}
}
private function generateEstimationLabel ( EstimationRequest $estimationRequest ): array
{
$maxInsuranceValue = max ( $this -> em -> getRepository ( Carrier ::class)-> findOneByInternalId ( ConstantsService :: CARRIER_ID_COLISSIMO )-> getInsurancePriceRanges ()-> map (fn( CarrierInsurancePriceRange $priceRange ) => $priceRange -> getInsuranceValue ())-> toArray ());
$data = array(
"contractNumber" => $this -> parameterBag -> get ( 'colissimo.login' ),
"password" => $this -> parameterBag -> get ( 'colissimo.password' ),
"outputFormat" => [
"x" => 0 ,
"y" => 0 ,
"outputPrintingType" => "PDF_10x15_300dpi"
],
"letter" => [
"service" => [
"productCode" => 'CORE' ,
"depositDate" => (new \DateTime ())-> format ( 'Y-m-d' ),
"orderNumber" => $estimationRequest -> getId (),
"commercialName" => $this -> brandService -> getBrand ()-> getName ()
],
"parcel" => [
"insuranceValue" => $estimationRequest -> getInsuredPrice () ? intval ( min ( $estimationRequest -> getInsuredPrice (), $maxInsuranceValue ) * 100 ) : "0" ,
"weight" => $estimationRequest -> getWeight (),
],
"sender" => [
"senderParcelRef" => "ESTIM_" . $estimationRequest -> getId (),
"address" => $this -> getEstimationLabelSender ( $estimationRequest )
],
"addressee" => [
"addresseeParcelRef" => "ESTIM_" . $estimationRequest -> getId (),
"address" => $this -> getEstimationLabelAddressee ()
]
]
);
$content = $this -> call ( 'POST' , endpoint : self :: ENDPOINTS [ 'generateLabel' ], bodyParams : $data )-> getContent ();
$pdf = $this -> getResponseSlicedToPDF ( $content );
$trackingNumber = $this -> getTrackingNumber ( $content );
return ['pdf' => $pdf , 'trackingNumber' => $trackingNumber ];
}
private function getEstimationLabelSender ( EstimationRequest $estimationRequest ): array
{
$addresseeFirstname = trim ( $estimationRequest -> getAddress ()[ 'firstname' ]);
$addresseeLastname = trim ( $estimationRequest -> getAddress ()[ 'lastname' ]);
return [
"lastName" => strlen ( $addresseeLastname ) ? $addresseeLastname : '.' ,
"firstName" => strlen ( $addresseeFirstname ) ? $addresseeFirstname : '.' ,
"line0" => $estimationRequest -> getAddress ()[ 'address_line2' ] ?? '' ,
"line1" => $estimationRequest -> getAddress ()[ 'address_line1' ] ?? '' ,
"line2" => $estimationRequest -> getAddress ()[ 'address' ],
"countryCode" => $estimationRequest -> getAddress ()[ 'countryCode' ],
"city" => $estimationRequest -> getAddress ()[ 'city' ],
"zipCode" => FormatExtension :: formatZipCode ( $estimationRequest -> getAddress ()[ 'zipcode' ]),
"mobileNumber" => '0600000000' ,
"email" => $estimationRequest -> getUser ()-> getEmail ()
];
}
private function getEstimationLabelAddressee (): array
{
$brand = $this -> brandService -> getBrand ();
return [
"companyName" => $brand -> getCompanyName (),
"line2" => $brand -> getAddress ()-> getAddress (),
"countryCode" => $brand -> getAddress ()-> getCountry ()-> getCode (),
"city" => $brand -> getAddress ()-> getCity (),
"zipCode" => $brand -> getAddress ()-> getZipcode (),
"mobileNumber" => $brand -> getPhone (),
"email" => $brand -> getContact ()
];
}
/**
* @param SupportRequest $supportRequest
* @return array
* @throws Exception
*/
public function generateSupportLabels ( SupportRequest $supportRequest ): array
{
try {
$trackingNumbers = [];
$pdfs = [];
$parcels = $this -> getAllParcelParams ( $supportRequest -> getBatches (), isReturnLabel : true );
foreach ($parcels as $parcel ) {
['pdf' => $pdf , 'trackingNumber' => $trackingNumber ] = $this -> generateSupportLabel ( $parcel [ 'data' ]);
$pdfs [] = $pdf ;
$trackingNumbers [] = $trackingNumber ;
}
$pdf = $this -> pdfGenerationService -> mergePdfs ( $pdfs );
return ['pdf' => $pdf , 'trackingNumbers' => $trackingNumbers ];
} catch (Throwable $e ) {
throw new Exception ( 'Erreur lors de la génération des étiquettes' );
}
}
private function generateSupportLabel (array $parcel ): array
{
$content = $this -> call ( 'POST' , endpoint : self :: ENDPOINTS [ 'generateLabel' ], bodyParams : $parcel )-> getContent ();
$pdf = $this -> getResponseSlicedToPDF ( $content );
$trackingNumber = $this -> getTrackingNumber ( $content );
return ['pdf' => $pdf , 'trackingNumber' => $trackingNumber ];
}
}