Files
xin-procurement/app/Services/BillDetailService.php
T
2026-08-14 01:19:47 +08:00

72 lines
2.6 KiB
PHP

<?php
namespace App\Services;
use App\Models\BillModel;
use App\Models\ProductModel;
use App\Models\StoreOrderItemModel;
/**
* 账单详情数据组装(后台门店账单页与小程序账单详情共用)
*/
class BillDetailService
{
/**
* 合并后的商品明细:按商品聚合账单关联的全部订单明细
* 单价为加权平均口径(Σ金额÷Σ数量),保证 单价×数量=金额
*
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string}>
*/
public function mergedItems(BillModel $bill): array
{
$items = StoreOrderItemModel::query()
->where('bill_id', $bill->id)
->orderBy('id')
->get();
// 排序键:分类 sort → 商品 sort(与采购单明细矩阵同序)
$products = ProductModel::withTrashed()
->with('category:id,sort')
->whereIn('id', $items->pluck('product_id')->unique())
->get()
->keyBy('id');
$rows = [];
foreach ($items->groupBy('product_id') as $productId => $group) {
$product = $products->get((int) $productId);
$first = $group->first();
$quantity = 0;
$weight = '0';
$amount = '0';
foreach ($group as $item) {
$quantity += (int) $item->quantity;
$weight = bcadd($weight, (string) $item->weight, 3);
$amount = bcadd($amount, (string) $item->amount, 2);
}
$rows[] = [
'product_id' => (int) $productId,
'product_name' => $first->product_name,
'product_spec' => $first->product_spec,
'unit' => $first->unit,
'price' => $quantity > 0
? bcdiv($amount, (string) $quantity, 2)
: (string) $first->price,
'quantity' => $quantity,
'weight' => $weight,
'amount' => $amount,
'category_sort' => (int) ($product->category->sort ?? 9999),
'product_sort' => (int) ($product->sort ?? 9999),
];
}
usort($rows, static fn (array $a, array $b): int =>
[$a['category_sort'], $a['product_sort'], $a['product_id']]
<=> [$b['category_sort'], $b['product_sort'], $b['product_id']]);
return array_map(static function (array $row): array {
unset($row['category_sort'], $row['product_sort']);
return $row;
}, $rows);
}
}