Merge duplicates in a grouped Laravel Collection and return a sum of a specific field

Viewed 163

Im making an app for a customer where the user can type in specifications of sold christmas trees, stored in a JSON format in the database as "line_items". It needs to be outputtet in a table on the delivery note for the customer to see. The user have cases where multiple pallets are loaded on to a truck with the same species of trees that share the same size. In that case I want to merge the duplicates and sum the amount.

I've come up with this:

$data = collect($deliveryNote->line_items)
->groupBy(['type', 'size']);

that gives me the output below.

{
"NGR": {
 "125-150": [
  {
   "slot": 2,
   "pallet": "cghjh",
   "type": "NGR",
   "label": "purple",
   "size": "125-150",
   "amount": "30"
  },
  {
   "slot": 3,
   "pallet": "cghjh",
   "type": "NGR",
   "label": "purple",
   "size": "125-150",
   "amount": "30"
  }
 ],
 "150-175": [
  {
   "slot": 2,
   "pallet": "yghiuj",
   "type": "NGR",
   "label": "orange",
   "size": "150-175",
   "amount": "30"
  }
 ]
 },
"NOB": {
 "125-150": [
  {
   "slot": 3,
   "pallet": "cghjh",
   "type": "NOB",
   "label": "purple",
   "size": "125-150",
   "amount": "30"
  }
 ]
 }
}

This is grouped almost how i want. Now i want to merge the duplicates, filter out the "slot", "pallet", "label" and update the amount for the collection to display like this:

{
"NGR": {
 "125-150": [
  {
   "type": "NGR",
   "size": "125-150",
   "amount": "60"
  },
 ],
 "150-175": [
  {
   "type": "NGR",
   "size": "150-175",
   "amount": "30"
  }
 ]
 },
"NOB": {
 "125-150": [
  {
   "type": "NOB",
   "size": "125-150",
   "amount": "30"
  }
 ]
 }
}

I've tried this:

$data = collect($deliveryNote->line_items)
->groupBy(['type', 'size']);
->map(function ($item) {
   return $item->sum('amount');
});

And it's not giving me the correct output.

I hope anybody has the the time to help me out. Thanks you in advance.

1 Answers

In your last example, you are only iterating the "NGR", "NOB" keys and therefor values, to get to the trees you want to sum, you have to go one level deeper in your iteration.

Having a hard time figuring out if line_items is a relationship or custom data set, assumptions written in comments.

$data = collect($deliveryNote->line_items)
    ->groupBy(['type', 'size']);
    ->map(function ($tree) {
        // i assume $trees is an array else don't wrap
        return collect($trees)->map(function ($shipments) {
            return [
                'amount' => $shipments->sum('amount'),
                // assuming object, if array access it like so
                'size' => $shipments->first()->size,
                'amount' => $shipments->first()->amount,
            ];
        });
    });
Related