Spranks_ConfigurableTierPrices - Version 2.0.0

Version Notes

Removed rewrite, now only uses events, implemented unit tests, dropped support for < 1.7

Download this release

Release Info

Developer Simon Sprankel
Extension Spranks_ConfigurableTierPrices
Version 2.0.0
Comparing to
See all releases


Code changes from version 1.0.1 to 2.0.0

app/code/community/Spranks/ConfigurableTierPrices/Helper/Admin.php CHANGED
@@ -11,7 +11,8 @@ class Spranks_ConfigurableTierPrices_Helper_Admin extends Mage_Core_Helper_Abstr
11
  if (Mage::getDesign()->getArea() == 'adminhtml') {
12
  return true;
13
  }
 
14
  return false;
15
  }
16
 
17
- }
11
  if (Mage::getDesign()->getArea() == 'adminhtml') {
12
  return true;
13
  }
14
+
15
  return false;
16
  }
17
 
18
+ }
app/code/community/Spranks/ConfigurableTierPrices/Model/{Product/Type/Configurable/Price.php → Observer.php} RENAMED
@@ -1,35 +1,32 @@
1
  <?php
2
 
3
- class Spranks_ConfigurableTierPrices_Model_Product_Type_Configurable_Price extends Mage_Catalog_Model_Product_Type_Configurable_Price
4
  {
5
 
6
  /**
7
- * Get product final price
8
  *
9
- * @param double $qty
10
- * @param Mage_Catalog_Model_Product $product
11
- * @return double
12
  */
13
- public function getFinalPrice($qty = null, $product)
14
  {
15
- $finalPrice = parent::getFinalPrice($qty, $product);
16
  // do not calculate tier prices based on cart items on product page
17
  // see https://github.com/sprankhub/Spranks_ConfigurableTierPrices/issues/14
18
- if (Mage::registry('current_product')) {
19
- return $finalPrice;
20
  }
21
  // if tier prices are defined, also adapt them to configurable products
22
- // example: if a shirt is available in red and black and if you buy
23
- // three or more the price is eight euro, you can also buy one red and
24
- // two black shirts and you will get the tier price of eight euro.
25
- // based on https://www.magentocommerce.com/boards/viewthread/10743/
26
  if ($product->getTierPriceCount() > 0) {
27
  $tierPrice = $this->_calcConfigProductTierPricing($product);
28
- if ($tierPrice < $finalPrice) {
29
- $finalPrice = $tierPrice;
30
  }
31
  }
32
- return $finalPrice;
 
33
  }
34
 
35
  /**
@@ -37,9 +34,10 @@ class Spranks_ConfigurableTierPrices_Model_Product_Type_Configurable_Price exten
37
  * Uses qty of parent item to determine price.
38
  *
39
  * @param Mage_Catalog_Model_Product $product
 
40
  * @return float
41
  */
42
- protected function _calcConfigProductTierPricing($product)
43
  {
44
  $tierPrice = PHP_INT_MAX;
45
 
@@ -59,14 +57,20 @@ class Spranks_ConfigurableTierPrices_Model_Product_Type_Configurable_Price exten
59
  }
60
  // compute the total quantity of items of the configurable product
61
  if (array_key_exists($product->getId(), $idQuantities)) {
62
- $totalQty = array_sum($idQuantities[$product->getId()]);
63
- $tierPrice = parent::getFinalPrice($totalQty, $product);
64
  }
65
  }
 
66
  return $tierPrice;
67
  }
68
 
69
- protected function _getAllVisibleItems()
 
 
 
 
 
