Completed
Push — master ( 888d0b...6476e7 )
by
unknown
04:54
created

Mygento_Payture_Helper_Discount::_checkReceipt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
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
    protected $_code = 'payture';
13
14
    /** Returns item's data as array with properly calculated discount
15
     * @param $entity Mage_Sales_Model_Order | Mage_Sales_Model_Order_Invoice | Mage_Sales_Model_Order_Creditmemo
16
     * @param $itemSku
17
     * @param string $taxValue
18
     * @param string $taxAttributeCode
19
     * @param string $shippingTaxValue
20
     * @return array|mixed
21
     */
22
    public function getItemWithDiscount($entity, $itemSku, $taxValue = '', $taxAttributeCode = '', $shippingTaxValue = '')
23
    {
24
        $items = $this->getRecalculated($entity, $taxValue, $taxAttributeCode, $shippingTaxValue)['items'];
25
26
        return isset($items[$itemSku]) ? $items[$itemSku] : [];
27
    }
28
29
    /** Returns all items of the entity (order|invoice|creditmemo) with properly calculated discount and properly calculated Sum
30
     * @param $entity Mage_Sales_Model_Order | Mage_Sales_Model_Order_Invoice | Mage_Sales_Model_Order_Creditmemo
31
     * @param string $taxValue
32
     * @param string $taxAttributeCode Set it if info about tax is stored in product in certain attr
33
     * @param string $shippingTaxValue
34
     * @return array with calculated items and sum
35
     */
36
    public function getRecalculated($entity, $taxValue = '', $taxAttributeCode = '', $shippingTaxValue = '')
37
    {
38
        $generalHelper = Mage::helper($this->_code);
39
        $generalHelper->addLog("== START == Recalculation of entity prices. Entity class: " . get_class($entity) . ". Entity id: {$entity->getId()}");
40
41
        $subTotal       = $entity->getData('subtotal');
42
        $shippingAmount = $entity->getData('shipping_amount');
43
        $grandTotal     = $entity->getData('grand_total');
44
        $grandDiscount  = $grandTotal-$subTotal-$shippingAmount;
45
46
        $percentageSum = 0;
47
48
        $items      = $entity->getAllVisibleItems() ? $entity->getAllVisibleItems() : $entity->getAllItems();
49
        $itemsFinal = [];
50
        $itemsSum   = 0.00;
51
        foreach ($items as $item) {
52
            if (!$this->isValidItem($item)) {
53
                continue;
54
            }
55
56
            if ($taxAttributeCode) {
57
                $storeId  = $entity->getStoreId();
58
                $store    = $storeId ? Mage::app()->getStore($storeId) : Mage::app()->getStore();
59
60
                $taxValue = Mage::getResourceModel('catalog/product')->getAttributeRawValue(
61
                    $item->getProductId(),
62
                    $taxAttributeCode,
63
                    $store
64
                );
65
            }
66
67
            $price    = $item->getData('price');
68
            $qty      = $item->getQty() ?: $item->getQtyOrdered();
69
            $rowTotal = $item->getData('row_total');
70
71
            //Calculate Percentage. The heart of logic.
72
            $rowPercentage =  $rowTotal / $subTotal;
73
            $percentageSum += $rowPercentage;
74
75
            $discountPerUnit = $rowPercentage * $grandDiscount / $qty;
76
            $priceWithDiscount = $this->slyFloor($price + $discountPerUnit);
77
78
            $entityItem = $this->_buildItem($item, $priceWithDiscount, $taxValue);
79
80
            $itemsFinal[$item->getSku()] = $entityItem;
81
            $itemsSum += $entityItem['sum'];
82
        }
83
84
        $generalHelper->addLog("Sum of all percentages: {$percentageSum}");
85
86
        //Calculate DIFF!
87
        $itemsSumDiff = $this->slyFloor($grandTotal - $itemsSum - $shippingAmount);
88
89
        $generalHelper->addLog("Items sum: {$itemsSum}. All Discounts: {$grandDiscount} Diff value: {$itemsSumDiff}");
90
        if (bccomp($itemsSumDiff, 0.00, 2) < 0) {
91
            //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...
92
            $generalHelper->addLog("Notice: Sum of all items is greater than sumWithAllDiscount of entity. ItemsSumDiff: {$itemsSumDiff}");
93
            $itemsSumDiff = 0.0;
94
        }
95
96
        $receipt = [
97
            'sum'            => $itemsSum,
98
            'origGrandTotal' => floatval($grandTotal)
99
        ];
100
101
        $shippingName = $entity->getShippingDescription()
102
            ?: ($entity->getOrder() ? $entity->getOrder()->getShippingDescription() : '');
103
104
        $shippingItem = [
105
            'name'      => $shippingName,
106
            'price'     => $entity->getShippingAmount() + $itemsSumDiff,
107
            'quantity'  => 1.0,
108
            'sum'       => $entity->getShippingAmount() + $itemsSumDiff,
109
            'tax'       => $shippingTaxValue,
110
        ];
111
112
        $itemsFinal['shipping'] = $shippingItem;
113
        $receipt['items']       = $itemsFinal;
114
115
        if (!$this->_checkReceipt($receipt)) {
116
            $generalHelper->addLog("WARNING: Calculation error! Sum of items is not equal to grandTotal!");
117
        }
118
        $generalHelper->addLog("Final result of recalculation:");
119
        $generalHelper->addLog($receipt);
120
        $generalHelper->addLog("== STOP == Recalculation of entity prices. ");
121
122
        return $receipt;
123
    }
124
125
    protected function _buildItem($item, $price, $taxValue = '')
126
    {
127
        $generalHelper = Mage::helper($this->_code);
128
129
        $qty = $item->getQty() ?: $item->getQtyOrdered();
130
        if (!$qty) {
131
            throw new Exception('Divide by zero. Qty of the item is equal to zero! Item: ' . $item->getId());
132
        }
133
134
        $entityItem = [
135
            'price' => round($price, 2),
136
            'name' => $item->getName(),
137
            'quantity' => round($qty, 2),
138
            'sum' => round($price * $qty, 2),
139
            'tax' => $taxValue,
140
        ];
141
142
        $generalHelper->addLog("Item calculation details:");
143
        $generalHelper->addLog("Item id: {$item->getId()}. Orig price: {$price} Item rowTotal: {$item->getRowTotal()} Price of 1 piece: {$price}. Result of calc:");
144
        $generalHelper->addLog($entityItem);
145
146
        return $entityItem;
147
    }
148
149
    /**Validation method. It sums up all items and compares it to grandTotal.
150
     * @param array $receipt
151
     * @return bool True if all items price equal to grandTotal. False - if not.
152
     */
153
    protected function _checkReceipt(array $receipt)
154
    {
155
        $sum = array_reduce($receipt['items'], function ($carry, $item) {
156
            $carry += $item['sum'];
157
            return $carry;
158
        });
159
160
        return bcsub($sum, $receipt['origGrandTotal'], 2) === '0.00';
161
    }
162
163
    public function isValidItem($item)
164
    {
165
        return $item->getRowTotal() && $item->getRowTotal() !== '0.0000';
166
    }
167
168
    public function slyFloor($val, $precision = 2)
169
    {
170
        $factor  = 1.00;
171
        $divider = pow(10, $precision);
172
173
        if ($val < 0) {
174
            $factor = -1.00;
175
        }
176
177
        return (floor(abs($val) * $divider) / $divider) * $factor;
178
    }
179
}
180