From eee89a9fc5582708cc51da6b08f277ee63aa6d68 Mon Sep 17 00:00:00 2001
From: Damien <damien.burel@maarch.org>
Date: Fri, 22 Mar 2019 17:39:10 +0100
Subject: [PATCH] FEAT #9107 Sending mechanic

---
 .gitignore                                    |   1 +
 .../xml/mailevaConfig.xml.default             |   6 +
 .../controllers/ActionMethodController.php    | 107 +--------
 src/app/action/controllers/ShippingTrait.php  | 212 ++++++++++++++++++
 src/core/models/CoreConfigModel.php           |  16 +-
 src/core/models/CurlModel.php                 |  54 +++--
 .../shipping-administration.component.ts      |   4 +-
 src/frontend/lang/lang-en.ts                  |   4 +-
 src/frontend/lang/lang-fr.ts                  |   4 +-
 src/frontend/lang/lang-nl.ts                  |   4 +-
 .../app/shipping/ShippingControllerTest.php   |   8 +-
 11 files changed, 283 insertions(+), 137 deletions(-)
 create mode 100644 apps/maarch_entreprise/xml/mailevaConfig.xml.default
 create mode 100644 src/app/action/controllers/ShippingTrait.php

diff --git a/.gitignore b/.gitignore
index 4db3d8f926c..d547762df19 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 composer.lock
 installed.lck
 apps/maarch_entreprise/xml/config.xml
+apps/maarch_entreprise/xml/mailevaConfig.xml
 apps/maarch_entreprise/xml/log4php.xml
 .vscode/
 .phplint-cache
diff --git a/apps/maarch_entreprise/xml/mailevaConfig.xml.default b/apps/maarch_entreprise/xml/mailevaConfig.xml.default
new file mode 100644
index 00000000000..f90ae64b328
--- /dev/null
+++ b/apps/maarch_entreprise/xml/mailevaConfig.xml.default
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <URI></URI>
+    <CLIENT_ID></CLIENT_ID>
+    <CLIENT_SECRET></CLIENT_SECRET>
+</ROOT>
diff --git a/src/app/action/controllers/ActionMethodController.php b/src/app/action/controllers/ActionMethodController.php
index 8b58a3a1f95..8b306372f0a 100644
--- a/src/app/action/controllers/ActionMethodController.php
+++ b/src/app/action/controllers/ActionMethodController.php
@@ -12,9 +12,6 @@
 
 namespace Action\controllers;
 
-use Attachment\models\AttachmentModel;
-use Convert\controllers\ConvertPdfController;
-use Docserver\models\DocserverModel;
 use Entity\controllers\ListInstanceController;
 use Entity\models\ListInstanceModel;
 use History\controllers\HistoryController;
@@ -23,7 +20,6 @@ use Resource\models\ResModel;
 use Action\models\ResMarkAsReadModel;
 use Action\models\BasketPersistenceModel;
 use Action\models\ActionModel;
-use SrcCore\models\CoreConfigModel;
 use SrcCore\models\ValidatorModel;
 use SrcCore\models\CurlModel;
 use AcknowledgementReceipt\models\AcknowledgementReceiptModel;
