join("manager_project", 'project.id', '=', 'manager_project.project_id') ->join('managers', 'managers.id', '=', 'manager_project.manager_id') ->whereRaw("managers.id = " . $this->manager->id) ->select("project.id", "project.name", "project.address", "project.latitude", "project.longitude") ->get(); return response()->json($projects->toArray()); } /** * @OA\Get( * path="/manager/get-care-product/{project_id}", * summary="V2-获取产品详情", * description="获取产品详情", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="project_id", in="path", @OA\Schema(type="integer"), required=true, description="project_id"), * @OA\Response( * response="200", * description="获取产品详情" * ) * ) */ public function getCareProduct($project_id) { DB::enableQueryLog(); $product = (new Product())->where("project_id", $project_id)->with([ "productItems" => function ($query) { $query->select("id", "name", "product_id", "patient_quantity", "price"); }, "productParamedicLevels" => function ($query) { $query ->select("product_paramedic_level.id", "product_paramedic_level.product_id", "product_paramedic_level.price") ->leftJoin("paramedic_level", "product_paramedic_level.paramedic_level_id", "=", "paramedic_level.id") ->addSelect("paramedic_level.name as paramedic_level_name"); }, "factors" => function ($query) { $query->with(["factorItems" => function ($query) { $query->select("id", "name", "factor_id", "price", "myindex")->orderBy("myindex"); }])->select("id", "name", "product_id")->orderBy("myindex"); }]) ->leftJoin("project", "project.id", "=", "product.project_id") ->select("product.id", "product.name", "product.project_id", "project.name as project_name")->first(); return response()->json($product->toArray()); } /** * @OA\Get( * path="/manager/get-project-orders-count/{project_id}", * summary="V2-获取医院订单数量角标", * description="获取医院订单数量角标", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="project_id", in="query", @OA\Schema(type="integer"), required=true, description="医院id"), * @OA\Response( * response="200", * description="获取医院订单数量角标" * ) * ) */ public function getProjectOrdersCount($project_id) { $orders_count = []; $orders_count["all"] = (new Orders())->ofProject($project_id)->count(); $orders_count["pending"] = (new Orders())->ofProject($project_id)->whereIn("status", [Orders::STATUS_UNCONFIRMED, Orders::STATUS_UNASSIGNED])->count(); $orders_count["ongoing"] = (new Orders())->ofProject($project_id)->where("status", Orders::STATUS_ONGOING)->count(); $orders_count["finished"] = (new Orders())->ofProject($project_id)->where("status", Orders::STATUS_ONGOING)->count(); return response()->json(compact("orders_count")); } /** * @OA\Get( * path="/manager/get-projcet-orders/{project_id}", * summary="V2-获取订单列表", * description="获取订单列表", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="project_id", in="path", @OA\Schema(type="integer"), required=false, description="医院ID"), * @OA\Parameter(name="keyword", in="query", @OA\Schema(type="string"), required=false, description="查询关键词"), * @OA\Parameter(name="page", in="query", @OA\Schema(type="integer"), required=false, description="当前页码,默认为1"), * @OA\Parameter(name="page_size", in="query", @OA\Schema(type="integer"), required=false, description="每页数量,默认为5"), * @OA\Parameter(name="status", in="query", @OA\Schema(type="string"), required=false, description="订单状态:[unconfirmed=>待确认,unassigned=>待派单,ongoing=>进行中,finished=>已完成]"), * @OA\Response( * response="200", * description="获取订单列表" * ) * ) */ public function list() { $data = (new Orders()); if (request()->keyword) { $keyword = request()->keyword; $data = $data->where(function ($query) use ($keyword) { $query ->where("serial", "like", "%{$keyword}%") ->orWhereHas("patient", function ($query) use ($keyword) { $query->where("name", "like", "%{$keyword}%"); })->orWhereHas("paramedic", function ($query) use ($keyword) { $query->where("name", "like", "%{$keyword}%"); }); }); } switch (request()->status) { case "unconfirmed": $data = $data ->where("status", Orders::STATUS_UNCONFIRMED) ->ofProject($this->manager->projects->pluck("id")->toArray()); break; case "unassigned": case "ongoing": case "finished": $data = $data ->where("status", constant(Orders::class . "::STATUS_" . strtoupper(request()->status))) ->ofProject($this->manager->projects->pluck("id")->toArray()); break; default: $data = $data ->ofProject($this->manager->projects->pluck("id")->toArray()); } $page_size = request()->page_size ?? 5; $data = $data ->with([ "patient" => function ($query) { $query->select("id", "customer_id", "name", "sex", "age"); }, "productItem", "productParamedicLevel", "bed" => function ($query) { $query->with(["room", "building"])->select("id", "room_id", "building_id"); }, "paramedic" => function ($query) { $query->select(); } ]) ->orderBy("id", "desc") ->select("id", "serial", "customer_id", "patient_id", "project_id", "product_id", "manager_id", "from_date", "to_date", "remark", "status", "contact", "mobile", "price", "patient_quantity") ->paginate($page_size); foreach ($data as $order) { $order = $order->refreshTotal(); } return response()->json($data->toArray()); } /** * @OA\Get( * path="/manager/get-order/{id}", * summary="V2-获取订单详情", * description="获取订单详情", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="id"), * @OA\Response( * response="200", * description="获取订单详情" * ) * ) */ public function getOrder($id) { //todo:check order belongs to manager $order = (new Orders())->with([ "orderItems" => function ($query) { $query->with([ "bed" => function ($query) { $query->with(["room", "building"]); }, "room", "building", "paramedic", "productParamedicLevel", "paramedicLevel" ]); }, "project", "product" => function ($query) { $query->with(["productParamedicLevels" => function ($query) { $query->with("paramedicLevel"); }]); }, "customer", "manager", "patient", "productItem", "productParamedicLevel", "bed" => function ($query) { $query->with(["room", "building"]); }, "room", "building", "paramedic", "handlingApprovalItem" => function ($query) { $query->with("approval"); }, "recharges" => function ($query) { $query->with("manager"); }, "refunds" => function ($query) { $query->with("manager"); } ])->find($id); $order = $order->refreshTotal(); $order->balance = $order->customer->balance; return response()->json($order->toArray()); } /** * @OA\Get( * path="/manager/get-project-areas/{project_id}", * summary="V2-获取医院病区", * description="获取医院病区", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="project_id", in="path", @OA\Schema(type="integer"), required=true, description="project id"), * @OA\Response( * response="200", * description="获取医院床位" * ) * ) */ public function getProjectAreas($project_id) { $areas = (new Area()) ->where("area.project_id", $project_id) ->select("area.id", "area.name", "area.building_id") ->leftJoin("building", "building.id", "=", "area.building_id") ->addSelect("building.name as building_name") ->orderBy("building.myindex") ->orderBy("area.myindex") ->get(); return response()->json($areas->toArray()); } /** * @OA\Get( * path="/manager/get-area-beds/{area_id}", * summary="V2-根据病区获取病床", * description="根据病区获取病床", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="area_id", in="path", @OA\Schema(type="integer"), required=true, description="area id"), * @OA\Response( * response="200", * description="根据病区获取病床" * ) * ) */ public function getAreaBeds($area_id) { $beds = (new Bed()) ->where("bed.area_id", $area_id) ->select("bed.id", "bed.name", "bed.area_id", "bed.room_id") ->leftJoin("room", "room.id", "=", "bed.room_id") ->addSelect("room.name as room_name") ->orderBy("bed.name") ->get(); return response()->json($beds->toArray()); } /** * @OA\Get( * path="/manager/get-available-paramedics", * summary="V2-获取可用护工列表(已基本准确,需进一步打磨)", * description="获取可用护工列表", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="bed_id", in="query", @OA\Schema(type="integer"), required=true, description="床位ID"), * @OA\Parameter(name="sex", in="query", @OA\Schema(type="string"), required=true, description="性别:[男/女]"), * @OA\Parameter(name="start_date", in="query", @OA\Schema(type="string"), required=false, description="日期,默认为当天"), * @OA\Parameter(name="factors", in="query", @OA\Schema(type="object"), required=true, description="价格因子选择,[{id:1,factor_item_id:1},{...}],如果为空数组请传[]"), * @OA\Response( * response="200", * description="获取可用护工列表" * ) * ) */ public function getAvailableParamedics(Request $request) { $paramedics = (new Orders())->getAvailableParamedics(); return response()->json($paramedics); } /** * @OA\Get( * path="/manager/get-project-paramedics/{project_id}", * summary="V2-获取护工", * description="获取护工", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="project_id", in="path", @OA\Schema(type="string"), required=true, description="医院id"), * @OA\Parameter(name="keyword", in="query", @OA\Schema(type="string"), required=true, description=""), * @OA\Parameter(name="page", in="query", @OA\Schema(type="integer"), required=false, description="当前页码,默认为1"), * @OA\Parameter(name="page_size", in="query", @OA\Schema(type="integer"), required=false, description="每页数量,默认为5"), * @OA\Parameter(name="has_ongoing_orders", in="query", @OA\Schema(type="integer"), required=false, description="是否空闲的筛选,枚举[0,1]"), * @OA\Response( * response="200", * description="获取护工" * ) * ) */ public function getProjectParamedics() { $paramedics = new Paramedic(); if (request()->keyword) { $keyword = request()->keyword; $paramedics = $paramedics->where(function ($query) use ($keyword) { $query ->where("name", "like", "%{$keyword}%") ->orWhere("serial", "like", "%{$keyword}%"); }); } $paramedics = $paramedics->OfProject(request()->project_id); switch (request()->has_ongoing_orders) { case "1": $paramedics = $paramedics->has("ongoingOrders"); break; case "0": $paramedics = $paramedics->doesntHave("ongoingOrders"); break; default: //do nothing } $page_size = request()->page_size ? (int)request()->page_size : 5; $paramedics = $paramedics ->select("id", "name", "sex", "mobile", "birthday", "avatar", "health_certificate", "work_certificate") ->withCount("ongoingOrders") ->orderBy("ongoing_orders_count") ->paginate($page_size); return response()->json($paramedics->toArray()); } /** * @OA\Get( * path="/manager/get-paramedic/{id}", * summary="V2-获取护工详情", * description="获取护工详情", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="id"), * @OA\Response( * response="200", * description="获取护工详情" * ) * ) */ public function getParamedic($id) { $paramedic = (new Paramedic())->with([ "project" => function ($query) { $query->select("id", "name", "address"); }, "level" => function ($query) { $query->select("id", "name"); } ])->find($id); return response()->json($paramedic ? $paramedic->toArray() : null); } /** * @OA\POST( * path="/manager/create-patient", * summary="V2-创建被护理人", * description="创建被护理人", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="name", in="query", @OA\Schema(type="string"), required=true, description="姓名"), * @OA\Parameter(name="sex", in="query", @OA\Schema(type="string"), required=true, description="性别:[男/女]"), * @OA\Parameter(name="age", in="query", @OA\Schema(type="integer"), required=true, description="年龄,只需填写入院时的年龄"), * @OA\Response( * response="200", * description="创建被护理人" * ) * ) */ public function createPatient() { $data = [ "name" => request()->name, "sex" => request()->sex, "age" => request()->age, "mobile" => request()->mobile ]; $vo = (new Patient())->create($data); return response()->json($vo); } /** * @OA\POST( * path="/manager/create-order", * summary="V2-创建订单", * description="创建订单", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="product_id", in="query", @OA\Schema(type="integer"), required=true, description="产品id"), * @OA\Parameter(name="product_item_id", in="query", @OA\Schema(type="integer"), required=true, description="产品型号id"), * @OA\Parameter(name="product_paramedic_level_id", in="query", @OA\Schema(type="integer"), required=true, description="产品-护工等级id"), * @OA\Parameter(name="factors", in="query", @OA\Schema(type="object"), required=true, description="价格因子选择,[{id:1,factor_item_id:1},{...}],如果为空数组请传[]"), * @OA\Parameter(name="bed_id", in="query", @OA\Schema(type="integer"), required=true, description="床位id"), * @OA\Parameter(name="paramedic_id", in="query", @OA\Schema(type="integer"), required=false, description="护工id"), * @OA\Parameter(name="patient_name", in="query", @OA\Schema(type="string"), required=true, description="被护理人姓名"), * @OA\Parameter(name="patient_mobile", in="query", @OA\Schema(type="string"), required=true, description="被护理人电话"), * @OA\Parameter(name="patient_sex", in="query", @OA\Schema(type="string"), required=true, description="被护理人性别:男,女"), * @OA\Parameter(name="patient_age", in="query", @OA\Schema(type="string"), required=true, description="被护理人年龄"), * @OA\Parameter(name="contact", in="query", @OA\Schema(type="string"), required=false, description="联系人"), * @OA\Parameter(name="mobile", in="query", @OA\Schema(type="string"), required=false, description="联系人电话"), * @OA\Parameter(name="from_date", in="query", @OA\Schema(type="string"), required=true, description="开始日期"), * @OA\Parameter(name="to_date", in="query", @OA\Schema(type="string"), required=true, description="结束日期"), * @OA\Parameter(name="price", in="query", @OA\Schema(type="number"), required=true, description="协商价格"), * @OA\Response( * response="200", * description="创建订单" * ) * ) */ public function createOrder() { DB::beginTransaction(); try { $customer = (new Customer())->firstOrCreate([ "mobile" => trim(request()->mobile) ]); $has_orders = Orders::where("customer_id", $customer->id)->whereIn("status", [Orders::STATUS_UNCONFIRMED, Orders::STATUS_UNASSIGNED, Orders::STATUS_ONGOING])->count(); if ($has_orders) { return response()->json([ "errorcode" => "0", "errormsg" => "客户名下有即将开始或正在进行中的订单,暂不可以再次下单" ]); } $product = (new Product())->find(request()->product_id); $product_paramedic_level = (new ProductParamedicLevel())->find(request()->product_paramedic_level_id); $product_item = (new ProductItems())->find(request()->product_item_id); $price = $product_item->price + $product_paramedic_level->price; $factors = (new Orders())->requestFactorsToOrderFactors(); $price += collect($factors)->sum("price"); if (request()->price < $price) { return response()->json([ "errorcode" => "0", "errormsg" => "协商价格不能低于系统指导价" ]); } $patient = (new Patient())->firstOrCreate([ "customer_id" => $customer->id, "name" => request()->patient_name ]); $patient->update([ "age" => request()->patient_age, "sex" => request()->patient_sex, "mobile" => request()->patient_mobile, ]); $order = (new Orders())->create([ "customer_id" => $customer->id, "project_id" => $product->id, "product_id" => request()->product_id, "patient_id" => $patient->id, "contact" => request()->contact ?? request()->patient_name, "mobile" => request()->mobile ?? request()->patient_mobile, "from_date" => request()->from_date, "to_date" => request()->to_date, "product_item_id" => request()->product_item_id, "product_paramedic_level_id" => request()->product_paramedic_level_id, "bed_id" => request()->bed_id, "paramedic_id" => request()->paramedic_id, "price" => request()->price, "factors" => json_encode($factors), "status" => request()->paramedic_id ? Orders::STATUS_ONGOING : Orders::STATUS_UNASSIGNED, "manager_id" => $this->manager->id ]); $order->getSerial(); if (request()->paramedic_id) { event(new OrderAssigned($order)); } DB::commit(); return $this->getOrder($order->id); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } /** * @OA\POST( * path="/manager/scan-pay/{order_id}", * summary="V2-扫用户支付码收款", * description="扫用户支付码收款", * @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="money", in="query", @OA\Schema(type="number"), required=true, description="支付金额"), * @OA\Parameter(name="auth_code", in="query", @OA\Schema(type="string"), required=true, description="扫码后获取的支付码"), * @OA\Parameter(name="type", in="query", @OA\Schema(type="string"), required=true, description="支付方式:weixin,alipay"), * @OA\Response( * response="200", * description="扫用户支付码收款" * ) * ) */ public function scanPay($order_id) { $order = (new Orders())->find($order_id); $recharge = (new Recharge())->create([ "customer_id" => $order->customer->id, "money" => request()->money, "order_id" => $order->id, "payment" => request()->type ]); $recharge = $recharge->getSerial(); switch (request()->type) { case "weixin": $res = (new WxMicroPay())->pay($recharge); if ($res !== true) { return response()->json([ "errorcode" => 60003, "errormsg" => $res->getMessage() ]); } return response()->json($res); break; case "alipay": //todo:支付宝支付实现 return response()->json([ "errorcode" => 60003, "errormsg" => "支付宝支付方式尚未开通,敬请期待" ]); break; default: return response()->json([ "errorcode" => 60003, "errormsg" => "不正确的支付方式" ]); } } /** * @OA\POST( * path="/manager/confirm-order/{id}", * summary="确认订单", * description="确认订单", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Parameter(name="bed_id", in="query", @OA\Schema(type="integer"), required=true, description="床位id"), * @OA\Parameter(name="price", in="query", @OA\Schema(type="number"), required=true, description="价格"), * @OA\Parameter(name="from_date", in="query", @OA\Schema(type="date"), required=true, description="开始日期"), * @OA\Parameter(name="to_date", in="query", @OA\Schema(type="date"), required=true, description="预计结束日期"), * @OA\Parameter(name="product_paramedic_level_id", in="query", @OA\Schema(type="integer"), required=true, description="产品护工等级id"), * @OA\Parameter(name="factors", in="query", @OA\Schema(type="object"), required=true, description="价格因子选择,[{id:1,factor_item_id:1},{...}],如果为空数组请传[]"), * @OA\Parameter(name="patient_quantity", in="query", @OA\Schema(type="integer"), required=true, description="护理人数"), * @OA\Parameter(name="auto_checkout", in="query", @OA\Schema(type="integer"), required=false, description="是否自动结算"), * @OA\Response( * response="200", * description="确认订单" * ) * ) */ public function confirmOrder($id) { $order = (new Orders())->with("firstItem")->find($id); if ($order->status !== Orders::STATUS_UNCONFIRMED) { return response()->json([ "errorcode" => 50001, "errormsg" => "订单状态不适配" ]); } DB::beginTransaction(); try { $dirty = []; foreach (request()->all() as $k => $v) { if ($k == "factors") continue; if ($order->{$k} && $order->{$k} != $v) { $dirty[$k] = $v; } } //单独处理factors if ($order->determineOrderFactorsIsDirty()) { $factors = (new Orders())->requestFactorsToOrderFactors(); $dirty["factors"] = json_encode($factors); } $dirty["status"] = Orders::STATUS_UNASSIGNED; $dirty["manager_id"] = $this->manager->id; $order->update($dirty); DB::commit(); return response()->json($order); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } /** * @OA\Get( * path="/manager/get-reservable-paramedics/{order_id}", * summary="获取可预约的护工", * description="获取可预约的护工", * @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=false, description="订单id"), * @OA\Parameter(name="has_ongoing_orders", in="query", @OA\Schema(type="integer"), required=false, description="是否空闲的筛选,枚举[0,1]"), * @OA\Response( * response="200", * description="获取可预约的护工" * ) * ) */ public function getReservableParamedics($order_id) { $order = (new Orders())->find($order_id); if ($order->status !== Orders::STATUS_UNCONFIRMED && $order->status !== Orders::STATUS_UNASSIGNED) { return response()->json([ "errorcode" => 50001, "errormsg" => "订单状态不适配" ]); } if (Carbon::parse(date("Y-m-d"))->greaterThanOrEqualTo($order->from_date)) { return response()->json([ "errorcode" => 50002, "errormsg" => "开始服务日需晚于当前日期才可以进行预约。请联系管理老师或取消订单" ]); } $paramedics = (new Paramedic()) ->where("status", Paramedic::STATUS_ACTIVE) ->where("project_id", $order->project_id) ->whereDoesntHave("orders", function ($query) use ($order) { //订单正在进行,或者未确认|未派单 $query->whereIn("status", [Orders::STATUS_UNCONFIRMED, Orders::STATUS_UNASSIGNED, Orders::STATUS_ONGOING]); }); switch (request()->has_ongoing_orders) { case "1": $paramedics = $paramedics->has("ongoingOrders"); break; case "0": $paramedics = $paramedics->doesntHave("ongoingOrders"); break; default: //do nothing } $paramedics = $paramedics ->withCount("ongoingOrders as ongoing_count") ->orderBy("ongoing_count") ->paginate(10); return response()->json($paramedics->toArray()); } /** * @OA\Get( * path="/manager/get-assignable-paramedics/{order_id}", * summary="获取可派单的护工", * description="获取可派单的护工", * @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=false, description="订单id"), * @OA\Parameter(name="has_ongoing_orders", in="query", @OA\Schema(type="integer"), required=false, description="是否空闲的筛选,枚举[0,1]"), * @OA\Parameter(name="exclude_level", in="query", @OA\Schema(type="integer"), required=false, description="是否筛选星级护工,建议前端默认提交筛选"), * @OA\Parameter(name="exclude_quantity_limit", in="query", @OA\Schema(type="integer"), required=false, description="是否筛选不超过一对多的护工,建议前端默认提交筛选"), * @OA\Parameter(name="exclude_reserved", in="query", @OA\Schema(type="integer"), required=false, description="是否筛选已被预约的护工,建议前端默认提交筛选"), * @OA\Response( * response="200", * description="获取可派单的护工" * ) * ) */ public function getAssignableParamedics($order_id) { $order = (new Orders())->find($order_id); //基础条件 $paramedics = (new Paramedic())->where("status", Paramedic::STATUS_ACTIVE) ->where("project_id", $order->project_id); //限制星级 if (request()->exclude_level) { $paramedic_level = $order->paramedicLevel; if ($paramedic_level) { $paramedics = $paramedics->where("paramedic_level_id", $paramedic_level->id); } } //一对多的数量限制 if (request()->exclude_quantity_limit) { $max_quantity = (new ProductItems())->where("product_id", $order->product_id)->orderBy("patient_quantity", "desc")->value("patient_quantity"); $paramedics = $paramedics ->whereRaw("(select count(*) from `orders` where `paramedic`.`id` = `orders`.`paramedic_id` and `orders`.`status`=" . Orders::STATUS_ONGOING . " and `orders`.`deleted_at` is null) > 2"); } //未被预约 if (request()->exclude_reserved) { $paramedics = $paramedics->whereDoesntHave("orders", function ($query) use ($order) { //订单未确认|未派单,表示已被预约 $query->whereIn("status", [Orders::STATUS_UNCONFIRMED, Orders::STATUS_UNASSIGNED, Orders::STATUS_ONGOING]); }); } //空闲状态 switch (request()->has_ongoing_orders) { case "1": $paramedics = $paramedics->has("ongoingOrders"); break; case "0": $paramedics = $paramedics->doesntHave("ongoingOrders"); break; default: //do nothing } $paramedics = $paramedics->withCount(["orders as reserved_count" => function ($query) { $query->whereIn("status", [Orders::STATUS_UNCONFIRMED, Orders::STATUS_UNASSIGNED]); }, "orders as ongoing_count" => function ($query) { $query->where("status", [Orders::STATUS_ONGOING]); }])->paginate(10); return response()->json($paramedics->toArray()); } /** * @OA\POST( * path="/manager/pre-assign-order/{id}", * summary="预派工", * description="预派工,获取可能产生影响的订单", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Parameter(name="paramedic_id", in="query", @OA\Schema(type="integer"), required=true, description="护工id"), * @OA\Response( * response="200", * description="预派工" * ) * ) */ /** * @OA\POST( * path="/manager/assign-order/{id}", * summary="订单派工", * description="订单派工", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Parameter(name="paramedic_id", in="query", @OA\Schema(type="integer"), required=true, description="护工id"), * @OA\Parameter(name="from_date", in="query", @OA\Schema(type="date"), required=true, description="开始日期"), * @OA\Parameter(name="to_date", in="query", @OA\Schema(type="date"), required=true, description="预计结束日期"), * @OA\Parameter(name="price", in="query", @OA\Schema(type="integer"), required=true, description="价格"), * @OA\Parameter(name="same_paramedic_orders_price", in="query", @OA\Schema( * type="object", * ), required=true, description="关联订单价格实体,[{id:1,price:120},{...}],如果为空数组请传[]"), * @OA\Response( * response="200", * description="订单派工" * ) * ) */ public function assignOrder($id) { $order = (new Orders())->with("handlingApprovalItem")->find($id); if ($order->approvalItem) { return response()->json([ "errorcode" => 50001, "errormsg" => "订单有未处理的审核流程,暂不可进行此操作" ]); } if ($order->status !== Orders::STATUS_UNASSIGNED) { return response()->json([ "errorcode" => 50001, "errormsg" => "订单状态不适配" ]); } if (Carbon::parse(date("Y-m-d"))->diffInDays($order->from_date, false) > 0) { return response()->json([ "errorcode" => 50002, "errormsg" => "开始服务日不能早于开始服务日,请先调整开始服务日期后再派单" ]); } //当天是否有相同护工的订单 $unGeneratedOrders = (new Orders())::where("status", Orders::STATUS_ONGOING) ->whereRaw("DATEDIFF(`from_date`, now()) <= 0") ->where("paramedic_id", request()->paramedic_id) ->whereDoesntHave("orderItems", function ($query) { $query->whereRaw("DATEDIFF(`service_date`, now()) = 0"); })->get(); if ($unGeneratedOrders->count()) { return response()->json([ "errorcode" => 50000, "errormsg" => "相关延续订单未生成完毕,请稍后再试:" . implode($unGeneratedOrders->pluck("id")->toArray()) ]); } //相同护工的订单 $same_paramedic_orders = (new Orders()) ->where("status", Orders::STATUS_ONGOING) ->where("paramedic_id", request()->paramedic_id) ->with("lastItem", "paramedic", "bed", "room", "building", "patient") ->get(); $patient_quantity = $same_paramedic_orders->count() + 1; //预指派 $url_split = explode("/", request()->url()); if ($url_split[count($url_split) - 2] == "pre-assign-order") { return response()->json($same_paramedic_orders ? $same_paramedic_orders->toArray() : []); } //判断是否每张关联子订单都提交了对应的价格,避免未经过预指派直接提交 //同时判断是否存在价格变动 $need_approve_price_change = $order->determineNeedApprovePriceChange(request()->price); $same_paramedic_orders_price = json_decode(request()->same_paramedic_orders_price, true); $same_paramedic_orders_price = collect($same_paramedic_orders_price)->pluck("price", "id")->toArray(); foreach ($same_paramedic_orders as $same_paramedic_order) { if (!in_array($same_paramedic_order->id, array_keys($same_paramedic_orders_price))) { return response()->json([ "errorcode" => 50004, "errormsg" => "关联订单({$same_paramedic_order->serial})的价格未提交" ]); } $need_approve_price_change = $need_approve_price_change || $same_paramedic_order->determineNeedApprovePriceChange($same_paramedic_orders_price[$same_paramedic_order->id]); } //最接近被护理人数的产品型号 $productItem = $order->product->productItems()->where("patient_quantity", "<=", $patient_quantity)->orderBy("patient_quantity", "desc")->first(); $price = request()->price; //需要修改/需要审批的明细 $approvalItems = []; //主订单 $updates_order = [ "status" => Orders::STATUS_ONGOING, "product_item_id" => $productItem->id, "paramedic_id" => request()->paramedic_id, "price" => request()->price, "patient_quantity" => $patient_quantity, "auto_checkout" => request()->auto_checkout ]; if (request()->from_date) { $updates_order["from_date"] = request()->from_date; } if (request()->from_date) { $updates_order["to_date"] = request()->to_date; } $approvalItems[] = new ApprovalItems([ "belongs_type" => Orders::class, "belongs_id" => $order->id, "updates" => json_encode($updates_order) ]); //相关订单 foreach ($same_paramedic_orders as $same_paramedic_order) { $productItem = $same_paramedic_order->product->productItems()->where("patient_quantity", "<=", $patient_quantity)->orderBy("patient_quantity", "desc")->first(); $price = $same_paramedic_orders_price[$same_paramedic_order->id]; $same_paramedic_order_updates = [ "product_item_id" => $productItem->id, "price" => $price, "patient_quantity" => $patient_quantity ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => Orders::class, "belongs_id" => $same_paramedic_order->id, "updates" => json_encode($same_paramedic_order_updates) ]); $same_paramedic_order_last_item_updates = [ "product_item_id" => $productItem->id, "total" => $price, "patient_quantity" => $patient_quantity ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => OrderItems::class, "belongs_id" => $same_paramedic_order->lastItem->id, "updates" => json_encode($same_paramedic_order_last_item_updates) ]); } //开始处理 if ($need_approve_price_change) { //写入审批记录 DB::beginTransaction(); try { $expire_at = (new Approval())->generateExpireTime(); $approval = (new Approval)->create([ "type" => Approval::TYPE_ASSIGN, "order_id" => $order->id, "project_id" => $order->project->id, "created_by" => $this->manager->id, "expire_at" => $expire_at ]); foreach ($approvalItems as $approvalItem) { $approvalItem->approval_id = $approval->id; $approvalItem->save(); } $order->status = "needapprove"; $order->approval = (new Approval())->with("approvalItems")->find($approval->id); DB::commit(); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } else { //执行变更(虚拟审批) $approval = new Approval(); $approval->type = Approval::TYPE_ASSIGN; $approval->order_id = $order->id; $approval->approvalItems = $approvalItems; $res = $approval->pass(); if (!$res["status"]) { return response()->json([ "errorcode" => $res["errorcode"], "errormsg" => $res["errormsg"] ]); } } return response()->json(compact("order")); } /** * @OA\Get( * path="/manager/get-beds-by-project/{id}", * summary="获取医院床位", * description="获取医院床位", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="project id"), * @OA\Response( * response="200", * description="获取医院床位" * ) * ) */ public function getBedsByProject($id) { $buildings = (new Building())->where("project_id", $id)->with(["areas" => function ($query) { $query->with("beds"); }])->get(); return response()->json($buildings->toArray()); } /** * @OA\POST( * path="/manager/pre-modify-order/{id}", * summary="预改单", * description="预修改订单,获取可能产生影响的订单", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Parameter(name="paramedic_id", in="query", @OA\Schema(type="integer"), required=true, description="护工id"), * @OA\Response( * response="200", * description="预改单" * ) * ) */ /** * @OA\POST( * path="/manager/modify-order/{id}", * summary="订单修改", * description="订单修改", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="id"), * @OA\Parameter(name="bed_id", in="query", @OA\Schema(type="integer"), required=true, description="床位id"), * @OA\Parameter(name="paramedic_id", in="query", @OA\Schema(type="integer"), required=true, description="护工id"), * @OA\Parameter(name="price", in="query", @OA\Schema(type="number"), required=true, description="价格"), * @OA\Parameter(name="to_date", in="query", @OA\Schema(type="date"), required=true, description="预计结束日期"), * @OA\Parameter(name="factors", in="query", @OA\Schema(type="object"), required=true, description="价格因子选择,[{id:1,factor_item_id:1},{...}],如果为空数组请传[]"), * @OA\Parameter(name="available_day", in="query", @OA\Schema(type="string"), required=false, description="生效日期(针对当前订单、旧的关联订单、新的关联订单),仅当值为today表示同步更新当日子订单价格,为其他值表示次日起生效"), * @OA\Parameter(name="old_same_paramedic_orders_price", in="query", @OA\Schema( * type="object", * ), required=true, description="旧关联订单价格实体,[{id:1,price:120},{...}],如果为空数组请传[]"), * @OA\Parameter(name="new_same_paramedic_orders_price", in="query", @OA\Schema( * type="object", * ), required=true, description="新关联订单价格实体,[{id:1,price:120},{...}],如果为空数组请传[]"), * @OA\Response( * response="200", * description="订单修改" * ) * ) */ public function modifyOrder($id) { $order = (new Orders())->with("handlingApprovalItem")->find($id); if ($order->handlingApprovalItem) { return response()->json([ "errorcode" => 50001, "errormsg" => "订单有未处理的审核流程,暂不可进行此操作" ]); } if ($order->status != Orders::STATUS_ONGOING) { return response()->json([ "errorcode" => 60010, "errormsg" => "订单状态不适配" ]); } if (request()->paramedic_id && request()->paramedic_id != $order->paramedic_id) { $old_same_paramedic_orders = (new Orders()) ->where("status", Orders::STATUS_ONGOING) ->where("id", "<>", $order->id) ->where("paramedic_id", $order->paramedic_id) ->with("lastItem", "paramedic", "bed", "room", "building", "patient") ->get(); $new_same_paramedic_orders = (new Orders()) ->where("status", Orders::STATUS_ONGOING) ->where("id", "<>", $order->id) ->where("paramedic_id", request()->paramedic_id) ->with("lastItem", "paramedic", "bed", "room", "building", "patient") ->get(); } else { $old_same_paramedic_orders = collect([]); $new_same_paramedic_orders = collect([]); } //预改单 $url_split = explode("/", request()->url()); if ($url_split[count($url_split) - 2] == "pre-modify-order") { return response()->json([ "order" => $order, "old_same_paramedic_orders" => $old_same_paramedic_orders->toArray(), "new_same_paramedic_orders" => $new_same_paramedic_orders->toArray() ]); } //判断是否每张关联子订单都提交了对应的价格,避免未经过预改单直接提交 //同时判断是否有价格变更 $need_approve_price_change = $order->determineNeedApprovePriceChange(request()->price); $old_same_paramedic_orders_price = json_decode(request()->old_same_paramedic_orders_price, true); $old_same_paramedic_orders_price = collect($old_same_paramedic_orders_price)->pluck("price", "id")->toArray(); foreach ($old_same_paramedic_orders as $old_same_paramedic_order) { if (!in_array($old_same_paramedic_order->id, array_keys($old_same_paramedic_orders_price))) { return response()->json([ "errorcode" => 50004, "errormsg" => "旧关联订单({$old_same_paramedic_order->serial})的价格未提交" ]); } $need_approve_price_change = $need_approve_price_change || $old_same_paramedic_order->determineNeedApprovePriceChange($old_same_paramedic_orders_price[$old_same_paramedic_order->id]); } $new_same_paramedic_orders_price = json_decode(request()->new_same_paramedic_orders_price, true); $new_same_paramedic_orders_price = collect($new_same_paramedic_orders_price)->pluck("price", "id")->toArray(); foreach ($new_same_paramedic_orders as $new_same_paramedic_order) { if (!in_array($new_same_paramedic_order->id, array_keys($new_same_paramedic_orders_price))) { return response()->json([ "errorcode" => 50004, "errormsg" => "新关联订单({$new_same_paramedic_order->serial})的价格未提交" ]); } $need_approve_price_change = $need_approve_price_change || $new_same_paramedic_order->determineNeedApprovePriceChange($new_same_paramedic_orders_price[$new_same_paramedic_order->id]); } //开始处理 //最接近被护理人数的产品型号 $productItem = $order->product->productItems()->where("patient_quantity", "<=", count($new_same_paramedic_orders_price) + 1)->orderBy("patient_quantity", "desc")->first(); $price = request()->price; //需要修改/需要审批的明细 $approvalItems = []; //主订单 //单独处理factors $factors_is_dirty = $order->determineOrderFactorsIsDirty(); $factors = (new Orders())->requestFactorsToOrderFactors(); $updates_order = [ "status" => Orders::STATUS_ONGOING, "product_item_id" => $productItem->id, "paramedic_id" => request()->paramedic_id, "bed_id" => (request()->bed_id ? request()->bed_id : $order->bed_id), "to_date" => (request()->to_date ? request()->to_date : $order->to_date), "price" => request()->price ]; if ($factors_is_dirty) { $updates_order["factors"] = json_encode($factors); } $approvalItems[] = new ApprovalItems([ "belongs_type" => Orders::class, "belongs_id" => $order->id, "updates" => json_encode($updates_order) ]); //子订单 if (request()->available_day == "today") { $today_order_item = [ "product_item_id" => $productItem->id, "bed_id" => (request()->bed_id ? request()->bed_id : $order->bed_id), "total" => $price, "patient_quantity" => (count($new_same_paramedic_orders_price) + 1) ]; if ($factors_is_dirty) { $today_order_item["factors"] = json_encode($factors); } $approvalItems[] = new ApprovalItems([ "belongs_type" => OrderItems::class, "updates" => json_encode($today_order_item) ]); } //旧相关订单 foreach ($old_same_paramedic_orders as $old_same_paramedic_order) { $productItem = $old_same_paramedic_order->product->productItems()->where("patient_quantity", "<=", count($old_same_paramedic_orders))->orderBy("patient_quantity", "desc")->first(); $price = $old_same_paramedic_orders_price[$old_same_paramedic_order->id]; $same_paramedic_order_updates = [ "product_item_id" => $productItem->id, "price" => $price, "patient_quantity" => count($old_same_paramedic_orders) ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => Orders::class, "belongs_id" => $old_same_paramedic_order->id, "updates" => json_encode($same_paramedic_order_updates) ]); if (request()->available_day == "today") { $same_paramedic_order_last_item_updates = [ "product_item_id" => $productItem->id, "total" => $price, "patient_quantity" => count($old_same_paramedic_orders) ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => OrderItems::class, "belongs_id" => $old_same_paramedic_order->lastItem->id, "updates" => json_encode($same_paramedic_order_last_item_updates) ]); } } //新相关订单 foreach ($new_same_paramedic_orders as $new_same_paramedic_order) { $productItem = $new_same_paramedic_order->product->productItems()->where("patient_quantity", "<=", count($new_same_paramedic_orders) + 1)->orderBy("patient_quantity", "desc")->first(); $price = $new_same_paramedic_orders_price[$new_same_paramedic_order->id]; $same_paramedic_order_updates = [ "product_item_id" => $productItem->id, "price" => $price, "patient_quantity" => (count($new_same_paramedic_orders) + 1) ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => Orders::class, "belongs_id" => $new_same_paramedic_order->id, "updates" => json_encode($same_paramedic_order_updates) ]); if (request()->available_day == "today") { $same_paramedic_order_last_item_updates = [ "product_item_id" => $productItem->id, "total" => $price, "patient_quantity" => (count($new_same_paramedic_orders) + 1) ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => OrderItems::class, "belongs_id" => $new_same_paramedic_order->lastItem->id, "updates" => json_encode($same_paramedic_order_last_item_updates) ]); } } //开始执行 if ($need_approve_price_change) { //写入审批记录 DB::beginTransaction(); try { $expire_at = (new Approval())->generateExpireTime(); $approval = (new Approval)->create([ "type" => Approval::TYPE_MODIFY, "order_id" => $order->id, "project_id" => $order->project->id, "created_by" => $this->manager->id, "expire_at" => $expire_at ]); foreach ($approvalItems as $approvalItem) { $approvalItem->approval_id = $approval->id; $approvalItem->save(); } $order->status = "needapprove"; $order->approval = (new Approval())->with("approvalItems")->find($approval->id); DB::commit(); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } else { //执行变更(虚拟审批) $approval = new Approval(); $approval->approvalItems = $approvalItems; $res = $approval->pass(); if (!$res["status"]) { return response()->json([ "errorcode" => $res["errorcode"], "errormsg" => $res["errormsg"] ]); } } return response()->json(compact("order", "old_same_paramedic_orders", "new_same_paramedic_orders")); } /** * @OA\POST( * path="/manager/modify-order-date/{id}", * summary="修改订单日期", * description="修改订单日期", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="id"), * @OA\Parameter(name="from_date", in="query", @OA\Schema(type="date"), required=false, description="开始日期"), * @OA\Parameter(name="to_date", in="query", @OA\Schema(type="date"), required=false, description="结束日期"), * @OA\Parameter(name="auto_checkout", in="query", @OA\Schema(type="integer"), required=false, description="是否自动结单"), * @OA\Response( * response="200", * description="修改订单日期" * ) * ) */ public function modifyOrderDate($id) { $order = (new Orders())->find($id); if (request()->from_date && $order->status != Orders::STATUS_UNASSIGNED) { return response()->json([ "errorcode" => 60002, "errormsg" => "修改开始时间只支持未派单状态的订单" ]); } request()->from_date ? $order->from_date = request()->from_date : ""; request()->to_date ? $order->to_date = request()->to_date : ""; isset(request()->auto_checkout) ? $order->auto_checkout = request()->auto_checkout : ""; $order->save(); return response()->json($order->toArray()); } /** * @OA\POST( * path="/manager/pre-checkout-order/{id}", * summary="预结单", * description="预结单", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="string"), required=true, description="id"), * @OA\Response( * response="200", * description="预结单" * ) * ) */ /** * @OA\POST( * path="/manager/checkout-order/{id}", * summary="订单结单", * description="订单结单", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="string"), required=true, description="id"), * @OA\Parameter(name="last_item_price", in="query", @OA\Schema(type="number"), required=true, description="结单日价格"), * @OA\Parameter(name="available_day", in="query", @OA\Schema(type="string"), required=false, description="生效日期(针对关联订单),仅当值为today表示同步更新当日子订单价格,为其他值表示次日起生效"), * @OA\Parameter(name="to_date", in="query", @OA\Schema(type="string"), required=false, description="生效日期(针对关联订单),仅当值为today表示同步更新当日子订单价格,为其他值表示次日起生效"), * @OA\Parameter(name="same_paramedic_orders_price", in="query", @OA\Schema( * type="object", * ), required=true, description="关联订单价格实体,[{id:1,price:120},{...}],如果为空数组请传[]"), * @OA\Response( * response="200", * description="订单结单" * ) * ) */ public function checkoutOrder($id) { $order = (new Orders())->with(["orderItems", "customer", "handlingApprovalItem"])->find($id); //获取当前结单时间的实时价格 $last_day_price_of_now = $order->getLastDayPriceOfNow(); //是否已有审批通过的审批单 $lastPassedApproval = (new Approval()) ->where("type", Approval::TYPE_CHECKOUT) ->where("order_id", $order->id) ->where("status", Approval::STATUS_PASSED) ->with("approvalItems") ->first(); if ($order->handlingApprovalItem) { return response()->json([ "errorcode" => 50001, "errormsg" => "订单有未处理的审核流程,暂不可进行此操作" ]); } if ($order->status !== Orders::STATUS_ONGOING) { return response()->json([ "errorcode" => 60001, "errormsg" => "订单状态不适配" ]); } //改期结算 //Log::info(request()->available_day); exit(); if (request()->to_date && Carbon::now("Asia/Shanghai")->diffInDays(request()->to_date, false) < 0) { //校验客户余额是否够 $unpaid_order_items = $order->orderItems->filter(function ($item) { return $item->paid_at == null && Carbon::parse($item->service_date)->diffInDays(request()->to_date, false) >= 0; }); $unpaid = $unpaid_order_items->sum("total"); $balance = $order->customer->balance; if ($unpaid > $balance) { $need_pay_money = $unpaid - $balance; return $this->nativepayOrder($order->id, $need_pay_money); } elseif ($unpaid < $balance) { $money = $balance - $unpaid; $recharge = Recharge::where("order_id", $order->id) ->whereNotIn("payment", ["cash", "pos"]) ->whereNotNull("paid_at") ->doesntHave("refunds") ->where("money", ">=", $money) ->orderBy("id", "desc") ->first(); return response()->json([ "money" => $money, "status" => "needrefund", "recharge" => $recharge ]); } //余额足够直接结单 try { DB::beginTransaction(); //处理改期日及改期日之前的未结单 foreach ($unpaid_order_items as $item) { $item->update([ "paid_at" => date("Y-m-d H:i:s") ]); $balance = $order->customer->balance - $item->total; $order->customer->update([ "balance" => $balance ]); if ($item->total == 0) { continue; } (new Balance())->create([ "customer_id" => $order->customer->id, "order_id" => $order->id, "belongs_type" => get_class($item), "belongs_id" => $item->id, "money" => -$item->total, "balance" => $balance ]); } //删除改期日之后的子订单 (new Orders())->orderItems()->whereRaw("DATEDIFF('" . request()->to_date . "'," . $item->service_date . ") > 0")->delete(); //更新订单状态 (new Orders())->find($order->id)->update([ "status" => Orders::STATUS_FINISHED ]); DB::commit(); return response()->json(compact("order")); } catch (\Exception $exception) { DB::rollBack(); return [ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]; } } //关联订单 $same_paramedic_orders = (new Orders()) ->where("status", Orders::STATUS_ONGOING) ->where("id", "<>", $order->id) ->where("paramedic_id", $order->paramedic_id) ->with("lastItem", "paramedic", "bed", "room", "building", "patient") ->get(); //预结单 $url_split = explode("/", request()->url()); if ($url_split[count($url_split) - 2] == "pre-checkout-order") { //最后一日的参考价,分两种情况取值:已审的取当前的最后一天的价格;未审的取运算出来的价格 $order->last_day_price_of_now = $lastPassedApproval ? $order->lastItem->total : $last_day_price_of_now; return response()->json(["order" => $order, "same_paramedic_orders" => $same_paramedic_orders->toArray()]); } //判断是否每张关联子订单都提交了对应的价格,避免未经过预结单直接提交 //同时判断是否需要审批 $same_paramedic_orders_price = json_decode(request()->same_paramedic_orders_price, true); $same_paramedic_orders_price = collect($same_paramedic_orders_price)->pluck("price", "id")->toArray(); $need_approve_price_change = false; foreach ($same_paramedic_orders as $same_paramedic_order) { if (!in_array($same_paramedic_order->id, array_keys($same_paramedic_orders_price))) { return response()->json([ "errorcode" => 50004, "errormsg" => "关联订单({$same_paramedic_order->serial})的价格未提交" ]); } $need_approve_price_change = $need_approve_price_change || $same_paramedic_order->determineNeedApprovePriceChange($same_paramedic_orders_price[$same_paramedic_order->id]); } //主订单是否需要审批,如需要审批直接拦断 //需要审批:没有审批单且提交价格小于当前价格;已有审批单但是价格不符,需要重新审 if ((!$lastPassedApproval && request()->last_item_price != $last_day_price_of_now) || ($lastPassedApproval && request()->last_item_price != $order->lastItem->total)) { $approvalItems = []; $last_item_updates = [ "total" => request()->last_item_price, ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => Orders::class, "belongs_id" => $order->id, "updates" => json_encode([]) ]); $approvalItems[] = new ApprovalItems([ "belongs_type" => OrderItems::class, "belongs_id" => $order->lastItem->id, "updates" => json_encode($last_item_updates) ]); DB::beginTransaction(); try { $expire_at = (new Approval())->generateExpireTime(); $approval = (new Approval)->create([ "type" => Approval::TYPE_CHECKOUT, "order_id" => $order->id, "project_id" => $order->project->id, "created_by" => $this->manager->id, "expire_at" => $expire_at ]); foreach ($approvalItems as $approvalItem) { $approvalItem->approval_id = $approval->id; $approvalItem->save(); } $order->status = "needapprove"; $order->approval = (new Approval())->with("approvalItems")->find($approval->id); DB::commit(); return response()->json($order); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } //校验客户余额是否够 $order->orderItems->last()->total = request()->last_item_price; $unpaid = $order->orderItems->filter(function ($item) { return $item->paid_at == null; })->sum("total"); $balance = $order->customer->balance; if ($unpaid > $balance) { $need_pay_money = $unpaid - $balance; return $this->nativepayOrder($order->id, $need_pay_money); } elseif ($unpaid < $balance) { $money = $balance - $unpaid; $recharge = Recharge::where("order_id", $order->id) ->whereNotIn("payment", ["cash", "pos"]) ->whereNotNull("paid_at") ->doesntHave("refunds") ->where("money", ">=", $money) ->orderBy("id", "desc") ->first(); return response()->json([ "money" => $money, "status" => "needrefund", "recharge" => $recharge ]); } //开始处置订单 DB::beginTransaction(); try { //写入最后一张子订单的价格 $order->orderItems->last()->save(); //筛选出未支付的子订单 $unpaid_order_items = $order->orderItems->filter(function ($item) { return $item->paid_at == null; }); foreach ($unpaid_order_items as $item) { $item->update([ "paid_at" => date("Y-m-d H:i:s") ]); $balance = $order->customer->balance - $item->total; $order->customer->update([ "balance" => $balance ]); if ($item->total == 0) { continue; } (new Balance())->create([ "customer_id" => $order->customer->id, "order_id" => $order->id, "belongs_type" => get_class($item), "belongs_id" => $item->id, "money" => -$item->total, "balance" => $balance ]); } (new Orders())->find($order->id)->update([ "status" => Orders::STATUS_FINISHED ]); //相关订单 $approvalItems = []; $patient_quantity = count($same_paramedic_orders); foreach ($same_paramedic_orders as $same_paramedic_order) { $productItem = $same_paramedic_order->product->productItems()->where("patient_quantity", "<=", $patient_quantity)->orderBy("patient_quantity", "desc")->first(); $price = $same_paramedic_orders_price[$same_paramedic_order->id]; $same_paramedic_order_updates = [ "product_item_id" => $productItem->id, "price" => $price, "patient_quantity" => $patient_quantity ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => Orders::class, "belongs_id" => $same_paramedic_order->id, "updates" => json_encode($same_paramedic_order_updates) ]); if (request()->available_day == "today") { $same_paramedic_order_last_item_updates = [ "product_item_id" => $productItem->id, "total" => $price, "patient_quantity" => $patient_quantity ]; $approvalItems[] = new ApprovalItems([ "belongs_type" => OrderItems::class, "belongs_id" => $same_paramedic_order->lastItem->id, "updates" => json_encode($same_paramedic_order_last_item_updates) ]); } } if ($need_approve_price_change) { $expire_at = (new Approval())->generateExpireTime(); $approval = (new Approval)->create([ "type" => Approval::TYPE_CAUSED_BY_CHECKOUT, "order_id" => $order->id, "project_id" => $order->project->id, "created_by" => $this->manager->id, "expire_at" => $expire_at ]); foreach ($approvalItems as $approvalItem) { $approvalItem->approval_id = $approval->id; $approvalItem->save(); } $order->status = "cause_same_paramedic_orders_approve"; } else { //执行变更(虚拟审批) foreach ($approvalItems as $approvalItem) { $updates = json_decode($approvalItem->updates, true); $belongs_type = "\\" . $approvalItem->belongs_type; $model = new $belongs_type(); $model->find($approvalItem->belongs_id)->update($updates); } } DB::commit(); return response()->json(compact("order", "same_paramedic_orders")); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } /** * @OA\POST( * path="/manager/cancel-order/{id}", * summary="V2-取消订单", * description="取消订单", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Response( * response="200", * description="取消订单" * ) * ) */ public function cancelOrder($id) { $order = (new Orders())->with("orderItems")->find($id); if (!in_array($order->status, [Orders::STATUS_UNCONFIRMED, Orders::STATUS_UNASSIGNED])) { return response()->json([ "errorcode" => 50001, "errormsg" => "订单状态不适配" ]); } DB::beginTransaction(); try { foreach ($order->orderItems as $orderItem) { $orderItem->delete(); } $order->delete(); DB::commit(); return response()->json($order); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } /** * @OA\POST( * path="/manager/get-balance/{customer_id}", * summary="获取用户余额", * description="获取用户余额", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="customer_id", in="path", @OA\Schema(type="integer"), required=true, description="用户id"), * @OA\Response( * response="200", * description="获取用户余额" * ) * ) */ public function getBalance($customer_id) { $customer = (new Customer())->find($customer_id); if (!$customer) { return response()->json([ "errorcode" => 70001, "errormsg" => "没找到用户信息" ]); } return response()->json([ "balance" => $customer->balance ]); } /** * @OA\POST( * path="/manager/recharge-for-order/{id}", * summary="现金或pos刷卡充值", * description="现金或pos刷卡充值", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Parameter(name="payment", in="query", @OA\Schema(type="string"), required=true, description="枚举:pos=>pos机刷卡支付, cash=>现金支付"), * @OA\Parameter(name="money", in="query", @OA\Schema(type="number"), required=true, description="金额,非负数"), * @OA\Parameter(name="remark", in="query", @OA\Schema(type="string"), required=false, description="备注信息:现金支付时可以忽略;刷卡支付时,填入回单号或卡号以便财务对账"), * @OA\Response( * response="200", * description="现金或pos刷卡充值" * ) * ) */ public function rechargeForOrder($id) { DB::beginTransaction(); try { $order = (new Orders())->find($id); //创建充值记录 $recharge = [ "customer_id" => $order->customer->id, "money" => request()->money, "order_id" => $order->id, "payment" => request()->payment, "manager_id" => $this->manager->id, "paid_at" => date("Y-m-d H:i:s") ]; switch (request()->payment) { case "pos": case "cash": $recharge["remark"] = request()->remark; break; default: return response()->json([ "errorcode" => "0", "errormsg" => "不正确的支付方式" ]); } $recharge = (new Recharge())->create($recharge); $recharge = $recharge->getSerial(); //更新用户余额,创建流水记录 $customer_balance = $recharge->customer->balance + $recharge->money; $recharge->customer->update([ "balance" => $customer_balance ]); $balance = (new Balance())->create([ "customer_id" => $recharge->customer->id, "order_id" => $recharge->order_id, "belongs_type" => get_class($recharge), "belongs_id" => $recharge->id, "money" => $recharge->money, "balance" => $customer_balance ]); DB::commit(); return response()->json([ "recharge" => $recharge, "balance" => $balance ]); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } /** * @OA\Get( * path="/manager/nativepay-order/{id}", * summary="扫码支付", * description="扫码支付", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Parameter(name="money", in="query", @OA\Schema(type="number"), required=true, description="支付金额"), * @OA\Response( * response="200", * description="扫码支付" * ) * ) */ public function nativepayOrder($id, $money = false) { if (!$money) { $money = request()->money; } if (!$money) { return response()->json([ "errorcode" => 60003, "errormsg" => "请设置充值金额" ]); } $order = (new Orders())->find($id); $recharge = (new Recharge())->create(["customer_id" => $order->customer->id, "money" => $money, "order_id" => $order->id, "payment" => "weixin"]); $recharge = $recharge->getSerial(); $openid = $order->customer->openid; $unifiedOrder = new \UnifiedOrderPub(); //$unifiedOrder->setParameter("openid", $openid);//openid $unifiedOrder->setParameter("body", "充值{$money}元");//商品描述 $unifiedOrder->setParameter("out_trade_no", $recharge->serial);//商户订单号 $unifiedOrder->setParameter("total_fee", $recharge->money * 100);//总金额 $unifiedOrder->setParameter("notify_url", get_http_type() . $_SERVER["HTTP_HOST"] . "/customer/pay-callback");//通知地址 $unifiedOrder->setParameter("trade_type", "NATIVE");//交易类型 $unifiedOrder->postXml(); $result = $unifiedOrder->xmlToArray($unifiedOrder->response); if (!isset($result["code_url"])) { return response()->json([ "errorcode" => 60003, "errormsg" => "生成支付二维码失败:" . $result["return_msg"] ]); } $qrcode = QrCode::format("png")->size(240)->generate($result["code_url"]); $filename = $recharge->serial . ".png"; $file = "public/recharge-qrcode/{$filename}"; $imageUrl = get_http_type() . $_SERVER["HTTP_HOST"] . "/storage/recharge-qrcode/{$filename}"; Storage::disk('local')->put($file, $qrcode); return response()->json([ "money" => $money, "imageUrl" => $imageUrl, "status" => "needrecharge" ]); } /** * @OA\POST( * path="/manager/refund-for-order/{id}", * summary="退款", * description="退款", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=true, description="订单id"), * @OA\Parameter(name="money", in="query", @OA\Schema(type="number"), required=true, description="金额,非负数"), * @OA\Parameter(name="payment", in="query", @OA\Schema(type="string"), required=true, description="退款方式:枚举cash,online。注意可用的退款方式需要通过pre-chackout获取,随意提交尽可能会造成问题"), * @OA\Parameter(name="recharge_id", in="query", @OA\Schema(type="integer"), required=false, description="相关在线支付的id,用于原路返回。退款方式为online时,必须给出"), * @OA\Parameter(name="remark", in="query", @OA\Schema(type="string"), required=false, description="备注信息"), * @OA\Response( * response="200", * description="退款" * ) * ) */ public function refundForOrder($id) { DB::beginTransaction(); try { $order = (new Orders())->find($id); //创建退款记录 $refund = [ "customer_id" => $order->customer->id, "manager_id" => $this->manager->id, "money" => request()->money, "order_id" => $order->id, "remark" => request()->remark ]; switch (request()->payment) { case "cash": $refund["payment"] = request()->payment; $refund["paid_at"] = date("Y-m-d H:i:s"); break; case "online": $recharge = Recharge::find(request()->recharge_id); $refund["payment"] = $recharge->payment; $refund["recharge_id"] = request()->recharge_id; break; default: return response()->json([ "errorcode" => "0", "errormsg" => "不正确的退款方式" ]); } $refund = (new Refund())->create($refund); $refund = $refund->getSerial(); //更新用户余额,创建流水记录 $customer_balance = $refund->customer->balance - $refund->money; $refund->customer->update([ "balance" => $customer_balance ]); $balance = (new Balance())->create([ "customer_id" => $refund->customer->id, "order_id" => $refund->order_id, "belongs_type" => get_class($refund), "belongs_id" => $refund->id, "money" => -$refund->money, "balance" => $customer_balance ]); DB::commit(); return response()->json([ "refund" => $refund, "balance" => $balance ]); } catch (\Exception $exception) { DB::rollBack(); return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } /** * @OA\Get( * path="/manager/get-approvals", * summary="获取审批列表", * description="获取审批列表", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="page", in="query", @OA\Schema(type="integer"), required=false, description="当前页码,默认为1"), * @OA\Parameter(name="pageLength", in="query", @OA\Schema(type="integer"), required=false, description="每页数量,默认为5"), * @OA\Parameter(name="project_id", in="query", @OA\Schema(type="integer"), required=false, description="项目/医院id"), * @OA\Parameter(name="status", in="query", @OA\Schema(type="string"), required=false, description="状态:[handling=>待处理,passed=>已通过,rejected=>已拒绝,expired=>已过期]"), * @OA\Response( * response="200", * description="获取审批列表" * ) * ) */ public function getApprovals() { $data = (new Approval()); $manager_id = $this->manager->id; switch ($this->manager->type) { case "teacher": $data = $data->where("created_by", $manager_id); break; case "manager": $project_ids = $this->manager->managerProjects->pluck("project_id")->toArray(); $data = $data->whereIn("project_id", $project_ids); break; default: $data = $data->whereRaw("1=0"); break; } if (request()->status) { $data = $data ->where("status", constant(Approval::class . "::STATUS_" . strtoupper(request()->status))); } $pageLength = request()->pageLength ? (int)request()->pageLength : 5; $data = $data->with(["primaryOrder", "approvalItems"])->orderBy("id", "desc")->paginate($pageLength); return response()->json($data->toArray()); } /** * @OA\Get( * path="/manager/get-approval/{id}", * summary="获取审批列表", * description="获取审批列表", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=false, description="审批单id"), * @OA\Response( * response="200", * description="获取审批列表" * ) * ) */ public function getApproval($id) { //todo:校验归属 $approval = (new Approval())->with(["primaryOrder", "approvalItems" => function ($query) { $query->with("belongs"); }])->find($id); foreach ($approval->approvalItems as $approvalItem) { $approvalItem->updates = json_decode($approvalItem->updates); } return response()->json($approval ? $approval->toArray() : null); } /** * @OA\POST( * path="/manager/pass-approval/{id}", * summary="通过审批", * description="通过审批", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=false, description="审批单id"), * @OA\Response( * response="200", * description="通过审批" * ) * ) */ public function passApproval($id) { //todo:校验归属 $approval = (new Approval())->find($id); if ($approval->status !== Approval::STATUS_HANDLING) { return response()->json([ "errorcode" => "60001", "errormsg" => "状态不适配" ]); } $res = $approval->pass(); if (!$res["status"]) { return response()->json([ "errorcode" => $res["errorcode"], "errormsg" => $res["errormsg"] ]); } $approval->update([ "handled_by" => $this->manager->id ]); return response()->json($approval); } /** * @OA\POST( * path="/manager/reject-approval/{id}", * summary="驳回审批", * description="驳回审批", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="id", in="path", @OA\Schema(type="integer"), required=false, description="审批单id"), * @OA\Parameter(name="rejected_reason", in="query", @OA\Schema(type="string"), required=false, description="驳回原因"), * @OA\Response( * response="200", * description="驳回审批" * ) * ) */ public function rejectApproval($id) { //todo:校验归属 $approval = (new Approval())->find($id); if ($approval->status !== Approval::STATUS_HANDLING) { return response()->json([ "errorcode" => "60001", "errormsg" => "状态不适配" ]); } $approval->update([ "status" => Approval::STATUS_REJECTED, "handled_by" => $this->manager->id, "rejected_reason" => request()->rejected_reason ]); return response()->json($approval); } /** * @OA\Get( * path="/manager/get-project-paramedic-levels/{project_id}", * summary="V2-获取医院护工等级", * description="获取医院护工等级", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="project_id", in="query", @OA\Schema(type="string"), required=true, description="医院ID"), * @OA\Response( * response="200", * description="获取医院护工等级" * ) * ) */ public function getProjectParamedicLevels($project_id) { $paramedic_levels = ParamedicLevel::where("project_id", $project_id)->orderBy("myindex")->get(); return response()->json($paramedic_levels->toArray()); } /** * @OA\POST( * path="/manager/create-paramedic/{project_id}", * summary="V2-新增护工", * description="", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="project_id", in="path", @OA\Schema(type="integer"), required=true, description="医院/项目ID"), * @OA\Parameter(name="name", in="query", @OA\Schema(type="string"), required=true, description="姓名"), * @OA\Parameter(name="id_card_number", in="query", @OA\Schema(type="string"), required=true, description="身份证号"), * @OA\Parameter(name="mobile", in="query", @OA\Schema(type="string"), required=true, description="手机号码"), * @OA\Parameter(name="join_at", in="query", @OA\Schema(type="string"), required=true, description="入职日期"), * @OA\Parameter(name="work_years", in="query", @OA\Schema(type="string"), required=true, description="护理经验年限"), * @OA\Parameter(name="paramedic_level_id", in="query", @OA\Schema(type="integer"), required=true, description="项目护工级别ID"), * @OA\Parameter(name="bank", in="query", @OA\Schema(type="string"), required=false, description="开户行"), * @OA\Parameter(name="account", in="query", @OA\Schema(type="string"), required=false, description="银行卡号"), * @OA\Parameter(name="idcard_front", in="query", @OA\Schema(type="integer"), required=false, description="身份证正面图片ID"), * @OA\Parameter(name="idcard_back", in="query", @OA\Schema(type="integer"), required=false, description="身份证反面图片ID"), * @OA\Parameter(name="has_health_certificate", in="query", @OA\Schema(type="integer"), required=true, description="是否持有健康证"), * @OA\Parameter(name="has_work_certificate", in="query", @OA\Schema(type="integer"), required=true, description="是否是有技能资格证"), * @OA\Response( * response="200", * description="新增护工" * ) * ) */ public function createParamedic(Request $request) { if (!$request->id_card_number) { return response()->json([ "errorcode" => "99999", "errormsg" => "身份证号不可以为空" ]); } if (!InfoHelper::identityCard()->validate($request->id_card_number)) { return response()->json([ "errorcode" => "99999", "errormsg" => "身份证号不正确" ]); } $birthday = InfoHelper::identityCard()->birthday($request->id_card_number); $sex = InfoHelper::identityCard()->sex($request->id_card_number); $paramedic = (new Paramedic())->where("id_card_number", $request->id_card_number)->first(); if ($paramedic) { return response()->json([ "errorcode" => "99999", "errormsg" => "已存在相同身份证号的护工" ]); } $data = (new Paramedic())->filterRequestColumns($request); $data["birthday"] = $birthday; $data["sex"] = $sex; $data["creator_type"] = get_class($this->manager); $data["creator_id"] = $this->manager->id; $res = (new Paramedic())->create($data); return response()->json($res); } /** * @OA\POST( * path="/manager/upload-image", * summary="V2-上传图片", * description="上传图片", * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Parameter(name="folder", in="query", @OA\Schema(type="string"), required=true, description="文件存放目录:[public/manager],public表示可以公开查看的,一般用于头像等公开图片,manager是需要鉴权后查看的,一般用于身份证、资格证书等非公开图片"), * @OA\Response( * response="200", * description="上传图片", * content={ * @OA\MediaType( * mediaType="application/json", * @OA\Schema( * @OA\Property( * property="id", * type="integer", * description="文件存储id" * ), * @OA\Property( * property="folder", * type="string", * description="文件存储目录" * ), * @OA\Property( * property="name", * type="string", * description="文件名" * ), * @OA\Property( * property="public_path", * type="string", * description="公开访问路径,如果为null,表示不可公开访问" * ), * example={ * "id": "1", * "folder": "public", * "name": "eufgw83ascasc.jpg", * "public_path": "/storage/eufgw83ascasc.jpg" * } * ) * ) * } * ) * ) */ public function uploadImage(Request $request) { try { $file = $request->file("file"); $original_name = $file->getClientOriginalName(); $extension = last(explode(".", $original_name)); if (!in_array($extension, ["jpg", "jpeg", "gif", "png", "bmp"])) { return response()->json([ "errorcode" => "403", "errormsg" => "不正确的文件格式" ]); } $save_folder = $request->folder ? $request->folder : "manager"; if (!is_dir(Storage::path($save_folder))) { Storage::makeDirectory($save_folder); } $name = uniqid() . "." . $extension; $store_result = $file->storeAs($save_folder, $name); $upload = new Uploads(); $upload->original_name = $original_name; $upload->folder = $save_folder; $upload->name = $name; $upload->extension = $extension; $upload->creator_type = get_class($this->manager); $upload->creator_id = $this->manager->id; $upload->size = Storage::size($save_folder . "/" . $name); $upload->save(); if ($save_folder == "public") { $upload->public_path = "/storage/" . $name; } else { $upload->public_path = null; } return response()->json($upload); } catch (\Exception $exception) { return response()->json([ "errorcode" => $exception->getCode(), "errormsg" => $exception->getMessage() ]); } } }