contacts_events-8.x-1.x-dev/modules/village_allocation/tests/src/Kernel/AutomaticAllocationTest.php

modules/village_allocation/tests/src/Kernel/AutomaticAllocationTest.php
<?php

namespace Drupal\Tests\village_allocation\Kernel;

use Drupal\commerce_order\Entity\Order;
use Drupal\commerce_order\Entity\OrderItem;
use Drupal\commerce_store\Entity\Store;
use Drupal\contacts_events\Entity\Event;
use Drupal\contacts_events_accommodation\Entity\Accommodation;
use Drupal\contacts_events_villages\Entity\Village;
use Drupal\contacts_events_villages\Entity\VillageGroup;
use Drupal\taxonomy\Entity\Term;
use Drupal\Tests\commerce\Kernel\CommerceKernelTestBase;

/**
 * Tests for automatic VA.
 *
 * @package Drupal\Tests\village_allocation\Kernel
 */
class AutomaticAllocationTest extends CommerceKernelTestBase {

  /**
   * {@inheritdoc}
   */
  public static $modules = [
    'block',
    'commerce',
    'commerce_checkout',
    'commerce_order',
    'commerce_price',
    'commerce_payment',
    'commerce_store',
    'crm_tools',
    'bookkeeping',
    'contacts',
    'contacts_events',
    'contacts_events_accommodation',
    'contacts_events_villages',
    'village_allocation',
    'village_allocation_test',
    'facets',
    'search_api',
    'search_api_db',
    'taxonomy',
    'ctools',
    'datetime',
    'datetime_range',
    'field_group',
    'entity',
    'entity_reference_revisions',
    'field',
    'file',
    'image',
    'state_machine',
    'profile',
    'name',
    'image',
    'views',
    'views_data_export',
    'rest',
    'serialization',
    'dynamic_entity_reference',
  ];

  /**
   * {@inheritdoc}
   */
  protected $strictConfigSchema = FALSE;

  /**
   * Test village.
   *
   * @var \Drupal\contacts_events_villages\Entity\Village
   */
  private $village1;

  /**
   * Test village.
   *
   * @var \Drupal\contacts_events_villages\Entity\Village
   */
  private $village2;

  /**
   * Test village.
   *
   * @var \Drupal\contacts_events_villages\Entity\Village
   */
  private $village3;

  /**
   * Event for testing.
   *
   * @var \Drupal\contacts_events\Entity\Event
   */
  private $event;

  /**
   * Fake accommodation instance for testing.
   *
   * @var \Drupal\contacts_events_accommodation\Entity\Accommodation
   */
  private $accommodation;

  /**
   * Whether debugging is enabled.
   *
   * @var bool
   */
  private $debug;

  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();

    $this->installEntitySchema('file');
    $this->installEntitySchema('profile');
    $this->installEntitySchema('commerce_order');
    $this->installEntitySchema('commerce_order_item');
    $this->installEntitySchema('commerce_payment');
    $this->installEntitySchema('contacts_event');
    $this->installEntitySchema('c_events_village');
    $this->installEntitySchema('c_events_accommodation');
    $this->installEntitySchema('c_events_village_group');
    $this->installEntitySchema('search_api_task');
    $this->installEntitySchema('bookkeeping_transaction');
    $this->installEntitySchema('taxonomy_term');

    $this->installConfig('search_api');
    $this->installConfig('field_group');
    $this->installConfig('bookkeeping');
    $this->installConfig('contacts');
    $this->installConfig('commerce_order');
    $this->installConfig('commerce_payment');
    $this->installConfig('contacts_events');
    $this->installConfig('contacts_events_accommodation');
    $this->installConfig('contacts_events_villages');
    $this->installConfig('village_allocation');
    $this->installConfig('village_allocation_test');

    $this->event = Event::create(['type' => 'default']);
    $this->event->save();

    $this->store = Store::create([
      'name' => 'Default',
      'type' => 'online',
      'default_currency' => 'GBP',
    ]);
    $this->store->save();

    // Create a couple of villages.
    // Create a couple villages.
    $this->village1 = Village::create([
      'name' => 'Blue 1',
      'event' => $this->event,
      'pitches' => 10,
      'fill_value' => 80,
      'weight' => 1,
    ]);
    $this->village2 = Village::create([
      'name' => 'Blue 2',
      'event' => $this->event,
      'pitches' => 10,
      'fill_value' => 80,
      'weight' => 2,
    ]);
    $this->village3 = Village::create([
      'name' => 'Blue 3',
      'event' => $this->event,
      'pitches' => 10,
      'fill_value' => 80,
      'weight' => 3,
    ]);

    $this->village1->save();
    $this->village2->save();
    $this->village3->save();

    // Fake accomodation item.
    $this->accommodation = Accommodation::create([
      'pitch_size' => 1,
      'title' => 'Tent',
      'event' => $this->event,
      'bundle' => 'camping',
    ]);
    $this->accommodation->save();

    // Set to TRUE to see full debug output in tests.
    $this->debug = FALSE;