@@ -33,6 +29,7 @@ use User\models\UserModel;
 class ActionMethodController
 {
     use AcknowledgementReceiptTrait;
+    use ShippingTrait;
 
     const COMPONENTS_ACTIONS = [
         'confirmAction'                         => null,
@@ -254,108 +251,6 @@ class ActionMethodController
             return ['errors' => [$controller['errors']]];
         }
 
-        return true;
-    }
-
-    public static function maileva(array $args)
-    {
-        ValidatorModel::notEmpty($args, ['resId']);
-        ValidatorModel::intVal($args, ['resId']);
-
-        $curlAuth = CurlModel::execSimple([
-            'url'           => 'https://api.sandbox.aws.maileva.net/authentication/oauth2/token',
-            'basicAuth'     => ['user' => 'd80cafd2bf3b42c79dc84f4dc8e6acea', 'password' => 'aaa7833f3e9e48e68bbe3e727b5b5360'],
-            'headers'       => ['Content-Type: application/x-www-form-urlencoded'],
-            'method'        => 'POST',
-            'queryParams'   => ['grant_type' => 'password', 'username' => 'sandbox.562', 'password' => 'lgileb']
-        ]);
-
-        $token = $curlAuth['access_token'];
-        $sendingName = CoreConfigModel::uniqueId();
-
-        $curl = CurlModel::execSimple([
-            'url'           => 'https://api.sandbox.aws.maileva.net/mail/v1/sendings',
-            'bearerAuth'    => ['token' => $token],
-            'headers'       => ['Content-Type: application/json'],
-            'method'        => 'POST',
-            'body'          => ['name' => $sendingName]
-        ]);
-        $curl = CurlModel::execSimple([
-            'url'           => 'https://api.sandbox.aws.maileva.net/mail/v1/sendings',
-            'bearerAuth'    => ['token' => $token],
-            'method'        => 'GET'
-        ]);
-
-        foreach ($curl['sendings'] as $sending) {
-            if ($sending['name'] == $sendingName) {
-                $sendingId = $sending['id'];
-            }
-        }
-
-        $attachments = AttachmentModel::getOnView(['select' => ['res_id', 'res_id_version'], 'where' => ['res_id_master = ?'], 'data' => [$args['resId']]]);
-        $convertedDocument = ConvertPdfController::getConvertedPdfById(['resId' => $attachments[0]['res_id'], 'collId' => 'attachment_coll', 'isVersion' => false]);
-
-        $docserver = DocserverModel::getByDocserverId(['docserverId' => $convertedDocument['docserver_id'], 'select' => ['path_template']]);
-        if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
-            //TODO
-            return ['errors' => 'Docserver does not exist'];
-        }
-
-        $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $convertedDocument['path']) . $convertedDocument['filename'];
-        if (!file_exists($pathToDocument)) {
-            //TODO
-            return ['errors' => 'Document not found on docserver'];
-        }
-
-        $curl = CurlModel::execSimple([
-            'url'           => "https://api.sandbox.aws.maileva.net/mail/v1/sendings/{$sendingId}/documents",
-            'bearerAuth'    => ['token' => $token],
-            'headers'       => ['Content-Type: multipart/form-data'],
-            'method'        => 'POST',
-            'body'          => ['document' => CurlModel::makeCurlFile(['path' => $pathToDocument]), 'metadata' => ['priority' => 0, 'name' => 'tata']],
-            'toto'          => 1
-        ]);
-        $curl = CurlModel::execSimple([
-            'url'           => "https://api.sandbox.aws.maileva.net/mail/v1/sendings/{$sendingId}/documents",
-            'bearerAuth'    => ['token' => $token],
-            'method'        => 'GET'
-        ]);
-
-        $curl = CurlModel::execSimple([
-            'url'           => "https://api.sandbox.aws.maileva.net/mail/v1/sendings/{$sendingId}/recipients",
-            'bearerAuth'    => ['token' => $token],
-            'headers'       => ['Content-Type: application/json'],
-            'method'        => 'POST',
-            'body'          => [
-                "address_line_1"    => "La Poste",
-                "address_line_2"    => "Me Eva DUPONT",
-                "address_line_3"    => "Résidence des Peupliers",
-                "address_line_4"    => "33 avenue de Paris",
-                "address_line_5"    => "BP 356",
-                "address_line_6"    => "75000 Paris",
-                "country_code"      => "FR"
-            ],
-        ]);
-        $curl = CurlModel::execSimple([
-            'url'           => "https://api.sandbox.aws.maileva.net/mail/v1/sendings/{$sendingId}/options",
-            'bearerAuth'    => ['token' => $token],
-            'headers'       => ['Content-Type: application/json'],
-            'method'        => 'PATCH',
-            'body'          => [
-                'postage_type'              => "FAST", //ECONOMIC
-                'color_printing'            => true,
-                'duplex_printing'           => true,
-                'optional_address_sheet'    => false
-            ],
-        ]);
-        $curl = CurlModel::execSimple([
-            'url'           => "https://api.sandbox.aws.maileva.net/mail/v1/sendings/{$sendingId}/submit",
-            'bearerAuth'    => ['token' => $token],
-            'headers'       => ['Content-Type: application/json'],
-            'method'        => 'POST'
-        ]);
-
-
         return true;
     }
 }
