bb2b_order.module

PHOTO EMBED

Sat May 21 2022 15:06:48 GMT+0000 (Coordinated Universal Time)

Saved by @igor #drupal #pseudo-field #form-render

<?php

/**
 * @file
 * Provides a bb2b_order.
 */

use Drupal\block\Entity\Block;
use Drupal\commerce_order\Entity\Order;
use Drupal\commerce_shipping\Entity\ShipmentInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\AppendCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\bb2b_order\Plugin\Commerce\CheckoutPane\OrderTypePane;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\views\Form\ViewsForm;
use Drupal\views\ViewExecutable;
use Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_cron().
 */
function bb2b_order_cron() {
  $request_time = \Drupal::time()->getRequestTime();
  $state_key = 'bb2b_order.last_queue_time';
  $last_queue_time = \Drupal::state()->get($state_key, 0);

  // Once daily.
  if ($request_time - $last_queue_time >= (24 * 60 * 60)) {
    \Drupal::service('bb2b_order.order_reservation_cron')->run();

    \Drupal::state()->set($state_key, $request_time);
  }
}

/**
 * Implements hook_form_alter().
 */
function bb2b_order_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Add to cart on product page. This page will be deactivated.
  if (strpos($form_id, 'commerce_order_item_add_to_cart_form') !== FALSE) {
    array_unshift($form['#validate'], 'validate_available_quantity');
  }

  // Cart page.
  if (strpos($form_id, 'views_form_commerce_cart_form_') !== FALSE) {
    array_unshift($form['#validate'], 'validate_min_quantity');
  }

  // Quick order page.
  if ($form_state->getFormObject() instanceof ViewsForm) {
    /** @var \Drupal\views\ViewExecutable $view */
    $view = reset($form_state->getBuildInfo()['args']);

    if ($view->storage->get('id') == 'quick_order' && !empty($view->result)) {
      $order_id = \Drupal::service('commerce_cart.cart_provider')->getCartIds(\Drupal::currentUser());
      $order_id = reset($order_id);
      $order = \Drupal::entityTypeManager()->getStorage('commerce_order')
        ->load($order_id);

      $form['ddp_package_list'] = [
        '#type' => 'details',
        '#title' => t('At DDP orders, every box must be filled with the MOQ / box quantity.'),
        '#weight' => -2,
        '#open' => FALSE,
      ];

      $form['ddp_package_list']['block'] = [
        '#type' => 'container',
        'block' => [
          '#markup' => bb2b_order_render_shipment_package_block(),
        ],
      ];

      $name = 'field_order_type';
      /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
      $form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')
        ->load('commerce_order.default.default');

      $widget = $form_display->getRenderer($name);

      $roles = \Drupal::currentUser()->getRoles();
      $is_admin = in_array('administrator', $roles) || in_array('site_administrator', $roles);

      if ($widget) {
        $items = $order->get($name);
        $items->filterEmptyItems();

        $store = \Drupal::service('commerce_store.current_store')->getStore();
        $cart_provider = \Drupal::service('commerce_cart.cart_provider');
        $cart = $cart_provider->getCart('default', $store);

        if (!$cart) {
          $cart = $cart_provider->createCart('default', $store);
        }

        $order_type = $cart->get('field_order_type')->value;

        $form[$name] = $widget->form($items, $form, $form_state);
        $form[$name]['#access'] = $items->access('edit');
        $form[$name]['#required'] = TRUE;
        $form[$name]['#weight'] = -1;
        $form[$name]['widget']['#default_value'] = $order_type ?? 'ddp';
        $form[$name]['widget']['#ajax'] = [
          'callback' => 'bb2b_order_update_min_values',
        ];

        if ($is_admin) {
          unset($form[$name]['widget']['#options']['ddp_reservation']);
        }
        else {
          $form[$name]['widget']['ddp_reservation'] = [
            '#description' => t('You have 5 days to pay the order, otherwise it will be canceled.'),
          ];
        }
      }

      $options = [];
      $companies = \Drupal::entityTypeManager()
        ->getStorage('company')
        ->loadMultiple();

      foreach ($companies as $company) {
        if ($employee = $company->getEmployeeByRole('company_manager')) {
          $options[$employee->id()] = $employee->getDisplayName() . ' (' . $company->getName() . ')';
        }
      }

      $form['client'] = [
        '#type' => 'select2',
        '#id' => 'update-client',
        '#options' => $options,
        '#title' => t('Client'),
        '#required' => FALSE,
        '#weight' => -2,
        '#access' => $is_admin,
        '#ajax' => [
          'callback' => 'bb2b_order_update_client',
        ],
      ];

      if ($client_id = $order->getData('client_id')) {
        $form['client']['#default_value'] = $client_id;
      }

      $form['actions']['checkout'] = [
        '#type' => 'submit',
        '#value' => t('Delivery data'),
        '#weight' => 5,
        '#access' => \Drupal::currentUser()->hasPermission('access checkout'),
        '#submit' => array_merge($form['#submit'], ['bb2b_order_checkout_views_form_submit']),
        '#order_id' => $order_id,
      ];

    }
  }

  if ($form_id == 'commerce_shipping_method_edit_form') {
    $form['plugin']['widget'][0]['target_plugin_configuration']['form']['rate_label']['#attributes'] = ['readonly' => 'readonly'];
    $form['plugin']['widget'][0]['target_plugin_configuration']['form']['rate_label']['#description'] = t('Shown to customers during checkout. This value cannot be changed because we need it to match the name in Linker.');
  }
}

