1<?php 2/** 3 * Copyright since 2007 PrestaShop SA and Contributors 4 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA 5 * 6 * NOTICE OF LICENSE 7 * 8 * This source file is subject to the Open Software License (OSL 3.0) 9 * that is bundled with this package in the file LICENSE.md. 10 * It is also available through the world-wide-web at this URL: 11 * https://opensource.org/licenses/OSL-3.0 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to license@prestashop.com so we can send you a copy immediately. 15 * 16 * DISCLAIMER 17 * 18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer 19 * versions in the future. If you wish to customize PrestaShop for your 20 * needs please refer to https://devdocs.prestashop.com/ for more information. 21 * 22 * @author PrestaShop SA and Contributors <contact@prestashop.com> 23 * @copyright Since 2007 PrestaShop SA and Contributors 24 * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) 25 */ 26 27namespace PrestaShop\PrestaShop\Adapter\Order\QueryHandler; 28 29use Address; 30use Carrier; 31use Cart; 32use ConnectionsSource; 33use Context; 34use Country; 35use Currency; 36use Customer; 37use DateTimeImmutable; 38use Gender; 39use Module; 40use Order; 41use OrderInvoice; 42use OrderPayment; 43use OrderSlip; 44use OrderState; 45use PrestaShop\Decimal\DecimalNumber; 46use PrestaShop\PrestaShop\Adapter\Address\AddressFormatter; 47use PrestaShop\PrestaShop\Adapter\Configuration; 48use PrestaShop\PrestaShop\Adapter\Customer\CustomerDataProvider; 49use PrestaShop\PrestaShop\Adapter\Order\AbstractOrderHandler; 50use PrestaShop\PrestaShop\Core\Address\AddressFormatterInterface; 51use PrestaShop\PrestaShop\Core\Domain\Address\ValueObject\AddressId; 52use PrestaShop\PrestaShop\Core\Domain\Exception\InvalidSortingException; 53use PrestaShop\PrestaShop\Core\Domain\Order\Exception\OrderException; 54use PrestaShop\PrestaShop\Core\Domain\Order\OrderDocumentType; 55use PrestaShop\PrestaShop\Core\Domain\Order\Query\GetOrderForViewing; 56use PrestaShop\PrestaShop\Core\Domain\Order\Query\GetOrderProductsForViewing; 57use PrestaShop\PrestaShop\Core\Domain\Order\QueryHandler\GetOrderForViewingHandlerInterface; 58use PrestaShop\PrestaShop\Core\Domain\Order\QueryHandler\GetOrderProductsForViewingHandlerInterface; 59use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\LinkedOrderForViewing; 60use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\LinkedOrdersForViewing; 61use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderCarrierForViewing; 62use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderCustomerForViewing; 63use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderDiscountForViewing; 64use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderDiscountsForViewing; 65use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderDocumentForViewing; 66use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderDocumentsForViewing; 67use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderForViewing; 68use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderHistoryForViewing; 69use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderInvoiceAddressForViewing; 70use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderMessageDateForViewing; 71use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderMessageForViewing; 72use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderMessagesForViewing; 73use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderPaymentForViewing; 74use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderPaymentsForViewing; 75use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderPricesForViewing; 76use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderProductsForViewing; 77use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderReturnForViewing; 78use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderReturnsForViewing; 79use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderShippingAddressForViewing; 80use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderShippingForViewing; 81use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderSourceForViewing; 82use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderSourcesForViewing; 83use PrestaShop\PrestaShop\Core\Domain\Order\QueryResult\OrderStatusForViewing; 84use PrestaShop\PrestaShop\Core\Domain\Order\ValueObject\OrderId; 85use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint; 86use PrestaShop\PrestaShop\Core\Localization\Exception\LocalizationException; 87use PrestaShop\PrestaShop\Core\Localization\Locale; 88use State; 89use Symfony\Component\Translation\TranslatorInterface; 90use Tools; 91use Validate; 92 93/** 94 * Handle getting order for viewing 95 * 96 * @internal 97 */ 98final class GetOrderForViewingHandler extends AbstractOrderHandler implements GetOrderForViewingHandlerInterface 99{ 100 /** 101 * @var Locale 102 */ 103 private $locale; 104 105 /** 106 * @var TranslatorInterface 107 */ 108 private $translator; 109 110 /** 111 * @var int 112 */ 113 private $contextLanguageId; 114 115 /** 116 * @var CustomerDataProvider 117 */ 118 private $customerDataProvider; 119 120 /** 121 * @var Configuration 122 */ 123 private $configuration; 124 125 /** 126 * @var Context 127 */ 128 private $context; 129 130 /** 131 * @var GetOrderProductsForViewingHandlerInterface 132 */ 133 private $getOrderProductsForViewingHandler; 134 135 /** 136 * @var AddressFormatterInterface 137 */ 138 private $addressFormatter; 139 140 /** 141 * @param TranslatorInterface $translator 142 * @param int $contextLanguageId 143 * @param Locale $locale 144 * @param Context $context 145 * @param CustomerDataProvider $customerDataProvider 146 * @param GetOrderProductsForViewingHandlerInterface $getOrderProductsForViewingHandler 147 */ 148 public function __construct( 149 TranslatorInterface $translator, 150 int $contextLanguageId, 151 Locale $locale, 152 Context $context, 153 CustomerDataProvider $customerDataProvider, 154 GetOrderProductsForViewingHandlerInterface $getOrderProductsForViewingHandler, 155 Configuration $configuration, 156 AddressFormatterInterface $addressFormatter = null 157 ) { 158 $this->translator = $translator; 159 $this->contextLanguageId = $contextLanguageId; 160 $this->locale = $locale; 161 $this->translator = $translator; 162 $this->context = $context; 163 $this->customerDataProvider = $customerDataProvider; 164 $this->getOrderProductsForViewingHandler = $getOrderProductsForViewingHandler; 165 $this->configuration = $configuration; 166 $this->addressFormatter = $addressFormatter ?? new AddressFormatter(); 167 } 168 169 /** 170 * {@inheritdoc} 171 */ 172 public function handle(GetOrderForViewing $query): OrderForViewing 173 { 174 $order = $this->getOrder($query->getOrderId()); 175 $orderCarrier = new Carrier($order->id_carrier); 176 $taxCalculationMethod = $this->getOrderTaxCalculationMethod($order); 177 178 $isTaxIncluded = ($taxCalculationMethod == PS_TAX_INC); 179 180 $taxMethod = $isTaxIncluded ? 181 $this->translator->trans('Tax included', [], 'Admin.Global') : 182 $this->translator->trans('Tax excluded', [], 'Admin.Global'); 183 184 $invoiceManagementIsEnabled = (bool) $this->configuration->get( 185 'PS_INVOICE', 186 null, 187 ShopConstraint::shop((int) $order->id_shop) 188 ); 189 190 $orderInvoiceAddress = $this->getOrderInvoiceAddress($order); 191 192 return new OrderForViewing( 193 (int) $order->id, 194 (int) $order->id_currency, 195 (int) $order->id_carrier, 196 (string) $orderCarrier->name, 197 (int) $order->id_shop, 198 $order->reference, 199 (bool) $order->isVirtual(), 200 $taxMethod, 201 $isTaxIncluded, 202 (bool) $order->valid, 203 $order->hasBeenPaid(), 204 $order->hasInvoice(), 205 $order->hasBeenDelivered(), 206 $order->hasBeenShipped(), 207 $invoiceManagementIsEnabled, 208 new DateTimeImmutable($order->date_add), 209 $this->getOrderCustomer($order, $orderInvoiceAddress), 210 $this->getOrderShippingAddress($order), 211 $orderInvoiceAddress, 212 $this->getOrderProducts($query->getOrderId(), $query->getProductsSorting()->getValue()), 213 $this->getOrderHistory($order), 214 $this->getOrderDocuments($order), 215 $this->getOrderShipping($order), 216 $this->getOrderReturns($order), 217 $this->getOrderPayments($order), 218 $this->getOrderMessages($order), 219 $this->getOrderPrices($order), 220 $this->getOrderDiscounts($order), 221 $this->getOrderSources($order), 222 $this->getLinkedOrders($order), 223 $this->addressFormatter->format(new AddressId((int) $order->id_address_delivery)), 224 $this->addressFormatter->format(new AddressId((int) $order->id_address_invoice)), 225 (string) $order->note 226 ); 227 } 228 229 /** 230 * @param Order $order 231 * 232 * @return OrderCustomerForViewing 233 */ 234 private function getOrderCustomer(Order $order, OrderInvoiceAddressForViewing $invoiceAddress): OrderCustomerForViewing 235 { 236 $currency = new Currency($order->id_currency); 237 $customer = new Customer($order->id_customer); 238 $genderName = ''; 239 $totalSpentSinceRegistration = null; 240 241 if (!Validate::isLoadedObject($customer)) { 242 $customer = $this->buildFakeCustomerObject($order, $invoiceAddress); 243 $customerStats = ['nb_orders' => 1]; // Count this current order as loaded 244 } else { 245 $gender = new Gender($customer->id_gender); 246 if (Validate::isLoadedObject($gender)) { 247 $genderName = $gender->name[(int) $order->getAssociatedLanguage()->getId()]; 248 } 249 250 $customerStats = $customer->getStats(); 251 $totalSpentSinceRegistration = Tools::convertPrice($customerStats['total_orders'], $order->id_currency); 252 } 253 254 $isB2BEnabled = $this->configuration->getBoolean('PS_B2B_ENABLE'); 255 256 return new OrderCustomerForViewing( 257 (int) $customer->id, 258 $customer->firstname, 259 $customer->lastname, 260 $genderName, 261 $customer->email, 262 new DateTimeImmutable($customer->date_add), 263 $totalSpentSinceRegistration !== null ? $this->locale->formatPrice($totalSpentSinceRegistration, $currency->iso_code) : '', 264 $customerStats['nb_orders'], 265 $customer->note, 266 (bool) $customer->is_guest, 267 (int) $order->getAssociatedLanguage()->getId(), 268 $isB2BEnabled ? ($customer->ape ?: '') : '', 269 $isB2BEnabled ? ($customer->siret ?: '') : '' 270 ); 271 } 272 273 /** 274 * @param Order $order 275 * 276 * @return OrderShippingAddressForViewing 277 */ 278 public function getOrderShippingAddress(Order $order): OrderShippingAddressForViewing 279 { 280 $address = new Address($order->id_address_delivery); 281 $country = new Country($address->id_country); 282 $stateName = ''; 283 284 if ($address->id_state) { 285 $state = new State($address->id_state); 286 287 $stateName = $state->name; 288 } 289 290 $dni = Address::dniRequired($address->id_country) ? $address->dni : null; 291 292 return new OrderShippingAddressForViewing( 293 $address->id, 294 $address->firstname, 295 $address->lastname, 296 $address->company, 297 $address->address1, 298 $address->address2, 299 $stateName, 300 $address->city, 301 $country->name[(int) $order->getAssociatedLanguage()->getId()], 302 $address->postcode, 303 $address->phone, 304 $address->phone_mobile, 305 $address->vat_number, 306 $dni 307 ); 308 } 309 310 /** 311 * @param Order $order 312 * 313 * @return OrderInvoiceAddressForViewing 314 */ 315 private function getOrderInvoiceAddress(Order $order): OrderInvoiceAddressForViewing 316 { 317 $address = new Address($order->id_address_invoice); 318 $country = new Country($address->id_country); 319 $stateName = ''; 320 321 if ($address->id_state) { 322 $state = new State($address->id_state); 323 324 $stateName = $state->name; 325 } 326 327 $dni = Address::dniRequired($address->id_country) ? $address->dni : null; 328 329 return new OrderInvoiceAddressForViewing( 330 $address->id, 331 $address->firstname, 332 $address->lastname, 333 $address->company, 334 $address->address1, 335 $address->address2, 336 $stateName, 337 $address->city, 338 $country->name[(int) $order->getAssociatedLanguage()->getId()], 339 $address->postcode, 340 $address->phone, 341 $address->phone_mobile, 342 $address->vat_number, 343 $dni 344 ); 345 } 346 347 /** 348 * @param Order $order 349 * 350 * @return OrderHistoryForViewing 351 */ 352 private function getOrderHistory(Order $order): OrderHistoryForViewing 353 { 354 $history = $order->getHistory($this->contextLanguageId); 355 356 $statuses = []; 357 358 foreach ($history as $item) { 359 $statuses[] = new OrderStatusForViewing( 360 (int) $item['id_order_history'], 361 (int) $item['id_order_state'], 362 $item['ostate_name'], 363 $item['color'], 364 new DateTimeImmutable($item['date_add']), 365 (bool) $item['send_email'], 366 $item['employee_firstname'], 367 $item['employee_lastname'] 368 ); 369 } 370 371 return new OrderHistoryForViewing( 372 $order->current_state, 373 $statuses 374 ); 375 } 376 377 /** 378 * @param Order $order 379 * 380 * @return OrderDocumentsForViewing 381 * 382 * @throws LocalizationException 383 */ 384 private function getOrderDocuments(Order $order): OrderDocumentsForViewing 385 { 386 $currency = new Currency($order->id_currency); 387 $documents = $order->getDocuments(); 388 389 $documentsForViewing = []; 390 391 /** @var OrderInvoice|OrderSlip $document */ 392 foreach ($documents as $document) { 393 $type = null; 394 $number = null; 395 $amount = null; 396 $numericAmount = null; 397 $amountMismatch = null; 398 $isAddPaymentAllowed = false; 399 400 if ($document instanceof OrderInvoice) { 401 $type = isset($document->is_delivery) ? OrderDocumentType::DELIVERY_SLIP : OrderDocumentType::INVOICE; 402 } elseif ($document instanceof OrderSlip) { 403 $type = OrderDocumentType::CREDIT_SLIP; 404 } 405 406 if (OrderDocumentType::INVOICE === $type) { 407 $number = $document->getInvoiceNumberFormatted( 408 $this->contextLanguageId, 409 $order->id_shop 410 ); 411 412 if ($document->getRestPaid()) { 413 $isAddPaymentAllowed = true; 414 } 415 $amount = $this->locale->formatPrice($document->total_paid_tax_incl, $currency->iso_code); 416 $numericAmount = $document->total_paid_tax_incl; 417 418 if ($document->getTotalPaid()) { 419 if ($document->getRestPaid() > 0) { 420 $amountMismatch = sprintf( 421 '%s %s', 422 $this->locale->formatPrice($document->getRestPaid(), $currency->iso_code), 423 $this->translator->trans('not paid', [], 'Admin.Orderscustomers.Feature') 424 ); 425 } elseif ($document->getRestPaid() < 0) { 426 $amountMismatch = sprintf( 427 '%s %s', 428 $this->locale->formatPrice($document->getRestPaid(), $currency->iso_code), 429 $this->translator->trans('overpaid', [], 'Admin.Orderscustomers.Feature') 430 ); 431 } 432 } 433 } elseif (OrderDocumentType::DELIVERY_SLIP === $type) { 434 $conf = $this->configuration->get( 435 'PS_DELIVERY_PREFIX', 436 null, 437 ShopConstraint::shop((int) $order->id_shop) 438 ); 439 $number = sprintf( 440 '%s%06d', 441 $conf[$this->contextLanguageId] ?? '', 442 $document->delivery_number 443 ); 444 $amount = $this->locale->formatPrice( 445 $document->total_paid_tax_incl, 446 $currency->iso_code 447 ); 448 $numericAmount = $document->total_paid_tax_incl; 449 } elseif (OrderDocumentType::CREDIT_SLIP === $type) { 450 $conf = $this->configuration->get('PS_CREDIT_SLIP_PREFIX'); 451 $number = sprintf( 452 '%s%06d', 453 $conf[$this->contextLanguageId] ?? '', 454 $document->id 455 ); 456 $amount = $this->locale->formatPrice( 457 $document->total_products_tax_incl + $document->total_shipping_tax_incl, 458 $currency->iso_code 459 ); 460 $numericAmount = $document->total_products_tax_incl + $document->total_shipping_tax_incl; 461 } 462 463 $documentsForViewing[] = new OrderDocumentForViewing( 464 $document->id, 465 $type, 466 new DateTimeImmutable($document->date_add), 467 $number, 468 $numericAmount, 469 $amount, 470 $amountMismatch, 471 $document instanceof OrderInvoice ? $document->note : null, 472 $isAddPaymentAllowed 473 ); 474 } 475 476 $canGenerateInvoice = $this->configuration->get('PS_INVOICE') && 477 count($order->getInvoicesCollection()) && 478 $order->invoice_number; 479 480 $canGenerateDeliverySlip = (bool) $order->delivery_number; 481 482 return new OrderDocumentsForViewing( 483 $canGenerateInvoice, 484 $canGenerateDeliverySlip, 485 $documentsForViewing 486 ); 487 } 488 489 /** 490 * @param Order $order 491 * 492 * @return OrderShippingForViewing 493 * 494 * @throws LocalizationException 495 */ 496 private function getOrderShipping(Order $order): OrderShippingForViewing 497 { 498 $taxCalculationMethod = $this->getOrderTaxCalculationMethod($order); 499 500 $shipping = $order->getShipping(); 501 $carriers = []; 502 $carrierModuleInfo = null; 503 504 $currency = new Currency($order->id_currency); 505 $carrier = new Carrier($order->id_carrier); 506 $carrierModuleInfo = null; 507 508 if ($carrier->is_module) { 509 $module = Module::getInstanceByName($carrier->external_module_name); 510 if (method_exists($module, 'displayInfoByCart')) { 511 $carrierModuleInfo = $module->displayInfoByCart($order->id_cart); 512 } 513 } 514 515 if (!$order->isVirtual()) { 516 foreach ($shipping as $item) { 517 if ($taxCalculationMethod == PS_TAX_INC) { 518 $price = Tools::displayPrice($item['shipping_cost_tax_incl'], $currency); 519 } else { 520 $price = Tools::displayPrice($item['shipping_cost_tax_excl'], $currency); 521 } 522 523 $trackingUrl = null; 524 $trackingNumber = $item['tracking_number']; 525 526 if ($item['url'] && $trackingNumber) { 527 $trackingUrl = str_replace('@', $trackingNumber, $item['url']); 528 } 529 530 $weight = sprintf('%.3f %s', $item['weight'], $this->configuration->get('PS_WEIGHT_UNIT')); 531 532 $carriers[] = new OrderCarrierForViewing( 533 (int) $item['id_order_carrier'], 534 new DateTimeImmutable($item['date_add']), 535 $item['carrier_name'], 536 $weight, 537 (int) $item['id_carrier'], 538 $price, 539 $trackingUrl, 540 $trackingNumber, 541 $item['can_edit'] 542 ); 543 } 544 } 545 546 return new OrderShippingForViewing( 547 $carriers, 548 (bool) $order->recyclable, 549 (bool) $order->gift, 550 $order->gift_message, 551 $carrierModuleInfo 552 ); 553 } 554 555 /** 556 * @param Order $order 557 * 558 * @return OrderReturnsForViewing 559 */ 560 private function getOrderReturns(Order $order): OrderReturnsForViewing 561 { 562 $returns = $order->getReturn(); 563 564 if ($order->isVirtual()) { 565 return new OrderReturnsForViewing(); 566 } 567 568 $orderReturns = []; 569 570 foreach ($returns as $orderReturn) { 571 $trackingUrl = null; 572 $trackingNumber = null; 573 574 if (isset($orderReturn['url'], $orderReturn['tracking_number'])) { 575 $trackingUrl = $orderReturn['url']; 576 $trackingNumber = $orderReturn['tracking_number']; 577 } elseif (isset($orderReturn['tracking_number'])) { 578 $trackingNumber = $orderReturn['tracking_number']; 579 } 580 581 $orderReturns[] = new OrderReturnForViewing( 582 (int) $orderReturn['id_order_return'], 583 isset($orderReturn['id_order_invoice']) ? (int) $orderReturn['id_order_invoice'] : 0, 584 isset($orderReturn['id_carrier']) ? (int) $orderReturn['id_carrier'] : 0, 585 new DateTimeImmutable($orderReturn['date_add']), 586 $orderReturn['type'], 587 $orderReturn['state_name'] ?? '', 588 $trackingUrl, 589 $trackingNumber 590 ); 591 } 592 593 return new OrderReturnsForViewing($orderReturns); 594 } 595 596 /** 597 * @param Order $order 598 * 599 * @return OrderPaymentsForViewing 600 * 601 * @throws LocalizationException 602 */ 603 private function getOrderPayments(Order $order): OrderPaymentsForViewing 604 { 605 $currency = new Currency($order->id_currency); 606 $payments = $order->getOrderPayments(); 607 608 $currentState = $order->getCurrentOrderState(); 609 610 $orderAmountToPay = null; 611 $orderAmountPaid = null; 612 $paymentMismatchOrders = []; 613 614 if (count($payments) > 0) { 615 $noPaymentMismatch = round($order->getOrdersTotalPaid(), 2) == round($order->getTotalPaid(), 2) 616 || ($currentState && $currentState->id == 6); 617 618 if (!$noPaymentMismatch) { 619 $orderAmountToPay = $this->locale->formatPrice($order->getOrdersTotalPaid(), $currency->iso_code); 620 $orderAmountPaid = $this->locale->formatPrice($order->getTotalPaid(), $currency->iso_code); 621 622 foreach ($order->getBrother() as $relatedOrder) { 623 $paymentMismatchOrders[] = $relatedOrder->id; 624 } 625 } 626 } 627 628 $orderPayments = []; 629 630 /** @var OrderPayment $payment */ 631 foreach ($order->getOrderPaymentCollection() as $payment) { 632 $currency = new Currency($payment->id_currency); 633 $invoice = $payment->getOrderInvoice($order->id); 634 $invoiceNumber = $invoice ? 635 $invoice->getInvoiceNumberFormatted($this->contextLanguageId, $order->id_shop) : 636 null; 637 638 $orderPayments[] = new OrderPaymentForViewing( 639 $payment->id, 640 new DateTimeImmutable($payment->date_add), 641 $payment->payment_method, 642 $payment->transaction_id, 643 $this->locale->formatPrice($payment->amount, $currency->iso_code), 644 $invoiceNumber, 645 $payment->card_number, 646 $payment->card_brand, 647 $payment->card_expiration, 648 $payment->card_holder 649 ); 650 } 651 652 return new OrderPaymentsForViewing( 653 $orderPayments, 654 $orderAmountToPay, 655 $orderAmountPaid, 656 $paymentMismatchOrders 657 ); 658 } 659 660 /** 661 * @param Order $order 662 * 663 * @return OrderMessagesForViewing 664 */ 665 private function getOrderMessages(Order $order): OrderMessagesForViewing 666 { 667 $orderMessagesForOrderPage = $this->customerDataProvider->getCustomerMessages( 668 (int) $order->id_customer, 669 (int) $order->id 670 ); 671 672 $messages = []; 673 674 foreach ($orderMessagesForOrderPage['messages'] as $orderMessage) { 675 $messageEmployeeId = (int) $orderMessage['id_employee']; 676 $isCurrentEmployeesMessage = (int) $this->context->employee->id === $messageEmployeeId; 677 678 $messages[] = new OrderMessageForViewing( 679 (int) $orderMessage['id_customer_message'], 680 $orderMessage['message'], 681 new OrderMessageDateForViewing( 682 new DateTimeImmutable($orderMessage['date_add']), 683 $this->context->language->date_format_full 684 ), 685 $messageEmployeeId, 686 $isCurrentEmployeesMessage, 687 $orderMessage['efirstname'], 688 $orderMessage['elastname'], 689 $orderMessage['cfirstname'], 690 $orderMessage['clastname'], 691 (bool) $orderMessage['private'] 692 ); 693 } 694 695 return new OrderMessagesForViewing($messages, $orderMessagesForOrderPage['total']); 696 } 697 698 /** 699 * @param Order $order 700 * 701 * @return OrderPricesForViewing 702 * 703 * @throws LocalizationException 704 */ 705 private function getOrderPrices(Order $order): OrderPricesForViewing 706 { 707 $currency = new Currency($order->id_currency); 708 $customer = $order->getCustomer(); 709 710 $isTaxExcluded = !$this->isTaxIncludedInOrder($order); 711 712 $shipping_refundable_tax_excl = $order->total_shipping_tax_excl; 713 $shipping_refundable_tax_incl = $order->total_shipping_tax_incl; 714 715 $slips = OrderSlip::getOrdersSlip($customer->id, $order->id); 716 foreach ($slips as $slip) { 717 $shipping_refundable_tax_excl -= $slip['total_shipping_tax_excl']; 718 $shipping_refundable_tax_incl -= $slip['total_shipping_tax_incl']; 719 } 720 721 if ($isTaxExcluded) { 722 $productsPrice = (float) $order->total_products; 723 $discountsAmount = (float) $order->total_discounts_tax_excl; 724 $wrappingPrice = (float) $order->total_wrapping_tax_excl; 725 $shippingPrice = (float) $order->total_shipping_tax_excl; 726 $shippingRefundable = max(0, $shipping_refundable_tax_excl); 727 } else { 728 $productsPrice = (float) $order->total_products_wt; 729 $discountsAmount = (float) $order->total_discounts_tax_incl; 730 $wrappingPrice = (float) $order->total_wrapping_tax_incl; 731 $shippingPrice = (float) $order->total_shipping_tax_incl; 732 $shippingRefundable = max(0, $shipping_refundable_tax_incl); 733 } 734 $totalAmount = (float) $order->total_paid_tax_incl; 735 736 $taxesAmount = $order->total_paid_tax_incl - $order->total_paid_tax_excl; 737 738 return new OrderPricesForViewing( 739 new DecimalNumber((string) $productsPrice), 740 new DecimalNumber((string) $discountsAmount), 741 new DecimalNumber((string) $wrappingPrice), 742 new DecimalNumber((string) $shippingPrice), 743 new DecimalNumber((string) $shippingRefundable), 744 new DecimalNumber((string) $taxesAmount), 745 new DecimalNumber((string) $totalAmount), 746 Tools::displayPrice($productsPrice, $currency), 747 Tools::displayPrice($discountsAmount, $currency), 748 Tools::displayPrice($wrappingPrice, $currency), 749 Tools::displayPrice($shippingPrice, $currency), 750 Tools::displayPrice($shippingRefundable, $currency), 751 Tools::displayPrice($taxesAmount, $currency), 752 Tools::displayPrice($totalAmount, $currency) 753 ); 754 } 755 756 /** 757 * @param Order $order 758 * 759 * @return OrderDiscountsForViewing 760 * 761 * @throws LocalizationException 762 */ 763 private function getOrderDiscounts(Order $order): OrderDiscountsForViewing 764 { 765 $isTaxIncluded = $this->isTaxIncludedInOrder($order); 766 $currency = new Currency($order->id_currency); 767 $discounts = $order->getCartRules(); 768 $discountsForViewing = []; 769 770 foreach ($discounts as $discount) { 771 $discountAmount = $isTaxIncluded ? $discount['value'] : $discount['value_tax_excl']; 772 $discountsForViewing[] = new OrderDiscountForViewing( 773 (int) $discount['id_order_cart_rule'], 774 $discount['name'], 775 new DecimalNumber((string) $discountAmount), 776 Tools::displayPrice($discountAmount, $currency) 777 ); 778 } 779 780 return new OrderDiscountsForViewing($discountsForViewing); 781 } 782 783 /** 784 * @param Order $order 785 * 786 * @return OrderSourcesForViewing 787 */ 788 private function getOrderSources(Order $order): OrderSourcesForViewing 789 { 790 $sourcesData = ConnectionsSource::getOrderSources($order->id); 791 $sources = []; 792 793 foreach ($sourcesData as $sourceItem) { 794 $sources[] = new OrderSourceForViewing( 795 $sourceItem['http_referer'], 796 $sourceItem['request_uri'], 797 new DateTimeImmutable($sourceItem['date_add']), 798 $sourceItem['keywords'] 799 ); 800 } 801 802 return new OrderSourcesForViewing($sources); 803 } 804 805 /** 806 * @return LinkedOrdersForViewing 807 */ 808 private function getLinkedOrders(Order $order): LinkedOrdersForViewing 809 { 810 $brothersData = $order->getBrother(); 811 $brothers = []; 812 /** @var Order $brotherItem */ 813 foreach ($brothersData as $brotherItem) { 814 $isTaxExcluded = !$this->isTaxIncludedInOrder($brotherItem); 815 816 $currency = new Currency($brotherItem->id_currency); 817 818 if ($isTaxExcluded) { 819 $totalAmount = $this->locale->formatPrice($brotherItem->total_paid_tax_excl, $currency->iso_code); 820 } else { 821 $totalAmount = $this->locale->formatPrice($brotherItem->total_paid_tax_incl, $currency->iso_code); 822 } 823 824 $orderState = new OrderState($brotherItem->current_state); 825 826 $brothers[] = new LinkedOrderForViewing( 827 $brotherItem->id, 828 $orderState->name[$this->context->language->getId()], 829 $totalAmount 830 ); 831 } 832 833 return new LinkedOrdersForViewing($brothers); 834 } 835 836 /** 837 * @param OrderId $orderId 838 * @param string $productsOrder 839 * 840 * @return OrderProductsForViewing 841 * 842 * @throws OrderException 843 * @throws InvalidSortingException 844 */ 845 private function getOrderProducts(OrderId $orderId, string $productsOrder): OrderProductsForViewing 846 { 847 return $this->getOrderProductsForViewingHandler->handle( 848 GetOrderProductsForViewing::all($orderId->getValue(), $productsOrder) 849 ); 850 } 851 852 /** 853 * If there is no valid customer attached to the order, the customer must have been deleted 854 * from the database. We then create a fake customer object, using the invoice address data 855 * and cart language. 856 * 857 * @param Order $order Order object 858 * @param OrderInvoiceAddressForViewing $invoiceAddress Invoice address information 859 * 860 * @return Customer The created customer 861 */ 862 private function buildFakeCustomerObject(Order $order, OrderInvoiceAddressForViewing $invoiceAddress): Customer 863 { 864 $cart = new Cart($order->id_cart); 865 866 $customer = new Customer(); 867 $customer->firstname = $invoiceAddress->getFirstName(); 868 $customer->lastname = $invoiceAddress->getLastName(); 869 $customer->email = ''; 870 $customer->id_lang = $cart->getAssociatedLanguage()->getId(); 871 $customer->is_guest = true; 872 873 return $customer; 874 } 875} 876