diff --git a/src/app/action/controllers/ShippingTrait.php b/src/app/action/controllers/ShippingTrait.php
new file mode 100644
index 00000000000..7786a434405
--- /dev/null
+++ b/src/app/action/controllers/ShippingTrait.php
@@ -0,0 +1,212 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+
+* @brief   AcknowledgementReceiptTrait
+* @author  dev <dev@maarch.org>
+* @ingroup core
+*/
+
+namespace Action\controllers;
+
+use Attachment\models\AttachmentModel;
+use Convert\controllers\ConvertPdfController;
+use Docserver\models\DocserverModel;
+use Shipping\models\ShippingTemplateModel;
+use SrcCore\models\CoreConfigModel;
+use SrcCore\models\CurlModel;
+use SrcCore\models\PasswordModel;
+use SrcCore\models\ValidatorModel;
+
+
+trait ShippingTrait
+{
+    public static function createMailevaShippings(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['resId']);
+        ValidatorModel::intVal($args, ['resId']);
+        ValidatorModel::arrayType($args, ['data']);
+
+        //TODO remove after test
+        $args['data']['shippingTemplateId'] = 1;
+
+        $mailevaConfig = CoreConfigModel::getMailevaConfiguration();
+        if (empty($mailevaConfig)) {
+            //TODO
+            return ['errors' => 'Maileva configuration does not exist'];
+        }
+        $shippingTemplate = ShippingTemplateModel::getById(['id' => $args['data']['shippingTemplateId']]);
+        if (empty($shippingTemplate)) {
+            //TODO
+            return ['errors' => 'Shipping template does not exist'];
+        }
+        $shippingTemplate['options'] = json_decode($shippingTemplate['options'], true);
+        $shippingTemplate['account'] = json_decode($shippingTemplate['account'], true);
+
+        //TODO recup les bon attachments
+        $attachments = AttachmentModel::getOnView(['select' => ['res_id', 'res_id_version', 'title'], 'where' => ['res_id_master = ?'], 'data' => [$args['resId']]]);
+        if (empty($attachments)) {
+            return true;
+        }
+        $attachments = [$attachments[0]]; //TODO Remove for test
+
+        $curlAuth = CurlModel::execSimple([
+            'url'           => $mailevaConfig['uri'] . '/authentication/oauth2/token',
+            'basicAuth'     => ['user' => $mailevaConfig['clientId'], 'password' => $mailevaConfig['clientSecret']],
+            'headers'       => ['Content-Type: application/x-www-form-urlencoded'],
+            'method'        => 'POST',
+            'queryParams'   => [
+                'grant_type'    => 'password',
+                'username'      => $shippingTemplate['account']['id'],
+                'password'      => PasswordModel::decrypt(['cryptedPassword' => $shippingTemplate['account']['password']])
+            ]
+        ]);
+
+        if ($curlAuth['code'] != 200) {
+            //TODO
+            return ['errors' => 'Maileva authentication failed'];
+        }
+        $token = $curlAuth['response']['access_token'];
+
+        $errors = [];
+        foreach ($attachments as $attachment) {
+            $sendingName = CoreConfigModel::uniqueId();
+            if (!empty($attachment['res_id'])) {
+                $isVersion = false;
+                $attachmentId = $attachment['res_id'];
+            } else {
+                $isVersion = true;
+                $attachmentId = $attachment['res_id_version'];
+            }
+
+            $createSending = CurlModel::execSimple([
+                'url'           => $mailevaConfig['uri'] . '/mail/v1/sendings',
+                'bearerAuth'    => ['token' => $token],
+                'headers'       => ['Content-Type: application/json'],
+                'method'        => 'POST',
+                'body'          => ['name' => $sendingName]
+            ]);
+            if ($createSending['code'] != 201) {
+                //TODO AttachmentId ??
+                $errors[] = 'Maileva sending creation failed';
+                continue;
+            }
+
+            $sendings = CurlModel::execSimple([
+                'url'           => $mailevaConfig['uri'] . '/mail/v1/sendings',
+                'bearerAuth'    => ['token' => $token],
+                'method'        => 'GET'
+            ]);
+            if ($sendings['code'] != 200) {
+                //TODO AttachmentId ??
+                $errors[] = 'Maileva get sendings failed';
+                continue;
+            }
+
+            foreach ($sendings['response']['sendings'] as $sending) {
+                if ($sending['name'] == $sendingName) {
+                    $sendingId = $sending['id'];
+                }
+            }
+            if (empty($sendingId)) {
+                //TODO AttachmentId ??
+                $errors[] = 'Maileva sending id not found';
+                continue;
+            }
+
+            $convertedDocument = ConvertPdfController::getConvertedPdfById(['resId' => $attachmentId, 'collId' => 'attachment_coll', 'isVersion' => $isVersion]);
+            $docserver = DocserverModel::getByDocserverId(['docserverId' => $convertedDocument['docserver_id'], 'select' => ['path_template']]);
+            if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
+                //TODO AttachmentId
+                $errors[] = 'Docserver does not exist';
+                continue;
+            }
+            $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $convertedDocument['path']) . $convertedDocument['filename'];
+            if (!file_exists($pathToDocument) || !is_file($pathToDocument)) {
+                //TODO AttachmentId
+                $errors[] = 'Document not found on docserver';
+                continue;
+            }
+
+            $createDocument = CurlModel::execSimple([
+                'url'           => $mailevaConfig['uri'] . "/mail/v1/sendings/{$sendingId}/documents",
+                'bearerAuth'    => ['token' => $token],
+                'method'        => 'POST',
+                'multipartBody' => ['document' => file_get_contents($pathToDocument), 'metadata' => json_encode(['priority' => 0, 'name' => $attachment['title']])]
+            ]);
+            if ($createDocument['code'] != 201) {
+                //TODO AttachmentId ??
+                $errors[] = 'Maileva document creation failed';
+                continue;
+            }
+
+            //TODO remove after test
+            $curl = CurlModel::execSimple([
+                'url'           => "https://api.sandbox.aws.maileva.net/mail/v1/sendings/{$sendingId}/documents",
+                'bearerAuth'    => ['token' => $token],
+                'method'        => 'GET'
+            ]);
+
+            //TODO Aller chercher le contact de l'attachment
+            $createRecipient = CurlModel::execSimple([
+                'url'           => $mailevaConfig['uri'] . "/mail/v1/sendings/{$sendingId}/recipients",
+                'bearerAuth'    => ['token' => $token],
+                'headers'       => ['Content-Type: application/json'],
+                'method'        => 'POST',
+                'body'          => [
+                    "address_line_1"    => "La Poste",
+                    "address_line_2"    => "Me Eva DUPONT",
+                    "address_line_3"    => "Résidence des Peupliers",
+                    "address_line_4"    => "33 avenue de Paris",
+                    "address_line_5"    => "BP 356",
+                    "address_line_6"    => "75000 Paris",
+                    "country_code"      => "FR"
+                ],
+            ]);
+            if ($createRecipient['code'] != 201) {
+                //TODO AttachmentId ??
+                $errors[] = 'Maileva recipient creation failed';
+                continue;
+            }
+
+            $setOptions = CurlModel::execSimple([
+                'url'           => $mailevaConfig['uri'] . "/mail/v1/sendings/{$sendingId}/options",
+                'bearerAuth'    => ['token' => $token],
+                'headers'       => ['Content-Type: application/json'],
+                'method'        => 'PATCH',
+                'body'          => [
+                    'postage_type'              => strtoupper($shippingTemplate['options']['sendMode']),
+                    'color_printing'            => in_array('color', $shippingTemplate['options']['shapingOptions']),
+                    'duplex_printing'           => in_array('duplexPrinting', $shippingTemplate['options']['shapingOptions']),
+                    'optional_address_sheet'    => in_array('addressPage', $shippingTemplate['options']['shapingOptions'])
+                ],
+            ]);
+            if ($setOptions['code'] != 200) {
+                //TODO AttachmentId ??
+                $errors[] = 'Maileva options modification failed';
+                continue;
+            }
+
+            $submit = CurlModel::execSimple([
+                'url'           => $mailevaConfig['uri'] . "/mail/v1/sendings/{$sendingId}/submit",
+                'bearerAuth'    => ['token' => $token],
+                'headers'       => ['Content-Type: application/json'],
+                'method'        => 'POST'
+            ]);
+            if ($submit['code'] != 200) {
+                //TODO AttachmentId ??
+                $errors[] = 'Maileva submit failed';
+                continue;
+            }
+        }
+
+        if (!empty($errors)) {
+            return ['errors' => $errors];
+        }
+
+        return true;
+    }
+}
diff --git a/src/core/models/CoreConfigModel.php b/src/core/models/CoreConfigModel.php
index a7801fa9675..08301dff8f4 100755
--- a/src/core/models/CoreConfigModel.php
+++ b/src/core/models/CoreConfigModel.php
@@ -187,12 +187,26 @@ class CoreConfigModel
         return $loggingMethod;
     }
 
