Passed
Pull Request — master (#300)
by
unknown
02:30
created

Invoice::addDiscountItem()   C

Complexity

Conditions 12
Paths 26

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 19
c 1
b 0
f 0
nc 26
nop 3
dl 0
loc 29
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * PAYONE Magento 2 Connector is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * PAYONE Magento 2 Connector is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with PAYONE Magento 2 Connector. If not, see <http://www.gnu.org/licenses/>.
16
 *
17
 * PHP version 5
18
 *
19
 * @category  Payone
20
 * @package   Payone_Magento2_Plugin
21
 * @author    FATCHIP GmbH <[email protected]>
22
 * @copyright 2003 - 2016 Payone GmbH
23
 * @license   <http://www.gnu.org/licenses/> GNU Lesser General Public License
24
 * @link      http://www.payone.de
25
 */
26
27
namespace Payone\Core\Model\Api;
28
29
use Payone\Core\Model\Api\Request\Base;
30
use Magento\Sales\Model\Order;
0 ignored issues
show
Bug introduced by
The type Magento\Sales\Model\Order was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
32
/**
33
 * Collect all invoice parameters
34
 *
35
 * @category  Payone
36
 * @package   Payone_Magento2_Plugin
37
 * @author    FATCHIP GmbH <[email protected]>
38
 * @copyright 2003 - 2016 Payone GmbH
39
 * @license   <http://www.gnu.org/licenses/> GNU Lesser General Public License
40
 * @link      http://www.payone.de
41
 */
42
class Invoice
43
{
44
    /**
45
     * Index of added invoice items
46
     *
47
     * @var integer
48
     */
49
    protected $iIndex = 1;
50
51
    /**
52
     * Invoice amount
53
     *
54
     * @var integer
55
     */
56
    protected $dAmount = 0;
57
58
    /**
59
     * Vat rate for following entities which may not have the vat attached to it
60
     *
61
     * @var double
62
     */
63
    protected $dTax = false;
64
65
    /**
66
     * PAYONE toolkit helper
67
     *
68
     * @var \Payone\Core\Helper\Toolkit
69
     */
70
    protected $toolkitHelper;
71
72
    /**
73
     * PAYONE amasty helper
74
     *
75
     * @var \Payone\Core\Helper\AmastyGiftcard
76
     */
77
    protected $amastyHelper;
78
79
    /**
80
     * Request object
81
     *
82
     * @var Base
83
     */
84
    protected $oRequest;
85
86
    /**
87
     * Constructor
88
     *
89
     * @param \Payone\Core\Helper\Toolkit $toolkitHelper Toolkit helper
90
     */
91
    public function __construct(\Payone\Core\Helper\Toolkit $toolkitHelper, \Payone\Core\Helper\AmastyGiftcard $amastyHelper)
92
    {
93
        $this->toolkitHelper = $toolkitHelper;
94
        $this->amastyHelper = $amastyHelper;
95
    }
96
97
    /**
98
     * Add parameters for a invoice position
99
     *
100
     * @param  string $sId       item identification
101
     * @param  double $dPrice    item price
102
     * @param  string $sItemType item type
103
     * @param  int    $iAmount   item amount
104
     * @param  string $sDesc     item description
105
     * @param  double $dVat      item tax rate
106
     * @return void
107
     */
108
    protected function addInvoicePosition($sId, $dPrice, $sItemType, $iAmount, $sDesc, $dVat)
109
    {
110
        $this->oRequest->addParameter('id['.$this->iIndex.']', $sId); // add invoice item id
111
        $this->oRequest->addParameter('pr['.$this->iIndex.']', $this->toolkitHelper->formatNumber($dPrice) * 100); // expected in smallest unit of currency
112
        $this->oRequest->addParameter('it['.$this->iIndex.']', $sItemType); // add invoice item type
113
        $this->oRequest->addParameter('no['.$this->iIndex.']', $iAmount); // add invoice item amount
114
        $this->oRequest->addParameter('de['.$this->iIndex.']', $sDesc); // add invoice item description
115
        $this->oRequest->addParameter('va['.$this->iIndex.']', $this->toolkitHelper->formatNumber($dVat * 100, 0)); // expected * 100 to also handle vats with decimals
116
        $this->dAmount += $dPrice * $iAmount; // needed for return of the main method
117
        $this->iIndex++; // increase index for next item
118
    }
119
120
    /**
121
     * Add invoicing data to the request and return the summed invoicing amount
122
     *
123
     * @param  Base  $oRequest   Request object
124
     * @param  Order $oOrder     Order object
125
     * @param  array $aPositions Is given with non-complete captures or debits
126
     * @param  bool  $blDebit    Is the call coming from a debit request
127
     * @return integer
128
     */
129
    public function addProductInfo(Base $oRequest, Order $oOrder, $aPositions = false, $blDebit = false)
130
    {
131
        $this->oRequest = $oRequest; // write request to property for manipulation of the object
132
        $sInvoiceAppendix = $this->toolkitHelper->getInvoiceAppendix($oOrder); // get invoice appendix
133
        if (!empty($sInvoiceAppendix)) {// invoice appendix existing?
134
            $this->oRequest->addParameter('invoiceappendix', $sInvoiceAppendix); // add appendix to request
135
        }
136
137
        $iQtyInvoiced = 0;
138
        foreach ($oOrder->getAllItems() as $oItem) { // add invoice items for all order items
139
            if ($oItem->isDummy() === false) { // prevent variant-products of adding 2 items
140
                $this->addProductItem($oItem, $aPositions); // add product invoice params to request
0 ignored issues
show
Bug introduced by
It seems like $aPositions can also be of type false; however, parameter $aPositions of Payone\Core\Model\Api\Invoice::addProductItem() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

140
                $this->addProductItem($oItem, /** @scrutinizer ignore-type */ $aPositions); // add product invoice params to request
Loading history...
141
            }
142
            $iQtyInvoiced += $oItem->getOrigData('qty_invoiced'); // get data pre-capture
143
        }
144
145
        $blFirstCapture = true; // Is first capture?
146
        if ($iQtyInvoiced > 0) {
147
            $blFirstCapture = false;
148
        }
149
150
        if ($aPositions === false || $blFirstCapture === true || $blDebit === true) {
151
            $this->addShippingItem($oOrder, $aPositions, $blDebit); // add shipping invoice params to request
0 ignored issues
show
Bug introduced by
It seems like $aPositions can also be of type false; however, parameter $aPositions of Payone\Core\Model\Api\Invoice::addShippingItem() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

151
            $this->addShippingItem($oOrder, /** @scrutinizer ignore-type */ $aPositions, $blDebit); // add shipping invoice params to request
Loading history...
152
            $this->addDiscountItem($oOrder, $aPositions, $blDebit); // add discount invoice params to request
0 ignored issues
show
Bug introduced by
It seems like $aPositions can also be of type false; however, parameter $aPositions of Payone\Core\Model\Api\Invoice::addDiscountItem() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

152
            $this->addDiscountItem($oOrder, /** @scrutinizer ignore-type */ $aPositions, $blDebit); // add discount invoice params to request
Loading history...
153
            $this->addGiftCardItem($oOrder);  // add gift card invoice params to request
154
            $this->addAmastyGiftcards($oOrder, $aPositions, $blDebit); // add amasty giftcard invoice params to request
0 ignored issues
show
Bug introduced by
It seems like $aPositions can also be of type false; however, parameter $aPositions of Payone\Core\Model\Api\In...e::addAmastyGiftcards() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

154
            $this->addAmastyGiftcards($oOrder, /** @scrutinizer ignore-type */ $aPositions, $blDebit); // add amasty giftcard invoice params to request
Loading history...
155
        }
156
        return $this->dAmount;
157
    }
158
159
    /**
160
     * Add invoicing item for a product
161
     *
162
     * @param  \Magento\Sales\Model\Order\Item $oItem
0 ignored issues
show
Bug introduced by
The type Magento\Sales\Model\Order\Item was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
163
     * @param  array $aPositions
164
     * @return void
165
     */
166
    protected function addProductItem($oItem, $aPositions)
167
    {
168
        $sPositionKey = $oItem->getProductId().$oItem->getSku();
169
        if ($aPositions === false || array_key_exists($sPositionKey, $aPositions) !== false) { // full or single-invoice?
170
            $dItemAmount = $oItem->getQtyOrdered(); // get ordered item amount
171
            if ($aPositions !== false && array_key_exists($sPositionKey, $aPositions) !== false) { // product existing in single-invoice?
172
                $dItemAmount = $aPositions[$sPositionKey]; // use amount from single-invoice
173
            }
174
            $iAmount = $this->convertItemAmount($dItemAmount);
175
            $dPrice = $oItem->getBasePriceInclTax();
176
            if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
177
                $dPrice = $oItem->getPriceInclTax();
178
            }
179
            $this->addInvoicePosition($oItem->getSku(), $dPrice, 'goods', $iAmount, $oItem->getName(), $oItem->getTaxPercent()); // add invoice params to request
180
            if ($this->dTax === false) { // is dTax not set yet?
0 ignored issues
show
introduced by
The condition $this->dTax === false is always false.
Loading history...
181
                $this->dTax = $oItem->getTaxPercent(); // set the tax for following entities which dont have the vat attached to it
182
            }
183
        }
184
    }
185
186
    protected function addGiftCardItem(Order $oOrder)
187
    {
188
        $giftCards = json_decode($oOrder->getData('gift_cards'), true);
189
190
        if(empty($giftCards) || !is_array($giftCards)) {
191
            return;
192
        }
193
194
        foreach($giftCards as $giftCard) {
195
            $this->addInvoicePosition($giftCard['c'], -$giftCard['authorized'], 'voucher', 1, 'Giftcard', 0);
196
        }
197
    }
198
199
    /**
200
     * Add invoicing item for shipping
201
     *
202
     * @param  Order $oOrder
203
     * @param  array $aPositions
204
     * @param  bool  $blDebit
205
     * @return void
206
     */
207
    protected function addShippingItem(Order $oOrder, $aPositions, $blDebit)
208
    {
209
        // shipping costs existing or given for partial captures/debits?
210
        if ($oOrder->getBaseShippingInclTax() != 0 && ($aPositions === false || ($blDebit === false || array_key_exists('delcost', $aPositions) !== false))) {
211
            $dPrice = $oOrder->getBaseShippingInclTax();
212
            if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
213
                $dPrice = $oOrder->getShippingInclTax();
214
            }
215
            if ($aPositions !== false && array_key_exists('delcost', $aPositions) !== false) { // product existing in single-invoice?
216
                $dPrice = $aPositions['delcost'];
217
            }
218
            $sDelDesc = __('Surcharge').' '.__('Shipping Costs'); // default description
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

218
            $sDelDesc = /** @scrutinizer ignore-call */ __('Surcharge').' '.__('Shipping Costs'); // default description
Loading history...
219
            if ($dPrice < 0) { // negative shipping cost
220
                $sDelDesc = __('Deduction').' '.__('Shipping Costs'); // change item description to deduction
221
            }
222
            $sShippingSku = $this->toolkitHelper->getConfigParam('sku', 'costs', 'payone_misc'); // get configured shipping SKU
223
            $this->addInvoicePosition($sShippingSku, $dPrice, 'shipment', 1, $sDelDesc, $this->dTax); // add invoice params to request
224
        }
225
    }
