Skip to content

Commit

Permalink
2.0.0.0-dev83
Browse files Browse the repository at this point in the history
* Created the Service API for the Magento_Catalog Module:
   * Product Attribute Media API
   * Product Group Price API
* Tax calculation updates:
  * Fixed tax calculation rounding issues which appeared when a discount was applied
  * Fixed extra penny issue which appeared when exact tax amount ended with 0.5 cent
  * Fixed tax calculation issues which appeared when a customer tax rate was different from the store tax rate
  * Fixed price inconsistencies between catalog and shopping cart
  * Added support for maintaining consistent prices including tax for customers with different tax rates
  * Added support for applying tax rules with different priorities to be applied to subtotal only
  * Added support for tax rounding at individual tax rate
* Porting Tax Features from Magento 1.x:
  * Price consistency UX and algorithm
  * Canadian provincial sales taxes
  * Fixed issues with bundle product price inconsistency across the system
  * Added warnings if invalid tax configuration is created in the Admin panel
  * Fixed issues with regards to hidden tax
* Fixed bugs:
  * Fixed an issue where grouped price was not applied for grouped products
  * Fixed an issue where a fatal error occurred when opening a grouped product page without assigned products on the frontend
  * Fixed an issue where it was possible to apply an inactive discount coupon
  * Fixed an issue where the linked products information was lost when exporting products
  * Fixed non-informative error messages for "Attribute Group Service"
  * Fixed the invalid default value of the "apply_after_discount" tax setting
  * Fixed an issue where the integration tests coverage whitelist was broken
  * Fixed Admin panel UI issues: grids, headers and footers
* Added the following functional tests:
  * Create Product Url Rewrite
  * Delete Catalog Price Rule
  * Delete Category Url Rewrite
  * Delete CMS Page Rewrite
  * Delete Product Rating
  * Delete Sales Rule
  * Delete Tax Rate
  * Update Catalog Price Rule
  * Update Shopping Cart
  • Loading branch information
magento-team committed Jun 20, 2014
1 parent 658b76f commit ea1a2b7
Show file tree
Hide file tree
Showing 185 changed files with 9,604 additions and 693 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ before_script:
# Create DB for Integration tests
- sh -c "if [ '$TEST_SUITE' = 'integration' ] || [ '$TEST_SUITE' = 'integration_integrity' ]; then mysql -e 'create database magento_integration_tests;'; mv dev/tests/integration/etc/local-mysql.travis.xml.dist dev/tests/integration/etc/local-mysql.xml; fi"
# Install tools for static tests
- sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ] || [ '$TEST_SUITE' = 'static_annotation' ]; then pear install pear/PHP_CodeSniffer-1.4.7; fi"
- sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ] || [ '$TEST_SUITE' = 'static_annotation' ]; then pear install pear/PHP_CodeSniffer-1.5.2; fi"
- phpenv rehash;
script:
# Unit tests
Expand Down
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
2.0.0.0-dev83
=============
* Created the Service API for the Magento_Catalog Module:
* Product Attribute Media API
* Product Group Price API
* Tax calculation updates:
* Fixed tax calculation rounding issues which appeared when a discount was applied
* Fixed extra penny issue which appeared when exact tax amount ended with 0.5 cent
* Fixed tax calculation issues which appeared when a customer tax rate was different from the store tax rate
* Fixed price inconsistencies between catalog and shopping cart
* Added support for maintaining consistent prices including tax for customers with different tax rates
* Added support for applying tax rules with different priorities to be applied to subtotal only
* Added support for tax rounding at individual tax rate
* Porting Tax Features from Magento 1.x:
* Price consistency UX and algorithm
* Canadian provincial sales taxes
* Fixed issues with bundle product price inconsistency across the system
* Added warnings if invalid tax configuration is created in the Admin panel
* Fixed issues with regards to hidden tax
* Fixed bugs:
* Fixed an issue where grouped price was not applied for grouped products
* Fixed an issue where a fatal error occurred when opening a grouped product page without assigned products on the frontend
* Fixed an issue where it was possible to apply an inactive discount coupon
* Fixed an issue where the linked products information was lost when exporting products
* Fixed non-informative error messages for "Attribute Group Service"
* Fixed the invalid default value of the "apply_after_discount" tax setting
* Fixed an issue where the integration tests coverage whitelist was broken
* Fixed Admin panel UI issues: grids, headers and footers
* Added the following functional tests:
* Create Product Url Rewrite
* Delete Catalog Price Rule
* Delete Category Url Rewrite
* Delete CMS Page Rewrite
* Delete Product Rating
* Delete Sales Rule
* Delete Tax Rate
* Update Catalog Price Rule
* Update Shopping Cart