+    public static function getMailevaConfiguration()
+    {
+        $loadedXml = CoreConfigModel::getXmlLoaded(['path' => 'apps/maarch_entreprise/xml/mailevaConfig.xml']);
+
+        $mailevaConfig = [];
+        if ($loadedXml) {
+            $mailevaConfig['uri']           = (string)$loadedXml->URI;
+            $mailevaConfig['clientId']      = (string)$loadedXml->CLIENT_ID;
+            $mailevaConfig['clientSecret']  = (string)$loadedXml->CLIENT_SECRET;
+        }
+
+        return $mailevaConfig;
+    }
+
     public static function getOzwilloConfiguration(array $aArgs = [])
     {
         ValidatorModel::stringType($aArgs, ['customId']);
 
-        if (empty($aArgs['customId'])) {
             $customId = CoreConfigModel::getCustomId();
+        if (empty($aArgs['customId'])) {
         } else {
             $customId = $aArgs['customId'];
         }
diff --git a/src/core/models/CurlModel.php b/src/core/models/CurlModel.php
index 8c7fced6fe6..51a00284367 100644
--- a/src/core/models/CurlModel.php
+++ b/src/core/models/CurlModel.php
@@ -275,6 +275,7 @@ class CurlModel
             $opts[CURLOPT_HTTPHEADER][] = 'Authorization: Bearer ' . $args['bearerAuth']['token'];
         }
 
+        //QueryParams
         if (!empty($args['queryParams'])) {
             $args['url'] .= '?';
             $i = 0;
@@ -286,50 +287,67 @@ class CurlModel
                 ++$i;
             }
         }
