Skip to content

Commit ea1a2b7

Browse files
committed
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
1 parent 658b76f commit ea1a2b7

File tree

185 files changed

+9604
-693
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

185 files changed

+9604
-693
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ before_script:
2828
# Create DB for Integration tests
2929
- 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"
3030
# Install tools for static tests
31-
- sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ] || [ '$TEST_SUITE' = 'static_annotation' ]; then pear install pear/PHP_CodeSniffer-1.4.7; fi"
31+
- sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ] || [ '$TEST_SUITE' = 'static_annotation' ]; then pear install pear/PHP_CodeSniffer-1.5.2; fi"
3232
- phpenv rehash;
3333
script:
3434
# Unit tests

CHANGELOG.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,42 @@
1+
2.0.0.0-dev83
2+
=============
3+
* Created the Service API for the Magento_Catalog Module:
4+
* Product Attribute Media API
5+
* Product Group Price API
6+
* Tax calculation updates:
7+
* Fixed tax calculation rounding issues which appeared when a discount was applied
8+
* Fixed extra penny issue which appeared when exact tax amount ended with 0.5 cent
9+
* Fixed tax calculation issues which appeared when a customer tax rate was different from the store tax rate
10+
* Fixed price inconsistencies between catalog and shopping cart
11+
* Added support for maintaining consistent prices including tax for customers with different tax rates
12+
* Added support for applying tax rules with different priorities to be applied to subtotal only
13+
* Added support for tax rounding at individual tax rate
14+
* Porting Tax Features from Magento 1.x:
15+
* Price consistency UX and algorithm
16+
* Canadian provincial sales taxes
17+
* Fixed issues with bundle product price inconsistency across the system
18+
* Added warnings if invalid tax configuration is created in the Admin panel
19+
* Fixed issues with regards to hidden tax
20+
* Fixed bugs:
21+
* Fixed an issue where grouped price was not applied for grouped products
22+
* Fixed an issue where a fatal error occurred when opening a grouped product page without assigned products on the frontend
23+
* Fixed an issue where it was possible to apply an inactive discount coupon
24+
* Fixed an issue where the linked products information was lost when exporting products
25+
* Fixed non-informative error messages for "Attribute Group Service"
26+
* Fixed the invalid default value of the "apply_after_discount" tax setting
27+
* Fixed an issue where the integration tests coverage whitelist was broken
28+
* Fixed Admin panel UI issues: grids, headers and footers
29+
* Added the following functional tests:
30+
* Create Product Url Rewrite
31+
* Delete Catalog Price Rule
32+
* Delete Category Url Rewrite
33+
* Delete CMS Page Rewrite
34+
* Delete Product Rating
35+
* Delete Sales Rule
36+
* Delete Tax Rate
37+
* Update Catalog Price Rule
38+
* Update Shopping Cart
39+
140
2.0.0.0-dev82
241
=============
342
* Added support for MTF Reporting Tool

app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<block class="Magento\AdminNotification\Block\Window" name="notification_window" as="notification_window" acl="Magento_AdminNotification::show_toolbar" template="notification/window.phtml"/>
3131
</referenceContainer>
3232
<referenceContainer name="header">
33-
<block class="Magento\AdminNotification\Block\ToolbarEntry" template="toolbar_entry.phtml" />
33+
<block class="Magento\AdminNotification\Block\ToolbarEntry" before="user" template="toolbar_entry.phtml" />
3434
</referenceContainer>
3535
<referenceBlock name="head">
3636
<block class="Magento\Theme\Block\Html\Head\Script" name="magento-adminnotification-toolbar-entry-js" after="jquery-jquery-js">

app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,31 @@
2424
namespace Magento\Bundle\Block\Catalog\Product\View\Type;
2525

2626
use Magento\Framework\Pricing\PriceCurrencyInterface;
27+
use Magento\Tax\Model\Calculation;
2728

