Passed
Push — master ( d3de96...c0d11d )
by
unknown
02:54 queued 12s
created

Invoice   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 84
c 3
b 0
f 0
dl 0
loc 231
rs 8.96
wmc 43

8 Methods

Rating   Name   Duplication   Size   Complexity  
A addInvoicePosition() 0 10 1
A __construct() 0 3 1
A addGiftCardItem() 0 10 4
B addShippingItem() 0 17 9
B addProductItem() 0 16 7
A convertItemAmount() 0 7 2
B addDiscountItem() 0 29 11
B addProductInfo() 0 27 8

How to fix   Complexity   

Complex Class

Complex classes like Invoice often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Invoice, and based on these observations, apply Extract Interface, too.

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
     * Request object
74
     *
75
     * @var Base
76
     */
77
    protected $oRequest;
78
79
    /**
80
     * Constructor
81
     *
82
     * @param \Payone\Core\Helper\Toolkit $toolkitHelper Toolkit helper
83
     */
84
    public function __construct(\Payone\Core\Helper\Toolkit $toolkitHelper)
85
    {
86
        $this->toolkitHelper = $toolkitHelper;
87
    }
88
89
    /**
90
     * Add parameters for a invoice position
91
     *
92
     * @param  string $sId       item identification
93
     * @param  double $dPrice    item price
94
     * @param  string $sItemType item type
95
     * @param  int    $iAmount   item amount
96
     * @param  string $sDesc     item description
97
     * @param  double $dVat      item tax rate
98
     * @return void
99
     */
100
    protected function addInvoicePosition($sId, $dPrice, $sItemType, $iAmount, $sDesc, $dVat)
101
    {
102
        $this->oRequest->addParameter('id['.$this->iIndex.']', $sId); // add invoice item id
103
        $this->oRequest->addParameter('pr['.$this->iIndex.']', $this->toolkitHelper->formatNumber($dPrice) * 100); // expected in smallest unit of currency
104
        $this->oRequest->addParameter('it['.$this->iIndex.']', $sItemType); // add invoice item type
105
        $this->oRequest->addParameter('no['.$this->iIndex.']', $iAmount); // add invoice item amount
106
        $this->oRequest->addParameter('de['.$this->iIndex.']', $sDesc); // add invoice item description
107
        $this->oRequest->addParameter('va['.$this->iIndex.']', $this->toolkitHelper->formatNumber($dVat * 100, 0)); // expected * 100 to also handle vats with decimals
108
        $this->dAmount += $dPrice * $iAmount; // needed for return of the main method
109
        $this->iIndex++; // increase index for next item
110
    }
111
112
    /**
113
     * Add invoicing data to the request and return the summed invoicing amount
114
     *
115
     * @param  Base  $oRequest   Request object
116
     * @param  Order $oOrder     Order object
117
     * @param  array $aPositions Is given with non-complete captures or debits
118
     * @param  bool  $blDebit    Is the call coming from a debit request
119
     * @return integer
120
     */
121
    public function addProductInfo(Base $oRequest, Order $oOrder, $aPositions = false, $blDebit = false)
122
    {
123
        $this->oRequest = $oRequest; // write request to property for manipulation of the object
124
        $sInvoiceAppendix = $this->toolkitHelper->getInvoiceAppendix($oOrder); // get invoice appendix
125
        if (!empty($sInvoiceAppendix)) {// invoice appendix existing?
126
            $this->oRequest->addParameter('invoiceappendix', $sInvoiceAppendix); // add appendix to request
127
        }
128
129
        $iQtyInvoiced = 0;
130
        foreach ($oOrder->getAllItems() as $oItem) { // add invoice items for all order items
131
            if ($oItem->isDummy() === false) { // prevent variant-products of adding 2 items
132
                $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

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

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

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

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

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

254
            $this->addInvoicePosition($sDiscountSku, /** @scrutinizer ignore-type */ $dDiscount, 'voucher', 1, $sDesc, $this->dTax); // add invoice params to request
Loading history...
255
        }
256
    }
257
258
    /**
259
     * Check if item amount has decimal places
260
     * Throw exception if given amount is no integer
261
     *
262
     * @param  double $dItemAmount
263
     * @throws \InvalidArgumentException
264
     * @return int
265
     */
266
    protected function convertItemAmount($dItemAmount)
267
    {
268
        if (fmod(floatval($dItemAmount), 1.0) > 0) { // input does not represent an integer
269
            $sErrorMessage = "Unable to use floating point values for item amounts! Parameter was: ";
270
            throw new \InvalidArgumentException($sErrorMessage . strval($dItemAmount), 1);
271
        } else { // return the integer value
272
            return intval($dItemAmount);
273
        }
274
    }
275
}
276