/**
 * Implements hook_views_pre_render().
 */
function bb2b_order_views_pre_render(ViewExecutable $view) {
  if ($view->id() == 'commerce_cart_form') {
    $order_id = $view->args[0];
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = Order::load($order_id);

    /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */
    $order_service = \Drupal::service('bb2b_order.order_service');

    if (!$order_service->packageMinQuantityIsValid($order)) {
      $view->build_info['substitutions']['{{ admin_shipment_packages_block }}'] = bb2b_order_render_shipment_package_block();
    }
  }
  if ($view->id() === 'quick_order') {
    //@todo: This will go to history when we create stock base field on product.
    //@todo: Query will be in the StockStatus filter.
    $input = $view->getExposedInput();
    if (isset($input['stock_status']) && $input['stock_status'] === 'only_available') {
      // Get products from the view.
      $products = [];
      foreach ($view->result as $key => $product) {
        $products[$key] = $product->_entity;
      }
      // Check if those products are available.
      $order_service = \Drupal::service('bb2b_order.order_service');
      foreach ($products as $key => $product) {
        if (!$order_service->checkAccessForProduct($product))
        unset($view->result[$key]);
      }

    }
  }
}

/**
 * Gets the cart order for the given store and user.
 *
 * @param \Drupal\Core\Session\AccountInterface $account
 *   The user. If empty, the current user is assumed.
 *
 * @return \Drupal\commerce_order\Entity\OrderInterface|null
 *   The cart order, or NULL if none found.
 */
function bb2b_order_get_cart(AccountInterface $account = NULL) {
  $store = \Drupal::service('commerce_store.current_store')->getStore();
  $cart_provider = \Drupal::service('commerce_cart.cart_provider');
  $cart = $cart_provider->getCart('default', $store, $account);

  if (!$cart) {
    $cart = $cart_provider->createCart('default', $store, $account);
  }

  return $cart;
}

/**
 * Ajax handler used to remove min values validation for drop shipping.
 */
function bb2b_order_update_client($form, FormStateInterface $form_state) {
  $response = new AjaxResponse();

  $triggering_element = $form_state->getTriggeringElement();
  $trigger_name = array_shift($triggering_element['#parents']);

  if ($trigger_name === 'client') {
    $client_id = $triggering_element['#value'];
    $cart = bb2b_order_get_cart();

    $user = \Drupal::entityTypeManager()
      ->getStorage('user')
      ->load($client_id);

    $email = $user ? $user->getEmail() : NULL;

    $cart->setData('client_id', $client_id);
    $cart->setData('client_email', $email);
    $cart->save();

    $content = '<div class="ajax-progress-throbber"></div>';
    $response->addCommand(new AppendCommand('body', $content));
    $response->addCommand(new RedirectCommand(Url::fromUri('internal:/orders/quick-order')->toString()));
  }

  return $response;
}

