修复一些错误
This commit is contained in:
@@ -9,6 +9,7 @@ use App\Models\ProductPriceModel;
|
||||
use App\Models\StoreOrderItemModel;
|
||||
use App\Models\StoreOrderModel;
|
||||
use App\Services\BillNumberService;
|
||||
use App\Services\ItemImageResolver;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -161,7 +162,7 @@ class OrderController extends BaseMiniController
|
||||
'total_amount', 'status', 'remark', 'purchase_id', 'bill_id', 'created_at',
|
||||
])
|
||||
->with(['items' => static fn ($itemsQuery) => $itemsQuery
|
||||
->select(['id', 'order_id', 'product_name', 'quantity', 'unit'])
|
||||
->select(['id', 'order_id', 'product_name', 'product_spec', 'quantity', 'unit', 'image_ids'])
|
||||
->orderBy('id')]);
|
||||
if (isset($params['status'])) {
|
||||
$query->where('status', (int) $params['status']);
|
||||
@@ -177,6 +178,28 @@ class OrderController extends BaseMiniController
|
||||
->orderBy('id', 'desc')
|
||||
->paginate((int) ($params['pageSize'] ?? 10));
|
||||
|
||||
// 商品预览(每单前 3 条明细):首图跨订单一次性批量解析
|
||||
$previewMap = [];
|
||||
$flatItems = [];
|
||||
foreach ($paginator->getCollection() as $order) {
|
||||
foreach ($order->items as $item) {
|
||||
$flatItems[] = [
|
||||
'order_id' => $order->id,
|
||||
'product_name' => $item->product_name,
|
||||
'product_spec' => $item->product_spec,
|
||||
'quantity' => $item->quantity,
|
||||
'unit' => $item->unit,
|
||||
'image_ids' => (array) $item->image_ids,
|
||||
];
|
||||
}
|
||||
}
|
||||
app(ItemImageResolver::class)->resolve($flatItems);
|
||||
foreach ($flatItems as $flatItem) {
|
||||
$orderId = $flatItem['order_id'];
|
||||
unset($flatItem['order_id']);
|
||||
$previewMap[$orderId][] = $flatItem;
|
||||
}
|
||||
|
||||
$paginator->getCollection()->transform(
|
||||
static fn (StoreOrderModel $order): array => [
|
||||
'id' => $order->id,
|
||||
@@ -193,12 +216,7 @@ class OrderController extends BaseMiniController
|
||||
'bill_id' => $order->bill_id,
|
||||
'created_at' => $order->created_at?->toDateTimeString(),
|
||||
'item_count' => $order->items->count(),
|
||||
'items' => $order->items->take(3)
|
||||
->map(static fn (StoreOrderItemModel $item): array => [
|
||||
'product_name' => $item->product_name,
|
||||
'quantity' => $item->quantity,
|
||||
'unit' => $item->unit,
|
||||
])->values()->all(),
|
||||
'items' => $previewMap[$order->id] ?? [],
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
@@ -46,35 +46,76 @@ class ProductController extends BaseMiniController
|
||||
}
|
||||
|
||||
$pageSize = (int) $request->input('pageSize', 10);
|
||||
$data = $query->orderBy('sort')
|
||||
$paginator = $query->orderBy('sort')
|
||||
->orderBy('id')
|
||||
->paginate($pageSize)
|
||||
->toArray();
|
||||
->paginate($pageSize);
|
||||
|
||||
foreach ($data['data'] as &$row) {
|
||||
$row['price'] = null;
|
||||
// 当前门店的等级价格(一次性取出,避免逐行查询)
|
||||
$user = $this->optionalUser($request);
|
||||
$store = $user !== null ? $this->boundStore($user) : null;
|
||||
$priceRows = collect();
|
||||
if ($store !== null && $store->level_id > 0) {
|
||||
$priceRows = ProductPriceModel::query()
|
||||
->where('level_id', $store->level_id)
|
||||
->whereIn('product_id', $paginator->getCollection()->pluck('id'))
|
||||
->get(['product_id', 'price', 'price_type', 'percent'])
|
||||
->keyBy('product_id');
|
||||
}
|
||||
|
||||
// 用户
|
||||
$user = $this->optionalUser($request);
|
||||
if (!$user) return $this->success($data);
|
||||
// 门店
|
||||
$store = $this->boundStore($user);
|
||||
if(!$store) return $this->success($data);
|
||||
$paginator->getCollection()->transform(
|
||||
static function (ProductModel $product) use ($priceRows): array {
|
||||
$row = $product->toArray();
|
||||
// 实际价(百分比计价行按成本价上浮换算;成本价不随序列化输出)
|
||||
$priceRow = $priceRows->get($product->id);
|
||||
$row['price'] = $priceRow !== null
|
||||
? ProductPriceModel::calcActualPrice(
|
||||
(int) $priceRow->price_type,
|
||||
(string) $priceRow->price,
|
||||
(string) $priceRow->percent,
|
||||
(string) $product->cost_price,
|
||||
)
|
||||
: null;
|
||||
return $row;
|
||||
}
|
||||
);
|
||||
|
||||
if ($store->level_id > 0) {
|
||||
foreach ($data['data'] as &$row) {
|
||||
$model = ProductPriceModel::where('product_id', $row['id'])->where('level_id', $store->level_id)->first();
|
||||
return $this->success($paginator->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品详情(免登录浏览;登录门店按等级显示换算价,未登录/未绑店/未设等级 price=null)
|
||||
*/
|
||||
#[GetRoute('/product/{id}', authorize: false, where: ['id' => '[0-9]+'])]
|
||||
public function detail(int $id, Request $request): JsonResponse
|
||||
{
|
||||
$product = ProductModel::query()
|
||||
->where('status', ProductModel::STATUS_ON)
|
||||
->with('category:id,name')
|
||||
->find($id);
|
||||
if ($product === null) {
|
||||
throw new RepositoryException('商品不存在或已下架');
|
||||
}
|
||||
|
||||
$price = null;
|
||||
$user = $this->optionalUser($request);
|
||||
$store = $user !== null ? $this->boundStore($user) : null;
|
||||
if ($store !== null && $store->level_id > 0) {
|
||||
$priceRow = ProductPriceModel::query()
|
||||
->forProductLevel($product->id, $store->level_id)
|
||||
->first(['price', 'price_type', 'percent']);
|
||||
if ($priceRow !== null) {
|
||||
$price = ProductPriceModel::calcActualPrice(
|
||||
$model->price_type,
|
||||
$model->price,
|
||||
$model->percent,
|
||||
$row->cost_price,
|
||||
(int) $priceRow->price_type,
|
||||
(string) $priceRow->price,
|
||||
(string) $priceRow->percent,
|
||||
(string) $product->cost_price,
|
||||
);
|
||||
$row['price'] = $price;
|
||||
}
|
||||
}
|
||||
|
||||
$data = $product->toArray();
|
||||
$data['price'] = $price;
|
||||
|
||||
return $this->success($data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Order;
|
||||
|
||||
use App\Exceptions\RepositoryException;
|
||||
use App\Models\BillModel;
|
||||
use App\Models\NoticeModel;
|
||||
use App\Models\StoreOrderModel;
|
||||
use App\Models\UserModel;
|
||||
@@ -38,7 +39,8 @@ class StoreOrderController extends BaseController
|
||||
$query = StoreOrderModel::query()->with([
|
||||
'store:id,name,address,contact,phone',
|
||||
'items:id,order_id,product_id,product_name,product_spec,unit,price,quantity,amount,image_ids',
|
||||
'purchase:id,purchase_no,purchase_date,status'
|
||||
'purchase:id,purchase_no,purchase_date,status',
|
||||
'bill:id,bill_no,bill_date,total_amount,status,payment_id,paid_at',
|
||||
]);
|
||||
|
||||
// 按包含的商品名称搜索:任一明细品名包含关键字即命中
|
||||
@@ -65,6 +67,7 @@ class StoreOrderController extends BaseController
|
||||
// 明细封面图:从快照 image_ids 批量解析(不再关联商品档案表)
|
||||
foreach ($data['data'] as &$order) {
|
||||
app(ItemImageResolver::class)->resolve($order['items']);
|
||||
$this->appendBillPayState($order);
|
||||
}
|
||||
unset($order);
|
||||
|
||||
@@ -78,6 +81,7 @@ class StoreOrderController extends BaseController
|
||||
$order = StoreOrderModel::with([
|
||||
'store:id,name,address,contact,phone',
|
||||
'items' => static fn ($query) => $query->with('supplier:id,name'),
|
||||
'bill',
|
||||
])->find($id);
|
||||
if (empty($order)) {
|
||||
throw new RepositoryException('订单不存在');
|
||||
@@ -90,6 +94,8 @@ class StoreOrderController extends BaseController
|
||||
|
||||
// 明细首图
|
||||
app(ItemImageResolver::class)->resolve($data['items']);
|
||||
// 关联账单详情:补充支付进度
|
||||
$this->appendBillPayState($data);
|
||||
|
||||
return $this->success($data);
|
||||
}
|
||||
@@ -234,4 +240,21 @@ class StoreOrderController extends BaseController
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单输出数组的关联账单补充支付进度(待支付/审核中/已支付,与小程序端口径一致)
|
||||
*
|
||||
* @param array<string, mixed> $order 订单数组(引用修改)
|
||||
*/
|
||||
private function appendBillPayState(array &$order): void
|
||||
{
|
||||
if (! is_array($order['bill'] ?? null)) {
|
||||
return;
|
||||
}
|
||||
// 复用模型支付进度推导(已支付 > 审核中 > 待支付)
|
||||
$bill = new BillModel($order['bill']);
|
||||
$payState = $bill->payState();
|
||||
$order['bill']['pay_state'] = $payState;
|
||||
$order['bill']['pay_state_name'] = BillModel::PAY_STATE_NAMES[$payState];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,10 @@ class PaymentModel extends Model
|
||||
if ($ids === []) {
|
||||
return [];
|
||||
}
|
||||
$urls = SysFileModel::query()->whereIn('id', $ids)->pluck('preview_url', 'id');
|
||||
$urls = [];
|
||||
foreach (SysFileModel::query()->whereIn('id', $ids)->get() as $file) {
|
||||
$urls[$file->id] = $file->preview_url;
|
||||
}
|
||||
$result = [];
|
||||
foreach ($ids as $id) {
|
||||
if (isset($urls[$id])) {
|
||||
|
||||
@@ -14,9 +14,9 @@ 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}>
|
||||
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string, image: string}>
|
||||
*/
|
||||
public function mergedItems(BillModel $bill): array
|
||||
{
|
||||
@@ -33,7 +33,7 @@ class BillDetailService
|
||||
* 用于账单合并导出,单价同为加权平均口径
|
||||
*
|
||||
* @param array<int, int> $billIds 账单ID列表
|
||||
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string}>
|
||||
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string, image: string}>
|
||||
*/
|
||||
public function mergedItemsOfBills(array $billIds): array
|
||||
{
|
||||
@@ -47,10 +47,10 @@ class BillDetailService
|
||||
|
||||
/**
|
||||
* 按商品聚合订单明细:数量累加、重量/金额 bc 累加、单价加权平均,
|
||||
* 按「分类sort → 商品sort」排序
|
||||
* 首图取明细快照 image_ids 批量解析,按「分类sort → 商品sort」排序
|
||||
*
|
||||
* @param Collection<int, StoreOrderItemModel> $items
|
||||
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string}>
|
||||
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string, image: string}>
|
||||
*/
|
||||
private function aggregateItems(Collection $items): array
|
||||
{
|
||||
@@ -85,6 +85,7 @@ class BillDetailService
|
||||
'quantity' => $quantity,
|
||||
'weight' => $weight,
|
||||
'amount' => $amount,
|
||||
'image_ids' => (array) $first->image_ids,
|
||||
'category_sort' => (int) ($product->category->sort ?? 9999),
|
||||
'product_sort' => (int) ($product->sort ?? 9999),
|
||||
];
|
||||
@@ -93,6 +94,9 @@ class BillDetailService
|
||||
[$a['category_sort'], $a['product_sort'], $a['product_id']]
|
||||
<=> [$b['category_sort'], $b['product_sort'], $b['product_id']]);
|
||||
|
||||
// 首图批量解析(写入 image、移除 image_ids)
|
||||
app(ItemImageResolver::class)->resolve($rows);
|
||||
|
||||
return array_map(static function (array $row): array {
|
||||
unset($row['category_sort'], $row['product_sort']);
|
||||
return $row;
|
||||
|
||||
Reference in New Issue
Block a user