226
227
    /**
228
     * Add invoicing item for discounts
229
     *
230
     * @param  Order $oOrder
231
     * @param  array $aPositions
232
     * @param  bool  $blDebit
233
     * @return void
234
     */
235
    protected function addDiscountItem(Order $oOrder, $aPositions, $blDebit)
236
    {
237
        // discount costs existing or given for partial captures/debit?
238
        $dTransmitDiscount = $oOrder->getBaseDiscountAmount();
239
        if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
240
            $dTransmitDiscount = $oOrder->getDiscountAmount();
241
        }
242
        if ($dTransmitDiscount != 0 && ($aPositions === false || ($blDebit === false || array_key_exists('discount', $aPositions) !== false))) {
243
            if ($aPositions !== false && array_key_exists('discount', $aPositions) !== false) {
244
                $dTransmitDiscount = $aPositions['discount'];
245
            }
246
            $dDiscount = $this->toolkitHelper->formatNumber($dTransmitDiscount); // format discount
247
            if ($aPositions === false && $this->amastyHelper->hasAmastyGiftcards($oOrder->getQuoteId()) === false) {
0 ignored issues
show
introduced by
The condition $aPositions === false is always false.
Loading history...
248
                // The calculations broken down to single items of Magento2 are unprecise and the Payone API will send an error if
249
                // the calculated positions don't match, so we compensate for rounding-problems here
250
                $dTotal = $oOrder->getBaseGrandTotal();
251
                if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
252
                    $dTotal = $oOrder->getGrandTotal();
253
                }
254
                $dDiff = ($this->dAmount + $dTransmitDiscount - $dTotal); // calc rounding discrepancy
255
                $dDiscount -= $dDiff; // subtract difference from discount
256
            }
257
            $sDiscountSku = $this->toolkitHelper->getConfigParam('sku', 'discount', 'payone_misc'); // get configured discount SKU
258
            $sDesc = (string)__('Discount'); // default description
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

258
            $sDesc = (string)/** @scrutinizer ignore-call */ __('Discount'); // default description
Loading history...
259
            if ($oOrder->getCouponCode()) {// was a coupon code used?
260
                $sDiscountSku = $this->toolkitHelper->getConfigParam('sku', 'voucher', 'payone_misc'); // get configured voucher SKU
261
                $sDesc = (string)__('Coupon').' - '.$oOrder->getCouponCode(); // add counpon code to description
262
            }
263
            $this->addInvoicePosition($sDiscountSku, $dDiscount, 'voucher', 1, $sDesc, $this->dTax); // add invoice params to request
0 ignored issues
show
Bug introduced by
$dDiscount of type string is incompatible with the type double expected by parameter $dPrice of Payone\Core\Model\Api\In...e::addInvoicePosition(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

263
            $this->addInvoicePosition($sDiscountSku, /** @scrutinizer ignore-type */ $dDiscount, 'voucher', 1, $sDesc, $this->dTax); // add invoice params to request
Loading history...
264
        }
265
    }
266
267
    /**
268
     * Adding amasty giftcards to request
269
     *
270
     * @param  Order $oOrder
271
     * @param  array $aPositions
272
     * @param  bool  $blDebit
273
     * @return void
274
     */