    if ($this->debug) {
      $this->container->set('devel.dumper', new ConsoleDumper());
    }
  }

  /**
   * Tests allocation.
   *
   * All tests are in the same test method to prevent multiple drupal installs.
   * Remember to call deleteOrders between each test.
   */
  public function testAllocation() {
    $church = $this->createChurch('Church1', 'WD24 6GX');
    $group = $this->createChurchGroup($church);

    // Simple allocation with single booking - assigns to first village.
    $booking = $this->createBooking($group);
    $this->runAllocation();
    $booking = Order::load($booking->id());
    $this->assertEqual($booking->get('village')->entity->name->value, 'Blue 1');
    $this->deleteOrders();

    // 2 bookings. One already allocated one not. Second one should end in the
    // same village as the first one.
    $booking1 = $this->createBooking($group);
    $booking2 = $this->createBooking($group);
    $booking1->set('village', $this->village2->id());
    $booking1->save();
    $this->runAllocation();
    $booking2 = Order::load($booking2->id());
    $this->assertEqual($booking2->get('village')->entity->name->value, 'Blue 2');
    $this->deleteOrders();

    // 2 bookings, one already allocated. If the village is full then the second
    // booking should end up in a different village.
    // Create booking1 with 8 order items (1 pitch per item), which will fill
    // the village to 80% (which is it's limit).
    $booking1 = $this->createBooking($group, 8);
    $booking2 = $this->createBooking($group);
    $booking1->set('village', $this->village1->id());
    $booking1->save();
    $this->runAllocation();
    $booking2 = Order::load($booking2->id());
    $this->assertEqual($booking2->get('village')->entity->name->value, 'Blue 2');
    $this->deleteOrders();

    // 3 bookings. 1st allocate to Blue 1 (which is now full). 2nd is part of
    // a different group, but has a similar postcode in Blue 3. Our booking
    // should be allocated to Blue 3, even though Blue 2 is the next available
    // empty village.
    $church2 = $this->createChurch('Church2', 'WD24 7XA');
    $group2 = $this->createChurchGroup($church2);
    $booking1 = $this->createBooking($group, 8);
    $booking2 = $this->createBooking($group);
    $booking3 = $this->createBooking($group2);
    $booking1->set('village', $this->village1->id());
    $booking3->set('village', $this->village3->id());
    $booking1->save();
    $booking3->save();
    $this->runAllocation();
    $booking2 = Order::load($booking2->id());
    $this->assertEqual($booking2->get('village')->entity->name->value, 'Blue 3');
    $this->deleteOrders();
  }

  /**
   * Creates a test booking.
   *
   * @param \Drupal\contacts_events_villages\Entity\VillageGroup $group
   *   The parent group.
   * @param int $quantity
   *   Accommodation quantity (each item is 1 pitch for testing purposes).
   *   Defaults to 1.
   *
   * @return \Drupal\commerce_order\Entity\Order
   *   Booking order.
   */
  private function createBooking(VillageGroup $group, $quantity = 1) {
    // Create a booking.
    $order = Order::create([
      'type' => 'contacts_booking',
      'event' => $this->event,
      'village_group' => $group,
      'store_id' => $this->store->id(),
      'state' => 'paid_in_full',
    ]);

    $order_item = OrderItem::create([
      'type' => 'ce_accom_camping',
      'purchased_entity' => $this->accommodation,
      'total_price' => ['number' => 10, 'currency_code' => 'GBP'],
      'quantity' => $quantity,
    ]);
    $order->addItem($order_item);

    $order->save();
    $order->get('state')->first()->applyTransitionById('confirmed_paid_in_full');
    $order->save();
    return $order;
  }

  /**
   * Creates a church group for bookings.
   *
   * @param \Drupal\taxonomy\Entity\Term $church
   *   The church associated with the group.
   *
   * @return \Drupal\contacts_events_villages\Entity\VillageGroup
   *   The created group.
   */
  private function createChurchGroup(Term $church) {
    $group = VillageGroup::create([
      'type' => 'church',
      'name' => 'Group',
      'church' => $church->id(),
      'allocation_sorting_code' => $church->church_address->postal_code,
    ]);
    $group->save();
    return $group;
  }

  /**
   * Creates a church.
   *
   * @param string $name
   *   Church name.
   * @param string $postcode
   *   Postcode for allocation purposes.
   *
   * @return \Drupal\taxonomy\Entity\Term
   *   Taxonomy term for the church.
   */
  private function createChurch($name, $postcode) {
    $church = Term::create(['vid' => 'church', 'name' => $name]);

    $church->set('church_address', [
      'country_code' => 'GB',
      'locality' => 'X',
      'given_name' => 'X',
      'family_name' => 'X',
      'postal_code' => $postcode,
    ]);
    $church->save();
    return $church;
  }

  /**
   * Runs the allocation.
   */
  private function runAllocation() {
    /** @var \Drupal\village_allocation\AutomaticAllocation $allocator */
    $allocator = $this->container->get('village_allocation.automatic');

    // Fake the batch api context.
    $context = ['finished' => FALSE];

    while (!$context['finished']) {
      $allocator->process($this->event, $context);
    }

    if ($this->debug) {
      print_r($context['results']);
    }
  }

  /**
   * Deletes all orders.
   */
  private function deleteOrders() {
    $storage = $this->entityTypeManager->getStorage('commerce_order');
    $all = $storage->loadMultiple();
    $storage->delete($all);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc