'=', 'status' => '=', 'bill_no' => 'like', 'bill_date' => 'betweenDate', ]; /** 账单列表 */ #[GetRoute(authorize: 'query')] public function query(Request $request): JsonResponse { $params = $request->all(); $pageSize = $params['pageSize'] ?? 10; $query = BillModel::query()->with([ 'store:id,name', 'purchase:id,purchase_no,purchase_date', 'operator:id,nickname', ])->withCount('orders'); // 按采购单号搜索 $purchaseNo = trim((string) ($params['purchase_no'] ?? '')); if ($purchaseNo !== '') { $keyword = '%' . str_replace('%', '\%', $purchaseNo) . '%'; $query->whereHas('purchase', static function ($purchaseQuery) use ($keyword) { $purchaseQuery->where('purchase_no', 'like', $keyword); }); } $data = $this->buildSearch($params, $query) ->orderBy('bill_date', 'desc') ->orderBy('id', 'desc') ->paginate($pageSize) ->toArray(); return $this->success($data); } /** * 账单详情:账单信息 + 合并后的商品明细(按商品聚合)+ 关联订单 */ #[GetRoute(route: '/{id}', authorize: 'query', where: ['id' => '[0-9]+'])] public function detail(int $id): JsonResponse { $bill = BillModel::with([ 'store:id,name,address,contact,phone', 'purchase:id,purchase_no,purchase_date,status', 'operator:id,nickname', 'paidOperator:id,nickname', ])->find($id); if (empty($bill)) { throw new RepositoryException('账单不存在'); } $orders = $bill->orders() ->orderBy('id') ->get(['id', 'order_no', 'order_date', 'total_quantity', 'total_weight', 'total_amount', 'status']) ->toArray(); return $this->success([ 'bill' => $bill->toArray(), 'items' => app(BillDetailService::class)->mergedItems($bill), 'orders' => $orders, ]); } /** * 确认收款:线下收款后手动登记付款信息,支付状态置为已支付 */ #[PutRoute(route: '/{id}/pay', authorize: 'pay', where: ['id' => '[0-9]+'])] public function pay(int $id, Request $request): JsonResponse { $data = $request->validate([ 'paid_at' => 'sometimes|date_format:Y-m-d H:i:s', 'pay_remark' => 'nullable|string|max:255', ], [ 'paid_at.date_format' => '付款时间格式为 Y-m-d H:i:s', 'pay_remark.max' => '付款备注超过最大长度', ]); $bill = BillModel::find($id); if (empty($bill)) { throw new RepositoryException('账单不存在'); } if ($bill->status === BillModel::STATUS_PAID) { throw new RepositoryException('账单已支付,请勿重复收款'); } $bill->status = BillModel::STATUS_PAID; $bill->paid_at = $data['paid_at'] ?? now(); $bill->pay_remark = (string) ($data['pay_remark'] ?? ''); $bill->paid_operator_id = (int) $request->user()->id; $bill->save(); return $this->success([], '收款已登记'); } }