contacts_events-8.x-1.x-dev/src/ContactsPaymentListBuilder.php
src/ContactsPaymentListBuilder.php
<?php namespace Drupal\contacts_events; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_order\Entity\OrderItemInterface; use Drupal\commerce_payment\PaymentListBuilder; use Drupal\commerce_price\Price; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Custom ListBuilder for payments that adds additional columns. * * @package Drupal\contacts */ class ContactsPaymentListBuilder extends PaymentListBuilder { /** * Partial payment order item tracking, if available. * * @var \Drupal\commerce_partial_payments\OrderItemTracking|null */ protected $tracking; /** * {@inheritdoc} */ public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { $self = parent::createInstance($container, $entity_type); $self->tracking = $container->get('commerce_partial_payments.order_item_tracking', ContainerInterface::NULL_ON_INVALID_REFERENCE); return $self; } /** * {@inheritdoc} */ public function buildHeader() { $header = parent::buildHeader(); $header['by'] = $this->t('By'); $header['date'] = $this->t('Date'); // Ensure operations goes at the end. $operations = $header['operations']; unset($header['operations']); $header['operations'] = $operations; return $header; } /** * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { /** @var \Drupal\commerce_payment\Entity\Payment $entity */ $row = parent::buildRow($entity); $row['by'] = $entity->get('creator')->entity ? $entity->get('creator')->entity->label() : ''; $completed = $entity->getCompletedTime(); $row['date'] = $completed ? $this->dateFormatter->format($completed, 'short') : $this->t('Not complete'); // Ensure operations goes at the end. $operations = $row['operations']; unset($row['operations']); $row['operations'] = $operations; return $row; } /** * {@inheritdoc} */ public function render() { $build = parent::render(); /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order = $this->routeMatch->getParameter('commerce_order'); $total = $order->getTotalPrice(); if ($total) { $paid = $order->getTotalPaid(); $balance = $order->getBalance(); $build['summary'] = [ '#type' => 'container', '#attributes' => [ 'class' => ['container-inline'], ], '#weight' => -99, ]; $build['summary']['total'] = [ '#type' => 'item', '#title' => new TranslatableMarkup('Total'), '#markup' => $this->currencyFormatter->format($total->getNumber(), $total->getCurrencyCode()), ]; if ($paid) { $build['summary']['paid'] = [ '#type' => 'item', '#title' => new TranslatableMarkup('Paid'), '#markup' => $this->currencyFormatter->format($paid->getNumber(), $paid->getCurrencyCode()), ]; $this->validateTracking($order); } if ($balance) { $build['summary']['balance'] = [ '#type' => 'item', '#title' => new TranslatableMarkup('Balance'), '#markup' => $this->currencyFormatter->format($balance->getNumber(), $balance->getCurrencyCode()), ]; } } return $build; } /** * Validate payment tracking for the order if we have partial payments. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order. */ protected function validateTracking(OrderInterface $order): void { // Do nothing if we don't have partial payments enabled. if (!$this->tracking) { return; } // Get the tracked amounts and find any that belong to items not on the // order. $tracking = $this->tracking->getTrackedAmountsForOrder($order); $item_ids = array_fill_keys( array_map( function (OrderItemInterface $item) { return $item->id(); }, $order->getItems(), ), TRUE, ); /** @var \Drupal\commerce_price\Price[] $missing_items */ $missing_items = array_filter( array_diff_key($tracking, $item_ids), function (Price $amount) { return !$amount->isZero(); } ); // Get a total for the tracked amounts against missing items. /** @var \Drupal\commerce_price\Price|null $missing_total */ $missing_total = NULL; foreach ($missing_items as $missing_item) { if (!$missing_item->isZero()) { $missing_total = $missing_total ? $missing_total->add($missing_item) : $missing_item; } } // Show an error message. if ($missing_total) { $formatted_amount = $this->currencyFormatter->format($missing_total->getNumber(), $missing_total->getCurrencyCode()); $this->messenger()->addError($this->formatPlural( count($missing_items), 'Payment of @amount is tracked against a missing item. Please Reallocate Funds to correct it.', 'Payment totalling @amount is tracked against @count missing item. Please Reallocate Funds to correct it.', ['@amount' => $formatted_amount], )); } } }