Background:
You have an eCommerce order of 10 products but you want to refund only 5 of them. The stock managing system needs to preserve the order of row number (orderline) when you do the returns, but don't send the items that are not refunded.
The order looks like this:
"Poduct1" Orderline ="1"
"Poduct2" Orderline ="2"
"Poduct3" Orderline ="3"
"Poduct4" Orderline ="4"
Refund all except Product2
and Product3
becomes:
"Poduct1" Orderline ="1"
"Poduct4" Orderline ="4"
But the creditmemo
object returns it like this:
"Poduct1" Orderline ="1"
"Poduct4" Orderline ="2"
Because there is nothing in the refunded object about non-refunded items, my strategy is to compare the refund object with the order one and spot the difference (empty place).
Get order items and build and array of all SKUs:
$items = $products->getAllVisibleItems();
$all_skus = array();
foreach ($items as $key => $item) {
$all_sku = $item->getData("sku");
$all_skus[] = $all_sku;
}
Get refunded items and build an array of all SKUs:
$all_memo_skus = array();
foreach ($creditmemo->getAllItems() as $key => $item) {
$memo_sku = $item->getData('sku');
$all_memo_skus[] = $memo_sku;
}
Check the difference between them:
$memo_diff = array_diff($all_skus, $all_memo_skus);
returns keys and SKUs. But I'm interested only in the key, the position where there is an empty place:
$memo_diff = array_keys($memo_diff);
because the array starts at 0, but the Orderline
rows have to begin with 1, add 1 to each item of the array:
$memo_increase = array();
foreach($memo_diff as $val){
$memo_increase[] = $val + 1;
}
If there are consecutive numbers group them, for example if rows 2,3,4,5 are not refunded, you want the Orderline
to jump to 6.
Here I am grouping the consecutive rows:
$result = array();
$temp = array();
foreach($memo_increase as $val) {
if(next($memo_increase) == ($val + 1)){
$temp[] = $val;
}
else{
if(count($temp) > 0) {
$temp[] = $val;
$result[] = $temp[0].'-'.end($temp);
$temp = array();
}
else{
$result[] = $val;
}
}
}
This will return something like array("1", "4-9", "12")
if rows 1,4,5,6,7,8,9,12
are missing.
//start array key from 1 instead of 0
array_unshift($result,"");
unset($result[0]);
Then loop through each refunded item and assign it the right Orderline
:
$i = 1;
foreach ($creditmemo->getAllItems() as $key => $item) {
//if item is inside a grouped element, i.e 2-7 put the orderline at 2 then the next one at 8
foreach($result as $val){
if(strpos($val,"-")){
$piece = explode("-", $val);
if(($piece[0]) == $i){
$orderline = $piece[0];
$i = $piece[1] + 1;
}
}
}
//if item is single
if(in_array($i, $result)){
$orderline = $i+1;
$i++;
}
else{
$orderline = $i;
}
It is overly complex for such a simple task. Is there a better way?