Commit 2e76c3ad authored by acrollet's avatar acrollet Committed by GitHub

Merge pull request #9 from Roomify/commerce_webform_order

Commerce webform order compatibility
parents 49d16108 5b357109
......@@ -128,3 +128,21 @@ function bee_uninstall() {
bat_event_delete_event_type_schema('availability_daily');
bat_event_delete_event_type_schema('availability_hourly');
}
/**
* Add booking "Capacity" field.
*/
function bee_update_8001() {
if (bat_booking_type_load('bee') !== NULL) {
bee_create_booking_capacity_field();
}
}
/**
* Set cardinality as unlimited for the "booking_event_reference" field.
*/
function bee_update_8002() {
if (bat_booking_type_load('bee') !== NULL) {
bee_set_booking_event_reference_field_cardinality();
}
}
......@@ -676,6 +676,8 @@ function bee_views_pre_render(ViewExecutable $view) {
}
/**
* Add "Availability" field to the node type.
*
* @param $field_name
* @param $node_type
*/
......@@ -714,6 +716,8 @@ function bee_add_availability_field($field_name, $node_type) {
}
/**
* Add "Open Hours" field to the node type.
*
* @param $field_name
* @param $node_type
*/
......@@ -775,6 +779,8 @@ function bee_add_open_hours_field($field_name, $node_type) {
}
/**
* Add "Set Open Hours" field to the node type.
*
* @param $field_name
* @param $node_type
*/
......@@ -818,6 +824,8 @@ function bee_add_use_open_hours_field($field_name, $node_type) {
}
/**
* Add "Product" field to the node type.
*
* @param $field_name
* @param $node_type
*/
......@@ -860,6 +868,8 @@ function bee_add_product_reference_field($field_name, $node_type) {
}
/**
* Add "Price" field to the node type.
*
* @param $field_name
* @param $node_type
*/
......@@ -907,6 +917,8 @@ function bee_add_price_field($field_name, $node_type) {
}
/**
* Add "Price frequency" field to the node type.
*
* @param $field_name
* @param $node_type
*/
......@@ -951,6 +963,9 @@ function bee_add_price_frequency_field($field_name, $node_type) {
}
}
/**
* Create "Product variation" type for BEE.
*/
function bee_create_bee_product_variation_type() {
if (ProductVariationType::load('bee') === NULL) {
$variation_type = ProductVariationType::create([
......@@ -976,6 +991,8 @@ function bee_create_bee_product_variation_type() {
}
/**
* Create a "Product" type for each node type in BEE.
*
* @param $node_type
*/
function bee_create_node_product_type($node_type) {
......@@ -993,6 +1010,9 @@ function bee_create_node_product_type($node_type) {
}
}
/**
* Create "Order item" type for BEE.
*/
function bee_create_bee_order_item_type() {
$id = 'bee';
......@@ -1129,6 +1149,9 @@ function bee_create_bee_order_item_type() {
}
}
/**
* Create "Booking" type for BEE.
*/
function bee_create_bee_booking_type() {
$id = 'bee';
......@@ -1138,9 +1161,66 @@ function bee_create_bee_booking_type() {
'type' => $id,
]);
$booking_type->save();
bee_set_booking_event_reference_field_cardinality();
bee_create_booking_capacity_field();
}
}
/**
* Set cardinality as unlimited for the "booking_event_reference" field.
*/
function bee_set_booking_event_reference_field_cardinality() {
$field_storage = FieldStorageConfig::loadByName('bat_booking', 'booking_event_reference');
$field_storage->setCardinality(-1);
$field_storage->save();
}
/**
* Add booking "Capacity" field.
*/
function bee_create_booking_capacity_field() {
$field_name = 'booking_capacity';
$field_storage = FieldStorageConfig::loadByName('bat_booking', $field_name);
$field = FieldConfig::loadByName('bat_booking', 'bee', $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'bat_booking',
'type' => 'integer',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'unsigned' => true,
'size' => 'normal',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'bat_booking',
'label' => 'Capacity',
'bundle' => 'bee',
'required' => FALSE,
'settings' => [
'min' => null,
'max' => null,
'prefix' => '',
'suffix' => '',
],
]);
$field->save();
}
}
/**
* Create a Product instance for this node.
*/
function bee_create_node_product($node) {
$store_storage = \Drupal::entityTypeManager()->getStorage('commerce_store');
$default_store = $store_storage->loadDefault();
......
......@@ -5,15 +5,18 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\Node;
use Drupal\webform\Entity\Webform;
use Drupal\webform\Entity\WebformSubmission;
/**
* Implements hook_form_alter().
*/
function bee_webform_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (isset($form['#webform_id'])) {
$webform = \Drupal\webform\Entity\Webform::load($form['#webform_id']);
foreach ($webform->getElementsDecodedAndFlattened() as $element_id => $element) {
if ($element['#type'] == 'webform_bee_reservation_form') {
$webform = Webform::load($form['#webform_id']);
if ($form['#form_id'] == 'webform_submission_' . $webform->id() . '_add_form') {
if (_bee_webform_get_webform_bee_reservation_element($webform)) {
$form['actions']['submit']['#submit'][] = 'bee_webform_form_submit';
}
}
......@@ -21,149 +24,133 @@ function bee_webform_form_alter(&$form, FormStateInterface $form_state, $form_id
}
/**
* bee_webform submission handler.
* Webform submission handler.
*/
function bee_webform_form_submit($form, FormStateInterface $form_state) {
$webform = \Drupal\webform\Entity\Webform::load($form['#webform_id']);
foreach ($webform->getElementsDecodedAndFlattened() as $element_id => $element) {
if ($element['#type'] == 'webform_bee_reservation_form') {
$bee_element_id = $element_id;
}
}
$value = $form_state->getValue($bee_element_id);
$webform = Webform::load($form['#webform_id']);
$webform_submission = $form_state->getFormObject()->getEntity();
if ($value['content_type'] && $value['start_date'] && $value['end_date'] && $value['capacity']) {
$webform_submission = $form_state->getFormObject()->getEntity();
$webform_bee_element = _bee_webform_get_webform_bee_reservation_element($webform);
$bee_element_id = $webform_bee_element['#id'];
$start_date = $value['start_date'];
$end_date = $value['end_date'];
if ($webform->getHandlers('commerce_webform_order')) {
bee_webform_add_reservation_to_cart($webform, $webform_submission, $bee_element_id);
}
$max_capacity = FALSE;
if (empty($webform_bee_element['#only_check_availability'])) {
$value = $form_state->getValue($bee_element_id);
$available_units = [];
if ($value['content_type'] && $value['start_date'] && $value['end_date'] && $value['capacity']) {
$start_date = $value['start_date'];
$end_date = $value['end_date'];
$query = \Drupal::entityQuery('node')
->condition('type', $value['content_type']);
$max_capacity = FALSE;
$nids = $query->execute();
$available_units = [];
// Allow other modules to alter the available units for this node.
$context = [
'form_values' => $value,
'nids' => $nids,
];
\Drupal::moduleHandler()->alter('bee_webform_available_node_ids', $nids, $context);
$nids = _bee_webform_get_nodeids_by_type($webform_submission, $bee_element_id);
foreach ($nids as $nid) {
$node = node_load($nid);
foreach ($nids as $nid) {
$node = node_load($nid);
if ($node_available_units = bee_webform_get_available_units_for_node($node, $value)) {
if ($node_available_units = bee_webform_get_available_units_for_node($node, $webform_submission, $bee_element_id)) {
if (count($node_available_units) == $value['capacity']) {
$available_units = [$node->id() => $node_available_units];
break;
}
elseif (count($node_available_units) > $value['capacity']) {
$available_units[$node->id()] = $node_available_units;
$max_capacity = TRUE;
}
elseif (!$max_capacity) {
$available_units[$node->id()] = $node_available_units;
if (count($node_available_units) == $value['capacity']) {
$available_units = [$node->id() => $node_available_units];
break;
}
elseif (count($node_available_units) > $value['capacity']) {
$available_units[$node->id()] = $node_available_units;
$max_capacity = TRUE;
}
elseif (!$max_capacity) {
$available_units[$node->id()] = $node_available_units;
}
}
}
}
uasort($available_units, function($a, $b) { return count($a) - count($b); });
uasort($available_units, function($a, $b) { return count($a) - count($b); });
$index = 0;
$events_created = [];
$index = 0;
$events_created = [];
foreach ($available_units as $nid => $node_available_units) {
if ($max_capacity && count($node_available_units) < $value['capacity']) {
continue;
}
$node = Node::load($nid);
foreach ($available_units as $nid => $node_available_units) {
if ($max_capacity && count($node_available_units) < $value['capacity']) {
continue;
}
$bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee');
$node = Node::load($nid);
if ($bee_settings['bookable_type'] == 'daily') {
$booked_state = bat_event_load_state_by_machine_name('bee_daily_booked');
}
else {
$booked_state = bat_event_load_state_by_machine_name('bee_hourly_booked');
}
$bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee');
$start_date = new \DateTime($start_date);
$end_date = new \DateTime($end_date);
foreach ($node_available_units as $unit) {
if ($bee_settings['bookable_type'] == 'daily') {
$event = bat_event_create(['type' => 'availability_daily']);
$event_dates = [
'value' => $start_date->format('Y-m-d\TH:i:00'),
'end_value' => $end_date->format('Y-m-d\TH:i:00'),
];
$event->set('event_dates', $event_dates);
$event->set('event_state_reference', $booked_state->id());
$booked_state = bat_event_load_state_by_machine_name('bee_daily_booked');
$event_type = 'availability_daily';
}
else {
$event = bat_event_create(['type' => 'availability_hourly']);
$booked_state = bat_event_load_state_by_machine_name('bee_hourly_booked');
$event_type = 'availability_hourly';
}
$start_date = new \DateTime($start_date);
$end_date = new \DateTime($end_date);
foreach ($node_available_units as $unit) {
$event = bat_event_create(['type' => $event_type]);
$event_dates = [
'value' => $start_date->format('Y-m-d\TH:i:00'),
'end_value' => $end_date->format('Y-m-d\TH:i:00'),
];
$event->set('event_dates', $event_dates);
$event->set('event_state_reference', $booked_state->id());
}
$event->set('field_event_webform_submission', $webform_submission->id());
$event->set('event_bat_unit_reference', $unit);
$event->save();
$event->set('field_event_webform_submission', $webform_submission->id());
$event->set('event_bat_unit_reference', $unit);
$event->save();
$events_created[] = $event->id();
$events_created[] = $event->id();
if (++$index == $value['capacity']) {
break 2;
if (++$index == $value['capacity']) {
break 2;
}
}
}
}
// Send email with summary of any allocations made.
if (count($events_created) == 0) {
$message = t("No nodes with sufficient capacity were found, therefore no reservations were created.\nTo view the submission, please go to @submission", ['@submission' => $webform_submission->url('canonical', ['absolute' => TRUE])]);
}
else {
$events = bat_event_load_multiple($events_created);
$event_links = [];
foreach ($events as $event) {
$event_links[] = $event->url('canonical', ['absolute' => TRUE]);
// Send email with summary of any allocations made.
if (count($events_created) == 0) {
$message = t("No nodes with sufficient capacity were found, therefore no reservations were created.\nTo view the submission, please go to @submission", ['@submission' => $webform_submission->url('canonical', ['absolute' => TRUE])]);
}
else {
$events = bat_event_load_multiple($events_created);
$event_links = [];
foreach ($events as $event) {
$event_links[] = $event->url('canonical', ['absolute' => TRUE]);
}
$message = t("The following BEE reservations were created for a new webform submission:\n\n@event_links\n\nTo view the submission, please go to @submission", ['@event_links' => implode("\n", $event_links), '@submission' => $webform_submission->url('canonical', ['absolute' => TRUE])]);
}
$mailManager = \Drupal::service('plugin.manager.mail');
$module = 'bee_webform';
$key = 'bee_webform_submission';
$to = $webform->getOwner()->getEmail();
$params['webform_title'] = $webform->get('title');
$params['message'] = $message;
$langcode = $webform->getOwner()->getPreferredLangcode();
$send = TRUE;
$result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);
if ($result['result'] !== true) {
$message = t('There was a problem sending your email notification to @email for creating a webform BEE reservation.', array('@email' => $to));
drupal_set_message($message, 'error');
\Drupal::logger('bee_webform')->error($message);
return;
}
$message = t("The following BEE reservations were created for a new webform submission:\n\n@event_links\n\nTo view the submission, please go to @submission", ['@event_links' => implode("\n", $event_links), '@submission' => $webform_submission->url('canonical', ['absolute' => TRUE])]);
}
$mailManager = \Drupal::service('plugin.manager.mail');
$module = 'bee_webform';
$key = 'bee_webform_submission';
$to = $webform->getOwner()->getEmail();
$params['webform_title'] = $webform->get('title');
$params['message'] = $message;
$langcode = $webform->getOwner()->getPreferredLangcode();
$send = TRUE;
$result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);
if ($result['result'] !== true) {
$message = t('There was a problem sending your email notification to @email for creating a webform BEE reservation.', array('@email' => $to));
drupal_set_message($message, 'error');
\Drupal::logger('bee_webform')->error($message);
return;
}
$message = t('An email notification has been sent to @email for creating a webform BEE reservation.', array('@email' => $to));
drupal_set_message($message);
\Drupal::logger('bee_webform')->notice($message);
$message = t('An email notification has been sent to @email for creating a webform BEE reservation.', array('@email' => $to));
drupal_set_message($message);
\Drupal::logger('bee_webform')->notice($message);
}
}
}
......@@ -222,17 +209,20 @@ function bee_webform_get_available_units($values) {
return $units;
}
/**
* Get available Units for a given node.
*
* @param $values
* @param $node
* @param WebformSubmission $webform_submission
* @param $bee_element_id
*
* return array
*/
function bee_webform_get_available_units_for_node($node, $values) {
$start_date = $values['start_date'];
$end_date = $values['end_date'];
function bee_webform_get_available_units_for_node($node, WebformSubmission $webform_submission, $bee_element_id) {
$data = $webform_submission->getData();
$start_date = $data[$bee_element_id]['start_date'];
$end_date = $data[$bee_element_id]['end_date'];
$bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee');
......@@ -313,3 +303,88 @@ function bee_webform_mail($key, &$message, $params) {
break;
}
}
/**
* @param Webform $webform
*
* @return array|false
*/
function _bee_webform_get_webform_bee_reservation_element(Webform $webform) {
foreach ($webform->getElementsDecodedAndFlattened() as $element_id => $element) {
if ($element['#type'] == 'webform_bee_reservation_form') {
$element['#id'] = $element_id;
return $element;
}
}
return FALSE;
}
/**
* @param WebformSubmission $webform_submission
* @param $bee_element_id
*
* @return array
*/
function _bee_webform_get_nodeids_by_type(WebformSubmission $webform_submission, $bee_element_id) {
$data = $webform_submission->getData();
$query = \Drupal::entityQuery('node')
->condition('type', $data[$bee_element_id]['content_type']);
$nids = $query->execute();
// Allow other modules to alter the available units for this node.
$context = [
'webform_submission' => $webform_submission,
'nids' => $nids,
];
\Drupal::moduleHandler()->alter('bee_webform_available_node_ids', $nids, $context);
return $nids;
}
/**
* @param Webform $webform
* @param WebformSubmission $webform_submission
* @param $bee_element_id
*/
function bee_webform_add_reservation_to_cart(Webform $webform, WebformSubmission $webform_submission, $bee_element_id) {
$data = $webform_submission->getData();
$store = \Drupal::service('commerce_store.current_store')->getStore();
$cart_provider = \Drupal::service('commerce_cart.cart_provider');
$cart = $cart_provider->getCart('default', $store);
$start_date = new \DateTime($data[$bee_element_id]['start_date']);
$end_date = new \DateTime($data[$bee_element_id]['end_date']);
foreach ($cart->getItems() as $order_item) {
if ($order_item->bundle() == 'bee') {
$nids = _bee_webform_get_nodeids_by_type($webform_submission, $bee_element_id);
foreach ($nids as $nid) {
$node = node_load($nid);
if (bee_webform_get_available_units_for_node($node, $webform_submission, $bee_element_id)) {
$booking = bat_booking_create([
'type' => 'bee',
'label' => $node->label(),
]);
$booking->set('booking_start_date', $start_date->format('Y-m-d\TH:i:s'));
$booking->set('booking_end_date', $end_date->format('Y-m-d\TH:i:s'));
$booking->set('booking_capacity', $data[$bee_element_id]['capacity']);
$booking->save();
$order_item->set('field_booking', $booking);
$order_item->set('field_node', $node);
$order_item->save();
break;
}
}
}
}
}
......@@ -27,6 +27,7 @@ class WebformBeeReservationForm extends WebformCompositeBase {
public function getDefaultProperties() {
return [
'content_types' => [],
'only_check_availability' => FALSE,
] + parent::getDefaultProperties();
}
......@@ -55,6 +56,11 @@ class WebformBeeReservationForm extends WebformCompositeBase {
'#element_validate' => [[get_class($this), 'validateContentTypes']],
];
$form['composite']['only_check_availability'] = [
'#type' => 'checkbox',
'#title' => $this->t('Only check availability'),
];
return $form;
}
......
......@@ -41,33 +41,35 @@ class OrderEventSubscriber implements EventSubscriberInterface {
if ($bee_settings['bookable_type'] == 'daily') {
$booked_state = bat_event_load_state_by_machine_name('bee_daily_booked');
$event = bat_event_create(['type' => 'availability_daily']);
$event_dates = [
'value' => $start_date->format('Y-m-d\TH:i:00'),
'end_value' => $end_date->format('Y-m-d\TH:i:00'),
];
$event->set('event_dates', $event_dates);
$event->set('event_state_reference', $booked_state->id());
$event_type = 'availability_daily';
}
else {
$booked_state = bat_event_load_state_by_machine_name('bee_hourly_booked');
$event_type = 'availability_hourly';
}
$capacity = ($booking->get('booking_capacity')->value) ? ($booking->get('booking_capacity')->value) : 1;
$events = [];
$event = bat_event_create(['type' => 'availability_hourly']);
for ($i = 0; $i < $capacity; $i++) {
$event = bat_event_create(['type' => $event_type]);
$event_dates = [
'value' => $start_date->format('Y-m-d\TH:i:00'),
'end_value' => $end_date->format('Y-m-d\TH:i:00'),
];
$event->set('event_dates', $event_dates);
$event->set('event_state_reference', $booked_state->id());
}
$available_units = $this->getAvailableUnits($node, $start_date, $end_date);
$available_units = $this->getAvailableUnits($node, $start_date, $end_date);
$event->set('event_bat_unit_reference', reset($available_units));
$event->save();
$event->set('event_bat_unit_reference', reset($available_units));
$event->save();
$events[] = $event;
}
$booking->set('booking_event_reference', $event->id());
$booking->set('booking_event_reference', $events);
$booking->save();
}
}
......
......@@ -183,8 +183,8 @@ class AddReservationForm extends FormBase {
'type' => 'bee',
'label' => $node->label(),
]);
$booking->set('booking_start_date', $start_date->format('Y-m-d H:i:s'));
$booking->set('booking_end_date', $end_date->format('Y-m-d H:i:s'));
$booking->set('booking_start_date', $start_date->format('Y-m-d\TH:i:s'));
$booking->set('booking_end_date', $end_date->format('Y-m-d\TH:i:s'));
$booking->save();
$product = $node->get('field_product')->entity;
......
......@@ -41,44 +41,48 @@ class SalepriceResolver implements PriceResolverInterface {
$bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee');
$booking = $order_item->get('field_booking')->entity;
$start_date = new \DateTime($booking->get('booking_start_date')->value);
$end_date = new \DateTime($booking->get('booking_end_date')->value);
$interval = $start_date->diff($end_date);
if ($booking = $order_item->get('field_booking')->entity) {
$start_date = new \DateTime($booking->get('booking_start_date')->value);
$end_date = new \DateTime($booking->get('booking_end_date')->value);
$capacity = 1;
if ($booking_capacity = $booking->get('booking_capacity')->value) {
$capacity = $booking_capacity;
}
$reservation_context = [
'order_item' => $order_item,
'booking' => $booking,
'node' => $node,
];
$interval = $start_date->diff($end_date);
$base_price = $node->get('field_price')->number;
$currency_code = $node->get('field_price')->currency_code;
$reservation_context = [
'order_item' => $order_item,
'booking' => $booking,
'node' => $node,
];
if ($bee_settings['bookable_type'] == 'daily') {
$days = $interval->days;
$amount = number_format($base_price * $days, 2, '.', '');
}
else {
$field_price_frequency = $node->get('field_price_frequency')->value;
$base_price = $node->get('field_price')->number;
$currency_code = $node->get('field_price')->currency_code;
if ($field_price_frequency == 'hour') {
$hours = ($interval->days * 24) + $interval->h;
$amount = number_format($base_price * $hours, 2, '.', '');
if ($bee_settings['bookable_type'] == 'daily') {
$days = $interval->days;
$amount = number_format($base_price * $days, 2, '.', '');
}
else {
$minutes = ($interval->days * 24 * 60) + ($interval->h * 60) + $interval->i;
$amount = number_format($base_price * $minutes, 2, '.', '');
$field_price_frequency = $node->get('field_price_frequency')->value;
if ($field_price_frequency == 'hour') {
$hours = ($interval->days * 24) + $interval->h;
$amount = number_format($base_price * $hours * $capacity, 2, '.', '');
}
else {
$minutes = ($interval->days * 24 * 60) + ($interval->h * 60) + $interval->i;
$amount = number_format($base_price * $minutes * $capacity, 2, '.', '');
}
}
}
$price = new Price($amount, $currency_code);
$price = new Price($amount, $currency_code);
\Drupal::moduleHandler()->alter('bee_reservation_price', $price, $reservation_context);
\Drupal::moduleHandler()->alter('bee_reservation_price', $price, $reservation_context);
return $price;
return $price;
}
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment