Passed
Pull Request — master (#315)
by
unknown
03:23
created

Invoice::addDiscountItem()   C

Complexity

Conditions 13
Paths 78

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 23
nc 78
nop 3
dl 0
loc 37
rs 6.6166
c 1
b 0
f 0

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

137
                $this->addProductItem($oItem, /** @scrutinizer ignore-type */ $aPositions); // add product invoice params to request
Loading history...
138
            }
139
            $iQtyInvoiced += $oItem->getOrigData('qty_invoiced'); // get data pre-capture
140
        }
141
142
        $blFirstCapture = true; // Is first capture?
143
        if ($iQtyInvoiced > 0) {
144
            $blFirstCapture = false;
145
        }
146
147
        if ($aPositions === false || $blFirstCapture === true || $blDebit === true) {
148
            $this->addShippingItem($oOrder, $aPositions, $blDebit, $dShippingCosts); // 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

148
            $this->addShippingItem($oOrder, /** @scrutinizer ignore-type */ $aPositions, $blDebit, $dShippingCosts); // add shipping invoice params to request
Loading history...
Bug introduced by
It seems like $dShippingCosts can also be of type false; however, parameter $dShippingCosts of Payone\Core\Model\Api\Invoice::addShippingItem() does only seem to accept double, 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

148
            $this->addShippingItem($oOrder, $aPositions, $blDebit, /** @scrutinizer ignore-type */ $dShippingCosts); // add shipping invoice params to request
Loading history...
149
            $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

149
            $this->addDiscountItem($oOrder, /** @scrutinizer ignore-type */ $aPositions, $blDebit); // add discount invoice params to request
Loading history...
150
            $this->addGiftCardItem($oOrder);  // add gift card invoice params to request
151
        }
152
        return $this->dAmount;
153
    }
154
155
    /**
156
     * Add invoicing item for a product
157
     *
158
     * @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...
159
     * @param  array $aPositions
160
     * @return void
161
     */
162
    protected function addProductItem($oItem, $aPositions)
163
    {
164
        $sPositionKey = $oItem->getProductId().$oItem->getSku();
165
        if ($aPositions === false || array_key_exists($sPositionKey, $aPositions) !== false) { // full or single-invoice?
166
            $dItemAmount = $oItem->getQtyOrdered(); // get ordered item amount
167
            if ($oItem instanceof QuoteItem) {
168
                $dItemAmount = $oItem->getQty();
169
            }
170
            if ($aPositions !== false && array_key_exists($sPositionKey, $aPositions) !== false) { // product existing in single-invoice?
171
                $dItemAmount = $aPositions[$sPositionKey]; // use amount from single-invoice
172
            }
173
            $iAmount = $this->convertItemAmount($dItemAmount);
174
            $dPrice = $oItem->getBasePriceInclTax();
175
            if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
176
                $dPrice = $oItem->getPriceInclTax();
177
            }
178
            $this->addInvoicePosition($oItem->getSku(), $dPrice, 'goods', $iAmount, $oItem->getName(), $oItem->getTaxPercent()); // add invoice params to request
179
            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...
180
                $this->dTax = $oItem->getTaxPercent(); // set the tax for following entities which dont have the vat attached to it
181
            }
182
        }
183
    }
184
185
    protected function addGiftCardItem($oOrder)
186
    {
187
        $giftCards = json_decode($oOrder->getData('gift_cards'), true);
188
189
        if(empty($giftCards) || !is_array($giftCards)) {
190
            return;
191
        }
192
193
        foreach($giftCards as $giftCard) {
194
            $this->addInvoicePosition($giftCard['c'], -$giftCard['authorized'], 'voucher', 1, 'Giftcard', 0);
195
        }
196
    }
197
198
    /**
199
     * Add invoicing item for shipping
200
     *
201
     * @param  Order    $oOrder
202
     * @param  array    $aPositions
203
     * @param  bool     $blDebit
204
     * @param  double   $dShippingCosts
205
     * @return void
206
     */
207
    protected function addShippingItem($oOrder, $aPositions, $blDebit, $dShippingCosts = false)
208
    {
209
        $dPrice = $dShippingCosts;
210
        if ($dPrice === false) {
211
            $dPrice = $oOrder->getBaseShippingInclTax();
212
            if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
213
                $dPrice = $oOrder->getShippingInclTax();
214
            }
215
        }
216
217
        // shipping costs existing or given for partial captures/debits?
218
        if ($dPrice != 0 && ($aPositions === false || ($blDebit === false || array_key_exists('delcost', $aPositions) !== false))) {
219
            if ($aPositions !== false && array_key_exists('delcost', $aPositions) !== false) { // product existing in single-invoice?
220
                $dPrice = $aPositions['delcost'];
221
            }
222
            $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

222
            $sDelDesc = /** @scrutinizer ignore-call */ __('Surcharge').' '.__('Shipping Costs'); // default description
Loading history...
223
            if ($dPrice < 0) { // negative shipping cost
224
                $sDelDesc = __('Deduction').' '.__('Shipping Costs'); // change item description to deduction
225
            }
226
            $sShippingSku = $this->toolkitHelper->getConfigParam('sku', 'costs', 'payone_misc'); // get configured shipping SKU
227
            $this->addInvoicePosition($sShippingSku, $dPrice, 'shipment', 1, $sDelDesc, $this->dTax); // add invoice params to request
228
        }
229
    }
230
231
    /**
232
     * Add invoicing item for discounts
233
     *
234
     * @param  Order $oOrder
235
     * @param  array $aPositions
236
     * @param  bool  $blDebit
237
     * @return void
238
     */
239
    protected function addDiscountItem($oOrder, $aPositions, $blDebit)
240
    {
241
        // discount costs existing or given for partial captures/debit?
242
        $dTransmitDiscount = $oOrder->getBaseDiscountAmount();
243
        if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
244
            $dTransmitDiscount = $oOrder->getDiscountAmount();
245
        }
246
247
        if ($oOrder instanceof Quote) {
248
            $dTransmitDiscount = $oOrder->getBaseSubtotal() - $oOrder->getBaseSubtotalWithDiscount();
249
            if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
250
                $dTransmitDiscount = $oOrder->getSubtotal() - $oOrder->getSubtotalWithDiscount();
251
            }
252
        }
253
254
        if ($dTransmitDiscount != 0 && ($aPositions === false || ($blDebit === false || array_key_exists('discount', $aPositions) !== false))) {
255
            if ($aPositions !== false && array_key_exists('discount', $aPositions) !== false) {
256
                $dTransmitDiscount = $aPositions['discount'];
257
            }
258
            $dDiscount = $this->toolkitHelper->formatNumber($dTransmitDiscount); // format discount
259
            if ($aPositions === false) {// full invoice?
0 ignored issues
show
introduced by
The condition $aPositions === false is always false.
Loading history...
260
                // The calculations broken down to single items of Magento2 are unprecise and the Payone API will send an error if
261
                // the calculated positions don't match, so we compensate for rounding-problems here
262
                $dTotal = $oOrder->getBaseGrandTotal();
263
                if ($this->toolkitHelper->getConfigParam('currency') == 'display') {
264
                    $dTotal = $oOrder->getGrandTotal();
265
                }
266
                $dDiff = ($this->dAmount + $dTransmitDiscount - $dTotal); // calc rounding discrepancy
267
                $dDiscount -= $dDiff; // subtract difference from discount
268
            }
269
            $sDiscountSku = $this->toolkitHelper->getConfigParam('sku', 'discount', 'payone_misc'); // get configured discount SKU
270
            $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

270
            $sDesc = (string)/** @scrutinizer ignore-call */ __('Discount'); // default description
Loading history...
271
            if ($oOrder->getCouponCode()) {// was a coupon code used?
272
                $sDiscountSku = $this->toolkitHelper->getConfigParam('sku', 'voucher', 'payone_misc'); // get configured voucher SKU
273
                $sDesc = (string)__('Coupon').' - '.$oOrder->getCouponCode(); // add counpon code to description
274
            }
275
            $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

275
            $this->addInvoicePosition($sDiscountSku, /** @scrutinizer ignore-type */ $dDiscount, 'voucher', 1, $sDesc, $this->dTax); // add invoice params to request
Loading history...
276
        }
277
    }
278
279
    /**
280
     * Check if item amount has decimal places
281
     * Throw exception if given amount is no integer
282
     *
283
     * @param  double $dItemAmount
284
     * @throws \InvalidArgumentException
285
     * @return int
286
     */
287
    protected function convertItemAmount($dItemAmount)
288
    {
289
        if (fmod(floatval($dItemAmount), 1.0) > 0) { // input does not represent an integer
290
            $sErrorMessage = "Unable to use floating point values for item amounts! Parameter was: ";
291
            throw new \InvalidArgumentException($sErrorMessage . strval($dItemAmount), 1);
292
        } else { // return the integer value
293
            return intval($dItemAmount);
294
        }
295
    }
296
}
297