Completed
Push — master ( fbcd5b...3da751 )
by
unknown
02:08
created

Mygento_Payture_Helper_Discount   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 0
dl 0
loc 187
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getItemWithDiscount() 0 6 2
C getRecalculated() 0 76 8
A _buildItem() 0 23 3
A getShippingName() 0 5 3
A _checkReceipt() 0 9 1
A isValidItem() 0 4 2
A slyFloor() 0 11 2
A addTaxValue() 0 20 4
1
<?php
2
3
/**
4
 *
5
 *
6
 * @category Mygento
7
 * @package Mygento_Payture
8
 * @copyright 2017 NKS LLC. (https://www.mygento.ru)
9
 */
10
class Mygento_Payture_Helper_Discount extends Mage_Core_Helper_Abstract
11
{
12
    const VERSION = '1.0.3';
13
14
    protected $_code = 'payture';
15
16
    /** Returns item's data as array with properly calculated discount
17
     * @param $entity Mage_Sales_Model_Order | Mage_Sales_Model_Order_Invoice | Mage_Sales_Model_Order_Creditmemo
18
     * @param $itemSku
19
     * @param string $taxValue
20
     * @param string $taxAttributeCode
21
     * @param string $shippingTaxValue
22
     * @return array|mixed
23
     */
24
    public function getItemWithDiscount($entity, $itemSku, $taxValue = '', $taxAttributeCode = '', $shippingTaxValue = '')
25
    {
26
        $items = $this->getRecalculated($entity, $taxValue, $taxAttributeCode, $shippingTaxValue)['items'];
27
28
        return isset($items[$itemSku]) ? $items[$itemSku] : [];
29
    }
30
31
    /** Returns all items of the entity (order|invoice|creditmemo) with properly calculated discount and properly calculated Sum
32
     * @param $entity Mage_Sales_Model_Order | Mage_Sales_Model_Order_Invoice | Mage_Sales_Model_Order_Creditmemo
33
     * @param string $taxValue
34
     * @param string $taxAttributeCode Set it if info about tax is stored in product in certain attr
35
     * @param string $shippingTaxValue
36
     * @return array with calculated items and sum
37
     */
38
    public function getRecalculated($entity, $taxValue = '', $taxAttributeCode = '', $shippingTaxValue = '')
39
    {
40
        $generalHelper = Mage::helper($this->_code);
41
        $generalHelper->addLog("== START == Recalculation of entity prices. Entity class: " . get_class($entity) . ". Entity id: {$entity->getId()}");
42
43
        $subTotal       = $entity->getData('subtotal');
44
        $shippingAmount = $entity->getData('shipping_amount');
45
        $grandTotal     = $entity->getData('grand_total');
46
        $grandDiscount  = $grandTotal-$subTotal-$shippingAmount;
47
48
        $percentageSum = 0;
49
50
        $items      = $entity->getAllVisibleItems() ? $entity->getAllVisibleItems() : $entity->getAllItems();
51
        $itemsFinal = [];
52
        $itemsSum   = 0.00;
53
        foreach ($items as $item) {
54
            if (!$this->isValidItem($item)) {
55
                continue;
56
            }
57
58
            $taxValue = $taxAttributeCode ? $this->addTaxValue($taxAttributeCode, $entity, $item) : $taxValue;
59
60
            $price    = $item->getData('price');
61
            $qty      = $item->getQty() ?: $item->getQtyOrdered();
62
            $rowTotal = $item->getData('row_total');
63
64
            //Calculate Percentage. The heart of logic.
65
            $rowPercentage =  $rowTotal / $subTotal;
66
            $percentageSum += $rowPercentage;
67
68
            $discountPerUnit = $rowPercentage * $grandDiscount / $qty;
69
            $priceWithDiscount = $this->slyFloor($price + $discountPerUnit);
70
71
            $entityItem = $this->_buildItem($item, $priceWithDiscount, $taxValue);
72
73
            $itemsFinal[$item->getId()] = $entityItem;
74
            $itemsSum += $entityItem['sum'];
75
        }
76
77
        $generalHelper->addLog("Sum of all percentages: {$percentageSum}");
78
79
        //Calculate DIFF!
80
        $itemsSumDiff = round($this->slyFloor($grandTotal - $itemsSum - $shippingAmount, 3), 2);
81
82
        $generalHelper->addLog("Items sum: {$itemsSum}. All Discounts: {$grandDiscount} Diff value: {$itemsSumDiff}");
83
        if (bccomp($itemsSumDiff, 0.00, 2) < 0) {
84
            //if: $itemsSumDiff < 0
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
85
            $generalHelper->addLog("Notice: Sum of all items is greater than sumWithAllDiscount of entity. ItemsSumDiff: {$itemsSumDiff}");
86
            $itemsSumDiff = 0.0;
87
        }
88
89
        $receipt = [
90
            'sum'            => $itemsSum,
91
            'origGrandTotal' => floatval($grandTotal)
92
        ];
93
94
        $shippingItem = [
95
            'name'      => $this->getShippingName($entity),
96
            'price'     => $entity->getShippingAmount() + $itemsSumDiff,
97
            'quantity'  => 1.0,
98
            'sum'       => $entity->getShippingAmount() + $itemsSumDiff,
99
            'tax'       => $shippingTaxValue,
100
        ];
101
102
        $itemsFinal['shipping'] = $shippingItem;
103
        $receipt['items']       = $itemsFinal;
104
105
        if (!$this->_checkReceipt($receipt)) {
106
            $generalHelper->addLog("WARNING: Calculation error! Sum of items is not equal to grandTotal!");
107
        }
108
        $generalHelper->addLog("Final result of recalculation:");
109
        $generalHelper->addLog($receipt);
110
        $generalHelper->addLog("== STOP == Recalculation of entity prices. ");
111
112
        return $receipt;
113
    }
114
115
    protected function _buildItem($item, $price, $taxValue = '')
116
    {
117
        $generalHelper = Mage::helper($this->_code);
118
119
        $qty = $item->getQty() ?: $item->getQtyOrdered();
120
        if (!$qty) {
121
            throw new Exception('Divide by zero. Qty of the item is equal to zero! Item: ' . $item->getId());
122
        }
123
124
        $entityItem = [
125
            'price' => round($price, 2),
126
            'name' => $item->getName(),
127
            'quantity' => round($qty, 2),
128
            'sum' => round($price * $qty, 2),
129
            'tax' => $taxValue,
130
        ];
131
132
        $generalHelper->addLog("Item calculation details:");
133
        $generalHelper->addLog("Item id: {$item->getId()}. Orig price: {$price} Item rowTotal: {$item->getRowTotal()} Price of 1 piece: {$price}. Result of calc:");
134
        $generalHelper->addLog($entityItem);
135
136
        return $entityItem;
137
    }
138
139
    public function getShippingName($entity)
140
    {
141
        return $entity->getShippingDescription()
142
            ?: ($entity->getOrder() ? $entity->getOrder()->getShippingDescription() : '');
143
    }
144
145
    /**Validation method. It sums up all items and compares it to grandTotal.
146
     * @param array $receipt
147
     * @return bool True if all items price equal to grandTotal. False - if not.
148
     */
149
    protected function _checkReceipt(array $receipt)
150
    {
151
        $sum = array_reduce($receipt['items'], function ($carry, $item) {
152
            $carry += $item['sum'];
153
            return $carry;
154
        });
155
156
        return bcsub($sum, $receipt['origGrandTotal'], 2) === '0.00';
157
    }
158
159
    public function isValidItem($item)
160
    {
161
        return $item->getRowTotal() && $item->getRowTotal() !== '0.0000';
162
    }
163
164
    public function slyFloor($val, $precision = 2)
165
    {
166
        $factor  = 1.00;
167
        $divider = pow(10, $precision);
168
169
        if ($val < 0) {
170
            $factor = -1.00;
171
        }
172
173
        return (floor(abs($val) * $divider) / $divider) * $factor;
174
    }
175
    
176
    protected function addTaxValue($taxAttributeCode, $entity, $item)
177
    {
178
        if (!$taxAttributeCode) {
179
            return '';
180
        }
181
        $storeId  = $entity->getStoreId();
182
        $store    = $storeId ? Mage::app()->getStore($storeId) : Mage::app()->getStore();
183
184
        $taxValue = Mage::getResourceModel('catalog/product')->getAttributeRawValue(
185
            $item->getProductId(),
186
            $taxAttributeCode,
187
            $store
188
        );
189
190
        $attributeModel = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $taxAttributeCode);
191
        if ($attributeModel->getData('frontend_input') == 'select') {
192
            $taxValue = $attributeModel->getSource()->getOptionText($taxValue);
193
        }
194
        return $taxValue;
195
    }
196
}