diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index 5c400af903..a9a00457fe 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -40,7 +40,7 @@ use Alchemy\Phrasea\Controller\Prod\Feed; use Alchemy\Phrasea\Controller\Prod\Language; use Alchemy\Phrasea\Controller\Prod\Lazaret; use Alchemy\Phrasea\Controller\Prod\MoveCollection; -use Alchemy\Phrasea\Controller\Prod\Order; +use Alchemy\Phrasea\Controller\Prod\Orders; use Alchemy\Phrasea\Controller\Prod\Printer; use Alchemy\Phrasea\Controller\Prod\Push; use Alchemy\Phrasea\Controller\Prod\Query; @@ -768,7 +768,7 @@ class Application extends SilexApplication $this->mount('/client/baskets', new ClientBasket()); $this->mount('/prod/query/', new Query()); - $this->mount('/prod/order/', new Order()); + $this->mount('/prod/order/', new Orders()); $this->mount('/prod/baskets', new Basket()); $this->mount('/prod/download', new Download()); $this->mount('/prod/story', new Story()); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Order.php b/lib/Alchemy/Phrasea/Controller/Prod/Orders.php similarity index 56% rename from lib/Alchemy/Phrasea/Controller/Prod/Order.php rename to lib/Alchemy/Phrasea/Controller/Prod/Orders.php index 819d29de80..2d8def8c26 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Order.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Orders.php @@ -13,6 +13,10 @@ namespace Alchemy\Phrasea\Controller\Prod; use Alchemy\Phrasea\Controller\RecordsRequest; use Doctrine\Common\Collections\ArrayCollection; +use Entities\Basket; +use Entities\BasketElement; +use Entities\Order; +use Entities\OrderElement; use Silex\Application; use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; @@ -25,7 +29,7 @@ use Symfony\Component\HttpFoundation\Response; * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -class Order implements ControllerProviderInterface +class Orders implements ControllerProviderInterface { /** @@ -156,42 +160,60 @@ class Order implements ControllerProviderInterface $records = RecordsRequest::fromRequest($app, $request, true, array('cancmd')); $query = new \User_Query($app); - foreach ($records as $key => $record) { - if ($collectionHasOrderAdmins->containsKey($record->get_base_id())) { - if (!$collectionHasOrderAdmins->get($record->get_base_id())) { + if (count($records) > 0) { + $order = new Order(); + $order->setUsrId($app['authentication']->getUser()->get_id()); + $order->setDeadline((null !== $deadLine = $request->request->get('deadline')) ? new \DateTime($deadLine) : $deadLine); + $order->setOrderUsage($request->request->get('use', '')); + foreach ($records as $key => $record) { + if ($collectionHasOrderAdmins->containsKey($record->get_base_id())) { + if (!$collectionHasOrderAdmins->get($record->get_base_id())) { + $records->remove($key); + } + } + + $hasOneAdmin = !!count($query->on_base_ids(array($record->get_base_id())) + ->who_have_right(array('order_master')) + ->execute()->get_results()); + + $collectionHasOrderAdmins->set($record->get_base_id(), $hasOneAdmin); + + if (!$hasOneAdmin) { + $toRemove[] = $key; + } else { + $orderElement = new OrderElement(); + $order->addElement($orderElement); + $orderElement->setOrder($order); + $orderElement->setBaseId($record->get_base_id()); + $orderElement->setRecordId($record->get_record_id()); + $app['EM']->persist($orderElement); + } + } + + foreach ($toRemove as $key) { + if ($records->containsKey($key)) { $records->remove($key); } } - $hasOneAdmin = !!count($query->on_base_ids(array($record->get_base_id())) - ->who_have_right(array('order_master')) - ->execute()->get_results()); + $noAdmins = $collectionHasOrderAdmins->forAll(function($key, $hasAdmin) { + return false === $hasAdmin; + }); - $collectionHasOrderAdmins->set($record->get_base_id(), $hasOneAdmin); - - if (!$hasOneAdmin) { - $toRemove[] = $key; + if ($noAdmins) { + $msg = _('There is no one to validate orders, please contact an administrator'); } - } - foreach ($toRemove as $key) { - if ($records->containsKey($key)) { - $records->remove($key); - } - } + $order->setTodo($order->getElements()->count()); - $noAdmins = $collectionHasOrderAdmins->forAll(function($key, $hasAdmin) { - return false === $hasAdmin; - }); + $app['EM']->persist($order); + $app['EM']->flush(); - if ($noAdmins) { - $msg = _('There is no one to validate orders, please contact an administrator'); - } - - if (count($records) > 0) { - $success = (Boolean) \set_order::create( - $app, $records, $app['authentication']->getUser(), $request->request->get('use', ''), ( (null !== $deadLine = $request->request->get('deadline')) ? new \DateTime($deadLine) : $deadLine) - ); + $app['events-manager']->trigger('__NEW_ORDER__', array( + 'order_id' => $order->getId(), + 'usr_id' => $order->getUsrId() + )); + $success = true; if ($success) { $msg = _('The records have been properly ordered'); @@ -202,7 +224,7 @@ class Order implements ControllerProviderInterface $msg = _('There is no record eligible for an order'); } } catch (\Exception $e) { - $msg = _('An error occured'); + $msg = _('An error occured') . $e->getMessage(); } if ('json' === $app['request']->getRequestFormat()) { @@ -235,8 +257,8 @@ class Order implements ControllerProviderInterface $baseIds = array_keys($app['authentication']->getUser()->ACL()->get_granted_base(array('order_master'))); - $ordersList = \set_order::listOrders($app, $baseIds, $offsetStart, $perPage, $sort); - $total = \set_order::countTotalOrder($app['phraseanet.appbox'], $baseIds); + $ordersList = $app['EM']->getRepository('Entities\Order')->listOrders($baseIds, $offsetStart, $perPage, $sort); + $total = $app['EM']->getRepository('Entities\Order')->countTotalOrders($baseIds); return $app['twig']->render('prod/orders/order_box.html.twig', array( 'page' => $page, @@ -258,7 +280,11 @@ class Order implements ControllerProviderInterface */ public function displayOneOrder(Application $app, Request $request, $order_id) { - $order = new \set_order($app, $order_id); + try { + $order = $app['EM']->getRepository('Entities\Order')->find($order_id); + } catch (\Exception_NotFound $e) { + $app->abort(404); + } return $app['twig']->render('prod/orders/order_item.html.twig', array( 'order' => $order @@ -276,12 +302,85 @@ class Order implements ControllerProviderInterface public function sendOrder(Application $app, Request $request, $order_id) { $success = false; - - $order = new \set_order($app, $order_id); + try { + $order = $app['EM']->getRepository('Entities\Order')->find($order_id); + } catch (\Exception_NotFound $e) { + $app->abort(404); + } try { - $order->send_elements($app, $request->request->get('elements', array()), !!$request->request->get('force', false)); + $dest_user = \User_Adapter::getInstance($order->getUsrId(), $app); + + $basket = null; + if ($order->getSselId()) { + $repository = $app['EM']->getRepository('\Entities\Basket'); + + try { + $basket = $repository->findUserBasket($app, $order->getSselId(), $dest_user, false); + } catch (\Exception $e) { + $basket = null; + } + } + + if (null === $basket) { + $basket = new Basket(); + $basket->setName(sprintf(_('Commande du %s'), $order->getCreatedOn()->format('Y-m-d'))); + $basket->setOwner($dest_user); + $basket->setPusher($app['authentication']->getUser()); + + $app['EM']->persist($basket); + $app['EM']->flush(); // this is necessary in order to use $basket->getId() + + $order->setSselId($basket->getId()); + + $app['EM']->persist($order); + $app['EM']->flush(); + } + + $n = 0; + foreach ($order->getElements() as $orderElement) { + if (in_array($orderElement->getId(), $request->request->get('elements', array()))) { + $sbas_id = \phrasea::sbasFromBas($app, $orderElement->getBaseId()); + $record = new \record_adapter($app, $sbas_id, $orderElement->getRecordId()); + + $basketElement = new BasketElement(); + $basketElement->setRecord($record); + $basketElement->setBasket($basket); + + $orderElement->setOrderMasterId($app['authentication']->getUser()->get_id()); + $orderElement->setDeny(false); + $orderElement->setBasket($basket); + + $basket->addElement($basketElement); + + $app['EM']->persist($basket); + $app['EM']->persist($orderElement); + + $app['EM']->flush(); + + $n++; + $dest_user->ACL()->grant_hd_on($record, $app['authentication']->getUser(), 'order'); + } + } + $success = true; + + if ($n > 0) { + + $order->setTodo($order->getTodo() - $n); + $app['EM']->persist($order); + $app['EM']->flush(); + + $params = array( + 'ssel_id' => $order->getSselId(), + 'from' => $app['authentication']->getUser()->get_id(), + 'to' => $dest_user->get_id(), + 'n' => $n + ); + + $app['events-manager']->trigger('__ORDER_DELIVER__', $params); + } + } catch (\Exception $e) { } @@ -312,10 +411,42 @@ class Order implements ControllerProviderInterface { $success = false; - $order = new \set_order($app, $order_id); + try { + $order = $app['EM']->getRepository('Entities\Order')->find($order_id); + } catch (\Exception_NotFound $e) { + $app->abort(404); + } try { - $order->deny_elements($request->request->get('elements', array())); + $n = 0; + foreach ($order->getElements() as $orderElement) { + if (in_array($orderElement->getId(), $request->request->get('elements', array()))) { + + $orderElement->setOrderMasterId($app['authentication']->getUser()->get_id()); + $orderElement->setDeny(true); + + $app['EM']->persist($orderElement); + $n++; + } + } + + $app['EM']->flush(); + + if ($n > 0) { + + $order->setTodo($order->getTodo() - $n); + $app['EM']->persist($order); + $app['EM']->flush(); + + $params = array( + 'from' => $app['authentication']->getUser()->get_id(), + 'to' => $order->getUsrId(), + 'n' => $n + ); + + $app['events-manager']->trigger('__ORDER_NOT_DELIVERED__', $params); + } + $success = true; } catch (\Exception $e) { diff --git a/lib/classes/set/order.php b/lib/classes/set/order.php deleted file mode 100644 index 16529bfa27..0000000000 --- a/lib/classes/set/order.php +++ /dev/null @@ -1,550 +0,0 @@ -get_connection()->beginTransaction(); - - try { - $sql = 'INSERT INTO `order` (`id`, `usr_id`, `created_on`, `usage`, `deadline`) - VALUES (null, :from_usr_id, NOW(), :usage, :deadline)'; - - $stmt = $app['phraseanet.appbox']->get_connection()->prepare($sql); - - $stmt->execute(array( - ':from_usr_id' => $orderer->get_id(), - ':usage' => $usage, - ':deadline' => (null !== $deadline ? $app['date-formatter']->format_mysql($deadline) : $deadline) - )); - - $stmt->closeCursor(); - - $orderId = $app['phraseanet.appbox']->get_connection()->lastInsertId(); - - $sql = 'INSERT INTO order_elements (id, order_id, base_id, record_id, order_master_id) - VALUES (null, :order_id, :base_id, :record_id, null)'; - - $stmt = $app['phraseanet.appbox']->get_connection()->prepare($sql); - - foreach ($records as $record) { - $stmt->execute(array( - ':order_id' => $orderId, - ':base_id' => $record->get_base_id(), - ':record_id' => $record->get_record_id() - )); - } - - $stmt->closeCursor(); - $app['phraseanet.appbox']->get_connection()->commit(); - } catch (Exception $e) { - $app['phraseanet.appbox']->get_connection()->rollBack(); - - return false; - } - - $app['events-manager']->trigger('__NEW_ORDER__', array( - 'order_id' => $orderId, - 'usr_id' => $orderer->get_id() - )); - - return $orderId; - } - - /** - * List orders - * - * @param Application $app - * @param array $baseIds - * @param integer $offsetStart - * @param integer $perPage - * @param string $sort - * - * @return array - */ - public static function listOrders(Application $app, array $baseIds, $offsetStart = 0, $perPage = 10, $sort = null) - { - - $sql = 'SELECT distinct o.id, o.usr_id, created_on, deadline, `usage` - FROM (`order_elements` e, `order` o) - WHERE e.base_id IN (' . implode(', ', $baseIds) . ') - AND e.order_id = o.id - GROUP BY o.id - ORDER BY o.id DESC - LIMIT ' . $offsetStart . ',' . $perPage; - - $elements = array(); - - $stmt = $app['phraseanet.appbox']->get_connection()->prepare($sql); - $stmt->execute(); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - foreach ($rs as $row) { - $id = (int) $row['id']; - $elements[$id] = new static($app, $id); - } - - unset($stmt); - - if ($sort && count($elements) > 0) { - if ($sort == 'created_on') { - uasort($elements, array(__CLASS__, 'date_orders_sort')); - } elseif ($sort == 'user') { - uasort($elements, array(__CLASS__, 'user_orders_sort')); - } elseif ($sort == 'usage') { - uasort($elements, array(__CLASS__, 'usage_orders_sort')); - } - } - - return $elements; - } - - /** - * Get total orders for selected base ids - * - * @param appbox $appbox - * @param array $baseIds - * @return integer - */ - public static function countTotalOrder(appbox $appbox, array $baseIds = array()) - { - $sql = 'SELECT distinct o.id - FROM (`order_elements` e, `order` o) - WHERE ' . (count($baseIds > 0 ) ? 'e.base_id IN (' . implode(', ', $baseIds) . ') AND ': '' ). - 'e.order_id = o.id - GROUP BY o.id - ORDER BY o.id DESC'; - - $stmt = $appbox->get_connection()->prepare($sql); - $stmt->execute(); - $total = $stmt->rowCount(); - $stmt->closeCursor(); - unset($stmt); - - return (int) $total; - } - - /** - * - * @param Application $app - * @param int $id - * - * @return set_order - */ - public function __construct(Application $app, $id) - { - $this->app = $app; - $conn = $app['phraseanet.appbox']->get_connection(); - - $sql = 'SELECT o.id, o.usr_id, o.created_on, o.`usage`, o.deadline, - COUNT(e.id) as total, o.ssel_id, COUNT(e2.id) as todo - FROM (`order` o, order_elements e) - LEFT JOIN order_elements e2 - ON ( - ISNULL(e2.order_master_id) - AND e.id = e2.id - ) - WHERE o.id = e.order_id - AND o.id = :order_id'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':order_id' => $id)); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - if ( ! $row) - throw new NotFoundHttpException('unknown order ' . $id); - - $current_user = User_Adapter::getInstance($row['usr_id'], $app); - - $this->id = $row['id']; - $this->user = $current_user; - $this->todo = $row['todo']; - $this->created_on = new DateTime($row['created_on']); - $this->usage = $row['usage']; - $this->deadline = new DateTime($row['deadline']); - $this->total = (int) $row['total']; - $this->ssel_id = (int) $row['ssel_id']; - - $base_ids = array_keys($app['authentication']->getUser()->ACL()->get_granted_base(array('order_master'))); - - $sql = 'SELECT e.base_id, e.record_id, e.order_master_id, e.id, e.deny - FROM order_elements e - WHERE order_id = :order_id - AND e.base_id - IN (' . implode(',', $base_ids) . ')'; - - $stmt = $conn->prepare($sql); - $stmt->execute(array(':order_id' => $id)); - $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - $elements = array(); - - foreach ($rs as $row) { - $order_master_id = $row['order_master_id'] ? $row['order_master_id'] : false; - - $elements[$row['id']] = new record_orderElement( - $app, - phrasea::sbasFromBas($this->app, $row['base_id']), - $row['record_id'], - $row['deny'], - $order_master_id - ); - } - - $this->elements = $elements; - - return $this; - } - - /** - * - * @return User_Adapter - */ - public function get_user() - { - return $this->user; - } - - /** - * - * @return DateTime - */ - public function get_created_on() - { - return $this->created_on; - } - - /** - * - * @return DateTime - */ - public function get_deadline() - { - return $this->deadline; - } - - /** - * - * @return string - */ - public function get_usage() - { - return $this->usage; - } - - /** - * - * @return int - */ - public function get_total() - { - return $this->total; - } - - /** - * - * @return int - */ - public function get_order_id() - { - return $this->id; - } - - /** - * - * @return int - */ - public function get_todo() - { - return $this->todo; - } - - /** - * - * @param Application $app - * @param Array $elements_ids - * @param boolean $force - * - * @return set_order - */ - public function send_elements(Application $app, Array $elements_ids, $force) - { - $conn = $app['phraseanet.appbox']->get_connection(); - - $basrecs = array(); - foreach ($elements_ids as $id) { - if (isset($this->elements[$id])) { - $basrecs[$id] = array( - 'base_id' => $this->elements[$id]->get_base_id(), - 'record_id' => $this->elements[$id]->get_record_id() - ); - } - } - - $dest_user = $this->user; - - $Basket = null; - /* @var $repository \Repositories\BasketRepository */ - if ($this->ssel_id) { - $repository = $app['EM']->getRepository('\Entities\Basket'); - - try { - $Basket = $repository->findUserBasket($app, $this->ssel_id, $dest_user, false); - } catch (\Exception $e) { - $Basket = null; - } - } - - if (! $Basket) { - $Basket = new \Entities\Basket(); - $Basket->setName(sprintf(_('Commande du %s'), $this->created_on->format('Y-m-d'))); - $Basket->setOwner($this->user); - $Basket->setPusher($app['authentication']->getUser()); - - $app['EM']->persist($Basket); - $app['EM']->flush(); - - $this->ssel_id = $Basket->getId(); - - $sql = 'UPDATE `order` SET ssel_id = :ssel_id WHERE id = :order_id'; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':ssel_id' => $Basket->getId(), ':order_id' => $this->id)); - $stmt->closeCursor(); - } - - $n = 0; - - $sql = 'UPDATE order_elements - SET deny="0", order_master_id = :usr_id - WHERE order_id = :order_id - AND id = :order_element_id'; - - if (! $force) { - $sql .= ' AND ISNULL(order_master_id)'; - } - - $stmt = $conn->prepare($sql); - - foreach ($basrecs as $order_element_id => $basrec) { - try { - $sbas_id = phrasea::sbasFromBas($app, $basrec['base_id']); - $record = new record_adapter($app, $sbas_id, $basrec['record_id']); - - $BasketElement = new \Entities\BasketElement(); - $BasketElement->setRecord($record); - $BasketElement->setBasket($Basket); - - $Basket->addElement($BasketElement); - - $app['EM']->persist($BasketElement); - - $params = array( - ':usr_id' => $app['authentication']->getUser()->get_id() - , ':order_id' => $this->id - , ':order_element_id' => $order_element_id - ); - - $stmt->execute($params); - - $n ++; - $this->user->ACL()->grant_hd_on($record, $app['authentication']->getUser(), 'order'); - - unset($record); - } catch (Exception $e) { - - } - } - - $app['EM']->flush(); - $stmt->closeCursor(); - - if ($n > 0) { - $params = array( - 'ssel_id' => $this->ssel_id, - 'from' => $app['authentication']->getUser()->get_id(), - 'to' => $this->user->get_id(), - 'n' => $n - ); - - $app['events-manager']->trigger('__ORDER_DELIVER__', $params); - } - - return $this; - } - - /** - * - * @param Array $elements_ids - * @return set_order - */ - public function deny_elements(Array $elements_ids) - { - $conn = $this->app['phraseanet.appbox']->get_connection(); - - $n = 0; - - foreach ($elements_ids as $order_element_id) { - $sql = 'UPDATE order_elements - SET deny="1", order_master_id = :order_master_id - WHERE order_id = :order_id AND id = :order_element_id - AND ISNULL(order_master_id)'; - - $params = array( - ':order_master_id' => $this->app['authentication']->getUser()->get_id() - , ':order_id' => $this->id - , ':order_element_id' => $order_element_id - ); - $stmt = $conn->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); - $n ++; - } - - if ($n > 0) { - $params = array( - 'from' => $this->app['authentication']->getUser()->get_id(), - 'to' => $this->user->get_id(), - 'n' => $n - ); - - $this->app['events-manager']->trigger('__ORDER_NOT_DELIVERED__', $params); - } - - return $this; - } - - /** - * Order orders by usage - * - * @param string $a - * @param string $b - * @return int - */ - private static function usage_orders_sort($a, $b) - { - $comp = strcasecmp($a['usage'], $b['usage']); - - if ($comp == 0) { - return 0; - } - - return $comp < 0 ? -1 : 1; - } - - /** - * Order orders by user - * - * @param string $a - * @param string $b - * @return int - */ - private static function user_orders_sort($a, $b) - { - $comp = strcasecmp($a['usr_display'], $b['usr_display']); - - if ($comp == 0) { - return 0; - } - - return $comp < 0 ? -1 : 1; - } - - /** - * Order orders by date - * - * @param DateTime $a - * @param DateTime $b - * @return int - */ - private static function date_orders_sort(DateTime $a, DateTime $b) - { - $comp = $b->format('U') - $a->format('U'); - - if ($comp == 0) { - return 0; - } - - return $comp < 0 ? -1 : 1; - } -} diff --git a/lib/conf.d/Doctrine/Entities.Order.dcm.yml b/lib/conf.d/Doctrine/Entities.Order.dcm.yml new file mode 100644 index 0000000000..e135d9e849 --- /dev/null +++ b/lib/conf.d/Doctrine/Entities.Order.dcm.yml @@ -0,0 +1,34 @@ +Entities\Order: + type: entity + repositoryClass: Repositories\OrderRepository + table: Orders + id: + id: + type: integer + generator: + strategy: AUTO + fields: + usr_id: + type: integer + ssel_id: + type: integer + nullable: true + order_usage: + type: string + length: 2048 + deadline: + type: datetime + todo: + type: integer + nullable: true + created_on: + type: datetime + gedmo: + timestampable: + on: create + oneToMany: + elements: + targetEntity: OrderElement + mappedBy: order + cascade: ["ALL"] + diff --git a/lib/conf.d/Doctrine/Entities.OrderElement.dcm.yml b/lib/conf.d/Doctrine/Entities.OrderElement.dcm.yml new file mode 100644 index 0000000000..bc8a2bb19a --- /dev/null +++ b/lib/conf.d/Doctrine/Entities.OrderElement.dcm.yml @@ -0,0 +1,31 @@ +Entities\OrderElement: + type: entity + repositoryClass: Repositories\OrderElementRepository + table: OrderElements + uniqueConstraints: + unique_ordercle: + columns: base_id,record_id,order_id + id: + id: + type: integer + generator: + strategy: AUTO + fields: + base_id: + type: integer + record_id: + type: integer + order_master_id: + type: integer + nullable: true + deny: + type: boolean + nullable: true + manyToOne: + order: + targetEntity: Order + inversedBy: elements + joinColumn: + name: order_id + referencedColumnName: id + cascade: ["persist"] diff --git a/templates/web/prod/orders/order_box.html.twig b/templates/web/prod/orders/order_box.html.twig index d292dc9e4d..f940e9a235 100644 --- a/templates/web/prod/orders/order_box.html.twig +++ b/templates/web/prod/orders/order_box.html.twig @@ -40,10 +40,10 @@
{% for order in orders %} - {% set deadline = app['date-formatter'].getPrettyString(order.get_deadline()) %} -{% trans 'Destinataire' %} | -{{ displayName }}({{ order.get_user().get_email() }}) | +{{ displayName }}({{ order.getUser(app).get_email() }}) |
{% trans 'Date de commande' %} | -{{ app['date-formatter'].getPrettyString(order.get_created_on()) }} | +{{ app['date-formatter'].getPrettyString(order.getCreatedOn()) }} |
{% trans 'Deadline' %} | -{{ app['date-formatter'].getPrettyString(order.get_deadline()) }} | +{{ app['date-formatter'].getPrettyString(order.getDeadline()) }} |
{% trans 'Utilisation prevue' %} | -{{ order.get_usage() | nl2br }} | +{{ order.getOrderUsage() | nl2br }} |
{% trans 'Nombre total d\'element commandes' %} | -{{ order.get_total() }} | +{{ order.getTotal() }} |