2.0.0.0-dev82
=============
* Added support for MTF Reporting Tool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<block class="Magento\AdminNotification\Block\Window" name="notification_window" as="notification_window" acl="Magento_AdminNotification::show_toolbar" template="notification/window.phtml"/>
</referenceContainer>
<referenceContainer name="header">
<block class="Magento\AdminNotification\Block\ToolbarEntry" template="toolbar_entry.phtml" />
<block class="Magento\AdminNotification\Block\ToolbarEntry" before="user" template="toolbar_entry.phtml" />
</referenceContainer>
<referenceBlock name="head">
<block class="Magento\Theme\Block\Html\Head\Script" name="magento-adminnotification-toolbar-entry-js" after="jquery-jquery-js">
Expand Down
31 changes: 31 additions & 0 deletions app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,31 @@
namespace Magento\Bundle\Block\Catalog\Product\View\Type;

use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Tax\Model\Calculation;

/**
* Catalog bundle product info block
*/
class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView
{
/**
* constants for different rounding methods
*/
const UNIT_ROUNDING = 0;
const ROW_ROUNDING = 1;
const TOTAL_ROUNDING = 2;

/**
* Mapping between constants in \Magento\Tax\Model\Calculation and this class
*
* @var array
*/
protected $mapping = [
Calculation::CALC_UNIT_BASE => self::UNIT_ROUNDING,
Calculation::CALC_ROW_BASE => self::ROW_ROUNDING,
Calculation::CALC_TOTAL_BASE => self::TOTAL_ROUNDING,
];

/**
* @var array
*/
Expand Down Expand Up @@ -305,4 +324,16 @@ public function getOptionHtml($option)
}
return $optionBlock->setOption($option)->toHtml();
}

/**
* Return the rounding method based on tax calculation
* This is a workaround as the proper way is to always call tax service to get taxed price
*
* @return int
*/
public function getRoundingMethod()
{
$algorithm = $this->_taxData->getCalculationAgorithm();
return isset($this->mapping[$algorithm]) ? $this->mapping[$algorithm] : self::TOTAL_ROUNDING;
}
}
33 changes: 29 additions & 4 deletions app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
use Magento\Framework\Pricing\Adjustment\Calculator as CalculatorBase;
use Magento\Bundle\Model\Product\Price;
use Magento\Bundle\Pricing\Price\BundleOptionPrice;
use Magento\Tax\Model\Calculation as TaxCalculation;
use Magento\Store\Model\Store;
use Magento\Tax\Helper\Data as TaxHelper;

/**
* Bundle price calculator
Expand All @@ -52,20 +55,29 @@ class Calculator implements BundleCalculatorInterface
*/
protected $selectionFactory;

/**
* Tax helper, needed to get rounding setting
*
* @var TaxHelper
*/
protected $taxHelper;
/**
* @param CalculatorBase $calculator
* @param AmountFactory $amountFactory
* @param BundleSelectionFactory $bundleSelectionFactory
* @param TaxHelper $taxHelper
* @return Calculator
*/
public function __construct(
CalculatorBase $calculator,
AmountFactory $amountFactory,
BundleSelectionFactory $bundleSelectionFactory
BundleSelectionFactory $bundleSelectionFactory,
TaxHelper $taxHelper
) {
$this->calculator = $calculator;
$this->amountFactory = $amountFactory;
$this->selectionFactory = $bundleSelectionFactory;
$this->taxHelper = $taxHelper;
}

/**
Expand Down Expand Up @@ -254,11 +266,24 @@ protected function calculateDynamicBundleAmount($basePriceValue, $bundleProduct,
foreach ($selectionPriceList as $selectionPrice) {
$amountList[] = $selectionPrice->getAmount();
}
/** @var Store $store */
$store = $bundleProduct->getStore();
$roundingMethod = $this->taxHelper->getCalculationAgorithm($store);
/** @var \Magento\Framework\Pricing\Amount\AmountInterface $itemAmount */
foreach ($amountList as $itemAmount) {
$fullAmount += $itemAmount->getValue();
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
if ($roundingMethod != TaxCalculation::CALC_TOTAL_BASE) {
//We need to round the individual selection first
$fullAmount += $store->roundPrice($itemAmount->getValue());
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
$adjustment = $store->roundPrice($adjustment);
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
}
} else {
$fullAmount += $itemAmount->getValue();
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
}

}
}
if ($exclude && isset($adjustments[$exclude])) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
$(document).ready(function() {
$('#product_addtocart_form').mage('bundleOption', {
"bundleConfig": <?php echo $this->getJsonConfig() ?>,
"roundingMethod" : "<?php echo $this->getRoundingMethod() ?>",
"bundleOptionQtyPrefix": "#bundle-option-",
"bundleOptionQtySuffix": "-qty-input",
"priceSelectors": {
Expand Down
18 changes: 17 additions & 1 deletion app/code/Magento/Bundle/view/frontend/web/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@
},

selectionPrice: function(optionId, selectionId) {
//Those constants need to be in sync with Magento\Bundle\Block\Catalog\Product\View\Type\Bundle
var TOTAL_ROUNDING = 2;
var ROW_ROUNDING = 1;
var UNIT_ROUNDING = 0;
var qty = null,
config = this.options.bundleConfig,
configOption = config.options[optionId];
Expand Down Expand Up @@ -281,7 +285,19 @@
});
}

return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty];
if (this.options.bundleConfig.isFixedPrice || this.options.roundingMethod == TOTAL_ROUNDING) {
return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty];
} else if (this.options.roundingMethod == UNIT_ROUNDING) {
price = Math.round(price * 100) / 100;
exclTaxPrice = Math.round(exclTaxPrice * 100) / 100;
inclTaxPrice = Math.round(inclTaxPrice * 100) / 100;
return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty];
} else {
var rowTotal = Math.round(price * qty * 100) /100;
var rowTotalExclTax = Math.round(exclTaxPrice * qty * 100) /100;
var rowTotalInclTax = Math.round(inclTaxPrice * qty * 100) /100;
return [rowTotal, rowTotalExclTax, rowTotalInclTax];
}
},