70
  {
71
  if (Mage::helper('spranks_configurabletierprices/admin')->isAdmin()) {
72
  return Mage::getSingleton('adminhtml/session_quote')->getQuote()->getAllVisibleItems();
1
  <?php
2
 
3
+ class Spranks_ConfigurableTierPrices_Model_Observer
4
  {
5
 
6
  /**
7
+ * Applies the tier pricing structure across different variants of configurable products.
8
  *
9
+ * @param Varien_Event_Observer $observer
10
+ *
11
+ * @return Spranks_ConfigurableTierPrices_Model_Observer
12
  */
13
+ public function catalogProductGetFinalPrice(Varien_Event_Observer $observer)
14
  {
15
+ $product = $observer->getProduct();
16
  // do not calculate tier prices based on cart items on product page
17
  // see https://github.com/sprankhub/Spranks_ConfigurableTierPrices/issues/14
18
+ if (Mage::registry('current_product') || ! $product->isConfigurable()) {
19
+ return $this;
20
  }
21
  // if tier prices are defined, also adapt them to configurable products
 
 
 
 
22
  if ($product->getTierPriceCount() > 0) {
23
  $tierPrice = $this->_calcConfigProductTierPricing($product);
24
+ if ($tierPrice < $product->getData('final_price')) {
25
+ $product->setData('final_price', $tierPrice);
26
  }
27
  }
28
+
29
+ return $this;
30
  }
31
 
32
  /**
34
  * Uses qty of parent item to determine price.
35
  *
36
  * @param Mage_Catalog_Model_Product $product
37
+ *
38
  * @return float
39
  */
40
+ private function _calcConfigProductTierPricing($product)
41
  {
42
  $tierPrice = PHP_INT_MAX;
43
 
57
  }
58
  // compute the total quantity of items of the configurable product
59
  if (array_key_exists($product->getId(), $idQuantities)) {
60
+ $totalQty = array_sum($idQuantities[$product->getId()]);
61
+ $tierPrice = $product->getPriceModel()->getBasePrice($product, $totalQty);
62
  }
63
  }
64
+
65
  return $tierPrice;
66
  }
67
 
68
+ /**
69
+ * Retrieves all visible quote items from the session.
70
+ *
71
+ * @return array with instances of Mage_Sales_Model_Quote_Item
72
+ */
73
+ private function _getAllVisibleItems()
74
  {
75
  if (Mage::helper('spranks_configurabletierprices/admin')->isAdmin()) {
76
  return Mage::getSingleton('adminhtml/session_quote')->getQuote()->getAllVisibleItems();
app/code/community/Spranks/ConfigurableTierPrices/Test/Config/Main.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Spranks_ConfigurableTierPrices_Test_Config_Main extends EcomDev_PHPUnit_Test_Case_Config
4
+ {
5
+
6
+ /**
7
+ * Check it the installed module has the correct module version
8
+ */
9
+ public function testModuleConfig()
10
+ {
11
+ $this->assertModuleVersionGreaterThanOrEquals($this->expected('module')->getVersion(), 'module is new enough');
12
+ $this->assertModuleCodePool($this->expected('module')->getCodePool(), 'correct module code pool');
13
+ $this->assertModuleIsActive('module is active');
14
+ }
15
+
16
+ /**
17
+ * Check if the helper aliases are returning the correct class names
18
+ */
19
+ public function testHelperAliases()
20
+ {
21
+ $this->assertHelperAlias(
22
+ 'spranks_configurabletierprices/admin', 'Spranks_ConfigurableTierPrices_Helper_Admin',
23
+ 'correct helper alias'
24
+ );
25
+ }
26
+
27
+ /**
28
+ * Check if the helper aliases are returning the correct class names
29
+ */
30
+ public function testModelAliases()
31
+ {
32
+ $this->assertModelAlias(
33
+ 'spranks_configurabletierprices/observer', 'Spranks_ConfigurableTierPrices_Model_Observer',
34
+ 'correct model alias'
35
+ );
36
+ }
37
+
38
+ }
app/code/community/Spranks/ConfigurableTierPrices/Test/Config/Main/expectations/testModuleConfig.yaml ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ module:
2
+ version: 2.0.0
3
+ code_pool: community
app/code/community/Spranks/ConfigurableTierPrices/Test/Model/ObserverTest.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Spranks_ConfigurableTierPrices_Test_Model_ObserverTest extends EcomDev_PHPUnit_Test_Case
4
+ {
5
+
6
+ /**
7
+ * Mock session singletons, set default store and fix session problems.
8
+ */
9
+ protected function setUp()
10
+ {
11
+ parent::setUp();
12
+ // mock core session
13
+ $mockCoreSession = $this->getModelMockBuilder('core/session')
14
+ ->disableOriginalConstructor()
15
+ ->setMethods(null)
16
+ ->getMock();
17
+ $this->replaceByMock('singleton', 'core/session', $mockCoreSession);
18
+
19
+ // mock checkout session
20
+ $mockCheckoutSession = $this->getModelMockBuilder('checkout/session')
21
+ ->disableOriginalConstructor()
22
+ ->setMethods(null)
23
+ ->getMock();
24
+ $this->replaceByMock('singleton', 'checkout/session', $mockCheckoutSession);
25
+
26
+ $this->app()->setCurrentStore('default');
27
+ // somehow needed to avoid exceptions of type "Cannot send session cookie - headers already sent by"
28
+ @session_start();
29
+ }
30
+
31
+ /**
32
+ * Revert to admin store and fix session problems.
33
+ */
34
+ protected function tearDown()
35
+ {
36
+ // somehow needed to avoid exceptions of type "Failed to write session data"
37
+ @session_destroy();
38
+ $this->setCurrentStore('admin');
39
+ }
40
+
41
+ /**
42
+ * @test
43
+ * @loadFixture createProducts
44
+ * @doNotIndexAll
45
+ */
46
+ public function testProduct1Pricing()
47
+ {
48
+ $product = Mage::getModel('catalog/product')->load(1);
49
+ $this->assertEquals(20.0, $product->getFinalPrice(1), 'test normal price');
50
+ $this->assertEventDispatched('catalog_product_get_final_price');
51
+ }
52
+
53
+ /**
54
+ * @test
55
+ * @loadFixture createProducts
56
+ * @doNotIndexAll
57
+ */
58
+ public function testProduct1TierPricing()
59
+ {
60
+ $product = Mage::getModel('catalog/product')->load(1);
61
+ $this->assertEquals(18.0, $product->getFinalPrice(2), 'test tier price');
62
+ $this->assertEventDispatched('catalog_product_get_final_price');
63
+ }
64
+
65
+ /**
66
+ * @test
67
+ * @loadFixture createProducts
68
+ * @doNotIndexAll
69
+ * @singleton checkout/cart
70
+ */
71
+ public function testProduct1CartPricing()
72
+ {
73
+ $cart = Mage::getSingleton('checkout/cart');
74
+ $cart->init();
75
+ $cart->addProduct(
76
+ 1, array(
77
+ 'super_attribute' => array(
78
+ 92 => 3
79
+ ),
80
+ 'qty' => 1
81
+ )
82
+ );
83
+ $cart->save();
84
+ $cart->getQuote()->collectTotals();
85
+ $this->assertEquals(20, $cart->getQuote()->getGrandTotal(), 'test normal price in cart');
86
+ }
87
+
88
+ /**
89
+ * @test
90
+ * @loadFixture createProducts
91
+ * @doNotIndexAll
92
+ * @singleton checkout/cart
93
+ */
94
+ public function testProduct1CartTierPricing()
95
+ {
96
+ $cart = Mage::getSingleton('checkout/cart');
97
+ $cart->init();
98
+ $cart->addProduct(1, array(
99
+ 'super_attribute' => array(
100
+ 92 => 3
101
+ ),
102
+ 'qty' => 1
103
+ ));
104
+ $cart->addProduct(1, array(
105
+ 'super_attribute' => array(
106
+ 92 => 4
107
+ ),
108
+ 'qty' => 1
109
+ ));
110
+ $cart->save();
111
+ $cart->getQuote()->collectTotals();
112
+ $this->assertEquals(36, $cart->getQuote()->getGrandTotal(), 'test tier price in cart');
113
+ }
114
+
115
+ /**
116
+ * @test
117
+ * @loadFixture createProducts
118
+ * @doNotIndexAll
119
+ */
120
+ public function testProduct1AdminPricing()
121
+ {
122
+ // TODO implement test
123
+ }
124
+
125
+ /**
126
+ * @test
127
+ * @loadFixture createProducts
128
+ * @doNotIndexAll
129
+ */
130
+ public function testProduct1AdminTierPricing()
131
+ {
132
+ // TODO implement test
133
+ }
134
+
135
+ }
app/code/community/Spranks/ConfigurableTierPrices/Test/Model/ObserverTest/fixtures/createProducts.yaml ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ tables:
2
+ eav_attribute_option:
3
+ - option_id: 3
4
+ attribute_id: 92
5
+ sort_order: 0
6
+ - option_id: 4
7
+ attribute_id: 92
8
+ sort_order: 0
9
+ eav_attribute_option_value:
10
+ - value_id: 3
11
+ option_id: 3
12
+ store_id: 0
13
+ value: red
14
+ - value_id: 4
15
+ option_id: 4
16
+ store_id: 0
17
+ value: blue
18
+
19
+ eav:
20
+ catalog_product:
21
+
22
+ # Product 1 is a configurable product with tier prices
23
+ - entity_id: 1
24
+ type_id: simple
25
+ attribute_set_id: 4
26
+ name: Product One
27
+ description: A configurable test product
28
+ short_description: A configurable test product
29
+ sku: product1-red
30
+ weight: 1
31
+ status: 1 # Enabled
32
+ visibility: 1 # Not Visible Individually
33
+ price: 20.00
34
+ tier_price:
35
+ - customer_group_id: 0
36
+ qty: 2
37
+ value: 18.00
38
+ tax_class_id: 2 # Taxable Goods
39
+ stock:
40
+ qty: 9999
41
+ is_in_stock: 1
42
+ category_ids:
43
+ - 2 # Default Category
44
+ website_ids:
45
+ - base
46
+ color: red
47
+ - entity_id: 2
48
+ type_id: simple
49
+ attribute_set_id: 4
50
+ name: Product One
51
+ description: A configurable test product
52
+ short_description: A configurable test product
53
+ sku: product1-blue
54
+ weight: 1
55
+ status: 1 # Enabled
56
+ visibility: 1 # Not Visible Individually
57
+ price: 20.00
58
+ tier_price:
59
+ - customer_group_id: 0
60
+ qty: 2
61
+ value: 18.00
62
+ tax_class_id: 2 # Taxable Goods
63
+ stock:
64
+ qty: 9999
65
+ is_in_stock: 1
66
+ category_ids:
67
+ - 2 # Default Category
68
+ website_ids:
69
+ - base
70
+ color: blue
71
+ - entity_id: 3
72
+ type_id: configurable
73
+ attribute_set_id: 4
74
+ name: Product One
75
+ description: A configurable test product
76
+ short_description: A configurable test product
77
+ sku: product1
78
+ status: 1 # Enabled
79
+ visibility: 4 # Visible in Catalog & Search
80
+ price: 20.00
81
+ tier_price:
82
+ - customer_group_id: 0
83
+ qty: 2
84
+ value: 18.00
85
+ tax_class_id: 2 # Taxable Goods
86
+ stock:
87
+ is_in_stock: 1
88
+ category_ids:
89
+ - 2 # Default Category
90
+ website_ids:
91
+ - base
92
+ super_attributes:
93
+ - color
94
+ configurable_children:
95
+ - 1
96
+ - 2
97
+
98
+ # TODO Product 2 is a configurable product with tier prices and prices for each product variation
99
+
100
+ # TODO Product 3 is a configurable product with tier prices and prices for individual options
101
+
102
+ # TODO Product 4 is a configurable product with tier prices, prices for individual options and prices for each product variation
app/code/community/Spranks/ConfigurableTierPrices/etc/config.xml CHANGED
@@ -2,21 +2,36 @@
2
  <config>
3
  <modules>
4
  <Spranks_ConfigurableTierPrices>
5
- <version>1.0.1</version>
6
  </Spranks_ConfigurableTierPrices>
7
  </modules>
8
  <global>
9
  <models>
10
- <catalog>
11
- <rewrite>
12
- <product_type_configurable_price>Spranks_ConfigurableTierPrices_Model_Product_Type_Configurable_Price</product_type_configurable_price>
13
- </rewrite>
14
- </catalog>
15
  </models>
16
  <helpers>
17
  <spranks_configurabletierprices>
18
  <class>Spranks_ConfigurableTierPrices_Helper</class>
19
  </spranks_configurabletierprices>
20
  </helpers>
 
 
 
 
 
 
 
 
 
 
21
  </global>
 
 
 
 
 
 
 
22
  </config>
2
  <config>
3
  <modules>
4
  <Spranks_ConfigurableTierPrices>
5
+ <version>2.0.0</version>
6
  </Spranks_ConfigurableTierPrices>
7
  </modules>
8
  <global>
9
  <models>
10
+ <spranks_configurabletierprices>
11
+ <class>Spranks_ConfigurableTierPrices_Model</class>
12
+ </spranks_configurabletierprices>
 
 
13
  </models>
14
  <helpers>
15
  <spranks_configurabletierprices>
16
  <class>Spranks_ConfigurableTierPrices_Helper</class>
17
  </spranks_configurabletierprices>
18
  </helpers>
19
+ <events>
20
+ <catalog_product_get_final_price>
21
+ <observers>
22
+ <spranks_configurabletierprices>
23
+ <class>spranks_configurabletierprices/observer</class>
24
+ <method>catalogProductGetFinalPrice</method>
25
+ </spranks_configurabletierprices>
26
+ </observers>
27
+ </catalog_product_get_final_price>
28
+ </events>
29
  </global>
30
+ <phpunit>
31
+ <suite>
32
+ <modules>
33
+ <Spranks_ConfigurableTierPrices/>
34
+ </modules>
35
+ </suite>
36
+ </phpunit>
37
  </config>
package.xml CHANGED
@@ -1,18 +1,18 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Spranks_ConfigurableTierPrices</name>
4
- <version>1.0.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">OSL 3.0</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>This module changes the way Magento calculates tier prices of configurable products.</summary>
10
  <description>This Magento module changes the way Magento calculates tier prices of configurable products. You can now add different variants of a configurable product to the cart and you will get the tier price for the total quantity of all variants in the cart.</description>
11
- <notes>Fixed problems when using individual options</notes>
12
  <authors><author><name>Simon Sprankel</name><user>spranks</user><email>simonsprankel@gmail.com</email></author></authors>
13
- <date>2014-06-19</date>
14
- <time>07:11:36</time>
15
- <contents><target name="magecommunity"><dir name="Spranks"><dir name="ConfigurableTierPrices"><dir name="Helper"><file name="Admin.php" hash="7ec6839ca9c1fa032d493eaba60e391a"/></dir><dir name="Model"><dir name="Product"><dir name="Type"><dir name="Configurable"><file name="Price.php" hash="e3573a3695f85627f41134a7f4bec32e"/></dir></dir></dir></dir><dir name="etc"><file name="config.xml" hash="6e2341355ff596dc68fced04b4df7945"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Spranks_ConfigurableTierPrices.xml" hash="8a3f62990ce094cb7e7e6313b66d5d51"/></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Spranks_ConfigurableTierPrices</name>
4
+ <version>2.0.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">OSL 3.0</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>This module changes the way Magento calculates tier prices of configurable products.</summary>
10
  <description>This Magento module changes the way Magento calculates tier prices of configurable products. You can now add different variants of a configurable product to the cart and you will get the tier price for the total quantity of all variants in the cart.</description>
11
+ <notes>Removed rewrite, now only uses events, implemented unit tests, dropped support for &lt; 1.7</notes>
12
  <authors><author><name>Simon Sprankel</name><user>spranks</user><email>simonsprankel@gmail.com</email></author></authors>
13
+ <date>2014-12-06</date>
14
+ <time>13:04:38</time>
15
+ <contents><target name="magecommunity"><dir name="Spranks"><dir name="ConfigurableTierPrices"><dir name="Helper"><file name="Admin.php" hash="719aeec97e6a35b4bea91d82ad39aa42"/></dir><dir name="Model"><file name="Observer.php" hash="20ffa6c695961f316e70d8c2e311be51"/></dir><dir name="Test"><dir name="Config"><dir name="Main"><dir name="expectations"><file name="testModuleConfig.yaml" hash="a0728d3db36c6cd79759b78a804ae122"/></dir></dir><file name="Main.php" hash="487596affa2958576eb8f8cf8b4ade5f"/></dir><dir name="Model"><dir name="ObserverTest"><dir name="fixtures"><file name="createProducts.yaml" hash="52d581525f75a2ffc86b2a361eae8c0a"/></dir></dir><file name="ObserverTest.php" hash="268a3b1275dfe621af53c8883199839c"/></dir></dir><dir name="etc"><file name="config.xml" hash="ff110f81978feff76fb25517ee084464"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Spranks_ConfigurableTierPrices.xml" hash="8a3f62990ce094cb7e7e6313b66d5d51"/></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>