/**
 * Ajax handler used to remove min values validation for drop shipping.
 */
function bb2b_order_update_min_values($form, FormStateInterface $form_state) {
  $response = new AjaxResponse();

  $triggering_element = $form_state->getTriggeringElement();
  $trigger_name = array_shift($triggering_element['#parents']);

  if ($trigger_name === 'field_order_type') {
    $order_type = $triggering_element['#value'];
    $rows = $form['output'][0]['#rows'];

    /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */
    $order_service = \Drupal::service('bb2b_order.order_service');

    $cart = bb2b_order_get_cart();

    /*if ($order_type !== 'drop_shipping') {
    $cart->setData('client_id', NULL);
    $cart->setData('client_email', NULL);
    }*/

    $cart->set('field_order_type', $order_type);
    $cart->save();

    foreach ($rows as $key => $row) {
      $field_stock = $form['warehouse_stock'][$key];
      $field_quantity = $form['edit_quantity'][$key];
      $field_chk = $form['chk_add_to_cart'][$key];
      $field_price = $form['price_group_price'][$key];
      $add_to_cart_button = $form['add_to_cart_button'][$key];

      /** @var \Drupal\commerce_product\Entity\ProductInterface $product */
      $product = $row->_entity;

      $access = $order_service->checkAccessForProduct($product);
      $available = $order_service->getAvailableStock($product);

      if ($order_type === 'drop_shipping') {
        $class = $field_quantity['#attributes']['class'] ?? [];
        $key = array_search('visually-hidden', $class);
        if ($key !== FALSE && $available > 0) {
          unset($field_quantity['#attributes']['class'][$key]);
        }

        $class = $field_chk['#attributes']['class'] ?? [];
        $key = array_search('visually-hidden', $class);
        if ($key !== FALSE && $available > 0) {
          unset($field_chk['#attributes']['class'][$key]);
        }

        $class = $add_to_cart_button['#attributes']['class'] ?? [];
        $key = array_search('visually-hidden', $class);
        if ($key !== FALSE && $available > 0) {
          unset($add_to_cart_button['#attributes']['class'][$key]);
        }
      }
      else {
        if (!$access || $available == 0) {
          if (!isset($field_quantity['#attributes']['class']['visually-hidden'])) {
            $field_quantity['#attributes']['class'][] = 'visually-hidden';
          }

          if (!isset($field_chk['#attributes']['class']['visually-hidden'])) {
            $field_chk['#attributes']['class'][] = 'visually-hidden';
          }

          $field_chk['#value'] = 0;
          if (!isset($add_to_cart_button['#attributes']['class']['visually-hidden'])) {
            $add_to_cart_button['#attributes']['class'][] = 'visually-hidden';
          }
        }
      }

      $method = $order_type === 'drop_shipping' ? 'addClass' : 'removeClass';
      $response->addCommand(new InvokeCommand('.min-qty', $method, ['visually-hidden']));

      $selector = $field_quantity['#attributes']['data-drupal-selector'];
      $quantity_selector = 'div[class*="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]';
      $response->addCommand(new ReplaceCommand($quantity_selector, $field_quantity));

      $selector = $field_chk['#attributes']['data-drupal-selector'];
      $chk_selector = 'div[class*="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]';
      $response->addCommand(new ReplaceCommand($chk_selector, $field_chk));

      $selector = $field_stock['#attributes']['data-drupal-selector'];
      $stock_selector = 'div[id="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]';
      $response->addCommand(new ReplaceCommand($stock_selector, $field_stock));

      $company = $order_service->getCompanyForClient($cart);
      $price = $order_service->getProductPriceForClient($product->getDefaultVariation(), $cart, $company);
      $field_price['list_price']['#value'] = $price['list_price'];
      $field_price['price']['#value'] = $price['price'];

      $selector = $field_price['#attributes']['data-drupal-selector'];
      $price_selector = 'div[id="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]';
      $response->addCommand(new ReplaceCommand($price_selector, $field_price));

      $button_selector = 'button[name="' . $add_to_cart_button['#name'] . '"]';
      $response->addCommand(new ReplaceCommand($button_selector, $add_to_cart_button));

      // Cart block.
      /** @var \Drupal\Core\Block\BlockPluginInterface $cart_block */
      $cart_block = \Drupal::service('plugin.manager.block')->createInstance('commerce_cart', []);
      if ($cart_block) {
        $response->addCommand(new ReplaceCommand('.cart--cart-block', $cart_block->build()));
      }
    }
  }

  return $response;
}