populateQty: function(optionId, selectionId) {
Expand Down
2 changes: 1 addition & 1 deletion app/code/Magento/Catalog/Block/Product/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public function getJsonConfig()
return $this->_jsonEncoder->encode($config);
}

$request = $this->_taxCalculation->getRateRequest(false, false, false);
$request = $this->_taxCalculation->getDefaultRateRequest();
/* @var $product \Magento\Catalog\Model\Product */
$product = $this->getProduct();
$request->setProductClassId($product->getTaxClassId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ public function validate($object)
if (isset($duplicates[$compare])) {
throw new \Magento\Framework\Model\Exception($this->_getDuplicateErrorMessage());
}

if (!preg_match('/^\d*(\.|,)?\d{0,4}$/i', $priceRow['price']) || $priceRow['price'] < 0) {
return __('Group price must be a number greater than 0.');
}

$duplicates[$compare] = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ public function afterSave($object)

$this->_getResource()->deleteGallery($recordsToDelete);
$this->removeDeletedImages($filesToDelete);
$object->setData($attrCode, $value);
}

/**
Expand Down
109 changes: 109 additions & 0 deletions app/code/Magento/Catalog/Model/Product/PriceModifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/

namespace Magento\Catalog\Model\Product;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\CouldNotSaveException;

class PriceModifier
{
/**
* @param \Magento\Catalog\Model\Product $product
* @param int $customerGroupId
* @param int $websiteId
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @throws \Magento\Framework\Exception\CouldNotSaveException
* @return void
*/
public function removeGroupPrice(\Magento\Catalog\Model\Product $product, $customerGroupId, $websiteId)
{
$prices = $product->getData('group_price');
if (is_null($prices)) {
throw new NoSuchEntityException("This product doesn't have group price");
}
$groupPriceQty = count($prices);

foreach ($prices as $key => $groupPrice) {
if ($groupPrice['cust_group'] == $customerGroupId
&& intval($groupPrice['website_id']) === intval($websiteId)) {
unset ($prices[$key]);
}
}
if ($groupPriceQty == count($prices)) {
throw new NoSuchEntityException(
"Product hasn't group price with such data: customerGroupId = '$customerGroupId',"
. "website = $websiteId."
);
}
$product->setData('group_price', $prices);
try {
$product->save();
} catch (\Exception $exception) {
throw new CouldNotSaveException("Invalid data provided for group price");
}
}

/**
* @param \Magento\Catalog\Model\Product $product
* @param int|string $customerGroupId
* @param int $qty
* @param int $websiteId
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @throws \Magento\Framework\Exception\CouldNotSaveException
* @return void
*/
public function removeTierPrice(\Magento\Catalog\Model\Product $product, $customerGroupId, $qty, $websiteId)
{
$prices = $product->getData('tier_price');
// verify if price exist
if (is_null($prices)) {
throw new NoSuchEntityException("This product doesn't have tier price");
}
$tierPricesQty = count($prices);

foreach ($prices as $key => $tierPrice) {
if ($customerGroupId == 'all' && $tierPrice['price_qty'] == $qty
&& $tierPrice['all_groups'] == 1 && intval($tierPrice['website_id']) === intval($websiteId)) {
unset ($prices[$key]);
} elseif ($tierPrice['price_qty'] == $qty && $tierPrice['cust_group'] == $customerGroupId
&& intval($tierPrice['website_id']) === intval($websiteId)) {
unset ($prices[$key]);
}
}

if ($tierPricesQty == count($prices)) {
throw new NoSuchEntityException(
"Product hasn't group price with such data: customerGroupId = '$customerGroupId',"
. "website = $websiteId, qty = $qty"
);
}
$product->setData('tier_price', $prices);
try {
$product->save();
} catch (\Exception $exception) {
throw new CouldNotSaveException("Invalid data provided for tier_price");
}
}
}
Loading

0 comments on commit ea1a2b7

Please sign in to comment.