7
7
8
8
use Magento \Sales \Api \InvoiceManagementInterface ;
9
9
use Magento \Sales \Model \Order ;
10
+ use Magento \Framework \App \ObjectManager ;
11
+ use Magento \Framework \Serialize \Serializer \Json ;
12
+ use Magento \Catalog \Model \Product \Type ;
10
13
11
14
/**
12
15
* Class InvoiceService
16
+ *
17
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
13
18
*/
14
19
class InvoiceService implements InvoiceManagementInterface
15
20
{
@@ -58,6 +63,13 @@ class InvoiceService implements InvoiceManagementInterface
58
63
*/
59
64
protected $ orderConverter ;
60
65
66
+ /**
67
+ * Serializer interface instance.
68
+ *
69
+ * @var Json
70
+ */
71
+ private $ serializer ;
72
+
61
73
/**
62
74
* Constructor
63
75
*
@@ -68,6 +80,7 @@ class InvoiceService implements InvoiceManagementInterface
68
80
* @param \Magento\Sales\Model\Order\InvoiceNotifier $notifier
69
81
* @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
70
82
* @param \Magento\Sales\Model\Convert\Order $orderConverter
83
+ * @param Json|null $serializer
71
84
*/
72
85
public function __construct (
73
86
\Magento \Sales \Api \InvoiceRepositoryInterface $ repository ,
@@ -76,7 +89,8 @@ public function __construct(
76
89
\Magento \Framework \Api \FilterBuilder $ filterBuilder ,
77
90
\Magento \Sales \Model \Order \InvoiceNotifier $ notifier ,
78
91
\Magento \Sales \Api \OrderRepositoryInterface $ orderRepository ,
79
- \Magento \Sales \Model \Convert \Order $ orderConverter
92
+ \Magento \Sales \Model \Convert \Order $ orderConverter ,
93
+ Json $ serializer = null
80
94
) {
81
95
$ this ->repository = $ repository ;
82
96
$ this ->commentRepository = $ commentRepository ;
@@ -85,6 +99,7 @@ public function __construct(
85
99
$ this ->invoiceNotifier = $ notifier ;
86
100
$ this ->orderRepository = $ orderRepository ;
87
101
$ this ->orderConverter = $ orderConverter ;
102
+ $ this ->serializer = $ serializer ?: ObjectManager::getInstance ()->get (Json::class);
88
103
}
89
104
90
105
/**
@@ -142,10 +157,10 @@ public function prepareInvoice(Order $order, array $qtys = [])
142
157
continue ;
143
158
}
144
159
$ item = $ this ->orderConverter ->itemToInvoiceItem ($ orderItem );
145
- if ($ orderItem ->isDummy ()) {
146
- $ qty = $ orderItem ->getQtyOrdered () ? $ orderItem ->getQtyOrdered () : 1 ;
147
- } elseif (isset ($ qtys [$ orderItem ->getId ()])) {
160
+ if (isset ($ qtys [$ orderItem ->getId ()])) {
148
161
$ qty = (double ) $ qtys [$ orderItem ->getId ()];
162
+ } elseif ($ orderItem ->isDummy ()) {
163
+ $ qty = $ orderItem ->getQtyOrdered () ? $ orderItem ->getQtyOrdered () : 1 ;
149
164
} elseif (empty ($ qtys )) {
150
165
$ qty = $ orderItem ->getQtyToInvoice ();
151
166
} else {
@@ -172,25 +187,61 @@ private function prepareItemsQty(Order $order, array $qtys = [])
172
187
{
173
188
foreach ($ order ->getAllItems () as $ orderItem ) {
174
189
if (empty ($ qtys [$ orderItem ->getId ()])) {
175
- continue ;
190
+ if ($ orderItem ->getProductType () == Type::TYPE_BUNDLE && !$ orderItem ->isShipSeparately ()) {
191
+ $ qtys [$ orderItem ->getId ()] = $ orderItem ->getQtyOrdered () - $ orderItem ->getQtyInvoiced ();
192
+ } else {
193
+ continue ;
194
+ }
176
195
}
177
- if ($ orderItem ->isDummy ()) {
178
- if ($ orderItem ->getHasChildren ()) {
179
- foreach ($ orderItem ->getChildrenItems () as $ child ) {
180
- if (!isset ($ qtys [$ child ->getId ()])) {
181
- $ qtys [$ child ->getId ()] = $ child ->getQtyToInvoice ();
182
- }
183
- }
184
- } elseif ($ orderItem ->getParentItem ()) {
185
- $ parent = $ orderItem ->getParentItem ();
186
- if (!isset ($ qtys [$ parent ->getId ()])) {
187
- $ qtys [$ parent ->getId ()] = $ parent ->getQtyToInvoice ();
196
+
197
+ $ this ->prepareItemQty ($ orderItem , $ qtys );
198
+ }
199
+
200
+ return $ qtys ;
201
+ }
202
+
203
+ /**
204
+ * Prepare qty_invoiced for order item
205
+ *
206
+ * @param \Magento\Sales\Api\Data\OrderItemInterface $orderItem
207
+ * @param array $qtys
208
+ */
209
+ private function prepareItemQty (\Magento \Sales \Api \Data \OrderItemInterface $ orderItem , &$ qtys )
210
+ {
211
+ $ this ->prepareBundleQty ($ orderItem , $ qtys );
212
+
213
+ if ($ orderItem ->isDummy ()) {
214
+ if ($ orderItem ->getHasChildren ()) {
215
+ foreach ($ orderItem ->getChildrenItems () as $ child ) {
216
+ if (!isset ($ qtys [$ child ->getId ()])) {
217
+ $ qtys [$ child ->getId ()] = $ child ->getQtyToInvoice ();
188
218
}
189
219
}
220
+ } elseif ($ orderItem ->getParentItem ()) {
221
+ $ parent = $ orderItem ->getParentItem ();
222
+ if (!isset ($ qtys [$ parent ->getId ()])) {
223
+ $ qtys [$ parent ->getId ()] = $ parent ->getQtyToInvoice ();
224
+ }
190
225
}
191
226
}
227
+ }
192
228
193
- return $ qtys ;
229
+ /**
230
+ * Prepare qty to invoice for bundle products
231
+ *
232
+ * @param \Magento\Sales\Api\Data\OrderItemInterface $orderItem
233
+ * @param array $qtys
234
+ */
235
+ private function prepareBundleQty (\Magento \Sales \Api \Data \OrderItemInterface $ orderItem , &$ qtys )
236
+ {
237
+ if ($ orderItem ->getProductType () == Type::TYPE_BUNDLE && !$ orderItem ->isShipSeparately ()) {
238
+ foreach ($ orderItem ->getChildrenItems () as $ childItem ) {
239
+ $ bundleSelectionAttributes = $ this ->serializer ->unserialize (
240
+ $ childItem ->getProductOptionByCode ('bundle_selection_attributes ' )
241
+ );
242
+ $ qtys [$ childItem ->getId ()] = $ qtys [$ orderItem ->getId ()] * $ bundleSelectionAttributes ['qty ' ];
243
+ }
244
+ }
194
245
}
195
246
196
247
/**
0 commit comments