diff --git a/app/Http/Controllers/Manager/OrdersController.php b/app/Http/Controllers/Manager/OrdersController.php index cc66845..015c039 100644 --- a/app/Http/Controllers/Manager/OrdersController.php +++ b/app/Http/Controllers/Manager/OrdersController.php @@ -854,7 +854,181 @@ class OrdersController extends CommonController $new_item = (new OrderItems())->createItem($order->id, $service_date); $unpaid_order_items->push($new_item); } - dd($unpaid_order_items); + + foreach ($unpaid_order_items as $order_item) { + //更新子订单支付状态 + $order_item->update(["paid_at" => date("Y-m-d H:i:s")]); + + //更新客户余额(暂不保存,最后统一保存) + $order->customer->balance = $order->customer->balance - $order_item->total; + + //创建收款记录 + (new Balance())->create([ + "customer_id" => $order->customer->id, + "order_id" => $order->id, + "belongs_type" => get_class($order_item), + "belongs_id" => $order_item->id, + "money" => -$order_item->total, + "balance" => $order->customer->balance + ]); + } + + $order->customer->save(); + + DB::commit(); + return response()->json([ + "checkout_items" => count($unpaid_order_items) + ]); + } catch (\Exception $exception) { + DB::rollBack(); + return response()->json([ + "errorcode" => $exception->getCode(), + "errormsg" => $exception->getMessage() + ]); + } + } + + /** + * @OA\POST( + * path="/manager/checkout-order/{order_id}", + * summary="V2-订单结算", + * description="交互流程如下:初次请求带上just_check参数,将返回to_recharge_total值;如果to_recharge_total大于0表示需要充值,充值完成之后,去除just_check参数再次提交;如果to_recharge_total <= 0,直接去除just_check参数再次提交", + * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), + * @OA\Parameter(name="order_id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), + * @OA\Parameter(name="to_date", in="query", @OA\Schema(type="date"), required=true, description="结算到的日子"), + * @OA\Parameter(name="just_check", in="query", @OA\Schema(type="boolean"), required=false, description="是否只是check一下要多少钱"), + * @OA\Response( + * response="200", + * description="中途结算", + * content={ + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="errorcode", + * type="integer", + * description="错误码;仅在发生错误时发送" + * ), + * @OA\Property( + * property="errormsg", + * type="string", + * description="返回消息;有errorcode时为错误内容,无errorcode时为提示内容" + * ), + * @OA\Property( + * property="prepay_total", + * type="decimal", + * description="总计需要预扣的金额,入参just_check为1时just_check为0但是客户余额不足时返回" + * ), + * @OA\Property( + * property="customer_balance", + * type="decimal", + * description="客户余额,入参just_check为1时just_check为0但是客户余额不足时返回" + * ), + * @OA\Property( + * property="to_recharge_total", + * type="decimal", + * description="需要充值的金额,入参just_check为1时(此时to_recharge_total值如果大于0则需要充值)或just_check为0但是客户余额不足时(此时to_recharge_total值一定大于0)返回" + * ), + * @OA\Property( + * property="updated_items", + * type="integer", + * description="结算的子订单总数;仅在成功的情况下发送" + * ), + * example={ + * "errorcode": "30003", + * "errormsg": "截止到中途结算日,没有需要结算的子订单,如需预充值请发起收款操作", + * "prepay_total": 1000, + * "customer_balance": 10, + * "to_recharge_total": 990, + * "checkout_items": 10 + * } + * ) + * ) + * } + * ) + * ) + */ + public function checkoutOrder($order_id, Request $request) + { + $order = Orders::with("customer")->find($order_id); + if ($order->status != Orders::STATUS_ONGOING) { + return response()->json([ + "errorcode" => 30000, + "errormsg" => "订单状态不匹配" + ]); + } + + $order_items = OrderItems::where("order_id", $order_id) + ->orderBy("service_date", "asc") + ->get(); + $last_paid_order_item = $order_items->filter(function ($item) { + return $item->total > 0 && $item->paid_at; + })->last(); + + //结算日早于最后一个已扣款的日期,退回先处理好子订单再结算 + if ($last_paid_order_item) { + if (Carbon::parse($last_paid_order_item->service_date)->greaterThan($request->to_date)) { + return response()->json([ + "errorcode" => 30006, + "errormsg" => "结算日不能早于最后一个已服务且扣款的子订单" + ]); + } + } + + //计算结算数据 + $unpaid_order_items = $order_items->filter(function ($item) { + return $item->total > 0 && !$item->paid_at; + }); + if ($order_items->count()) { + $to_generate_days = Carbon::parse($order_items->last()->service_date)->diffInDays($request->to_date, false); + $to_generate_start_date = Carbon::parse($order_items->last()->service_date)->addDay()->toDateString(); + } else { + $to_generate_days = Carbon::parse($order->from_date)->diffInDays($request->to_date, false) + 1; + $to_generate_start_date = $order->from_date; + } + $to_generate_days = max(0, $to_generate_days); + $prepay_total = $unpaid_order_items->sum("total") + $to_generate_days * $order->price; + $to_recharge_total = $prepay_total - $order->customer->balance; + + //如果只是检查一下需要充值金额,直接返回 + if ($request->just_check) { + return response()->json([ + "prepay_total" => $prepay_total, + "customer_balance" => $order->customer->balance, + "to_recharge_total" => $to_recharge_total + ]); + } + + //没有需要操作的子订单,无意义 + if (!$unpaid_order_items->count() && !$to_generate_days) { + return response()->json([ + "errorcode" => 30001, + "errormsg" => "截止到中途结算日,没有需要结算的子订单,如需预充值请发起收款操作" + ]); + } + + //需要预先充值 + if ($to_recharge_total > 0) { + return response()->json([ + "errorcode" => 30002, + "errormsg" => "余额不足,请先充值", + "prepay_total" => $prepay_total, + "customer_balance" => $order->customer->balance, + "to_recharge_total" => $to_recharge_total + ]); + } + + DB::beginTransaction(); + try { + for ($i = 0; $i < $to_generate_days; $i++) { + if ($i > 0) { + $service_date = Carbon::parse($to_generate_start_date)->addDays($i)->toDateString(); + } else { + $service_date = $to_generate_start_date; + } + $new_item = (new OrderItems())->createItem($order->id, $service_date); + $unpaid_order_items->push($new_item); + } foreach ($unpaid_order_items as $order_item) { //更新子订单支付状态 diff --git a/app/Models/OrderItems.php b/app/Models/OrderItems.php index d5dd924..66651d6 100755 --- a/app/Models/OrderItems.php +++ b/app/Models/OrderItems.php @@ -12,6 +12,20 @@ class OrderItems extends SoftDeletesModel protected $table = "order_items"; CONST PREV_MONTH = "往月服务单"; + protected $appends = ["paid_status"]; + + public function getPaidStatusAttribute() + { + if (!($this->total) > 0) { + return "未服务"; + } + if ($this->paid_at) { + return "已扣款"; + } else { + return "未扣款"; + } + } + public function order() { return $this->belongsTo(Orders::class);