1616use Magento \Sales \Model \Order \Creditmemo ;
1717use Magento \Sales \Model \Order \Item ;
1818use Magento \Sales \Model \ValidatorInterface ;
19+ use Magento \Sales \Api \Data \CreditmemoItemInterface ;
20+ use Magento \Framework \Phrase ;
1921
2022/**
2123 * Creditmemo QuantityValidator
@@ -74,23 +76,13 @@ public function validate($entity)
7476
7577 $ totalQuantity = 0 ;
7678 foreach ($ entity ->getItems () as $ item ) {
77- if (!isset ($ orderItemsById [$ item ->getOrderItemId ()])) {
78- $ messages [] = __ (
79- 'The creditmemo contains product SKU "%1" that is not part of the original order. ' ,
80- $ item ->getSku ()
81- );
82- continue ;
83- }
84- $ orderItem = $ orderItemsById [$ item ->getOrderItemId ()];
85-
86- if (!$ this ->canRefundItem ($ orderItem , $ item ->getQty (), $ invoiceQtysRefundLimits ) ||
87- !$ this ->isQtyAvailable ($ orderItem , $ item ->getQty ())
88- ) {
89- $ messages [] =__ (
90- 'The quantity to creditmemo must not be greater than the unrefunded quantity '
91- . ' for product SKU "%1". ' ,
92- $ orderItem ->getSku ()
93- );
79+ $ message = $ this ->validateTotalQuantityRefundable (
80+ $ orderItemsById ,
81+ $ item ,
82+ $ invoiceQtysRefundLimits
83+ );
84+ if ($ message ) {
85+ $ messages [] = $ message ;
9486 } else {
9587 $ totalQuantity += $ item ->getQty ();
9688 }
@@ -105,6 +97,60 @@ public function validate($entity)
10597 return $ messages ;
10698 }
10799
100+ /**
101+ * To check the refund qty is decimal if getIsQtyDecimal is unset.
102+ *
103+ * @param mixed $isQtyDecimal
104+ * @param float $itemQty
105+ * @return bool
106+ */
107+ private function isValidDecimalRefundQty ($ isQtyDecimal , float $ itemQty ): bool
108+ {
109+ if (!$ isQtyDecimal && (floor ($ itemQty ) !== $ itemQty )) {
110+ return false ;
111+ }
112+ return true ;
113+ }
114+
115+ /**
116+ * Calculate total quantity.
117+ *
118+ * @param array $orderItemsById
119+ * @param CreditmemoItemInterface $item
120+ * @param array $invoiceQtysRefundLimits
121+ * @return Phrase|void
122+ */
123+ private function validateTotalQuantityRefundable (
124+ array $ orderItemsById ,
125+ CreditmemoItemInterface $ item ,
126+ array $ invoiceQtysRefundLimits
127+ ) {
128+ if (!isset ($ orderItemsById [$ item ->getOrderItemId ()])) {
129+ return __ (
130+ 'The creditmemo contains product SKU "%1" that is not part of the original order. ' ,
131+ $ item ->getSku ()
132+ );
133+ }
134+ $ orderItem = $ orderItemsById [$ item ->getOrderItemId ()];
135+
136+ if (!$ this ->isValidDecimalRefundQty ($ orderItem ->getIsQtyDecimal (), $ item ->getQty ())) {
137+ return __ (
138+ 'We found an invalid quantity to refund item "%1". ' ,
139+ $ orderItem ->getSku ()
140+ );
141+ }
142+
143+ if (!$ this ->canRefundItem ($ orderItem , $ item ->getQty (), $ invoiceQtysRefundLimits ) ||
144+ !$ this ->isQtyAvailable ($ orderItem , $ item ->getQty ())
145+ ) {
146+ return __ (
147+ 'The quantity to creditmemo must not be greater than the unrefunded quantity '
148+ . ' for product SKU "%1". ' ,
149+ $ orderItem ->getSku ()
150+ );
151+ }
152+ }
153+
108154 /**
109155 * We can have problem with float in php (on some server $a=762.73;$b=762.73; $a-$b!=0)
110156 * for this we have additional diapason for 0
0 commit comments