diff --git a/uc_cart/src/Form/CartForm.php b/uc_cart/src/Form/CartForm.php index 4068b16..3da879c 100644 --- a/uc_cart/src/Form/CartForm.php +++ b/uc_cart/src/Form/CartForm.php @@ -94,7 +94,10 @@ class CartForm extends FormBase { $i = 0; $subtotal = 0; foreach ($cart->getContents() as $cart_item) { + // Prepare the CartItem entity to be displayed in the cart form $item = \Drupal::moduleHandler()->invoke($cart_item->data->module, 'uc_cart_display', array($cart_item)); + // Allow other modules (for example Tax module) to alter the cart item before display + \Drupal::moduleHandler()->alter('uc_cart_display', $item, $cart_item); if (Element::children($item)) { $form['items'][$i]['remove'] = $item['remove']; $form['items'][$i]['remove']['#name'] = 'remove-' . $i; diff --git a/uc_tax/src/Form/TaxRateAddForm.php b/uc_tax/src/Form/TaxRateAddForm.php deleted file mode 100644 index d864dea..0000000 --- a/uc_tax/src/Form/TaxRateAddForm.php +++ /dev/null @@ -1,21 +0,0 @@ -t('Create tax rate'); - return $actions; - } - -} diff --git a/uc_tax/src/Form/TaxRateEditForm.php b/uc_tax/src/Form/TaxRateEditForm.php deleted file mode 100644 index 5926a0d..0000000 --- a/uc_tax/src/Form/TaxRateEditForm.php +++ /dev/null @@ -1,31 +0,0 @@ -entity; - // Set title to show what rate we're editing. - $form['#title'] = $this->t('Edit %rate', ['%rate' => $rate->label()]); - return parent::buildForm($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function actions(array $form, FormStateInterface $form_state) { - $actions = parent::actions($form, $form_state); - $actions['submit']['#value'] = $this->t('Update tax rate'); - return $actions; - } - -} diff --git a/uc_tax/src/Form/TaxRateFormBase.php b/uc_tax/src/Form/TaxRateFormBase.php deleted file mode 100644 index d32b334..0000000 --- a/uc_tax/src/Form/TaxRateFormBase.php +++ /dev/null @@ -1,199 +0,0 @@ -entity; - - $form['label'] = array( - '#type' => 'textfield', - '#title' => $this->t('Label'), - '#description' => $this->t('This name will appear to the customer when this tax is applied to an order.'), - '#default_value' => $rate->label(), - '#required' => TRUE, - ); - - $form['id'] = array( - '#type' => 'machine_name', - '#title' => $this->t('Machine name'), - '#default_value' => $rate->id(), - '#machine_name' => array( - 'exists' => array($this, 'exists'), - 'replace_pattern' => '([^a-z0-9_]+)|(^custom$)', - 'error' => 'The machine-readable name must be unique, and can only contain lowercase letters, numbers, and underscores. Additionally, it can not be the reserved word "custom".', - ), -// '#disabled' => !$this->isNew(), - ); - - $form['rate'] = array( - '#type' => 'textfield', - '#title' => $this->t('Rate'), - '#description' => $this->t('The tax rate as a percent or decimal. Examples: 6%, .06'), - '#size' => 15, - '#default_value' => (float) $rate->getRate() * 100.0 . '%', - '#required' => TRUE, - ); - - $form['shippable'] = array( - '#type' => 'radios', - '#title' => $this->t('Taxed products'), - '#options' => array( - 0 => $this->t('Apply tax to any product regardless of its shippability.'), - 1 => $this->t('Apply tax to shippable products only.'), - ), - '#default_value' => (int) $rate->isForShippable(), - ); - - // TODO: Remove the need for a special case for product kit module. - $options = array(); - foreach (node_type_get_names() as $type => $name) { - if ($type != 'product_kit' && uc_product_is_product($type)) { - $options[$type] = $name; - } - } - $options['blank-line'] = $this->t('"Blank line" product'); - - $form['product_types'] = array( - '#type' => 'checkboxes', - '#title' => $this->t('Taxed product types'), - '#description' => $this->t('Apply taxes to the specified product types/classes.'), - '#default_value' => $rate->getProductTypes(), - '#options' => $options, - ); - - $options = array(); - $definitions = \Drupal::service('plugin.manager.uc_order.line_item')->getDefinitions(); - foreach ($definitions as $id => $line_item) { - if (!in_array($id, ['subtotal', 'tax_subtotal', 'total', 'tax_display'])) { - $options[$id] = $line_item['title']; - } - } - - $form['line_item_types'] = array( - '#type' => 'checkboxes', - '#title' => $this->t('Taxed line items'), - '#description' => $this->t('Adds the checked line item types to the total before applying this tax.'), - '#default_value' => $rate->getLineItemTypes(), - '#options' => $options, - ); - - $form['weight'] = array( - '#type' => 'weight', - '#title' => $this->t('Weight'), - '#description' => $this->t('Taxes are sorted by weight and then applied to the order sequentially. This value is important when taxes need to include other tax line items.'), - '#default_value' => $rate->getWeight(), - ); - - $form['display_include'] = array( - '#type' => 'checkbox', - '#title' => $this->t('Include this tax when displaying product prices.'), - '#default_value' => $rate->isIncludedInPrice(), - ); - - $form['inclusion_text'] = array( - '#type' => 'textfield', - '#title' => $this->t('Tax inclusion text'), - '#description' => $this->t('This text will be displayed near the price to indicate that it includes tax.'), - '#default_value' => $rate->getInclusionText(), - ); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validate(array $form, FormStateInterface $form_state) { - parent::validate($form, $form_state); - $rate = $form_state->getValue('rate'); - $rate = trim($rate); - // @TODO Would be nice to better validate rate, maybe with preg_match - if (floatval($rate) < 0) { - $form_state->setErrorByName('rate', $this->t('Rate must be a positive number. No commas and only one decimal point.')); - } - // Save trimmed rate back to form if it passes validation. - $form_state->setValue('rate', $rate); - } - - /** - * {@inheritdoc} - */ - public function save(array $form, FormStateInterface $form_state) { - $tax_rate = $this->getEntity(); - - // Save rate. - $rate = $form_state->getValue('rate'); - if (substr($rate, -1) == '%') { - // Rate given in percentage, so convert it to a fraction for storage. - $tax_rate->setRate(floatval($rate) / 100.0); - } - - // Save machine names of product types and line item types. - $tax_rate->setProductTypes(array_filter($form_state->getValue('product_types'))); - $tax_rate->setLineItemTypes(array_filter($form_state->getValue('line_item_types'))); - - // @TODO When Rules is working in D8 .. - // Update the name of the associated conditions. - // $conditions = rules_config_load('uc_tax_' . $form_state->getValue('id')); - // if ($conditions) { - // $conditions->label = $form_state->getVolue('name'); - // $conditions->save(); - // } - - $status = $tax_rate->save(); - - // Create an edit link. - $edit_link = Link::fromTextAndUrl($this->t('Edit'), $tax_rate->toUrl())->toString(); - - if ($status == SAVED_UPDATED) { - // If we edited an existing entity... - drupal_set_message($this->t('Tax rate %label has been updated.', ['%label' => $tax_rate->label()])); - $this->logger('uc_tax')->notice('Tax rate %label has been updated.', ['%label' => $tax_rate->label(), 'link' => $edit_link]); - } - else { - // If we created a new entity... - drupal_set_message($this->t('Tax rate %label has been added.', ['%label' => $tax_rate->label()])); - $this->logger('uc_tax')->notice('Tax rate %label has been added.', ['%label' => $tax_rate->label(), 'link' => $edit_link]); - } - - // Redirect the user back to the listing route after the save operation. - $form_state->setRedirect('entity.uc_tax_rate.collection'); - } - - /** - * {@inheritdoc} - */ - protected function actions(array $form, FormStateInterface $form_state) { - $actions = parent::actions($form, $form_state); - - // Change the submit button text. - $actions['submit']['#value'] = $this->t('Save'); - $actions['submit']['#suffix'] = Link::fromTextAndUrl($this->t('Cancel'), $this->getCancelUrl())->toString(); - - return $actions; - } - -} diff --git a/uc_tax/src/Form/TaxRateMethodsForm.php b/uc_tax/src/Form/TaxRateMethodsForm.php deleted file mode 100644 index fda5467..0000000 --- a/uc_tax/src/Form/TaxRateMethodsForm.php +++ /dev/null @@ -1,133 +0,0 @@ -config('uc_tax.settings'); - - $header = array($this->t('Name'), $this->t('Rate'), $this->t('Taxed products'), $this->t('Taxed product types'), $this->t('Taxed line items'), $this->t('Weight'), $this->t('Operations')); - $form['methods'] = array( - '#type' => 'table', - '#header' => $header, - '#tabledrag' => array( - array( - 'action' => 'order', - 'relationship' => 'sibling', - 'group' => 'uc-tax-method-weight', - ), - ), - '#empty' => $this->t('No tax rates have been configured yet.'), - ); - - $rows = array(); - foreach (uc_tax_rate_load() as $rate_id => $rate) { - - // Build a list of operations links. - $operations = array( - 'edit' => array( - 'title' => $this->t('edit'), - 'url' => Url::fromRoute('uc_tax.rate_edit', ['tax_rate' => $rate_id]), - ), -// @todo: Fix when Rules works. -// 'conditions' => array( -// 'title' => $this->t('conditions'), -// 'url' => Url::fromRoute('admin/store/config/taxes/manage/uc_tax_', ['rate_id' => $rate_id]), -// 'weight' => 5, -// ), - 'clone' => array( - 'title' => $this->t('clone'), - 'url' => Url::fromRoute('uc_tax.rate_clone', ['tax_rate' => $rate_id]), - ), - 'delete' => array( - 'title' => $this->t('delete'), - 'url' => Url::fromRoute('uc_tax.rate_delete', ['tax_rate' => $rate_id]), - ), - ); - - // Ensure "delete" comes towards the end of the list. - if (isset($operations['delete'])) { - $operations['delete']['weight'] = 10; - } - uasort($operations, 'Drupal\Component\Utility\SortArray::sortByWeightElement'); - - $form['methods'][$rate_id]['status'] = array( - '#type' => 'checkbox', - '#title' => $rate->name, - '#default_value' => $rate->enabled, - ); - $form['methods'][$rate_id]['rate'] = array( - '#markup' => $rate->rate * 100 . '%', - ); - $form['methods'][$rate_id]['taxed_products'] = array( - '#markup' => $rate->shippable ? $this->t('Shippable products') : $this->t('Any product'), - ); - $form['methods'][$rate_id]['taxed_types'] = array( - '#markup' => implode(', ', $rate->taxed_product_types), - ); - $form['methods'][$rate_id]['taxed_line_items'] = array( - '#markup' => implode(', ', $rate->taxed_line_items), - ); - $form['methods'][$rate_id]['weight'] = array( - '#type' => 'weight', - '#default_value' => $rate->weight, - '#attributes' => array('class' => array('uc-tax-method-weight')), - ); - $form['methods'][$rate_id]['operations'] = array( - '#type' => 'operations', - '#links' => $operations, - ); - } - - return parent::buildForm($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $enabled = array(); - $method_weight = array(); - foreach ($form_state->getValue('methods') as $rate_id => $rate) { - $enabled[$rate_id] = $rate['status']; - $method_weight[$rate_id] = $rate['weight']; - } - - $tax_config = $this->config('uc_tax.settings'); - $tax_config - ->set('enabled', $enabled) - ->set('method_weight', $method_weight) - ->set('type_weight', $form_state->getValue('uc_tax_type_weight')) - ->save(); - - return parent::submitForm($form, $form_state); - } - -} diff --git a/uc_tax/src/Plugin/Ubercart/TaxRate/PercentageTaxRate.php b/uc_tax/src/Plugin/Ubercart/TaxRate/PercentageTaxRate.php index ffddcca..e1c87bf 100644 --- a/uc_tax/src/Plugin/Ubercart/TaxRate/PercentageTaxRate.php +++ b/uc_tax/src/Plugin/Ubercart/TaxRate/PercentageTaxRate.php @@ -2,9 +2,12 @@ namespace Drupal\uc_tax\Plugin\Ubercart\TaxRate; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\field\Entity\FieldConfig; +use Drupal\node\NodeInterface; use Drupal\uc_order\OrderInterface; +use Drupal\uc_tax\TaxRateInterface; use Drupal\uc_tax\TaxRatePluginBase; /** @@ -35,7 +38,7 @@ class PercentageTaxRate extends TaxRatePluginBase { public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $fields = ['' => $this->t('- None -')]; $result = \Drupal::entityQuery('field_config') - ->condition('field_type', 'number') + ->condition('field_type', array('integer', 'float', 'decimal', 'list_integer', 'list_float'), 'IN') ->execute(); foreach (FieldConfig::loadMultiple($result) as $field) { $fields[$field->getName()] = $field->label(); @@ -87,23 +90,63 @@ class PercentageTaxRate extends TaxRatePluginBase { /** * {@inheritdoc} */ - public function calculateTax(OrderInterface $order) { + public function calculateProductTax(EntityInterface $item, OrderInterface $order=NULL) { + $nid = $item instanceof NodeInterface ? $item->id() : $item->nid->target_id; + $node = node_load($nid); + $price = is_object($item->price) ? $item->price->value : $item->price; + $rate = $this->configuration['rate']; - $jurisdiction = $this->configuration['jurisdiction']; $field = $this->configuration['field']; - foreach ($order->products as $product) { - if (isset($product->nid->entity->$field->value)) { - $product_rate = $product->nid->entity->$field->value * $product->qty->value; - } - else { - $product_rate = $this->configuration['rate'] * $product->qty->value; + if (isset($node->$field->value)) { + $product_rate = $node->$field->value; + } + else { + $product_rate = $rate; + } + + $calculated_tax = $price * floatval($product_rate) / 100; + + return $calculated_tax; + } + + /** + * {@inheritdoc} + */ + public function calculateOrderTax(OrderInterface $order, TaxRateInterface $tax) { + $rate = $this->configuration['rate']; + $field = $this->configuration['field']; + $line_item_types = $tax->getLineItemTypes(); + $product_types = $tax->getProductTypes(); + $calculated_tax = 0; + + + if ( in_array('generic', $line_item_types) ) { + foreach ($order->products as $product) { + $node = node_load($product->nid->target_id); + + if (in_array($node->bundle(), $product_types)) { + if (isset($node->$field->value)) { + $product_rate = $node->$field->value * $product->qty->value; + } + else { + $product_rate = $rate * $product->qty->value; + } + + $calculated_tax += $product->price->value * floatval($product_rate) / 100; + } } + } + - $rate += $product->price->value * floatval($product_rate) / 100; + foreach($order->line_items as $line_item) { + if (in_array($line_item['type'], $line_item_types)) { + $calculated_tax += $line_item['amount'] * floatval($rate) / 100; + } } - return [$rate]; + + return $calculated_tax; } } diff --git a/uc_tax/src/TaxRateListBuilder.php b/uc_tax/src/TaxRateListBuilder.php index 5827cd8..c54bd0d 100644 --- a/uc_tax/src/TaxRateListBuilder.php +++ b/uc_tax/src/TaxRateListBuilder.php @@ -105,13 +105,15 @@ class TaxRateListBuilder extends DraggableListBuilder implements FormInterface { */ public function buildOperations(EntityInterface $entity) { $build = parent::buildOperations($entity); + $build['#links']['clone'] = array( 'title' => $this->t('Clone'), 'url' => Url::fromRoute('entity.uc_tax_rate.clone', ['uc_tax_rate' => $entity->id()]), - 'weight' => 10, // 'edit' is 0, 'delete' is 100 + 'weight' => 20, ); uasort($build['#links'], 'Drupal\Component\Utility\SortArray::sortByWeightElement'); + return $build; } diff --git a/uc_tax/uc_tax.install b/uc_tax/uc_tax.install deleted file mode 100644 index c2cc979..0000000 --- a/uc_tax/uc_tax.install +++ /dev/null @@ -1,96 +0,0 @@ - 'Stores tax information.', - 'fields' => array( - 'id' => array( - 'description' => 'Primary key: Unique tax rate id.', - 'type' => 'serial', - 'unsigned' => TRUE, - 'not null' => TRUE, - ), - 'name' => array( - 'description' => 'The tax rate name.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'rate' => array( - 'description' => 'The tax rate multiplier.', - 'type' => 'float', - 'not null' => TRUE, - 'default' => 0.0, - ), - 'shippable' => array( - 'description' => 'Flag that describes how this rate applies to shippable and non-shippable products. 0 => Disregard shipability. 1 => Apply tax to shippable products only.', - 'type' => 'int', - 'size' => 'tiny', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'weight' => array( - 'description' => 'The weight of this tax rate in relation to other rates.', - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - ), - 'display_include' => array( - 'description' => 'Boolean flag indicating that product prices should be displayed including the tax.', - 'type' => 'int', - 'size' => 'tiny', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'inclusion_text' => array( - 'description' => 'Text to be shown near a product price that includes tax.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - ), - 'primary key' => array('id'), - ); - - $schema['uc_tax_taxed_product_types'] = array( - 'fields' => array( - 'tax_id' => array( - 'description' => 'Tax rate id', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'type' => array( - 'description' => 'Node type', - 'type' => 'varchar', - 'length' => 32, - 'not null' => TRUE, - 'default' => '', - ), - ), - 'primary key' => array('tax_id', 'type'), - 'indexes' => array( - 'type' => array('type'), - ), - ); - - $schema['uc_tax_taxed_line_items'] = $schema['uc_tax_taxed_product_types']; - $schema['uc_tax_taxed_line_items']['fields']['type']['description'] = 'Line item type'; - - return $schema; -} diff --git a/uc_tax/uc_tax.module b/uc_tax/uc_tax.module index 6ef53c1..7fea8a7 100644 --- a/uc_tax/uc_tax.module +++ b/uc_tax/uc_tax.module @@ -13,6 +13,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\node\Entity\NodeType; use Drupal\node\NodeInterface; use Drupal\uc_order\OrderInterface; +use Drupal\uc_tax\Entity\TaxRate; /** * Implements hook_module_implements_alter(). @@ -21,7 +22,7 @@ use Drupal\uc_order\OrderInterface; * calculations are made. */ function uc_tax_module_implements_alter(&$implementations, $hook) { - if (in_array($hook, ['uc_order_insert', 'uc_order_update', 'entity_view_alter'])) { + if (in_array($hook, ['uc_order_insert', 'uc_order_update', 'uc_cart_display_alter'])) { $group = $implementations['uc_tax']; unset($implementations['uc_tax']); $implementations['uc_tax'] = $group; @@ -34,14 +35,15 @@ function uc_tax_module_implements_alter(&$implementations, $hook) { function uc_tax_form_uc_order_edit_form_alter(&$form, FormStateInterface $form_state) { $order = $form['#order']; $line_items = $order->line_items; + foreach ($line_items as $item) { // Tax line items are stored in the database, but they can't be changed by // the user. if ($item['type'] == 'tax') { - $form['line_items'][$item['line_item_id']]['title'] = array( + $form['line_items']['line_items'][$item['line_item_id']]['title'] = array( '#markup' => $item['title'], ); - $form['line_items'][$item['line_item_id']]['amount'] = array( + $form['line_items']['line_items'][$item['line_item_id']]['amount'] = array( '#theme' => 'uc_price', '#price' => $item['amount'], ); @@ -61,39 +63,6 @@ function uc_tax_uc_product_alter(&$node) { } /** - * Implements hook_entity_view_alter(). - * - * Adds included tax (VAT) to display price of applicable products. - */ -function uc_tax_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) { - switch ($entity->getEntityTypeId()) { - case 'uc_cart_item': - list($amount, $suffixes) = uc_tax_get_included_tax($entity, isset($entity->order) ? $entity->order : NULL); - - if (!empty($amount) && !empty($build['#total'])) { - $build['#total'] += $amount * $build['qty']['#default_value']; - } - - if (!empty($suffixes)) { - if (empty($build['#suffixes'])) { - $build['#suffixes'] = array(); - } - $build['#suffixes'] += $suffixes; - } - break; - - case 'uc_order_product': - list($amount, $suffixes) = uc_tax_get_included_tax($entity, isset($entity->order) ? $entity->order : NULL); - - $build['price']['#price'] += $amount; - $build['total']['#price'] += $amount * $entity->qty->value; - $build['price']['#suffixes'] += $suffixes; - $build['total']['#suffixes'] += $suffixes; - break; - } -} - -/** * Implements hook_uc_order_insert(). */ function uc_tax_uc_order_insert(OrderInterface $order) { @@ -161,7 +130,7 @@ function uc_tax_uc_order_update(OrderInterface $order) { */ function uc_tax_node_type_update(EntityInterface $info) { $original_id = $info->getOriginalId(); - $existing_type = !empty($original_id) ? $info->getOriginalId() : $info->getEntityTypeId(); + $existing_type = !empty($original_id) ? $original_id : $info->getEntityTypeId(); db_update('uc_tax_taxed_product_types') ->fields(array( @@ -192,75 +161,6 @@ function _uc_tax_to_line_item($tax) { } /** - * Saves a tax rate to the database. - * - * @param $rate - * The tax rate object to be saved. - * @param $reset - * If TRUE, resets the Rules cache after saving. Defaults to TRUE. - * - * @return - * The saved tax rate object including the rate ID for new rates. - */ -function uc_tax_rate_save($rate, $reset = TRUE) { - $fields = array( - 'name' => $rate->name, - 'rate' => $rate->rate, - 'shippable' => $rate->shippable, - 'weight' => $rate->weight, - 'display_include' => $rate->display_include, - 'inclusion_text' => $rate->inclusion_text, - ); - - if (isset($rate->id)) { - db_merge('uc_tax') - ->key('id', $rate->id) - ->fields($fields) - ->execute(); - } - else { - $rate->id = db_insert('uc_tax') - ->fields($fields) - ->execute(); - } - - db_delete('uc_tax_taxed_product_types') - ->condition('tax_id', $rate->id) - ->execute(); - db_delete('uc_tax_taxed_line_items') - ->condition('tax_id', $rate->id) - ->execute(); - - $p_insert = db_insert('uc_tax_taxed_product_types')->fields(array('tax_id', 'type')); - $l_insert = db_insert('uc_tax_taxed_line_items')->fields(array('tax_id', 'type')); - - foreach ($rate->taxed_product_types as $type) { - $p_insert->values(array( - 'tax_id' => $rate->id, - 'type' => $type, - )); - } - - foreach ($rate->taxed_line_items as $type) { - $l_insert->values(array( - 'tax_id' => $rate->id, - 'type' => $type, - )); - } - - $p_insert->execute(); - $l_insert->execute(); - - // if ($reset) { - // // Ensure Rules picks up the new condition. - // entity_flush_caches(); - // } - - return $rate; -} - - -/** * List all the taxes that can apply to an order. * * The taxes depend on the order status. For orders which are still in @@ -328,23 +228,14 @@ function uc_tax_rate_load($rate_id = NULL) { // If the rates have not been cached yet... if (empty($rates)) { - // Get all the rate data from the database. - $result = db_query('SELECT id, name, rate, shippable, weight, display_include, inclusion_text FROM {uc_tax} ORDER BY weight'); - - // Loop through each returned row. - foreach ($result as $rate) { - $rate->taxed_product_types = array(); - $rate->taxed_line_items = array(); - // Disabled by default, overridden in config. - $rate->enabled = FALSE; - $rates[$rate->id] = $rate; - } + $tax_rates = TaxRate::loadMultiple(); + uasort($tax_rates, 'Drupal\uc_tax\Entity\TaxRate::sort'); - foreach (['taxed_product_types', 'taxed_line_items'] as $field) { - $result = db_select('uc_tax_' . $field, 't')->fields('t', array('tax_id', 'type'))->execute(); - foreach ($result as $record) { - $rates[$record->tax_id]->{$field}[] = $record->type; + $rates = []; + foreach ($tax_rates as $tax_rate) { + if ($tax_rate->status()) { + $rates[$tax_rate->id()] = $tax_rate; } } } @@ -360,30 +251,6 @@ function uc_tax_rate_load($rate_id = NULL) { } /** - * Deletes a tax rate from the database. - * - * @param $rate_id - * The ID of the tax rate to delete. - */ -function uc_tax_rate_delete($rate_id) { - // Delete the tax rate record. - db_delete('uc_tax') - ->condition('id', $rate_id) - ->execute(); - - db_delete('uc_tax_taxed_product_types') - ->condition('tax_id', $rate_id) - ->execute(); - - db_delete('uc_tax_taxed_line_items') - ->condition('tax_id', $rate_id) - ->execute(); - - // Delete the associated conditions if they have been saved to the database. - // rules_config_delete(array('uc_tax_' . $rate_id)); -} - -/** * Calculates the taxes for an order based on enabled tax modules. * * @param $order @@ -393,16 +260,6 @@ function uc_tax_rate_delete($rate_id) { * An array of taxes for the order. */ function uc_tax_calculate($order) { - // Find any taxes specified by enabled modules. - $taxes = \Drupal::moduleHandler()->invokeAll('uc_calculate_tax', [$order]); - - return $taxes; -} - -/** - * Calculates the amount and types of taxes that apply to an order. - */ -function uc_tax_uc_calculate_tax($order) { if (!is_object($order)) { return array(); } @@ -429,8 +286,7 @@ function uc_tax_uc_calculate_tax($order) { /** * Calculates taxable amount for a single product. */ -function uc_tax_apply_item_tax($item, $tax) { - // @todo The $item parameter can be many different objects, refactor this! +function uc_tax_calculate_product_tax($item, $tax, $order=NULL) { $nid = $item instanceof NodeInterface ? $item->id() : $item->nid->target_id; // Determine the product type. @@ -464,11 +320,11 @@ function uc_tax_apply_item_tax($item, $tax) { // Tax products if they are of a taxed type and if it is shippable if // the tax only applies to shippable products. - if (in_array($type, $tax->taxed_product_types) && ($tax->shippable == 0 || $shippable == 1)) { - return is_object($item->price) ? $item->price->value : $item->price; + if (in_array($type, $tax->getProductTypes()) && ($tax->isForShippable() == 0 || $shippable)) { + return $tax->getPlugin()->calculateProductTax($item, $order); } else { - return FALSE; + return 0; } } @@ -484,6 +340,7 @@ function uc_tax_apply_item_tax($item, $tax) { * The line item array representing the amount of tax. */ function uc_tax_apply_tax($order, $tax) { + /* $taxable_amount = 0; if (is_array($order->products)) { foreach ($order->products as $item) { @@ -507,22 +364,19 @@ function uc_tax_apply_tax($order, $tax) { foreach ($order->tax as $other_tax) { $taxable_amount += $other_tax->amount; } - } - $amount = $taxable_amount * $tax->rate; + }*/ + + $amount = $tax->getPlugin()->calculateOrderTax($order, $tax); + if ($amount) { $line_item = (object)array( - 'id' => $tax->id, - 'name' => $tax->name, + 'id' => $tax->id(), + 'name' => $tax->label(), 'amount' => $amount, - 'weight' => $tax->weight, + 'weight' => $tax->getWeight(), 'summed' => 1, ); - $line_item->data = array( - 'tax_rate' => $tax->rate, - 'tax' => $tax, - 'taxable_amount' => $taxable_amount, - 'tax_jurisdiction' => $tax->name, - ); + return $line_item; } } @@ -541,14 +395,39 @@ function uc_tax_get_included_tax($product, $order = NULL) { $amount = 0; $suffixes = array(); foreach (uc_tax_filter_rates($order) as $tax) { - if ($tax->display_include) { - $taxable = uc_tax_apply_item_tax($product, $tax); - if (!empty($taxable)) { - $amount += $taxable * $tax->rate; - $suffixes[$tax->inclusion_text] = $tax->inclusion_text; + if ($tax->isIncludedInPrice()) { + $tax_amount = uc_tax_calculate_product_tax($product, $tax, $order); + if (!empty($tax_amount)) { + $amount += $tax_amount; + $suffixes[$tax->getInclusionText()] = $tax->getInclusionText(); } } } return array($amount, $suffixes); } + +/** + * Implements hook_uc_cart_display_alter(). + */ +function uc_tax_uc_cart_display_alter(&$item, $cart_item) { + list($amount, $suffixes) = uc_tax_get_included_tax($cart_item, isset($cart_item->order) ? $cart_item->order : NULL); + if (!empty($amount)) { + $item['#total'] += $amount * $cart_item->qty->value; + } +} + +/** + * Implements hook_preprocess_HOOK(). + */ +function uc_tax_preprocess_uc_cart_review_table(&$variables) { + + foreach($variables['items'] as $key => $item) { + list($amount, $suffixes) = uc_tax_get_included_tax($item, $item->order_id->entity); + if (!empty($amount)) { + $new_item = clone $item; + $new_item->price->value += $amount; + $variables['items'][$key] = $new_item; + } + } +} \ No newline at end of file diff --git a/uc_tax/uc_tax.routing.yml b/uc_tax/uc_tax.routing.yml index 9b3480f..edbb480 100644 --- a/uc_tax/uc_tax.routing.yml +++ b/uc_tax/uc_tax.routing.yml @@ -1,40 +1,3 @@ -uc_tax.methods: - path: '/admin/store/config/taxes' - defaults: - _form: '\Drupal\uc_tax\Form\TaxRateMethodsForm' - _title: 'Taxes' - requirements: - _permission: 'administer taxes' - -uc_tax.rate_add: - path: '/admin/store/config/taxes/add' - defaults: - _form: '\Drupal\uc_tax\Form\TaxRateAddForm' - requirements: - _permission: 'administer taxes' - -uc_tax.rate_edit: - path: '/admin/store/config/taxes/{tax_rate}/edit' - defaults: - _form: '\Drupal\uc_tax\Form\TaxRateEditForm' - requirements: - _permission: 'administer taxes' - -uc_tax.rate_clone: - path: '/admin/store/config/taxes/{tax_rate}/clone' - defaults: - _controller: '\Drupal\uc_tax\Controller\TaxController::saveClone' - requirements: - _permission: 'administer taxes' - _csrf_token: 'TRUE' - -uc_tax.rate_delete: - path: '/admin/store/config/taxes/{tax_rate}/delete' - defaults: - _form: '\Drupal\uc_tax\Form\TaxRateDeleteForm' - requirements: - _permission: 'administer taxes' - entity.uc_tax_rate.collection: path: '/admin/store/config/tax' defaults: @@ -92,4 +55,4 @@ entity.uc_tax_rate.disable: op: 'disable' requirements: _permission: 'administer taxes' - _csrf_token: 'TRUE' + _csrf_token: 'TRUE' \ No newline at end of file