Invoice   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 201
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 201
c 1
b 0
f 0
wmc 34
lcom 1
cbo 2
rs 9.2

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A addInvoicePosition() 0 11 1
C addProductInfo() 0 27 8
B addProductItem() 0 14 6
B addShippingItem() 0 16 8
B addDiscountItem() 0 20 8
A convertItemAmount() 0 9 2
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;
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 defined by parameter $aPositions on line 121 can also be of type false; however, Payone\Core\Model\Api\Invoice::addProductItem() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

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 defined by parameter $aPositions on line 121 can also be of type false; however, Payone\Core\Model\Api\Invoice::addShippingItem() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

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 defined by parameter $aPositions on line 121 can also be of type false; however, Payone\Core\Model\Api\Invoice::addDiscountItem() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
145
        }
146
        return $this->dAmount;
147
    }
148
149
    /**
150
     * Add invoicing item for a product
151
     *
152
     * @param  \Magento\Sales\Model\Order\Item $oItem
153
     * @param  array $aPositions
154
     * @return void
155
     */
156
    protected function addProductItem($oItem, $aPositions)
157
    {
158
        if ($aPositions === false || array_key_exists($oItem->getProductId(), $aPositions) !== false) { // full or single-invoice?
159
            $dItemAmount = $oItem->getQtyOrdered(); // get ordered item amount
160
            if ($aPositions !== false && array_key_exists($oItem->getProductId(), $aPositions) !== false) { // product existing in single-invoice?
161
                $dItemAmount = $aPositions[$oItem->getProductId()]; // use amount from single-invoice
162
            }
163
            $iAmount = $this->convertItemAmount($dItemAmount);
164
            $this->addInvoicePosition($oItem->getSku(), $oItem->getPriceInclTax(), 'goods', $iAmount, $oItem->getName(), $oItem->getTaxPercent()); // add invoice params to request
165
            if ($this->dTax === false) { // is dTax not set yet?
166
                $this->dTax = $oItem->getTaxPercent(); // set the tax for following entities which dont have the vat attached to it
167
            }
168
        }
169
    }
170
171
    /**
172
     * Add invoicing item for shipping
173
     *
174
     * @param  Order $oOrder
175
     * @param  array $aPositions
176
     * @param  bool  $blDebit
177
     * @return void
178
     */
179
    protected function addShippingItem(Order $oOrder, $aPositions, $blDebit)
180
    {
181
        // shipping costs existing or given for partial captures/debits?
182
        if ($oOrder->getBaseShippingInclTax() != 0 && ($aPositions === false || ($blDebit === false || array_key_exists('delcost', $aPositions) !== false))) {
183
            $dPrice = $oOrder->getBaseShippingInclTax();
184
            if ($aPositions !== false && array_key_exists('delcost', $aPositions) !== false) { // product existing in single-invoice?
185
                $dPrice = $aPositions['delcost'];
186
            }
187
            $sDelDesc = __('Surcharge').' '.__('Shipping Costs'); // default description
188
            if ($dPrice < 0) { // negative shipping cost
189
                $sDelDesc = __('Deduction').' '.__('Shipping Costs'); // change item description to deduction
190
            }
191
            $sShippingSku = $this->toolkitHelper->getConfigParam('sku', 'costs', 'payone_misc'); // get configured shipping SKU
192
            $this->addInvoicePosition($sShippingSku, $dPrice, 'shipment', 1, $sDelDesc, $this->dTax); // add invoice params to request
193
        }
194
    }
195
196
    /**
197
     * Add invoicing item for discounts
198
     *
199
     * @param  Order $oOrder
200
     * @param  array $aPositions
201
     * @param  bool  $blDebit
202
     * @return void
203
     */
204
    protected function addDiscountItem(Order $oOrder, $aPositions, $blDebit)
205
    {
206
        // discount costs existing or given for partial captures/debis?
207
        if ($oOrder->getBaseDiscountAmount() != 0 && $oOrder->getCouponCode() && ($aPositions === false || ($blDebit === false || array_key_exists('oxvoucherdiscount', $aPositions) !== false))) {
208
            $dDiscount = $this->toolkitHelper->formatNumber($oOrder->getBaseDiscountAmount()); // format discount
209
            if ($aPositions === false) {// full invoice?
210
                // The calculations broken down to single items of Magento2 are unprecise and the Payone API will send an error if
211
                // the calculated positions don't match, so we compensate for rounding-problems here
212
                $dDiff = ($this->dAmount + $oOrder->getBaseDiscountAmount()) - $oOrder->getGrandTotal(); // calc rounding discrepancy
213
                $dDiscount -= $dDiff; // subtract difference from discount
214
            }
215
            $sDiscountSku = $this->toolkitHelper->getConfigParam('sku', 'discount', 'payone_misc'); // get configured discount SKU
216
            $sDesc = (string)__('Discount'); // default description
217
            if ($oOrder->getCouponCode()) {// was a coupon code used?
218
                $sDiscountSku = $this->toolkitHelper->getConfigParam('sku', 'voucher', 'payone_misc'); // get configured voucher SKU
219
                $sDesc = (string)__('Coupon').' - '.$oOrder->getCouponCode(); // add counpon code to description
220
            }
221
            $this->addInvoicePosition($sDiscountSku, $dDiscount, 'voucher', 1, $sDesc, $this->dTax); // add invoice params to request
222
        }
223
    }
224
225
    /**
226
     * Check if item amount has decimal places
227
     * Throw exception if given amount is no integer
228
     *
229
     * @param  double $dItemAmount
230
     * @throws \InvalidArgumentException
231
     * @return int
232
     */
233
    protected function convertItemAmount($dItemAmount)
234
    {
235
        if (fmod(floatval($dItemAmount), 1.0) > 0) { // input does not represent an integer
236
            $sErrorMessage = "Unable to use floating point values for item amounts! Parameter was: ";
237
            throw new \InvalidArgumentException($sErrorMessage . strval($dItemAmount), 1);
238
        } else { // return the integer value
239
            return intval($dItemAmount);
240
        }
241
    }
242
}
243