From a32ed3c1eb55b9e1265c0ef0485839b51a5b9e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Caruso?= Date: Fri, 4 May 2018 18:31:59 +0200 Subject: [PATCH 1/5] Payment functionality --- bee.install | 8 + bee.module | 434 +++++++++++++++++++ bee.services.yml | 9 + src/EventSubscriber/OrderEventSubscriber.php | 106 +++++ src/Form/AddReservationForm.php | 99 +++-- src/Resolvers/SalepriceResolver.php | 80 ++++ 6 files changed, 708 insertions(+), 28 deletions(-) create mode 100644 src/EventSubscriber/OrderEventSubscriber.php create mode 100644 src/Resolvers/SalepriceResolver.php diff --git a/bee.install b/bee.install index d60df84..3ff19da 100644 --- a/bee.install +++ b/bee.install @@ -97,6 +97,10 @@ function bee_uninstall() { Drupal::configFactory()->getEditable('field.field.node.' . $node_type->id() . '.field_open_hours')->delete(); Drupal::configFactory()->getEditable('field.field.node.' . $node_type->id() . '.field_use_open_hours')->delete(); + + Drupal::configFactory()->getEditable('field.field.node.' . $node_type->id() . '.field_product')->delete(); + Drupal::configFactory()->getEditable('field.field.node.' . $node_type->id() . '.field_price')->delete(); + Drupal::configFactory()->getEditable('field.field.node.' . $node_type->id() . '.field_price_frequency')->delete(); } Drupal::configFactory()->getEditable('field.storage.node.field_availability_daily')->delete(); @@ -105,6 +109,10 @@ function bee_uninstall() { Drupal::configFactory()->getEditable('field.storage.node.field_open_hours')->delete(); Drupal::configFactory()->getEditable('field.storage.node.field_use_open_hours')->delete(); + Drupal::configFactory()->getEditable('field.storage.node.field_product')->delete(); + Drupal::configFactory()->getEditable('field.storage.node.field_price')->delete(); + Drupal::configFactory()->getEditable('field.storage.node.field_price_frequency')->delete(); + $states = [ 'bee_daily_available', 'bee_daily_not_available', diff --git a/bee.module b/bee.module index b80e4e6..fb4f8f8 100644 --- a/bee.module +++ b/bee.module @@ -3,9 +3,17 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; +use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\office_hours\OfficeHoursDateHelper; +use Drupal\commerce_product\Entity\ProductType; +use Drupal\commerce_product\Entity\ProductVariationType; +use Drupal\commerce_product\Entity\Product; +use Drupal\commerce_product\Entity\ProductVariation; +use Drupal\commerce_order\Entity\OrderItemType; +use Drupal\commerce_order\Entity\OrderItemInterface; +use Drupal\commerce_store\Entity\Store; /** * Implements hook_form_alter(). @@ -64,6 +72,22 @@ function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) { ], ], ]; + $form['bee']['payment'] = [ + '#type' => 'checkbox', + '#title' => t('Enable payment for bookings'), + '#default_value' => isset($bee_settings['payment']) ? $bee_settings['payment'] : 0, + '#states' => [ + 'visible' => [ + ':input[name="bee[bookable]"]' => ['checked' => TRUE], + ], + ], + ]; + + if (!(\Drupal::moduleHandler()->moduleExists('commerce_checkout') && + \Drupal::moduleHandler()->moduleExists('commerce_payment'))) { + $form['bee']['payment']['#disabled'] = TRUE; + $form['bee']['payment']['#description'] = t('To enable payments for bookings, install and enable the Drupal Commerce checkout and payment modules.'); + } if (isset($bee_settings['type_id'])) { $form['bee']['type_id'] = [ @@ -126,6 +150,51 @@ function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) { '#weight' => $form['field_open_hours']['#weight'] + 1, ]; + if ($bee_settings['payment']) { + $form['payments'] = [ + '#type' => 'details', + '#title' => t('Payments'), + '#open' => TRUE, + '#group' => 'bee', + '#weight' => $form['field_open_hours']['#weight'] + 1, + ]; + + if ($bee_settings['bookable_type'] == 'daily') { + $form['field_price']['#group'] = 'payments'; + $form['field_price']['#title'] = t('Price per day'); + + $form['field_price_frequency']['#access'] = FALSE; + } + else { + $form['field_price']['#group'] = 'payments'; + $form['field_price']['widget'][0]['#title'] = t('Price per'); + + $form['field_price_frequency']['#group'] = 'payments'; + $form['field_price_frequency']['widget']['#default_value'] = 'hour'; + $form['field_price_frequency']['widget']['#title'] = ''; + unset($form['field_price_frequency']['widget']['#options']['_none']); + + /*$form['bee']['payments']['price'] = [ + '#type' => 'commerce_number', + '#title' => t('Price per'), + '#default_value' => '', + ];*/ + + /*$form['bee']['payments']['price_frequency'] = [ + '#type' => 'select', + '#options' => [ + 'hour' => t('Hour'), + 'minute' => t('Minute'), + ], + '#default_value' => 'hour', + ];*/ + } + } + else { + $form['field_price ']['#access'] = FALSE; + $form['field_price_frequency']['#access'] = FALSE; + } + if ($bee_settings['bookable_type'] == 'hourly') { $form['field_use_open_hours']['#group'] = 'bee'; $form['field_use_open_hours']['#weight'] = $form['field_open_hours']['#weight'] - 1; @@ -268,6 +337,18 @@ function bee_node_type_edit_form_submit(array &$form, FormStateInterface $form_s $bee_settings['type_id'] = $bat_type->id(); } + if ($bee_settings['payment']) { + bee_create_bee_product_variation_type(); + bee_create_bee_order_item_type(); + bee_create_bee_booking_type(); + + bee_create_node_product_type($node_type); + + bee_add_product_reference_field('field_product', $node_type); + bee_add_price_field('field_price', $node_type); + bee_add_price_frequency_field('field_price_frequency', $node_type); + } + \Drupal::configFactory()->getEditable('node.type.' . $node_type->id())->set('bee', $bee_settings)->save(); } else { @@ -310,6 +391,27 @@ function bee_node_insert(EntityInterface $node) { $bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee'); if (isset($bee_settings['bookable']) && $bee_settings['bookable']) { + if ($bee_settings['payment']) { + $variation = ProductVariation::create([ + 'type' => 'bee', + 'sku' => 'bee_' . $node->bundle() . '_' . $node->id(), + 'price' => [ + 'number' => 0, + 'currency_code' => 'USD', + ], + ]); + $variation->save(); + $product = Product::create([ + 'type' => 'bee_' . $node->bundle(), + 'title' => $node->label(), + 'variations' => [$variation], + 'stores' => Store::loadMultiple(), + ]); + $product->save(); + + $node->set('field_product', $product->id()); + } + $bat_unit = bat_unit_create( [ 'name' => $node->label() . ' 1', @@ -335,6 +437,21 @@ function bee_node_delete(EntityInterface $node) { if ($bat_unit = $node->get('field_availability_' . $bee_settings['bookable_type'])->entity) { bat_unit_delete($bat_unit); } + + if ($product = $node->get('field_product')->entity) { + $product->delete(); + } + } +} + +/** + * Implements hook_ENTITY_TYPE_delete(). + */ +function bee_commerce_order_item_delete(OrderItemInterface $order_item) { + if ($order_item->bundle() == 'bee') { + if ($booking = $order_item->get('field_booking')->entity) { + $booking->delete(); + } } } @@ -662,3 +779,320 @@ function bee_add_use_open_hours_field($field_name, $node_type) { $form_display->save(); } } + +/** + * @param $field_name + * @param $node_type + */ +function bee_add_product_reference_field($field_name, $node_type) { + $field_storage = FieldStorageConfig::loadByName('node', $field_name); + $field = FieldConfig::loadByName('node', $node_type->id(), $field_name); + + if (empty($field_storage)) { + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'node', + 'type' => 'entity_reference', + 'cardinality' => 1, + 'locked' => 1, + 'settings' => [ + 'target_type' => 'commerce_product', + ], + ]); + $field_storage->save(); + } + + if (empty($field)) { + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'entity_type' => 'node', + 'label' => 'Product', + 'bundle' => $node_type->id(), + 'required' => FALSE, + 'settings' => [ + 'handler' => 'default:commerce_product', + 'handler_settings' => [ + 'target_bundles' => [ + 'bee_' . $node_type->id() => 'bee_' . $node_type->id(), + ], + ], + ], + ]); + $field->save(); + } +} + +/** + * @param $field_name + * @param $node_type + */ +function bee_add_price_field($field_name, $node_type) { + $field_storage = FieldStorageConfig::loadByName('node', $field_name); + $field = FieldConfig::loadByName('node', $node_type->id(), $field_name); + + if (empty($field_storage)) { + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'node', + 'type' => 'commerce_price', + 'cardinality' => 1, + 'locked' => 1, + 'settings' => [], + ]); + $field_storage->save(); + } + + if (empty($field)) { + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'entity_type' => 'node', + 'label' => 'Price', + 'bundle' => $node_type->id(), + 'required' => FALSE, + 'settings' => [], + ]); + $field->save(); + + $form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load('node.' . $node_type->id() . '.default'); + $form_display->setComponent($field_name, [ + 'type' => 'commerce_price_default', + 'weight' => 3, + ]); + $form_display->save(); + } +} + +/** + * @param $field_name + * @param $node_type + */ +function bee_add_price_frequency_field($field_name, $node_type) { + $field_storage = FieldStorageConfig::loadByName('node', $field_name); + $field = FieldConfig::loadByName('node', $node_type->id(), $field_name); + + if (empty($field_storage)) { + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'node', + 'type' => 'list_string', + 'cardinality' => 1, + 'locked' => 1, + 'settings' => [ + 'allowed_values' => [ + 'hour' => 'Hour', + 'minute' => 'Minute', + ], + ], + ]); + $field_storage->save(); + } + + if (empty($field)) { + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'entity_type' => 'node', + 'label' => 'Price frequency', + 'bundle' => $node_type->id(), + 'required' => FALSE, + 'settings' => [], + ]); + $field->save(); + + $form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load('node.' . $node_type->id() . '.default'); + $form_display->setComponent($field_name, [ + 'type' => 'options_select', + 'weight' => 4, + ]); + $form_display->save(); + } +} + +function bee_create_bee_product_variation_type() { + if (ProductVariationType::load('bee') === NULL) { + $variation_type = ProductVariationType::create([ + 'id' => 'bee', + 'label' => 'BEE', + 'orderItemType' => 'default', + 'generateTitle' => TRUE, + ]); + $variation_type->save(); + + $view_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('commerce_product_variation.bee.default'); + if (!$view_display) { + $view_display = EntityViewDisplay::create([ + 'targetEntityType' => 'commerce_product_variation', + 'bundle' => 'bee', + 'mode' => 'default', + 'status' => TRUE, + ]); + } + $view_display->setComponent('price', ['type' => 'commerce_price_calculated']); + $view_display->save(); + } +} + +/** + * @param $node_type + */ +function bee_create_node_product_type($node_type) { + $id = 'bee_' . $node_type->id(); + + if (ProductType::load($id) === NULL) { + $product_type = ProductType::create([ + 'id' => $id, + 'label' => $node_type->label(), + 'variationType' => 'bee', + ]); + $product_type->save(); + commerce_product_add_stores_field($product_type); + commerce_product_add_variations_field($product_type); + } +} + +function bee_create_bee_order_item_type() { + $id = 'bee'; + + if (OrderItemType::load($id) === NULL) { + OrderItemType::create([ + 'id' => $id, + 'label' => 'BEE', + 'purchasableEntityType' => 'commerce_product_variation', + 'orderType' => 'default', + ])->save(); + + $view_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('commerce_order_item.bee.default'); + if (!$view_display) { + $view_display = EntityViewDisplay::create([ + 'targetEntityType' => 'commerce_order_item', + 'bundle' => 'bee', + 'mode' => 'default', + 'status' => TRUE, + ]); + $view_display->setComponent('total_price', [ + 'type' => 'commerce_price_default', + 'region' => 'content', + 'label' => 'above', + 'settings' => [ + 'strip_trailing_zeroes' => FALSE, + 'display_currency_code' => FALSE, + ], + ]); + $view_display->setComponent('purchased_entity', [ + 'type' => 'entity_reference_entity_view', + 'region' => 'content', + 'label' => 'above', + 'settings' => [ + 'view_mode' => 'default', + 'link' => FALSE, + ], + ]); + $view_display->setComponent('quantity', [ + 'type' => 'number_decimal', + 'region' => 'content', + 'label' => 'above', + 'settings' => [ + 'thousand_separator' => '', + 'decimal_separator' => '.', + 'scale' => 2, + 'prefix_suffix' => TRUE, + ], + ]); + $view_display->setComponent('unit_price', [ + 'type' => 'commerce_price_default', + 'region' => 'content', + 'label' => 'above', + 'settings' => [ + 'strip_trailing_zeroes' => FALSE, + 'display_currency_code' => FALSE, + ], + ]); + $view_display->save(); + } + } + + $field_name = 'field_booking'; + + $field_storage = FieldStorageConfig::loadByName('commerce_order_item', $field_name); + $field = FieldConfig::loadByName('commerce_order_item', 'bee', $field_name); + + if (empty($field_storage)) { + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'commerce_order_item', + 'type' => 'entity_reference', + 'cardinality' => 1, + 'locked' => 1, + 'settings' => [ + 'target_type' => 'bat_booking', + ], + ]); + $field_storage->save(); + } + + if (empty($field)) { + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'entity_type' => 'commerce_order_item', + 'label' => 'Booking', + 'bundle' => 'bee', + 'required' => FALSE, + 'settings' => [ + 'handler' => 'default:bat_booking', + 'handler_settings' => [ + 'target_bundles' => [ + 'bee' => 'bee', + ], + ], + ], + ]); + $field->save(); + } + + $field_name = 'field_node'; + + $field_storage = FieldStorageConfig::loadByName('commerce_order_item', $field_name); + $field = FieldConfig::loadByName('commerce_order_item', 'bee', $field_name); + + if (empty($field_storage)) { + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'commerce_order_item', + 'type' => 'entity_reference', + 'cardinality' => 1, + 'locked' => 1, + 'settings' => [ + 'target_type' => 'node', + ], + ]); + $field_storage->save(); + } + + if (empty($field)) { + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'entity_type' => 'commerce_order_item', + 'label' => 'Node', + 'bundle' => 'bee', + 'required' => FALSE, + 'settings' => [ + 'handler' => 'default:node', + 'handler_settings' => [ + 'target_bundles' => [], + ], + ], + ]); + $field->save(); + } +} + +function bee_create_bee_booking_type() { + $id = 'bee'; + + if (bat_booking_type_load($id) === NULL) { + $booking_type = bat_booking_type_create([ + 'name' => 'BEE', + 'type' => $id, + ]); + $booking_type->save(); + } +} diff --git a/bee.services.yml b/bee.services.yml index 4a1a43b..c6ad313 100644 --- a/bee.services.yml +++ b/bee.services.yml @@ -9,3 +9,12 @@ services: arguments: ['@entity.manager'] tags: - { name: access_check, applies_to: _bee_add_reservation_access } + bee.saleprice_resolver: + class: Drupal\bee\Resolvers\SalepriceResolver + arguments: ['@request_stack'] + tags: + - { name: commerce_price.price_resolver, priority: 600 } + bee.order_subscriber: + class: Drupal\bee\EventSubscriber\OrderEventSubscriber + tags: + - { name: event_subscriber } diff --git a/src/EventSubscriber/OrderEventSubscriber.php b/src/EventSubscriber/OrderEventSubscriber.php new file mode 100644 index 0000000..21281a2 --- /dev/null +++ b/src/EventSubscriber/OrderEventSubscriber.php @@ -0,0 +1,106 @@ + 'finalizeCart']; + return $events; + } + + /** + * Finalizes the cart when the order is placed. + * + * @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event + * The workflow transition event. + */ + public function finalizeCart(WorkflowTransitionEvent $event) { + $order = $event->getEntity(); + + foreach ($order->getItems() as $item) { + if ($booking = $item->get('field_booking')->entity) { + $node = $item->get('field_node')->entity; + + $start_date = new \DateTime($booking->get('booking_start_date')->value); + $end_date = new \DateTime($booking->get('booking_end_date')->value); + + $bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee'); + + 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()); + } + else { + $booked_state = bat_event_load_state_by_machine_name('bee_hourly_booked'); + + $event = bat_event_create(['type' => 'availability_hourly']); + $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); + + $event->set('event_bat_unit_reference', reset($available_units)); + $event->save(); + + $booking->set('booking_event_reference', $event->id()); + $booking->save(); + } + } + } + + /** + * Get available Units. + * + * @param $node + * @param $start_date + * @param $end_date + * + * return array + */ + protected function getAvailableUnits($node, $start_date, $end_date) { + $bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee'); + + $units_ids = []; + foreach ($node->get('field_availability_' . $bee_settings['bookable_type']) as $unit) { + $units_ids[] = $unit->entity->id(); + } + + $temp_end_date = clone($end_date); + $temp_end_date->sub(new \DateInterval('PT1M')); + + if ($bee_settings['bookable_type'] == 'daily') { + $available_units_ids = bat_event_get_matching_units($start_date, $temp_end_date, ['bee_daily_available'], $bee_settings['type_id'], 'availability_daily'); + } + else { + $available_units_ids = bat_event_get_matching_units($start_date, $temp_end_date, ['bee_hourly_available'], $bee_settings['type_id'], 'availability_hourly'); + } + + return array_intersect($units_ids, $available_units_ids); + } + +} diff --git a/src/Form/AddReservationForm.php b/src/Form/AddReservationForm.php index 2d35760..1aaf312 100644 --- a/src/Form/AddReservationForm.php +++ b/src/Form/AddReservationForm.php @@ -160,48 +160,91 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee'); - $units_ids = []; - foreach ($node->get('field_availability_' . $bee_settings['bookable_type']) as $unit) { - $units_ids[] = $unit->entity->id(); - } - if ($bee_settings['bookable_type'] == 'daily') { $start_date = new \DateTime($start_date); $end_date = new \DateTime($end_date); - - $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()); } else { $start_date = new \DateTime($start_date->format('Y-m-d H:i')); $end_date = new \DateTime($end_date->format('Y-m-d H:i')); + } + + if ($bee_settings['payment']) { + $booking = bat_booking_create([ + '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->save(); + + $product = $node->get('field_product')->entity; + + $stores = $product->getStores(); + $store = reset($stores); - $booked_state = bat_event_load_state_by_machine_name('bee_hourly_booked'); + $variations = $product->getVariations(); + $product_variation = reset($variations); - $event = bat_event_create(['type' => 'availability_hourly']); - $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()); + $cart_manager = \Drupal::service('commerce_cart.cart_manager'); + $cart_provider = \Drupal::service('commerce_cart.cart_provider'); + + $cart = $cart_provider->getCart('default', $store); + if (!$cart) { + $cart = $cart_provider->createCart('default', $store); + } + else { + $cart_manager->emptyCart($cart); + } + + $order_item = \Drupal::entityManager()->getStorage('commerce_order_item')->create([ + 'title' => $node->label(), + 'type' => 'bee', + 'purchased_entity' => $product_variation->id(), + 'quantity' => 1, + 'unit_price' => $product_variation->getPrice(), + ]); + $order_item->set('field_booking', $booking); + $order_item->set('field_node', $node); + $order_item->save(); + + $cart_manager->addOrderItem($cart, $order_item); + + $form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $cart->id()]); } + else { + 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()); + } + else { + $booked_state = bat_event_load_state_by_machine_name('bee_hourly_booked'); + + $event = bat_event_create(['type' => 'availability_hourly']); + $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($values); + $available_units = $this->getAvailableUnits($values); - $event->set('event_bat_unit_reference', reset($available_units)); - $event->save(); + $event->set('event_bat_unit_reference', reset($available_units)); + $event->save(); - drupal_set_message(t('Reservation created!')); + drupal_set_message(t('Reservation created!')); - $form_state->setRedirect('entity.node.canonical', ['node' => $node->id()]); + $form_state->setRedirect('entity.node.canonical', ['node' => $node->id()]); + } } /** diff --git a/src/Resolvers/SalepriceResolver.php b/src/Resolvers/SalepriceResolver.php new file mode 100644 index 0000000..20ca6c4 --- /dev/null +++ b/src/Resolvers/SalepriceResolver.php @@ -0,0 +1,80 @@ +bundle() != 'bee') { + return; + } + + $cart_provider = \Drupal::service('commerce_cart.cart_provider'); + + $stores = $entity->getProduct()->getStores(); + $store = reset($stores); + + if ($cart = $cart_provider->getCart('default', $store)) { + $order_items = $cart->getItems(); + foreach ($order_items as $order_item) { + if ($order_item->bundle() == 'bee') { + if ($order_item->getPurchasedEntityId() == $entity->id()) { + $query = \Drupal::entityQuery('node') + ->condition('field_product', $entity->getProductId()); + + $nids = $query->execute(); + $node = Node::load(reset($nids)); + + $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); + + $reservation_context = [ + 'order_item' => $order_item, + 'booking' => $booking, + 'node' => $node, + ]; + + $base_price = $node->get('field_price')->number; + $currency_code = $node->get('field_price')->currency_code; + + $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, 2); + } + else { + $minutes = ($interval->days * 24 * 60) + ($interval->h * 60) + $interval->i; + $amount = number_format($base_price * $minutes, 2); + } + + $price = new Price($amount, $currency_code); + + \Drupal::moduleHandler()->alter('bee_reservation_price', $price, $reservation_context); + + return $price; + } + } + } + } + } + +} From 8de3ce1b0c4437c4d5d448db28b3f8b2f2195fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Caruso?= Date: Sat, 12 May 2018 18:15:39 +0200 Subject: [PATCH 2/5] Update pre-existing nodes when Payment is enabled --- bee.module | 86 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/bee.module b/bee.module index fb4f8f8..52df06c 100644 --- a/bee.module +++ b/bee.module @@ -86,7 +86,13 @@ function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) { if (!(\Drupal::moduleHandler()->moduleExists('commerce_checkout') && \Drupal::moduleHandler()->moduleExists('commerce_payment'))) { $form['bee']['payment']['#disabled'] = TRUE; - $form['bee']['payment']['#description'] = t('To enable payments for bookings, install and enable the Drupal Commerce checkout and payment modules.'); + $form['bee']['payment']['#description'] = t('To enable payments for bookings, install and enable the Drupal Commerce checkout and payment modules and configure a Commerce Store.'); + } + elseif (\Drupal::moduleHandler()->moduleExists('commerce')) { + if (empty(Store::loadMultiple())) { + $form['bee']['payment']['#disabled'] = TRUE; + $form['bee']['payment']['#description'] = t('To enable payments for bookings, install and enable the Drupal Commerce checkout and payment modules and configure a Commerce Store.'); + } } if (isset($bee_settings['type_id'])) { @@ -164,30 +170,21 @@ function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) { $form['field_price']['#title'] = t('Price per day'); $form['field_price_frequency']['#access'] = FALSE; + + $form['field_price']['#prefix'] = '
'; + $form['field_price']['#suffix'] = '
'; } else { $form['field_price']['#group'] = 'payments'; - $form['field_price']['widget'][0]['#title'] = t('Price per'); + $form['field_price']['widget'][0]['#title'] = t('Price'); $form['field_price_frequency']['#group'] = 'payments'; $form['field_price_frequency']['widget']['#default_value'] = 'hour'; - $form['field_price_frequency']['widget']['#title'] = ''; + $form['field_price_frequency']['widget']['#title'] = t('per'); unset($form['field_price_frequency']['widget']['#options']['_none']); - /*$form['bee']['payments']['price'] = [ - '#type' => 'commerce_number', - '#title' => t('Price per'), - '#default_value' => '', - ];*/ - - /*$form['bee']['payments']['price_frequency'] = [ - '#type' => 'select', - '#options' => [ - 'hour' => t('Hour'), - 'minute' => t('Minute'), - ], - '#default_value' => 'hour', - ];*/ + $form['field_price']['#prefix'] = '
'; + $form['field_price_frequency']['#suffix'] = '
'; } } else { @@ -347,6 +344,23 @@ function bee_node_type_edit_form_submit(array &$form, FormStateInterface $form_s bee_add_product_reference_field('field_product', $node_type); bee_add_price_field('field_price', $node_type); bee_add_price_frequency_field('field_price_frequency', $node_type); + + if (!$form['bee']['payment']['#default_value']) { + $node_storage = \Drupal::entityManager()->getStorage('node'); + + $query = \Drupal::entityQuery('node') + ->condition('type', $node_type->id()); + + $nids = $query->execute(); + foreach ($node_storage->loadMultiple($nids) as $node) { + if (!$node->get('field_product')->entity) { + $product = bee_create_node_product($node); + + $node->set('field_product', $product->id()); + $node->save(); + } + } + } } \Drupal::configFactory()->getEditable('node.type.' . $node_type->id())->set('bee', $bee_settings)->save(); @@ -392,22 +406,7 @@ function bee_node_insert(EntityInterface $node) { if (isset($bee_settings['bookable']) && $bee_settings['bookable']) { if ($bee_settings['payment']) { - $variation = ProductVariation::create([ - 'type' => 'bee', - 'sku' => 'bee_' . $node->bundle() . '_' . $node->id(), - 'price' => [ - 'number' => 0, - 'currency_code' => 'USD', - ], - ]); - $variation->save(); - $product = Product::create([ - 'type' => 'bee_' . $node->bundle(), - 'title' => $node->label(), - 'variations' => [$variation], - 'stores' => Store::loadMultiple(), - ]); - $product->save(); + $product = bee_create_node_product($node); $node->set('field_product', $product->id()); } @@ -1096,3 +1095,24 @@ function bee_create_bee_booking_type() { $booking_type->save(); } } + +function bee_create_node_product($node) { + $variation = ProductVariation::create([ + 'type' => 'bee', + 'sku' => 'bee_' . $node->bundle() . '_' . $node->id(), + 'price' => [ + 'number' => 0, + 'currency_code' => 'USD', + ], + ]); + $variation->save(); + $product = Product::create([ + 'type' => 'bee_' . $node->bundle(), + 'title' => $node->label(), + 'variations' => [$variation], + 'stores' => Store::loadMultiple(), + ]); + $product->save(); + + return $product; +} From b069a438110ea259842bba124b0517588f19bfd0 Mon Sep 17 00:00:00 2001 From: Adrian Rollett Date: Mon, 14 May 2018 16:17:49 -0600 Subject: [PATCH 3/5] Fix validation for daily bookings --- src/Form/AddReservationForm.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Form/AddReservationForm.php b/src/Form/AddReservationForm.php index 1aaf312..d36da44 100644 --- a/src/Form/AddReservationForm.php +++ b/src/Form/AddReservationForm.php @@ -65,15 +65,19 @@ public function buildForm(array $form, FormStateInterface $form_state, NodeInter public function validateForm(array &$form, FormStateInterface $form_state) { $values = $form_state->getValues(); $node = Node::load($values['node']); + $bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee'); $start_date = $values['start_date']; $end_date = $values['end_date']; + if ($bee_settings['bookable_type'] == 'daily') { + $start_date = new \DateTime($start_date); + $end_date = new \DateTime($end_date); + } + $date_start_date = $start_date->format('Y-m-d'); $date_end_date = $end_date->format('Y-m-d'); - $bee_settings = \Drupal::config('node.type.' . $node->bundle())->get('bee'); - $dates_valid = TRUE; if ($bee_settings['bookable_type'] == 'hourly') { From 61c28f82072d9b451ec0366694c5d5666dec2074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Caruso?= Date: Tue, 15 May 2018 10:22:19 +0200 Subject: [PATCH 4/5] BAT-89: Calculate right price for daily bookings --- src/Resolvers/SalepriceResolver.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Resolvers/SalepriceResolver.php b/src/Resolvers/SalepriceResolver.php index 20ca6c4..0a435e7 100644 --- a/src/Resolvers/SalepriceResolver.php +++ b/src/Resolvers/SalepriceResolver.php @@ -39,6 +39,8 @@ public function resolve(PurchasableEntityInterface $entity, $quantity, Context $ $nids = $query->execute(); $node = Node::load(reset($nids)); + $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); @@ -55,15 +57,21 @@ public function resolve(PurchasableEntityInterface $entity, $quantity, Context $ $base_price = $node->get('field_price')->number; $currency_code = $node->get('field_price')->currency_code; - $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, 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, 2, '.', ''); + } + else { + $minutes = ($interval->days * 24 * 60) + ($interval->h * 60) + $interval->i; + $amount = number_format($base_price * $minutes, 2, '.', ''); + } } $price = new Price($amount, $currency_code); From b9e30fbaa8d9574d3cbb607b704643a5ee35818a Mon Sep 17 00:00:00 2001 From: Adrian Rollett Date: Fri, 18 May 2018 13:38:53 -0600 Subject: [PATCH 5/5] Hide price fields on node creation --- bee.module | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bee.module b/bee.module index 52df06c..8d42238 100644 --- a/bee.module +++ b/bee.module @@ -167,7 +167,7 @@ function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) { if ($bee_settings['bookable_type'] == 'daily') { $form['field_price']['#group'] = 'payments'; - $form['field_price']['#title'] = t('Price per day'); + $form['field_price']['widget'][0]['#title'] = t('Price per day'); $form['field_price_frequency']['#access'] = FALSE; @@ -188,7 +188,7 @@ function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) { } } else { - $form['field_price ']['#access'] = FALSE; + $form['field_price']['#access'] = FALSE; $form['field_price_frequency']['#access'] = FALSE; } @@ -219,6 +219,14 @@ function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) { } } elseif (preg_match('/^node_.*_form$/', $form_id)) { + if (isset($form['field_price'])) { + $form['field_price']['#access'] = FALSE; + } + + if (isset($form['field_price_frequency'])) { + $form['field_price_frequency']['#access'] = FALSE; + } + if (isset($form['field_use_open_hours'])) { $form['field_use_open_hours']['#access'] = FALSE; }