/**
 * Submit handler used to redirect to the checkout page.
 */
function bb2b_order_checkout_views_form_submit($form, FormStateInterface $form_state) {
  $order_id = $form_state->getTriggeringElement()['#order_id'];
  $form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $order_id]);
}

/**
 * Form validation handler for commerce_order_item_add_to_cart_form*().
 *
 * @param array $form
 *   A build form array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The form state.
 */
function validate_available_quantity(array $form, FormStateInterface $form_state) {
  $product = $form_state->get('product');
  $quantity = (int) $form_state->getValue('quantity')[0]['value'];

  /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */
  $order_service = \Drupal::service('bb2b_order.order_service');

  $available = $order_service->getAvailableStock($product);
  if ($available < $quantity) {
    $form_state->setErrorByName('quantity][0][value', t('There are not enough quantity on the stock. Available: @available', [
      '@available' => $available,
    ]));
  }

}

/**
 * Form validation handler for views_form_commerce_cart_form_*().
 *
 * @param array $form
 *   A build form array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The form state.
 */
function validate_min_quantity(array $form, FormStateInterface $form_state) {
  $quantity = $form_state->getValue('edit_quantity');
  $rows = $form['output'][0]['#rows'];

  $triggering_element = $form_state->getTriggeringElement();
  $trigger_name = array_shift($triggering_element['#parents']);

  if ($trigger_name !== 'remove_button') {
    foreach ($rows as $key => $row) {
      /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $product_variation */
      $product_variation = $row->_relationship_entities['commerce_product_variation'];

      /** @var \Drupal\commerce_product\Entity\ProductInterface $product */
      $product = $product_variation->getProduct();

      /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
      $order = $row->_entity;

      /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */
      $order_service = \Drupal::service('bb2b_order.order_service');

      $available = $order_service->getAvailableStock($product);

      foreach ($order->getItems() as $order_item) {
        if ($order_item->getPurchasedEntityId() == $product_variation->id()) {
          $order_quantity = (int) $order_item->getQuantity();
          $diff_quantity = $quantity[$key] - $order_quantity;

          if ($available < $diff_quantity || ($diff_quantity == 0 && $available < $order_quantity)) {
            $form_state->setErrorByName('edit_quantity][' . $key, t('There are not enough quantity on the stock for product: @product_title. Available: @available', [
              '@product_title' => $product->getTitle(),
              '@available' => $diff_quantity == 0 ? $available : $available + $order_quantity,
            ]));
          }
        }
      }

    }
  }

}

/**
 * Implements hook_commerce_inline_form_PLUGIN_ID_alter().
 */
function bb2b_order_commerce_inline_form_customer_profile_alter(array &$inline_form, FormStateInterface $form_state, array &$complete_form) {
  if ($inline_form['#profile_scope'] === 'checkout' && !isset($inline_form['rendered'])) {
    $inline_form['address']['widget'][0]['address']['#after_build'] = [
      'change_country_code_ajax_callback',
      ['\Drupal\address\Element\Address', 'clearValues'],
    ];
  }
}

/**
 * Form API callback: Change ajax callback on country select.
 *
 * @param array $element
 *   The element array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Form state object.
 *
 * @return array
 *   The element array.
 */
function change_country_code_ajax_callback(array $element, FormStateInterface &$form_state) {
  $element['country_code']['country_code']['#ajax']['callback'] = [
    OrderTypePane::class,
    'ajaxRefresh',
  ];

  if ($form_state->getTriggeringElement()) {
    if ($form_state->getTriggeringElement()['#name'] === $element['country_code']['country_code']['#name']) {
      $form_state->setTriggeringElement($element['country_code']['country_code']);
    }
  }

  return $element;
}

/**
 * Implements hook_mail_alter().
 */
function bb2b_order_mail_alter(&$message) {
  if ($message['key'] == 'order_receipt' && !empty($message['params']['order'])) {
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $message['params']['order'];
    $message['from'] = 'noreply@bescool.net';

    $subject_order_number = $order->getOrderNumber();
    if ($order->get('field_your_order_id')->isEmpty() === FALSE) {
      $client_order_number = $order->get('field_your_order_id')->value;
      $subject_order_number .= ' (' . $client_order_number . ')';
    }

    $message['subject'] = t('Order confirmation ID: @number', [
      '@number' => $subject_order_number,
    ]);
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function bb2b_order_form_views_exposed_form_alter(&$form, FormStateInterface $form_state) {
  $view = $form_state->get('view');

  if ($view && in_array($view->id(), ['ongoing_orders', 'orders'])) {
    $form['search']['#placeholder'] = t('By email, order IDs, recipient name');
  }
}

/**
 * Implements hook_views_data_alter().
 */
function bb2b_order_views_data_alter(array &$data) {
  $data['commerce_order']['own_company_orders'] = [
    'title' => t('Own company orders'),
    'help' => t('Filter orders by own company for company managers.'),
    'filter' => [
      'group' => 'Order',
      'field' => 'uid',
      'id' => 'own_company_orders_filter',
      'entity_type' => 'commerce_order',
    ],
  ];
}

/**
 * Implements hook_views_data().
 */
function bb2b_order_views_data() {
  $data = [];

  //@todo: Maybe we could put ["products"] instead of ["views"].
  $data['views']['stock_status'] = [
    'title' => t('Stock status - Custom Filter'),
    'filter' => [
      'title' => t('Stock status - Custom Filter'),
      'field' => 'id',
      'id' => 'stock_status',
    ]
  ];

  return $data;
}

/**
 * Implements hook_ENTITY_TYPE_presave().
 */
function bb2b_order_commerce_order_presave(EntityInterface $entity) {
  if ($entity->get('field_created_invoice')->isEmpty()) {
    $entity->set('field_created_invoice', 'no');
  }
  // In case the your_order_id is edited after the order has been created,
  // and before the order is being shipped.
  if (!empty($entity->get('placed')->value)) {
    $order_service = \Drupal::service('bb2b_order.order_service');
    $order_service->resolveShipping($entity);
  }
}

/**
 * Implements hook_entity_access().
 */
function bb2b_order_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
  $allowed_entities = [
    'commerce_order',
    'commerce_order_item',
    'commerce_shipment',
  ];

  if (in_array($entity->getEntityTypeId(), $allowed_entities)) {
    if ($account->hasPermission('update default commerce_order')) {
      return AccessResult::allowed();
    }
  }

  return AccessResult::neutral();
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function bb2b_order_form_commerce_shipment_default_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if (!\Drupal::currentUser()->hasPermission('access commerce administration pages')) {
    $form['title']['#access'] = FALSE;
    $form['shipping_method']['#access'] = FALSE;
    $form['tracking_code']['#access'] = FALSE;
    $form['shipment_items']['#access'] = FALSE;
    $form['recalculate_shipping']['#access'] = FALSE;
    $form['actions']['delete']['#access'] = FALSE;

    $request = \Drupal::requestStack()->getCurrentRequest();
    $shipment = $request->get('commerce_shipment');
    $form_state->set('shipment', $shipment);
    $shipment->setData('shipping_force_resolve', TRUE);

    if (isset($form['shipping_profile']['widget'][0]['profile']['edit_button'])) {
      $form['shipping_profile']['widget'][0]['profile']['edit_button']['#attributes']['class'][] = 'button-secondary';
    }

    // Redirect user to order view.
    $form['actions']['submit']['#submit'][] = 'bb2b_order_shipment_edit_form_submit';
  }
}

/**
 * Custom submit handler for the shipment edit form.
 */
function bb2b_order_shipment_edit_form_submit($form, FormStateInterface $form_state) {
  $shipment = $form_state->get('shipment');
  $account = \Drupal::currentUser();
  if ($shipment) {
    $admin_permission = $account
      ->hasPermission($shipment->getEntityType()->getAdminPermission());
    $order = $shipment->getOrder();

    if ($order && !$admin_permission) {
      /*$form_state->setRedirect('entity.commerce_order.user_view', [
      'commerce_order' => $order->id(),
      'user' => $order->getCustomerId(),
      ]);*/

      $form_state->setRedirect('entity.commerce_order.edit_form', [
        'commerce_order' => $order->id(),
      ]);
    }
  }
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function bb2b_order_form_commerce_order_default_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $user = \Drupal::currentUser();
  if (!$user->hasPermission('access commerce administration pages')) {
    $form['field_credit_note']['#access'] = FALSE;
    $form['field_internal_note']['#access'] = FALSE;
    $form['field_order_notes']['#access'] = FALSE;
    $form['field_order_type']['#access'] = FALSE;
    $form['field_vat_verified']['#access'] = FALSE;
    $form['field_tracking_code_date']['#access'] = FALSE;
    $form['coupons']['#access'] = FALSE;
    $form['billing_profile']['widget'][0]['profile']['select_address']['#access'] = FALSE;
    $form['billing_profile']['widget'][0]['profile']['edit_button']['#access'] = FALSE;
    $form['billing_profile']['widget'][0]['profile']['copy_fields']['enable']['#access'] = FALSE;
    $form['shipments']['#access'] = FALSE;

    $form['order_items']['widget']['actions']['ief_add']['#attributes']['class'][] = 'button-secondary';

    if (isset($form['order_items']['widget']['entities'])) {
      foreach ($form['order_items']['widget']['entities'] as $key => &$entity) {
        if (is_numeric($key)) {
          $entity['actions']['ief_entity_edit']['#attributes']['class'][] = 'button-secondary';
          $entity['actions']['ief_entity_remove']['#attributes']['class'][] = 'delete-order-item';
        }
      }
    }

    $form['ddp_package_list'] = [
      '#type' => 'details',
      '#title' => t('At DDP orders, every box must be filled with the MOQ / box quantity.'),
      '#weight' => -2,
      '#open' => FALSE,
    ];

    $form['ddp_package_list']['block'] = [
      '#type' => 'container',
      'block' => [
        '#markup' => bb2b_order_render_shipment_package_block(),
      ],
    ];

    $header = [t('Title'), t('Shipping method'), t('Price'), t('Actions')];
    $rows = [];
    $request = \Drupal::requestStack()->getCurrentRequest();

    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $request->get('commerce_order');
    if ($order && $user->hasPermission('update default commerce_order')) {
      $form_state->set('order', $order);
      /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface[] $shipments */
      $shipments = $order->get('shipments')->referencedEntities();
      foreach ($shipments as $shipment) {
        $row = $links = [];
        $links['edit'] = [
          'title' => t('Edit'),
          'url' => $shipment->toUrl('edit-form'),
          'attributes' => [
            'role' => 'button',
            'class' => ['button button-secondary'],
            // 'target' => '_blank',
          ],
        ];

        $row[] = [
          'data' => [
            '#type' => 'markup',
            '#markup' => $shipment->label(),
          ],
        ];

        $row[] = [
          'data' => [
            '#type' => 'markup',
            '#markup' => $shipment->getShippingMethod()->label(),
          ],
        ];

        $row[] = [
          'data' => [
            '#type' => 'markup',
            '#markup' => $shipment->getAmount(),
          ],
        ];

        $row[] = [
          'data' => [
            '#type' => 'operations',
            '#links' => $links,
          ],
        ];

        $rows[] = $row;
      }
    }

    $form['shipments_list'] = [
      '#type' => 'container',
      '#weight' => $form['shipments']['#weight'] ?? 0,
      'shipments' => [
        '#type' => 'fieldset',
        '#title' => t('Shipments'),
        'entities' => [
          '#theme' => 'table',
          '#rows' => $rows,
          '#header' => $header,
        ],
      ],
    ];

    array_unshift($form['#validate'], 'validate_first_package_is_full');

    // Redirect user to order view.
    $form['actions']['submit']['#submit'][] = 'bb2b_order_order_edit_form_submit';
  }
}

/**
 * Custom submit handler for the order edit form.
 */
function bb2b_order_order_edit_form_submit($form, FormStateInterface $form_state) {
  $order = $form_state->get('order');
  if ($order) {
    $form_state->setRedirect('entity.commerce_order.user_view', [
      'commerce_order' => $order->id(),
      'user' => $order->getCustomerId(),
    ]);
  }
}

/**
 * Render shipment packages block content.
 *
 * @return mixed
 *   The rendered content.
 */
function bb2b_order_render_shipment_package_block() {
  $shipment_package_view = views_embed_view('shipment_package_list', 'block_1');

  return \Drupal::service('renderer')
    ->render($shipment_package_view);
}

/**
 * Form validation handler for commerce_order_default_edit_form().
 *
 * @param array $form
 *   A build form array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The form state.
 */
function validate_first_package_is_full(array $form, FormStateInterface $form_state) {
  $triggering_element = $form_state->getTriggeringElement();

  $parents = $triggering_element['#array_parents'];
  $triggering_element_name = array_pop($parents);

  if ($triggering_element_name === 'submit') {
    $storage = $form_state->getStorage();
    $order_items_array = $storage['inline_entity_form']['order_items-form']['entities'] ?? [];

    /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */
    $order_service = \Drupal::service('bb2b_order.order_service');

    $order_type = NULL;
    $order_items = [];
    foreach ($order_items_array as $order_item_array) {
      if (isset($order_item_array['entity'])) {
        $order_items[] = $order_item_array['entity'];
        if (!$order_type) {
          $order = $order_item_array['entity']->getOrder();
          $order_type = $order ? $order->get('field_order_type')->value : NULL;
        }
      }
    }

    if ($order_items && $order_type !== 'drop_shipping') {
      $quantities = $order_service->getOrderedQuantitiesByTag($order_items);
      if ($order_service->minQuantityIsNotValid($quantities)) {
        $form_state->setErrorByName('full_package', t('Your order can not be completed because the conditions for minimum order quantity is not met.'));
      }
    }
  }

}

/**
 * Implements hook_inline_entity_form_entity_form_alter().
 */
function bb2b_order_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) {
  $access_commerce_admin_pages = \Drupal::currentUser()
    ->hasPermission('access commerce administration pages');
  if (!$access_commerce_admin_pages) {
    if ($entity_form['#entity_type'] === 'commerce_shipment') {
      $entity_form['title']['#access'] = FALSE;
      $entity_form['shipping_method']['#access'] = FALSE;
      $entity_form['tracking_code']['#access'] = FALSE;
    }
    elseif ($entity_form['#entity_type'] === 'commerce_order_item') {
      $entity_form['unit_price']['#access'] = FALSE;
      $default_quantity = (int) ($entity_form['quantity']['widget'][0]['value']['#default_value'] ?? 0);
      $entity_form['quantity']['widget'][0]['value']['#default_value'] = $default_quantity;
      $entity_form['purchased_entity']['widget'][0]['target_id']['#attributes']['class'][] = 'form-order-item-autocomplete';
    }
  }
}

