Files
xin-procurement/app/Http/Controllers/Recon/BillController.php
T
2026-08-14 01:19:47 +08:00

117 lines
3.9 KiB
PHP

<?php
namespace App\Http\Controllers\Recon;
use App\Exceptions\RepositoryException;
use App\Models\BillModel;
use App\Services\BillDetailService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\AnnoRoute\Attribute\GetRoute;
use Modules\AnnoRoute\Attribute\PutRoute;
use Modules\AnnoRoute\Attribute\RequestAttribute;
use Modules\Common\Http\Controllers\BaseController;
/**
* 门店账单管理(采购单完成后按门店生成,后台查看 + 线下收款登记)
*/
#[RequestAttribute('/recon/bill', 'recon.bill')]
class BillController extends BaseController
{
protected array $searchField = [
'store_id' => '=',
'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([], '收款已登记');
}
}