-        $opts[CURLOPT_URL] = $args['url'];
-
 
+        //Body
         if (!empty($args['body'])) {
             $opts[CURLOPT_POSTFIELDS] = json_encode($args['body']);
         }
+        //MultipartBody
+        if (!empty($args['multipartBody'])) {
+            $boundary = uniqid();
+            $postData = CurlModel::createMultipartFormData(['boundary' => $boundary, 'body' => $args['multipartBody']]);
+            $opts[CURLOPT_HTTPHEADER][] = "Content-Type: multipart/form-data; boundary=-------------{$boundary}";
+            $opts[CURLOPT_POSTFIELDS] = $postData;
+        }
+        //Method
         if ($args['method'] == 'POST') {
             $opts[CURLOPT_POST] = true;
         } elseif ($args['method'] == 'PUT' || $args['method'] == 'PATCH' || $args['method'] == 'DELETE') {
             $opts[CURLOPT_CUSTOMREQUEST] = $args['method'];
         }
 
+        //Url
+        $opts[CURLOPT_URL] = $args['url'];
+
         $curl = curl_init();
         curl_setopt_array($curl, $opts);
         $rawResponse = curl_exec($curl);
+
         $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
-        $error = curl_error($curl);
+        $errors = curl_error($curl);
         curl_close($curl);
 
         LogsController::add([
             'isTech'    => true,
             'moduleId'  => 'curl',
             'level'     => 'DEBUG',
-            'tableName' => '',
+            'tableName' => 'curl',
             'recordId'  => 'execSimple',
-            'eventType' => 'Exec Curl : ' . $args['url'],
-            'eventId'   => $rawResponse
+            'eventType' => "Url : {$args['url']} HttpCode : {$code} Errors : {$errors}",
+            'eventId'   => "Response : {$rawResponse}"
         ]);
 
