From b68ad879c8b4a66855eea8614c7dff296ff6ae81 Mon Sep 17 00:00:00 2001 From: ctexthuang Date: Tue, 1 Apr 2025 11:49:50 +0800 Subject: [PATCH] feat: driver --- app/Constants/Common/DriverCode.php | 13 ++ app/Constants/Common/OrderCode.php | 2 +- app/Controller/Admin/CateringController.php | 4 +- app/Controller/Api/DriverController.php | 40 ++++ app/Model/DriverException.php | 34 ++++ app/Model/DriverStatus.php | 41 ++++ .../Api/Driver/AbnormalReportingService.php | 74 +++++++ app/Service/Api/Driver/BaseDriverService.php | 181 ++++++++++++++++++ app/Service/Api/Driver/DeliverService.php | 78 ++++++++ app/Service/Api/Driver/GetSiteListService.php | 126 +----------- app/Service/Api/Driver/LoadActionService.php | 85 ++++++++ 11 files changed, 554 insertions(+), 124 deletions(-) create mode 100644 app/Constants/Common/DriverCode.php create mode 100644 app/Model/DriverException.php create mode 100644 app/Model/DriverStatus.php create mode 100644 app/Service/Api/Driver/AbnormalReportingService.php create mode 100644 app/Service/Api/Driver/DeliverService.php create mode 100644 app/Service/Api/Driver/LoadActionService.php diff --git a/app/Constants/Common/DriverCode.php b/app/Constants/Common/DriverCode.php new file mode 100644 index 0000000..bdc481e --- /dev/null +++ b/app/Constants/Common/DriverCode.php @@ -0,0 +1,13 @@ +handle(); + return (new MealCateringService())->handle(); } /** diff --git a/app/Controller/Api/DriverController.php b/app/Controller/Api/DriverController.php index 7397b78..21d38c9 100644 --- a/app/Controller/Api/DriverController.php +++ b/app/Controller/Api/DriverController.php @@ -6,7 +6,10 @@ namespace App\Controller\Api; use App\Controller\AbstractController; use App\Middleware\Api\JwtAuthMiddleware; +use App\Service\Api\Driver\AbnormalReportingService; +use App\Service\Api\Driver\DeliverService; use App\Service\Api\Driver\GetSiteListService; +use App\Service\Api\Driver\LoadActionService; use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\Middlewares; use Hyperf\HttpServer\Annotation\RequestMapping; @@ -18,10 +21,47 @@ use Hyperf\Validation\Annotation\Scene; ])] class DriverController extends AbstractController { + /** + * 获取信息 + * @return array + */ #[RequestMapping(path: 'get_site_list',methods: 'GET')] #[Scene(scene: 'get_site_list')] public function get_site_list() { return (new GetSiteListService)->handle(); } + + /** + * 装车出餐 + * @return array + */ + #[RequestMapping(path: 'load_action',methods: 'GET')] + #[Scene(scene: 'load_action')] + public function load_action() + { + return (new LoadActionService)->handle(); + } + + /** + * 异常上报 + * @return array + */ + #[RequestMapping(path: 'abnormal_reporting',methods: 'POST')] + #[Scene(scene: 'abnormal_reporting')] + public function abnormal_reporting() + { + return (new AbnormalReportingService)->handle(); + } + + /** + * 送达 + * @return array + */ + #[RequestMapping(path: 'deliver',methods: 'GET')] + #[Scene(scene: 'deliver')] + public function deliver() + { + return (new DeliverService)->handle(); + } } diff --git a/app/Model/DriverException.php b/app/Model/DriverException.php new file mode 100644 index 0000000..84c8e9c --- /dev/null +++ b/app/Model/DriverException.php @@ -0,0 +1,34 @@ + 'integer', 'cycle_id' => 'integer', 'site_id' => 'integer', 'driver_id' => 'integer', 'image_id' => 'integer']; +} diff --git a/app/Model/DriverStatus.php b/app/Model/DriverStatus.php new file mode 100644 index 0000000..2245ebc --- /dev/null +++ b/app/Model/DriverStatus.php @@ -0,0 +1,41 @@ + 'integer', 'cycle_id' => 'integer', 'site_id' => 'integer', 'driver_id' => 'integer', 'meal_order_quantity' => 'integer', 'meal_add_staple_food_num' => 'integer', 'option_order_quantity' => 'integer', 'option_add_staple_food_num' => 'integer', 'status' => 'integer']; +} diff --git a/app/Service/Api/Driver/AbnormalReportingService.php b/app/Service/Api/Driver/AbnormalReportingService.php new file mode 100644 index 0000000..ed3dc14 --- /dev/null +++ b/app/Service/Api/Driver/AbnormalReportingService.php @@ -0,0 +1,74 @@ +driverStatusModel + ->where('cycle_id',$this->cycleId) + ->where('site_id',$this->request->input('site_id')) + ->where('driver_id',$this->adminInfo->id) + ->first(); + + if (empty($info)) throw new ErrException('今日无该点位的送餐数据'); + + if ($info->status == DriverCode::DESTINATION) throw new ErrException('该点位已送达,无需上报异常信息'); + + $todaySiteIds = $this->driverStatusModel + ->where('cycle_id',$this->cycleId) + ->where('driver_id',$this->adminInfo->id) + ->whereIn('status',[DriverCode::DEPARTURES,DriverCode::EXCEPTIONS]) + ->pluck('site_id') + ->toArray(); + if (empty($todaySiteIds)) throw new ErrException('数据错误-1'); + + $insertData = []; + foreach ($todaySiteIds as $siteId) { + $insertData[] = [ + 'cycle_id' => $this->cycleId, + 'site_id' => $siteId, + 'driver_id' => $this->adminInfo->id, + 'exceptions_msg' => $this->request->input('exceptions_msg'), + 'image_id' => $this->request->input('image_id'), + 'create_time' => date('Y-m-d H:i:s') + ]; + } + + if (empty($insertData)) throw new ErrException('数据错误-2'); + + Db::transaction(function () use ($todaySiteIds,$insertData) { + $this->driverExceptionModel->insert($insertData); + + $this->driverStatusModel->update([ + 'status' => DriverCode::EXCEPTIONS, + ]); + }); + + return $this->return->success(); + } +} \ No newline at end of file diff --git a/app/Service/Api/Driver/BaseDriverService.php b/app/Service/Api/Driver/BaseDriverService.php index 9e2075d..72e03ca 100644 --- a/app/Service/Api/Driver/BaseDriverService.php +++ b/app/Service/Api/Driver/BaseDriverService.php @@ -10,9 +10,15 @@ declare(strict_types=1); namespace App\Service\Api\Driver; +use App\Constants\Admin\CateringCode; +use App\Constants\Common\GoodCode; use App\Constants\Common\RoleCode; use App\Exception\ErrException; use App\Model\AdminUser; +use App\Model\DriverStatus; +use App\Model\OrderMealCateringLog; +use App\Model\OrderOptionCateringLog; +use App\Model\Site; use App\Service\Api\BaseService; use App\Service\ServiceTrait\Common\CycleTrait; use Hyperf\Database\Model\Builder; @@ -31,6 +37,40 @@ abstract class BaseDriverService extends BaseService #[Inject] protected AdminUser $adminUserModel; + /** + * @var Site + */ + #[Inject] + protected Site $siteModel; + + /** + * @var OrderMealCateringLog + */ + #[Inject] + protected OrderMealCateringLog $orderMealCateringLogModel; + + /** + * @var OrderOptionCateringLog + */ + #[Inject] + protected OrderOptionCateringLog $orderOptionCateringLogModel; + + /** + * @var DriverStatus + */ + #[Inject] + protected DriverStatus $driverStatusModel; + + /** + * @var array + */ + protected array $siteIds; + + /** + * @var array + */ + protected array $siteArr; + /** * @var Builder|Model|AdminUser|null */ @@ -50,7 +90,148 @@ abstract class BaseDriverService extends BaseService $this->adminInfo = $this->adminUserModel->getAdminInfoByBindUserId($this->userId); if ($this->adminInfo->role_id != RoleCode::DRIVER) throw new ErrException('暂无权限,请联系客服并提供相关信息绑定账号'); + + $siteArr = $this->siteModel + ->where('delivered_id',$this->adminInfo->id) + ->orderBy('sequence') + ->get(); + if ($siteArr->isEmpty()) throw new ErrException('该司机并未绑定站点'); + $this->siteArr = array_column($siteArr->toArray(),null,'id'); + $this->siteIds = array_keys($siteArr); } abstract public function handle(); + + + /** + * @return array + */ + protected function getTodayList(): array + { + $info = $this->driverStatusModel + ->where('driver_id',$this->adminInfo->id) + ->where('cycle_id',$this->cycleId) + ->whereIn('site_id',$this->siteIds) + ->get(); + + if ($info->isEmpty()) return []; + $info = $info->toArray(); + + foreach ($info as $infoItem) { + $info['meal_list'] = json_decode($info['meal_list'], true); + } + + return $info; + } + + /** + * @return array + */ + protected function getMealData(): array + { + $mealArr = $this->orderMealCateringLogModel + ->where('cycle_id',$this->cycleId) + ->where('status',CateringCode::CATERING_STATUS_FINISH) + ->whereIn('site_id', $this->siteIds) + ->select(['quantity','site_id','sku_id']) + ->get(); + if ($mealArr->isEmpty()) $mealArr = []; + $mealArr = $mealArr->toArray(); + + $skuIds = array_column($mealArr, 'sku_id'); + $skuArr = $this->skuModel->getDataArrByIds($skuIds); + $skuArr = array_column($skuArr,null,'id'); + + + $res = []; + foreach ($mealArr as $oneLog) { + if (empty($res[$oneLog['site_id']])) { + $res[$oneLog['site_id']] = [ + 'total_copies' => 0, + 'add_staple_food_num' => 0, + 'sku' => [] + ]; + } + + if (empty($res[$oneLog['site_id']]['sku'][$oneLog['sku_id']])) { + $res[$oneLog['site_id']]['sku'][$oneLog['sku_id']] = [ + 'sku_id' => $oneLog['sku_id'], + 'sku_name' => $skuArr[$oneLog['sku_id']]['title'] ?? '', + 'quantity' => 0, + ]; + } + + if ($skuArr[$oneLog['sku_id']]['is_add_staple_food'] == GoodCode::IS_ADD_STAPLE_FOOD) { + $res[$oneLog['site_id']]['add_staple_food_num'] += $oneLog['quantity']; + } else { + $res[$oneLog['site_id']]['total_copies'] += $oneLog['quantity']; + } + + $res[$oneLog['site_id']]['sku'][$oneLog['sku_id']]['quantity'] += $oneLog['quantity']; + } + + return $res; + } + + /** + * @return array + */ + protected function getOptionData(): array + { + $optionArr = $this->orderOptionCateringLogModel + ->where('cycle_id',$this->cycleId) + ->where('status',CateringCode::CATERING_STATUS_FINISH) + ->whereIn('site_id', $this->siteIds) + ->select(['quantity','site_id','add_staple_food_num']) + ->get(); + if ($optionArr->isEmpty()) $optionArr = []; + $optionArr = $optionArr->toArray(); + + $res = []; + foreach ($optionArr as $oneSite) { + if (empty($res[$oneSite['site_id']])) { + $res[$oneSite['site_id']] = [ + 'copies' => 0, + 'add_staple_food_num' => 0 + ]; + } + + $res[$oneSite['site_id']]['copies'] = $oneSite['quantity'] + $res[$oneSite['site_id']]['copies']; + $res[$oneSite['site_id']]['add_staple_food_num'] = $oneSite['add_staple_food_num'] + $res[$oneSite['site_id']]['add_staple_food_num']; + } + + return $res; + } + + /** + * @return array + */ + protected function buildListData(): array + { + $optionArr = $this->getOptionData(); + + $mealArr = $this->getMealData(); + + $res = []; + $dateTime = date('Y-m-d H:i:s'); + + foreach ($this->siteArr as $site) { + $res[] = [ + 'cycle_id' => $this->cycleId, + 'site_id' => $site['id'], + 'site_name' => $site['name'], + 'driver_id' => $this->adminInfo->id, + 'line_name' => '', + 'meal_order_quantity' => $mealArr[$site['id']]['quantity'] ?? 0, + 'meal_add_staple_food_num' => $mealArr[$site['id']]['add_staple_food_num'] ?? 0, + 'meal_list' => $mealArr[$site['id']]['sku'] ?? [], + 'option_order_quantity' => $optionArr[$site['id']]['quantity'] ?? 0, + 'option_add_staple_food_num' => $optionArr[$site['id']]['add_staple_food_num'] ?? 0, + 'create_time' => $dateTime, + 'update_time' => $dateTime, + ]; + } + + return $res; + } } \ No newline at end of file diff --git a/app/Service/Api/Driver/DeliverService.php b/app/Service/Api/Driver/DeliverService.php new file mode 100644 index 0000000..fa8a409 --- /dev/null +++ b/app/Service/Api/Driver/DeliverService.php @@ -0,0 +1,78 @@ +siteId = (int)$this->request->input('site_id'); + + $info = $this->driverStatusModel + ->where('cycle_id',$this->cycleId) + ->where('site_id',$this->siteId) + ->where('driver_id',$this->adminInfo->id) + ->first(); + + if (empty($info)) throw new ErrException('今日无该点位的送餐数据'); + + if ($info->status == DriverCode::DESTINATION) throw new ErrException('该点位已送达'); + + $orderIds = $this->orderModel + ->where('cycle_id',$this->cycleId) + ->where('status',OrderCode::DEPART) + ->where('site_id',$this->siteId) + ->pluck('id') + ->toArray(); + + Db::transaction(function () use ($info,$orderIds) { +// $this->orderModel->whereIn('id', $orderIds)->update([ +// 'status' => OrderCode::DEPART, +// 'set_out_time' => date('Y-m-d H:i:s'), +// ]); + + $info->status = DriverCode::DESTINATION; + if (!$info->save()) throw new ErrException('送达失败-01'); + + + $dateTime = date('Y-m-d H:i:s'); + foreach (array_chunk($orderIds, 500) as $chunk) { + $this->orderModel->whereIn('id', $chunk)->update([ + 'status' => OrderCode::ARRIVE, + 'delivery_time' => $dateTime, + ]); + } + }); + + return $this->return->success(); + } +} \ No newline at end of file diff --git a/app/Service/Api/Driver/GetSiteListService.php b/app/Service/Api/Driver/GetSiteListService.php index 0ce8252..93c15d3 100644 --- a/app/Service/Api/Driver/GetSiteListService.php +++ b/app/Service/Api/Driver/GetSiteListService.php @@ -21,23 +21,6 @@ use Hyperf\Di\Annotation\Inject; class GetSiteListService extends BaseDriverService { - /** - * @var Site - */ - #[Inject] - protected Site $siteModel; - - /** - * @var OrderMealCateringLog - */ - #[Inject] - protected OrderMealCateringLog $orderMealCateringLogModel; - - /** - * @var OrderOptionCateringLog - */ - #[Inject] - protected OrderOptionCateringLog $orderOptionCateringLogModel; /** * @var Sku @@ -50,117 +33,18 @@ class GetSiteListService extends BaseDriverService */ protected array $siteIds; - public function handle(): void - { - - } - - private function setCache() - { - $siteArr = $this->siteModel - ->where('delivered_id',$this->adminInfo->id) - ->orderBy('sequence') - ->get(); - if ($siteArr->isEmpty()) throw new ErrException('该司机并未绑定站点'); - $siteArr = array_column($siteArr->toArray(),null,'id'); - $this->siteIds = array_keys($siteArr); - - $optionArr = $this->getOptionData(); - - $mealArr = $this->getMealData(); - - $res = []; - foreach ($siteArr as $site) { - if (empty($res[$site['id']])) { - $res[$site['id']] = [ - 'site_id' => $site['id'], - 'site_name' => $site['name'], - 'name' => '', - 'meal_order_quantity' => 0, - 'meal_add_staple_food_num' => 0, - 'option_order_quantity' => 0, - 'option_add_staple_food_num' => 0, - ]; - } - } - } - /** * @return array */ - private function getMealData(): array + public function handle(): array { - $mealArr = $this->orderMealCateringLogModel - ->where('cycle_id',$this->cycleId) - ->where('status',CateringCode::CATERING_STATUS_FINISH) - ->whereIn('site_id', $this->siteIds) - ->select(['quantity','site_id','sku_id']) - ->get(); - if ($mealArr->isEmpty()) $mealArr = []; - $mealArr = $mealArr->toArray(); + $res = $this->getTodayList(); - $skuIds = array_column($mealArr, 'sku_id'); - $skuArr = $this->skuModel->getDataArrByIds($skuIds); - $skuArr = array_column($skuArr,null,'id'); + if (empty($res)) $res = $this->buildListData(); - - $res = []; - foreach ($mealArr as $oneLog) { - if (empty($res[$oneLog['site_id']])) { - $res[$oneLog['site_id']] = [ - 'total_copies' => 0, - 'add_staple_food_num' => 0, - 'sku' => [] - ]; - } - - if (empty($res[$oneLog['site_id']]['sku'][$oneLog['sku_id']])) { - $res[$oneLog['site_id']]['sku'][$oneLog['sku_id']] = [ - 'sku_id' => $oneLog['sku_id'], - 'sku_name' => $skuArr[$oneLog['sku_id']]['title'] ?? '', - 'quantity' => 0, - ]; - } - - if ($skuArr[$oneLog['sku_id']]['is_add_staple_food'] == GoodCode::IS_ADD_STAPLE_FOOD) { - $res[$oneLog['site_id']]['add_staple_food_num'] += $oneLog['quantity']; - } else { - $res[$oneLog['site_id']]['total_copies'] += $oneLog['quantity']; - } - - $res[$oneLog['site_id']]['sku'][$oneLog['sku_id']]['quantity'] += $oneLog['quantity']; - } - - return $res; + return $this->return->success('success', ['list' => $res]); } - /** - * @return array - */ - private function getOptionData(): array - { - $optionArr = $this->orderOptionCateringLogModel - ->where('cycle_id',$this->cycleId) - ->where('status',CateringCode::CATERING_STATUS_FINISH) - ->whereIn('site_id', $this->siteIds) - ->select(['quantity','site_id','add_staple_food_num']) - ->get(); - if ($optionArr->isEmpty()) $optionArr = []; - $optionArr = $optionArr->toArray(); +// private function setCache() {} //todo 赶时间 后续优化 - $res = []; - foreach ($optionArr as $oneSite) { - if (empty($res[$oneSite['site_id']])) { - $res[$oneSite['site_id']] = [ - 'copies' => 0, - 'add_staple_food_num' => 0 - ]; - } - - $res[$oneSite['site_id']]['copies'] = $oneSite['quantity'] + $res[$oneSite['site_id']]['copies']; - $res[$oneSite['site_id']]['add_staple_food_num'] = $oneSite['add_staple_food_num'] + $res[$oneSite['site_id']]['add_staple_food_num']; - } - - return $res; - } } diff --git a/app/Service/Api/Driver/LoadActionService.php b/app/Service/Api/Driver/LoadActionService.php new file mode 100644 index 0000000..bccd830 --- /dev/null +++ b/app/Service/Api/Driver/LoadActionService.php @@ -0,0 +1,85 @@ +orderOptionCateringLogModel + ->where('cycle_id',$this->cycleId) + ->where('status',CateringCode::CATERING_STATUS_UNDERWAY) + ->whereIn('site_id', $this->siteIds) + ->where('quantity','>',0) + ->sum('quantity') ?? 0) > 0 + ) throw new ErrException('自选配餐还未完成'); + + if ( + ($this->orderMealCateringLogModel + ->where('cycle_id',$this->cycleId) + ->where('status',CateringCode::CATERING_STATUS_UNDERWAY) + ->whereIn('site_id', $this->siteIds) + ->where('quantity','>',0) + ->sum('quantity') ?? 0) > 0 + ) throw new ErrException('套餐配餐还未完成'); + + $orderIds = $this->orderModel + ->where('cycle_id',$this->cycleId) + ->where('status',OrderCode::PLAN) + ->whereIn('site_id',$this->siteIds) + ->pluck('id') + ->toArray(); + + if (empty($orderIds)) throw new ErrException('数据不存在'); + + $list = $this->buildListData(); + foreach ($list as &$one) { + $one['meal_list'] = json_encode($one['meal_list']); + } + + Db::transaction(function () use ($orderIds,$list) { +// $this->orderModel->whereIn('id', $orderIds)->update([ +// 'status' => OrderCode::DEPART, +// 'set_out_time' => date('Y-m-d H:i:s'), +// ]); + + $this->driverStatusModel->insert($list); + + $dateTime = date('Y-m-d H:i:s'); + foreach (array_chunk($orderIds, 500) as $chunk) { + $this->orderModel->whereIn('id', $chunk)->update([ + 'status' => OrderCode::DEPART, + 'set_out_time' => $dateTime, + ]); + } + }); + + return $this->return->success(); + } +} \ No newline at end of file