2829
/**
2930
* Catalog bundle product info block
3031
*/
3132
class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView
3233
{
34+
/**
35+
* constants for different rounding methods
36+
*/
37+
const UNIT_ROUNDING = 0;
38+
const ROW_ROUNDING = 1;
39+
const TOTAL_ROUNDING = 2;
40+
41+
/**
42+
* Mapping between constants in \Magento\Tax\Model\Calculation and this class
43+
*
44+
* @var array
45+
*/
46+
protected $mapping = [
47+
Calculation::CALC_UNIT_BASE => self::UNIT_ROUNDING,
48+
Calculation::CALC_ROW_BASE => self::ROW_ROUNDING,
49+
Calculation::CALC_TOTAL_BASE => self::TOTAL_ROUNDING,
50+
];
51+
3352
/**
3453
* @var array
3554
*/
@@ -305,4 +324,16 @@ public function getOptionHtml($option)
305324
}
306325
return $optionBlock->setOption($option)->toHtml();
307326
}
327+
328+
/**
329+
* Return the rounding method based on tax calculation
330+
* This is a workaround as the proper way is to always call tax service to get taxed price
331+
*
332+
* @return int
333+
*/
334+
public function getRoundingMethod()
335+
{
336+
$algorithm = $this->_taxData->getCalculationAgorithm();
337+
return isset($this->mapping[$algorithm]) ? $this->mapping[$algorithm] : self::TOTAL_ROUNDING;
338+
}
308339
}

app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
use Magento\Framework\Pricing\Adjustment\Calculator as CalculatorBase;
3232
use Magento\Bundle\Model\Product\Price;
3333
use Magento\Bundle\Pricing\Price\BundleOptionPrice;
34+
use Magento\Tax\Model\Calculation as TaxCalculation;
35+
use Magento\Store\Model\Store;
36+
use Magento\Tax\Helper\Data as TaxHelper;
3437

3538
/**
3639
* Bundle price calculator
@@ -52,20 +55,29 @@ class Calculator implements BundleCalculatorInterface
5255
*/
5356
protected $selectionFactory;
5457

58+
/**
59+
* Tax helper, needed to get rounding setting
60+
*
61+
* @var TaxHelper
62+
*/
63+
protected $taxHelper;
5564
/**
5665
* @param CalculatorBase $calculator
5766
* @param AmountFactory $amountFactory
5867
* @param BundleSelectionFactory $bundleSelectionFactory
68+
* @param TaxHelper $taxHelper
5969
* @return Calculator
6070
*/
6171
public function __construct(
6272
CalculatorBase $calculator,
6373
AmountFactory $amountFactory,
64-
BundleSelectionFactory $bundleSelectionFactory
74+
BundleSelectionFactory $bundleSelectionFactory,
75+
TaxHelper $taxHelper
6576
) {
6677
$this->calculator = $calculator;
6778
$this->amountFactory = $amountFactory;
6879
$this->selectionFactory = $bundleSelectionFactory;
80+
$this->taxHelper = $taxHelper;
6981
}
7082

