6
6
namespace Magento \Sales \Model ;
7
7
8
8
use Magento \Catalog \Model \Product \Type ;
9
+ use Magento \Catalog \Api \ProductRepositoryInterface ;
10
+ use Magento \Catalog \Model \Product \Visibility ;
9
11
use Magento \Config \Model \Config \Source \Nooptreq ;
10
12
use Magento \Directory \Model \Currency ;
13
+ use Magento \Directory \Model \CurrencyFactory ;
11
14
use Magento \Directory \Model \RegionFactory ;
12
15
use Magento \Directory \Model \ResourceModel \Region as RegionResource ;
13
16
use Magento \Framework \Api \AttributeValueFactory ;
17
+ use Magento \Framework \Api \ExtensionAttributesFactory ;
14
18
use Magento \Framework \Api \SearchCriteriaBuilder ;
15
19
use Magento \Framework \App \Config \ScopeConfigInterface ;
16
20
use Magento \Framework \App \ObjectManager ;
21
+ use Magento \Framework \Data \Collection \AbstractDb ;
17
22
use Magento \Framework \Exception \LocalizedException ;
18
23
use Magento \Framework \Locale \ResolverInterface ;
24
+ use Magento \Framework \Model \Context ;
25
+ use Magento \Framework \Model \ResourceModel \AbstractResource ;
19
26
use Magento \Framework \Pricing \PriceCurrencyInterface ;
27
+ use Magento \Framework \Registry ;
28
+ use Magento \Framework \Stdlib \DateTime \TimezoneInterface ;
20
29
use Magento \Sales \Api \Data \OrderInterface ;
21
30
use Magento \Sales \Api \Data \OrderItemInterface ;
22
31
use Magento \Sales \Api \Data \OrderStatusHistoryInterface ;
32
+ use Magento \Sales \Api \InvoiceManagementInterface ;
23
33
use Magento \Sales \Api \OrderItemRepositoryInterface ;
34
+ use Magento \Sales \Model \Order \Config ;
35
+ use Magento \Sales \Model \Order \CreditmemoValidator ;
24
36
use Magento \Sales \Model \Order \Payment ;
25
37
use Magento \Sales \Model \Order \ProductOption ;
38
+ use Magento \Sales \Model \Order \Status \HistoryFactory ;
26
39
use Magento \Sales \Model \ResourceModel \Order \Address \Collection ;
27
40
use Magento \Sales \Model \ResourceModel \Order \Creditmemo \Collection as CreditmemoCollection ;
28
41
use Magento \Sales \Model \ResourceModel \Order \Invoice \Collection as InvoiceCollection ;
29
42
use Magento \Sales \Model \ResourceModel \Order \Item \Collection as ItemCollection ;
43
+ use Magento \Sales \Model \ResourceModel \Order \Item \CollectionFactory ;
30
44
use Magento \Sales \Model \ResourceModel \Order \Payment \Collection as PaymentCollection ;
31
45
use Magento \Sales \Model \ResourceModel \Order \Shipment \Collection as ShipmentCollection ;
32
46
use Magento \Sales \Model \ResourceModel \Order \Shipment \Track \Collection as TrackCollection ;
33
47
use Magento \Sales \Model \ResourceModel \Order \Status \History \Collection as HistoryCollection ;
34
48
use Magento \Store \Model \ScopeInterface ;
35
49
use Magento \Framework \App \Area ;
36
50
use Magento \Sales \Model \Order \StatusLabel ;
51
+ use Magento \Store \Model \StoreManagerInterface ;
37
52
38
53
/**
39
54
* Order model
@@ -334,20 +349,25 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface
334
349
private $ statusLabel ;
335
350
336
351
/**
337
- * @param \Magento\Framework\Model\Context $context
338
- * @param \Magento\Framework\Registry $registry
339
- * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
352
+ * @var ?CreditmemoValidator
353
+ */
354
+ private $ creditmemoValidator ;
355
+
356
+ /**
357
+ * @param Context $context
358
+ * @param Registry $registry
359
+ * @param ExtensionAttributesFactory $extensionFactory
340
360
* @param AttributeValueFactory $customAttributeFactory
341
- * @param \Magento\Framework\Stdlib\DateTime\ TimezoneInterface $timezone
342
- * @param \Magento\Store\Model\ StoreManagerInterface $storeManager
343
- * @param Order\ Config $orderConfig
344
- * @param \Magento\Catalog\Api\ ProductRepositoryInterface $productRepository
345
- * @param \Magento\Sales\Model\ResourceModel\Order\Item\ CollectionFactory $orderItemCollectionFactory
346
- * @param \Magento\Catalog\Model\Product\ Visibility $productVisibility
347
- * @param \Magento\Sales\Api\ InvoiceManagementInterface $invoiceManagement
348
- * @param \Magento\Directory\Model\ CurrencyFactory $currencyFactory
361
+ * @param TimezoneInterface $timezone
362
+ * @param StoreManagerInterface $storeManager
363
+ * @param Config $orderConfig
364
+ * @param ProductRepositoryInterface $productRepository
365
+ * @param CollectionFactory $orderItemCollectionFactory
366
+ * @param Visibility $productVisibility
367
+ * @param InvoiceManagementInterface $invoiceManagement
368
+ * @param CurrencyFactory $currencyFactory
349
369
* @param \Magento\Eav\Model\Config $eavConfig
350
- * @param Order\Status\ HistoryFactory $orderHistoryFactory
370
+ * @param HistoryFactory $orderHistoryFactory
351
371
* @param \Magento\Sales\Model\ResourceModel\Order\Address\CollectionFactory $addressCollectionFactory
352
372
* @param \Magento\Sales\Model\ResourceModel\Order\Payment\CollectionFactory $paymentCollectionFactory
353
373
* @param \Magento\Sales\Model\ResourceModel\Order\Status\History\CollectionFactory $historyCollectionFactory
@@ -358,8 +378,8 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface
358
378
* @param ResourceModel\Order\CollectionFactory $salesOrderCollectionFactory
359
379
* @param PriceCurrencyInterface $priceCurrency
360
380
* @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productListFactory
361
- * @param \Magento\Framework\Model\ResourceModel\ AbstractResource|null $resource
362
- * @param \Magento\Framework\Data\Collection\ AbstractDb|null $resourceCollection
381
+ * @param AbstractResource|null $resource
382
+ * @param AbstractDb|null $resourceCollection
363
383
* @param array $data
364
384
* @param ResolverInterface|null $localeResolver
365
385
* @param ProductOption|null $productOption
@@ -369,8 +389,10 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface
369
389
* @param RegionFactory|null $regionFactory
370
390
* @param RegionResource|null $regionResource
371
391
* @param StatusLabel|null $statusLabel
392
+ * @param CreditmemoValidator|null $creditmemoValidator
372
393
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
373
394
* @SuppressWarnings(PHPMD.NPathComplexity)
395
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
374
396
*/
375
397
public function __construct (
376
398
\Magento \Framework \Model \Context $ context ,
@@ -407,7 +429,8 @@ public function __construct(
407
429
ScopeConfigInterface $ scopeConfig = null ,
408
430
RegionFactory $ regionFactory = null ,
409
431
RegionResource $ regionResource = null ,
410
- StatusLabel $ statusLabel = null
432
+ StatusLabel $ statusLabel = null ,
433
+ CreditmemoValidator $ creditmemoValidator = null
411
434
) {
412
435
$ this ->_storeManager = $ storeManager ;
413
436
$ this ->_orderConfig = $ orderConfig ;
@@ -440,6 +463,8 @@ public function __construct(
440
463
$ this ->regionResource = $ regionResource ?: ObjectManager::getInstance ()->get (RegionResource::class);
441
464
$ this ->regionItems = [];
442
465
$ this ->statusLabel = $ statusLabel ?: ObjectManager::getInstance ()->get (StatusLabel::class);
466
+ $ this ->creditmemoValidator = $ creditmemoValidator ?:
467
+ ObjectManager::getInstance ()->get (CreditmemoValidator::class);
443
468
parent ::__construct (
444
469
$ context ,
445
470
$ registry ,
@@ -745,23 +770,43 @@ private function canCreditmemoForZeroTotalRefunded($totalRefunded)
745
770
*/
746
771
private function canCreditmemoForZeroTotal ($ totalRefunded )
747
772
{
773
+ if ($ this ->areThereRefundableItems ()) {
774
+ return true ;
775
+ }
776
+
748
777
$ totalPaid = $ this ->getTotalPaid ();
749
778
//check if total paid is less than grandtotal
750
779
$ checkAmtTotalPaid = $ totalPaid <= $ this ->getGrandTotal ();
751
780
//case when amount is due for invoice
752
781
$ hasDueAmount = $ this ->canInvoice () && ($ checkAmtTotalPaid );
753
782
//case when paid amount is refunded and order has creditmemo created
754
- $ creditmemos = ( $ this ->getCreditmemosCollection () === false ) ?
755
- true : ( $ this ->_memoCollectionFactory ->create ()->setOrderFilter ($ this )->getTotalCount () > 0 ) ;
783
+ $ creditmemos = $ this ->getCreditmemosCollection () === false ||
784
+ $ this ->_memoCollectionFactory ->create ()->setOrderFilter ($ this )->getTotalCount () > 0 ;
756
785
$ paidAmtIsRefunded = $ this ->getTotalRefunded () == $ totalPaid && $ creditmemos ;
757
- if (( $ hasDueAmount || $ paidAmtIsRefunded ) ||
758
- (! $ checkAmtTotalPaid &&
759
- abs ($ totalRefunded - $ this ->getAdjustmentNegative ()) < .0001 )) {
786
+ if ($ hasDueAmount ||
787
+ $ paidAmtIsRefunded ||
788
+ (! $ checkAmtTotalPaid && abs ($ totalRefunded - $ this ->getAdjustmentNegative ()) < .0001 )) {
760
789
return false ;
761
790
}
762
791
return true ;
763
792
}
764
793
794
+ /**
795
+ * Check if there are order items available for refund.
796
+ *
797
+ * @return bool
798
+ */
799
+ private function areThereRefundableItems (): bool
800
+ {
801
+ foreach ($ this ->getAllItems () as $ orderItem ) {
802
+ if ($ this ->creditmemoValidator ->canRefundItem ($ orderItem )) {
803
+ return true ;
804
+ }
805
+ }
806
+
807
+ return false ;
808
+ }
809
+
765
810
/**
766
811
* Retrieve order hold availability
767
812
*
0 commit comments