-        if (!empty($error)) {
-            LogsController::add([
-                'isTech'    => true,
-                'moduleId'  => 'curl',
-                'level'     => 'ERROR',
-                'tableName' => '',
-                'recordId'  => '',
-                'eventType' => 'Error Exec Curl : ' . $error,
-                'eventId'   => $rawResponse
-            ]);
+        return ['code' => $code, 'response' => json_decode($rawResponse, true), 'errors' => $errors];
+    }
 
-            return ['errors' => $error];
+    private static function createMultipartFormData(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['boundary', 'body']);
+        ValidatorModel::stringType($args, ['boundary']);
+        ValidatorModel::arrayType($args, ['body']);
+
+        $delimiter = "-------------{$args['boundary']}";
+
+        $postData = '';
+        foreach ($args['body'] as $key => $value) {
+            $postData .= "--{$delimiter}\r\n";
+            $postData .= "Content-Disposition: form-data; name=\"{$key}\"\r\n";
+            $postData .= "\r\n";
+            $postData .= "{$value}\r\n";
         }
+        $postData .= "--{$delimiter}--\r\n";
 
-        return json_decode($rawResponse, true);
+        return $postData;
     }
 
     public static function isEnabled(array $aArgs)
diff --git a/src/frontend/app/administration/shipping/shipping-administration.component.ts b/src/frontend/app/administration/shipping/shipping-administration.component.ts
index 5368f909a9f..e8607f0d0b2 100644
--- a/src/frontend/app/administration/shipping/shipping-administration.component.ts
+++ b/src/frontend/app/administration/shipping/shipping-administration.component.ts
@@ -52,8 +52,8 @@ export class ShippingAdministrationComponent implements OnInit {
 
     shapingOptions: string[] = [
         'color',
-        'both_sides',
-        'address_page',
+        'duplexPrinting',
+        'addressPage',
     ];
 
     sendModes: string[] = [
diff --git a/src/frontend/lang/lang-en.ts b/src/frontend/lang/lang-en.ts
index ab696c70dd8..720c3430aa2 100755
--- a/src/frontend/lang/lang-en.ts
+++ b/src/frontend/lang/lang-en.ts
@@ -884,8 +884,8 @@ export const LANG_EN = {
     "willBeAutomaticallyInCopy"                 : "will be automatically <b>in copy</b>",
     "confirm"                                   : "Confirm",
     "shipping_color"                            : "Color",
-    "shipping_both_sides"                            : "Both sides",
-    "shipping_address_page"                            : "Address page",
+    "shipping_duplexPrinting"                            : "Both sides",
+    "shipping_addressPage"                            : "Address page",
     "shipping_fast"                            : "Fast (J+2)",
     "shipping_economic"                            : "Economic (J+4)",
     "shipping_registered_mail"                            : "Registered mail",
diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts
index 1888944be2e..8a86069b30e 100755
--- a/src/frontend/lang/lang-fr.ts
+++ b/src/frontend/lang/lang-fr.ts
@@ -910,8 +910,8 @@ export const LANG_FR = {
     "willBeAutomaticallyInCopy"                 : "sera automatiquement mise <b>en copie</b>",
     "confirm"                                   : "Confirmer",
     "shipping_color"                            : "Couleur",
-    "shipping_both_sides"                            : "Recto verso",
-    "shipping_address_page"                            : "Page porte adresse",
+    "shipping_duplexPrinting"                            : "Recto verso",
+    "shipping_addressPage"                            : "Page porte adresse",
     "shipping_fast"                            : "Rapide (J+2)",
     "shipping_economic"                            : "Economique (J+4)",
     "shipping_registered_mail"                            : "Recommandé",
diff --git a/src/frontend/lang/lang-nl.ts b/src/frontend/lang/lang-nl.ts
index 9279c70b6f3..442a6113f8c 100755
--- a/src/frontend/lang/lang-nl.ts
+++ b/src/frontend/lang/lang-nl.ts
@@ -912,8 +912,8 @@ export const LANG_NL = {
     "willBeAutomaticallyInCopy"                 : "wordt automatisch <b>gekopieerd</b>", //_TO_TRANSLATE
     "confirm"                                   : "Bevestigen", //_TO_TRANSLATE
     "shipping_color"                            : "Color", //_TO_TRANSLATE
-    "shipping_both_sides"                            : "Both sides", //_TO_TRANSLATE
-    "shipping_address_page"                            : "Address page", //_TO_TRANSLATE
+    "shipping_duplexPrinting"                            : "Both sides", //_TO_TRANSLATE
+    "shipping_addressPage"                            : "Address page", //_TO_TRANSLATE
     "shipping_fast"                            : "Fast (J+2)", //_TO_TRANSLATE
     "shipping_economic"                            : "Economic (J+4)", //_TO_TRANSLATE
     "shipping_registered_mail"                            : "Registered mail", //_TO_TRANSLATE
diff --git a/test/unitTests/app/shipping/ShippingControllerTest.php b/test/unitTests/app/shipping/ShippingControllerTest.php
index 8a5fe740b13..b6632e895c6 100755
--- a/test/unitTests/app/shipping/ShippingControllerTest.php
+++ b/test/unitTests/app/shipping/ShippingControllerTest.php
@@ -23,7 +23,7 @@ class ShippingTemplateControllerTest extends TestCase
             'label'           => 'TEST',
             'description'     => 'description du TEST',
             'options'         => [
-                'shaping'    => ['color', 'both_sides', 'address_page'],
+                'shaping'    => ['color', 'duplexPrinting', 'addressPage'],
                 'sendMode'   => 'fast'
             ],
             'fee'             => ['first_page' => 1, 'next_page' => 2, 'postage_price' => 12],
@@ -42,7 +42,7 @@ class ShippingTemplateControllerTest extends TestCase
         $aArgs = [
             'description'     => 'description du TEST',
             'options'         => [
-                'shaping'     => ['color', 'both_sides', 'address_page'],
+                'shaping'     => ['color', 'duplexPrinting', 'addressPage'],
                 'sendMode'    => 'fast'
             ],
             'fee'             => ['first_page' => 1, 'next_page' => 2, 'postage_price' => 12],
@@ -70,8 +70,8 @@ class ShippingTemplateControllerTest extends TestCase
         $this->assertSame('TEST', $responseBody->shipping->label);
         $this->assertSame('description du TEST', $responseBody->shipping->description);
         $this->assertSame('color', $responseBody->shipping->options->shaping[0]);
-        $this->assertSame('both_sides', $responseBody->shipping->options->shaping[1]);
-        $this->assertSame('address_page', $responseBody->shipping->options->shaping[2]);
+        $this->assertSame('duplexPrinting', $responseBody->shipping->options->shaping[1]);
+        $this->assertSame('addressPage', $responseBody->shipping->options->shaping[2]);
         $this->assertSame('fast', $responseBody->shipping->options->sendMode);
         $this->assertSame(1, $responseBody->shipping->fee->first_page);
         $this->assertSame(2, $responseBody->shipping->fee->next_page);
-- 
GitLab