7183
/**
@@ -254,11 +266,24 @@ protected function calculateDynamicBundleAmount($basePriceValue, $bundleProduct,
254266
foreach ($selectionPriceList as $selectionPrice) {
255267
$amountList[] = $selectionPrice->getAmount();
256268
}
269+
/** @var Store $store */
270+
$store = $bundleProduct->getStore();
271+
$roundingMethod = $this->taxHelper->getCalculationAgorithm($store);
257272
/** @var \Magento\Framework\Pricing\Amount\AmountInterface $itemAmount */
258273
foreach ($amountList as $itemAmount) {
259-
$fullAmount += $itemAmount->getValue();
260-
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
261-
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
274+
if ($roundingMethod != TaxCalculation::CALC_TOTAL_BASE) {
275+
//We need to round the individual selection first
276+
$fullAmount += $store->roundPrice($itemAmount->getValue());
277+
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
278+
$adjustment = $store->roundPrice($adjustment);
279+
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
280+
}
281+
} else {
282+
$fullAmount += $itemAmount->getValue();
283+
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
284+
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
285+
}
286+
262287
}
263288
}
264289
if ($exclude && isset($adjustments[$exclude])) {

app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle.phtml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
$(document).ready(function() {
3333
$('#product_addtocart_form').mage('bundleOption', {
3434
"bundleConfig": <?php echo $this->getJsonConfig() ?>,
35+
"roundingMethod" : "<?php echo $this->getRoundingMethod() ?>",
3536
"bundleOptionQtyPrefix": "#bundle-option-",
3637
"bundleOptionQtySuffix": "-qty-input",
3738
"priceSelectors": {

app/code/Magento/Bundle/view/frontend/web/bundle.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,10 @@
251251
},
252252

253253
selectionPrice: function(optionId, selectionId) {
254+
//Those constants need to be in sync with Magento\Bundle\Block\Catalog\Product\View\Type\Bundle
255+
var TOTAL_ROUNDING = 2;
256+
var ROW_ROUNDING = 1;
257+
var UNIT_ROUNDING = 0;
254258
var qty = null,
255259
config = this.options.bundleConfig,
256260
configOption = config.options[optionId];
@@ -281,7 +285,19 @@
281285
});
282286
}
283287

284-
return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty];
288+
if (this.options.bundleConfig.isFixedPrice || this.options.roundingMethod == TOTAL_ROUNDING) {
289+
return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty];
290+
} else if (this.options.roundingMethod == UNIT_ROUNDING) {
291+
price = Math.round(price * 100) / 100;
292+
exclTaxPrice = Math.round(exclTaxPrice * 100) / 100;
293+
inclTaxPrice = Math.round(inclTaxPrice * 100) / 100;
294+
return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty];
295+
} else {
296+
var rowTotal = Math.round(price * qty * 100) /100;
297+
var rowTotalExclTax = Math.round(exclTaxPrice * qty * 100) /100;
298+
var rowTotalInclTax = Math.round(inclTaxPrice * qty * 100) /100;
299+
return [rowTotal, rowTotalExclTax, rowTotalInclTax];
300+
}
285301
},
286302

287303
populateQty: function(optionId, selectionId) {

app/code/Magento/Catalog/Block/Product/View.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ public function getJsonConfig()
236236
return $this->_jsonEncoder->encode($config);
237237
}
238238

239-
$request = $this->_taxCalculation->getRateRequest(false, false, false);
239+
$request = $this->_taxCalculation->getDefaultRateRequest();
240240
/* @var $product \Magento\Catalog\Model\Product */
241241
$product = $this->getProduct();
242242
$request->setProductClassId($product->getTaxClassId());

app/code/Magento/Catalog/Model/Product/Attribute/Backend/Groupprice/AbstractGroupprice.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ public function validate($object)
169169
if (isset($duplicates[$compare])) {
170170
throw new \Magento\Framework\Model\Exception($this->_getDuplicateErrorMessage());
171171
}
172+
173+
if (!preg_match('/^\d*(\.|,)?\d{0,4}$/i', $priceRow['price']) || $priceRow['price'] < 0) {
174+
return __('Group price must be a number greater than 0.');
175+
}
176+
172177
$duplicates[$compare] = true;
173178
}
174179

app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ public function afterSave($object)
346346

347347
$this->_getResource()->deleteGallery($recordsToDelete);
348348
$this->removeDeletedImages($filesToDelete);
349+
$object->setData($attrCode, $value);
349350
}
350351