/**
 * Implements hook_entity_base_field_info_alter().
 */
function bb2b_order_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'commerce_order_item' && isset($fields['quantity'])) {
    $fields['quantity']->addConstraint('CheckAvailable');
  }
}

/**
 * Implements hook_ENTITY_TYPE_presave().
 */
function bb2b_order_commerce_shipment_presave(ShipmentInterface $shipment) {
  $order = $shipment->getOrder();
  $pending_order = $order && $order->getState()->getId() === 'pending';
  $shipping_force_resolve = $shipment->getData('shipping_force_resolve', FALSE);

  if ($shipment->original && $pending_order && $shipping_force_resolve) {
    /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */
    $order_service = \Drupal::service('bb2b_order.order_service');
    $order = $shipment->getOrder();

    $shipping_method = $order_service
      ->getShippingMethodForOrder($order, $shipment->getShippingProfile());

    if ($shipping_method) {
      $adjustments = $order->getAdjustments();
      $order_service->setShippingMethodForShipment($shipment, $shipping_method, 0, $adjustments);
      $order->set('adjustments', $adjustments);
    }
    $shipment->setData('shipping_force_resolve', FALSE);
  }
}

/**
 * Implements hook_theme().
 */
function bb2b_order_theme($existing, $type, $theme, $path) {
  return [
    'commerce_checkout_form__with_sidebar' => [
      'base hook' => 'commerce_checkout_form',
      'variables' => [
        'ordered_products' => NULL,
      ],
    ],
  ];
}