275
    protected function addAmastyGiftcards(Order $oOrder, $aPositions, $blDebit)
276
    {
277
        $aGiftCards = $this->amastyHelper->getAmastyGiftCards($oOrder->getQuoteId());
278
        for ($i = 0; $i < count($aGiftCards); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
279
            $aGiftCard = $aGiftCards[$i];
280
            $blIsLastGiftcard = false;
281
            if ($i + 1 == count($aGiftCards)) {
282
                $blIsLastGiftcard = true;
283
            }
284
285
            $dTransmitDiscount = $aGiftCard['base_gift_amount'];
286
            if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
287
                $dTransmitDiscount = $aGiftCard['gift_amount'];
288
            }
289
            if ($dTransmitDiscount != 0 && ($aPositions === false || ($blDebit === false || array_key_exists('discount', $aPositions) !== false))) {
290
                $dTransmitDiscount = $dTransmitDiscount * -1;
291
                $dDiscount = $this->toolkitHelper->formatNumber($dTransmitDiscount); // format discount
292
                if ($aPositions === false && $blIsLastGiftcard === true) {
293
                    // The calculations broken down to single items of Magento2 are unprecise and the Payone API will send an error if
294
                    // the calculated positions don't match, so we compensate for rounding-problems here
295
                    $dTotal = $oOrder->getBaseGrandTotal();
296
                    if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
297
                        $dTotal = $oOrder->getGrandTotal();
298
                    }
299
                    $dDiff = ($this->dAmount + $dTransmitDiscount - $dTotal); // calc rounding discrepancy
300
                    $dDiscount -= $dDiff; // subtract difference from discount
301
                }
302
303
                if ($dDiscount != 0) {
304
                    $sDiscountSku = $this->toolkitHelper->getConfigParam('sku', 'voucher', 'payone_misc'); // get configured voucher SKU
305
                    $sDesc = (string)__('Amasty Coupon').' - '.$aGiftCard['code']; // add counpon code to description
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

305
                    $sDesc = (string)/** @scrutinizer ignore-call */ __('Amasty Coupon').' - '.$aGiftCard['code']; // add counpon code to description
Loading history...
306
                    $this->addInvoicePosition($sDiscountSku, $dDiscount, 'voucher', 1, $sDesc, $this->dTax); // add invoice params to request
0 ignored issues
show
Bug introduced by
$dDiscount of type string is incompatible with the type double expected by parameter $dPrice of Payone\Core\Model\Api\In...e::addInvoicePosition(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

306
                    $this->addInvoicePosition($sDiscountSku, /** @scrutinizer ignore-type */ $dDiscount, 'voucher', 1, $sDesc, $this->dTax); // add invoice params to request
Loading history...
307
                }
308
            }
309
        }
310
    }
311
312
    /**
313
     * Check if item amount has decimal places
314
     * Throw exception if given amount is no integer
315
     *
316
     * @param  double $dItemAmount
317
     * @throws \InvalidArgumentException
318
     * @return int
319
     */
320
    protected function convertItemAmount($dItemAmount)
321
    {
322
        if (fmod(floatval($dItemAmount), 1.0) > 0) { // input does not represent an integer
323
            $sErrorMessage = "Unable to use floating point values for item amounts! Parameter was: ";
324
            throw new \InvalidArgumentException($sErrorMessage . strval($dItemAmount), 1);
325
        } else { // return the integer value
326
            return intval($dItemAmount);
327
        }
328
    }
329
}
330