351352
/**
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
/**
3+
* Magento
4+
*
5+
* NOTICE OF LICENSE
6+
*
7+
* This source file is subject to the Open Software License (OSL 3.0)
8+
* that is bundled with this package in the file LICENSE.txt.
9+
* It is also available through the world-wide-web at this URL:
10+
* http://opensource.org/licenses/osl-3.0.php
11+
* If you did not receive a copy of the license and are unable to
12+
* obtain it through the world-wide-web, please send an email
13+
* to license@magentocommerce.com so we can send you a copy immediately.
14+
*
15+
* DISCLAIMER
16+
*
17+
* Do not edit or add to this file if you wish to upgrade Magento to newer
18+
* versions in the future. If you wish to customize Magento for your
19+
* needs please refer to http://www.magentocommerce.com for more information.
20+
*
21+
* @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
22+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
23+
*/
24+
25+
namespace Magento\Catalog\Model\Product;
26+
27+
use Magento\Framework\Exception\NoSuchEntityException;
28+
use Magento\Framework\Exception\CouldNotSaveException;
29+
30+
class PriceModifier
31+
{
32+
/**
33+
* @param \Magento\Catalog\Model\Product $product
34+
* @param int $customerGroupId
35+
* @param int $websiteId
36+
* @throws \Magento\Framework\Exception\NoSuchEntityException
37+
* @throws \Magento\Framework\Exception\CouldNotSaveException
38+
* @return void
39+
*/
40+
public function removeGroupPrice(\Magento\Catalog\Model\Product $product, $customerGroupId, $websiteId)
41+
{
42+
$prices = $product->getData('group_price');
43+
if (is_null($prices)) {
44+
throw new NoSuchEntityException("This product doesn't have group price");
45+
}
46+
$groupPriceQty = count($prices);
47+
48+
foreach ($prices as $key => $groupPrice) {
49+
if ($groupPrice['cust_group'] == $customerGroupId
50+
&& intval($groupPrice['website_id']) === intval($websiteId)) {
51+
unset ($prices[$key]);
52+
}
53+
}
54+
if ($groupPriceQty == count($prices)) {
55+
throw new NoSuchEntityException(
56+
"Product hasn't group price with such data: customerGroupId = '$customerGroupId',"
57+
. "website = $websiteId."
58+
);
59+
}
60+
$product->setData('group_price', $prices);
61+
try {
62+
$product->save();
63+
} catch (\Exception $exception) {
64+
throw new CouldNotSaveException("Invalid data provided for group price");
65+
}
66+
}
67+
68+
/**
69+
* @param \Magento\Catalog\Model\Product $product
70+
* @param int|string $customerGroupId
71+
* @param int $qty
72+
* @param int $websiteId
73+
* @throws \Magento\Framework\Exception\NoSuchEntityException
74+
* @throws \Magento\Framework\Exception\CouldNotSaveException
75+
* @return void
76+
*/
77+
public function removeTierPrice(\Magento\Catalog\Model\Product $product, $customerGroupId, $qty, $websiteId)
78+
{
79+
$prices = $product->getData('tier_price');
80+
// verify if price exist
81+
if (is_null($prices)) {
82+
throw new NoSuchEntityException("This product doesn't have tier price");
83+
}
84+
$tierPricesQty = count($prices);
85+
86+
foreach ($prices as $key => $tierPrice) {
87+
if ($customerGroupId == 'all' && $tierPrice['price_qty'] == $qty
88+
&& $tierPrice['all_groups'] == 1 && intval($tierPrice['website_id']) === intval($websiteId)) {
89+
unset ($prices[$key]);
90+
} elseif ($tierPrice['price_qty'] == $qty && $tierPrice['cust_group'] == $customerGroupId
91+
&& intval($tierPrice['website_id']) === intval($websiteId)) {
92+
unset ($prices[$key]);
93+
}
94+
}
95+
96+
if ($tierPricesQty == count($prices)) {
97+
throw new NoSuchEntityException(
98+
"Product hasn't group price with such data: customerGroupId = '$customerGroupId',"
99+
. "website = $websiteId, qty = $qty"
100+
);
101+
}
102+
$product->setData('tier_price', $prices);
103+
try {
104+
$product->save();
105+
} catch (\Exception $exception) {
106+
throw new CouldNotSaveException("Invalid data provided for tier_price");
107+
}
108+
}
109+
}

0 commit comments

Comments
 (0)