/**
 * Implements hook_preprocess_HOOK().
 */
function bb2b_order_preprocess_commerce_checkout_form__with_sidebar(&$variables) {
  $block = Block::load('views_block__ordered_products_block_2');
  $step = $variables['form']['#step_id'] ?? NULL;

  if ($block && $step === 'complete') {
    $variables['ordered_products'] = $block->getPlugin()->build();
    $variables['ordered_products']['#attributes']['class'][] = 'ordered-products-block';
  }
}

/**
 * Implements hook_tokens_alter().
 */
function bb2b_order_tokens_alter(array &$replacements, array $context, BubbleableMetadata $bubbleable_metadata) {
  // Clear empty token.
  if (isset($context['data']['entity_type']) &&
    $context['data']['entity_type'] === 'commerce_order'
  ) {
    foreach ($context['tokens'] as $token) {
      if (!isset($replacements[$token])) {
        $replacements[$token] = '';
      }
    }
  }
}

/**
 * Implements hook_entity_view_alter().
 */
function bb2b_order_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  if ($build['#view_mode'] === 'user' &&
    $build['#entity_type'] === 'commerce_order'
  ) {
    /** @var \Drupal\commerce_order\Entity\OrderInterface $entity */
    $entity_state = $entity->getState()->getId();

    if ($entity_state === 'pending') {
      $order = $build['#commerce_order'];
      $vat_verified = $order->get('field_vat_verified')->value;

      if (($vat_verified === '1') || ($vat_verified === '0')) {
        $ship_uri = '/orders/' . $entity->id() . '/send';
        $ship_url = Url::fromUri('internal:' . $ship_uri);

        $build['ship_the_order_link'] = [
          '#type' => 'link',
          '#title' => t('Ship the order'),
          '#url' => $ship_url,
          '#weight' => -11,
          '#attributes' => [
            'class' => ['button button-secondary'],
          ],
        ];
      }

      $user = $entity->getCustomer();
      if ($user->hasPermission('update default commerce_order')) {
        $build['edit_link'] = [
          '#type' => 'link',
          '#title' => t('Edit order'),
          '#url' => $entity->toUrl('edit-form'),
          '#weight' => -10,
          '#attributes' => [
            'class' => ['button button-secondary'],
          ],
        ];
      }
    }
  }
}
content_copyCOPY