diff --git a/app/Http/Controllers/Admin/ParkingGateControlController.php b/app/Http/Controllers/Admin/ParkingGateControlController.php index fc8facf..87da0c0 100644 --- a/app/Http/Controllers/Admin/ParkingGateControlController.php +++ b/app/Http/Controllers/Admin/ParkingGateControlController.php @@ -2,14 +2,20 @@ namespace App\Http\Controllers\Admin; +use App\Exceptions\CustomException; use App\Models\ParkingGateControl; use App\Models\ParkingLicensePlate; +use App\Models\ParkingReservation; use App\Models\ParkingSpaceType; use App\Services\ApiResponseService; +use App\Services\OperationLogService; use App\Services\ParkingGateControlService; +use App\Services\ParkingLicensePlateService; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Validator; +use Illuminate\Validation\ValidationException; class ParkingGateControlController extends BaseController { @@ -23,7 +29,7 @@ class ParkingGateControlController extends BaseController /** * 构造函数 - * @param ApiResponseService $responseService + * @param ApiResponseService $responseService * @param ParkingGateControlService $service */ public function __construct( @@ -141,7 +147,68 @@ class ParkingGateControlController extends BaseController { try { $data = ParkingGateControl::query()->find($id); - return $this->responseService->success($this->service->getItem($data)); + return $this->responseService->success( + $this->service->getItem($data) + ); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } + + public function getNumber(Request $request): JsonResponse + { + try { + $data = $request->all(); + $rules = [ + 'number' => 'required' + ]; + $messages = [ + 'number.required' => __validation( + 'gate_control.n_empty' + ) + ]; + $this->validateData($data, $rules, $messages); + + $is_reservation = false; + $exists = ParkingReservation::query()->where([ + 'reserve_id' => $data['number'], + 'status' => 1, + 'date' => date('Y-m-d', time()) + ])->exists(); + if ($exists) { + $is_reservation = true; + } + + if (!$is_reservation) { + $license_plate_id = (new ParkingLicensePlateService( + new OperationLogService() + ))->createLicenseId($data['number']); + $exists = ParkingReservation::query()->where([ + 'license_plate_id' => $license_plate_id, + 'status' => 1, + 'date' => date('Y-m-d', time()) + ])->exists(); + if ($exists) { + $is_reservation = true; + } + } + if (!$is_reservation) { + throw new CustomException( + __service( + 'gate_control.not_reservation' + ) + ); + } + return $this->responseService->success( + [], + __service( + 'gate_control.yes_reservation' + ) + ); + } catch (CustomException $e) { + throw $e; } catch (Exception $e) { return $this->responseService->systemError( __('exception.get_data_failed') . ':' . $e->getMessage() @@ -149,5 +216,101 @@ class ParkingGateControlController extends BaseController } } + public function getScreenshot() + { + try { + throw new CustomException(__service('gate_control.get_error')); + return $this->responseService->success( + [ + 'screenshot_url' => 'aa.jpeg' + ] + ); + } catch (CustomException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } + + protected function validateData($data, $rules, $messages) + { + $validator = Validator::make($data, $rules, $messages); + if ($validator->fails()) { + throw new ValidationException($validator); + } + } + + public function enter(Request $request): JsonResponse + { + try { + $data = $request->all(); + $rules = [ + 'number' => 'required', + 'enter_time' => 'required', + 'channel_id' => 'required' + ]; + $messages = [ + 'number.required' => __validation( + 'gate_control.n_empty' + ), + 'enter_time.required' => __validation( + 'gate_control.et_empty' + ), + 'channel_id.required' => __validation( + 'gate_control.c_empty' + ) + ]; + $this->validateData($data, $rules, $messages); + $this->service->enterModel($data); + return $this->responseService->success( + null, + __('admin.operation_successful') + ); + } catch (ValidationException|CustomException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('admin.operation_failed') . ':' + . $e->getMessage() + ); + } + } + public function leave(Request $request): JsonResponse + { + try { + $data = $request->all(); + $rules = [ + 'license_plate' => 'required', + 'leave_time' => 'required', + 'channel_id' => 'required' + ]; + $messages = [ + 'license_plate.required' => __validation( + 'gate_control.lp_empty' + ), + 'leave_time.required' => __validation( + 'gate_control.lt_empty' + ), + 'channel_id.required' => __validation( + 'gate_control.c_empty' + ) + ]; + $this->validateData($data, $rules, $messages); + $this->service->leaveModel($data); + return $this->responseService->success( + null, + __('admin.operation_successful') + ); + } catch (ValidationException|CustomException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('admin.operation_failed') . ':' + . $e->getMessage() + ); + } + } } diff --git a/app/Models/ParkingGateControl.php b/app/Models/ParkingGateControl.php index a1f4e9d..0456501 100644 --- a/app/Models/ParkingGateControl.php +++ b/app/Models/ParkingGateControl.php @@ -19,7 +19,12 @@ class ParkingGateControl extends Model 'leave_at', 'leave_type', 'enter_img', - 'leave_img' + 'leave_img', + 'member_type', + 'customer_id', + 'member_id', + 'free_passage', + 'reservation_id' ]; protected $hidden diff --git a/app/Services/ParkingGateControlService.php b/app/Services/ParkingGateControlService.php index d8d2894..2531811 100644 --- a/app/Services/ParkingGateControlService.php +++ b/app/Services/ParkingGateControlService.php @@ -4,41 +4,36 @@ namespace App\Services; use App\Models\Parking; use App\Models\ParkingChannel; +use App\Models\ParkingGateControl; use App\Models\ParkingLicensePlate; use App\Models\ParkingReservation; use App\Models\ParkingSpaceType; +use Exception; +use Illuminate\Support\Facades\DB; class ParkingGateControlService extends BaseService { - protected string $menuTitle = 'gate_control'; - - public static array $typeArr = [ - 1 => 'automatic', - 2 => 'manual' - ]; - - /** - * @return array|string[] - */ - public function getType(): array - { - $typeArr = self::$typeArr; - foreach ($typeArr as $key => $value) { - $typeArr[$key] = __service($this->menuTitle . '.' . $value); - } - return $typeArr; - } + public static array $typeArr + = [ + 1 => 'automatic', + 2 => 'manual' + ]; + protected string $menuTitle = 'gate_control'; public function getItem($item) { $typeArr = $this->getType(); - $date = date("Y-m-d", strtotime($item['enter_at'])); + $item['reserve_id'] = ParkingReservation::query()->where( - 'license_plate_id', - $item['license_plate_id'] - )->where('date', $date)->value('reserve_id'); + 'id', + $item['reservation_id'] + )->value( + 'reserve_id' + ); $item['member_type'] = ParkingSpaceType::getName($item['member_type']); - $item['license_plate'] = ParkingLicensePlate::getNumber($item['license_plate_id']); + $item['license_plate'] = ParkingLicensePlate::getNumber( + $item['license_plate_id'] + ); $ParkingChannel = ParkingChannel::getFirst($item['channel_id']); $item['channel'] = ''; $item['parking'] = ''; @@ -48,11 +43,131 @@ class ParkingGateControlService extends BaseService } $item['enter_type_str'] = $typeArr[$item['enter_type']]; $item['leave_type_str'] = $typeArr[$item['leave_type']] ?? ''; - $item['dwell_time'] = get_time_difference_str($item['enter_at'], $item['leave_at']); + $item['dwell_time'] = get_time_difference_str( + $item['enter_at'], + $item['leave_at'] + ); $item['enter_img'] = get_image_url($item['enter_img']); $item['leave_img'] = get_image_url($item['leave_img']); - unset($item['license_plate_id'], $item['channel_id']); + unset($item['license_plate_id'], $item['channel_id'], $item['reservation_id'], $item['free_passage']); return $item; } + + /** + * @return array|string[] + */ + public function getType(): array + { + $typeArr = self::$typeArr; + foreach ($typeArr as $key => $value) { + $typeArr[$key] = __service($this->menuTitle . '.' . $value); + } + return $typeArr; + } + + public function enterModel($data) + { + try { + DB::beginTransaction(); + $number = $data['number']; + $enter_time = $data['enter_time']; + $is_reservation = $data['is_reservation'] ?? 0; + $date = date("Y-m-d", strtotime($enter_time)); + $reservation_id = 0; + $license_plate_id = ''; + $member_type = 0; + $customer_id = ''; + $member_id = ''; + $ParkingReservation = ParkingReservation::query()->where([ + 'reserve_id' => $number, + 'status' => 1, + 'date' => $date + ])->first(); + if ($ParkingReservation) { + $reservation_id = $ParkingReservation['id']; + $license_plate_id = $ParkingReservation['license_plate_id']; + $member_type = $ParkingReservation['member_type']; + $customer_id = $ParkingReservation['customer_id']; + $member_id = $ParkingReservation['member_id']; + } + $enter_img = $data['enter_img'] ?? ''; + $channel_id = $data['channel_id']; + if (!$license_plate_id) { + $license_plate_id = (new ParkingLicensePlateService( + $this->logService + ))->createLicenseId($number); + } + + $id = ParkingGateControl::query()->where( + 'license_plate_id', + $license_plate_id + )->whereNull('leave_at')->value('id'); + if ($id) { + throw new Exception( + __service($this->menuTitle . '.cat_exists') + ); + } + + $model = ParkingGateControl::query()->create([ + 'license_plate_id' => $license_plate_id, + 'channel_id' => $channel_id, + 'enter_type' => 2, + 'enter_img' => $enter_img, + 'enter_at' => $enter_time, + 'reservation_id' => $reservation_id, + 'member_type' => $member_type, + 'customer_id' => $customer_id, + 'member_id' => $member_id, + 'created_at' => get_datetime() + ]); + $this->logService->logCreated($model, $this->menuTitle . '.create_enter'); + DB::commit(); + return $model; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } + + public function leaveModel($data) + { + try { + DB::beginTransaction(); + $license_plate = $data['license_plate']; + $leave_time = $data['leave_time']; + $leave_img = $data['leave_img'] ?? ''; + $free_passage = $data['free_passage'] ?? 0; + $license_plate_id = (new ParkingLicensePlateService( + $this->logService + ))->createLicenseId($license_plate); + $id = ParkingGateControl::query()->where( + 'license_plate_id', + $license_plate_id + )->whereNull('leave_at')->value('id'); + if (!$id) { + throw new Exception( + __service($this->menuTitle . '.cat_not_exists') + ); + } + $model = ParkingGateControl::query()->findOrFail($id); + $oldValue = $model->toArray(); + + $model->update([ + 'enter_type' => 2, + 'leave_img' => $leave_img, + 'leave_at' => $leave_time, + 'free_passage' => $free_passage, + 'updated_at' => get_datetime() + ]); + $this->logService->logUpdated($model, $oldValue, $this->menuTitle . '.update_leave'); + DB::commit(); + return $model; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } + + } diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index 7dc70f4..c6aae81 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -286,14 +286,17 @@ class AdminMenuSeeder extends Seeder ], 'gate_control' => [ 'uri' => 'gateControl', - 'page_uri' => '/gate/gateControl', + 'page_uri' => '/gate/guardpost', 'child' => [ - 'read_only' => 'gateControl.index' + 'read_only' => 'gateControl.index', + 'add_enter' => 'gateControl.enter', + 'add_leave' => 'gateControl.leave', + 'get_screenshot' => 'gateControl.getScreenshot' ] ], 'prohibited_passage' => [ 'uri' => 'prohibitedPassage', - 'page_uri' => '/prohibitedPassage/Lanevideo', + 'page_uri' => '/gate/Lanevideo', 'child' => [ 'read_only' => 'prohibitedPassage.index' ] diff --git a/resources/lang/en/log.php b/resources/lang/en/log.php index 0df7020..953f603 100644 --- a/resources/lang/en/log.php +++ b/resources/lang/en/log.php @@ -143,5 +143,9 @@ return [ 'create' => 'Create a maintenance parking space', 'update' => 'Update and repair parking spaces', 'delete' => 'Delete maintenance parking space' + ], + 'gate_control' => [ + 'create_enter' => 'Create entry record', + 'update_leave' => 'Update departure records' ] ]; diff --git a/resources/lang/en/menu.php b/resources/lang/en/menu.php index 2e84c0c..636c88e 100644 --- a/resources/lang/en/menu.php +++ b/resources/lang/en/menu.php @@ -97,5 +97,8 @@ return [ 'allocation' => 'allocation', 'edit_remark' => "Editor's note", 'gate_control' => 'Gate control', - 'prohibited_passage' => 'Record of prohibited passage' + 'prohibited_passage' => 'Record of prohibited passage', + 'add_enter' => 'Create entry record', + 'add_leave' => 'Create exit record', + 'get_screenshot' => 'Get screenshot' ]; diff --git a/resources/lang/en/service.php b/resources/lang/en/service.php index 828cd6b..c6e4dd3 100644 --- a/resources/lang/en/service.php +++ b/resources/lang/en/service.php @@ -168,8 +168,13 @@ return [ 'synced' => 'Synchronized' ], 'gate_control' => [ - 'automatic' => 'Automatic entry', - 'manual' => 'Manual entry' + 'automatic' => 'Automatic entry', + 'manual' => 'Manual entry', + 'cat_exists' => 'The current vehicle has not left yet', + 'cat_not_exists' => 'The current vehicle has not entered the venue', + 'not_reservation' => 'No appointment available', + 'yes_reservation' => 'Appointment', + 'get_error' => 'Failed to obtain' ], 'prohibited_passage' => [ 'remark1' => 'No appointment, no entry allowed', diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php index 1c8f7b4..e582198 100644 --- a/resources/lang/en/validation.php +++ b/resources/lang/en/validation.php @@ -178,5 +178,12 @@ return [ 'ids_empty' => '請選擇要删除的數據', 'ids_array' => '所選數據必須是數組', 'date_error' => '開始時間不能大於結束時間' + ], + 'gate_control' => [ + 'n_empty' => 'Order number or license plate number cannot be empty', + 'et_empty' => 'The entry time cannot be empty', + 'channel_id' => 'Channel cannot be empty', + 'lp_empty' => 'The license plate number cannot be empty', + 'lt_empty' => 'Departure time cannot be empty' ] ]; diff --git a/resources/lang/zh-CN/log.php b/resources/lang/zh-CN/log.php index 8c7e6f4..3e48301 100644 --- a/resources/lang/zh-CN/log.php +++ b/resources/lang/zh-CN/log.php @@ -143,5 +143,9 @@ return [ 'create' => '创建维修车位', 'update' => '更新维修车位', 'delete' => '删除维修车位' + ], + 'gate_control' => [ + 'create_enter' => '创建入场记录', + 'update_leave' => '更新离场记录' ] ]; diff --git a/resources/lang/zh-CN/menu.php b/resources/lang/zh-CN/menu.php index d7ecec5..48b94dc 100644 --- a/resources/lang/zh-CN/menu.php +++ b/resources/lang/zh-CN/menu.php @@ -97,5 +97,8 @@ return [ 'allocation' => '分配', 'edit_remark' => '编辑备注', 'gate_control' => '闸机控制', - 'prohibited_passage' => '违禁通行记录' + 'prohibited_passage' => '违禁通行记录', + 'add_enter' => '创建入场记录', + 'add_leave' => '创建离场记录', + 'get_screenshot' => '获取截图' ]; diff --git a/resources/lang/zh-CN/service.php b/resources/lang/zh-CN/service.php index f2d93d0..c327164 100644 --- a/resources/lang/zh-CN/service.php +++ b/resources/lang/zh-CN/service.php @@ -168,8 +168,13 @@ return [ 'synced' => '已同步' ], 'gate_control' => [ - 'automatic' => '自动入场', - 'manual' => '手动入场' + 'automatic' => '自动入场', + 'manual' => '手动入场', + 'cat_exists' => '当前车辆还未离场', + 'cat_not_exists' => '当前车辆未入场', + 'not_reservation' => '无预约', + 'yes_reservation' => '有预约', + 'get_error' => '获取失败' ], 'prohibited_passage' => [ 'remark1' => '无预约,不可进场', diff --git a/resources/lang/zh-CN/validation.php b/resources/lang/zh-CN/validation.php index a779b8e..c3717d4 100644 --- a/resources/lang/zh-CN/validation.php +++ b/resources/lang/zh-CN/validation.php @@ -178,5 +178,12 @@ return [ 'ids_empty' => '请选择要删除的数据', 'ids_array' => '所选数据必须是数组', 'date_error' => '开始时间不能大于结束时间' + ], + 'gate_control' => [ + 'n_empty' => '订单号码或车牌号码不能为空', + 'et_empty' => '入场时间不能为空', + 'channel_id' => '通道不能为空', + 'lp_empty' => '车牌号码不能为空', + 'lt_empty' => '离场时间不能为空' ] ]; diff --git a/resources/lang/zh-TW/log.php b/resources/lang/zh-TW/log.php index 86fe102..dd08bcf 100644 --- a/resources/lang/zh-TW/log.php +++ b/resources/lang/zh-TW/log.php @@ -143,5 +143,9 @@ return [ 'create' => '創建維修車位', 'update' => '更新維修車位', 'delete' => '删除維修車位' + ], + 'gate_control' => [ + 'create_enter' => '创建入场记录', + 'update_leave' => '更新离场记录' ] ]; diff --git a/resources/lang/zh-TW/menu.php b/resources/lang/zh-TW/menu.php index 5b6e406..bcc390b 100644 --- a/resources/lang/zh-TW/menu.php +++ b/resources/lang/zh-TW/menu.php @@ -97,5 +97,8 @@ return [ 'allocation' => '分配', 'edit_remark' => '編輯備註', 'gate_control' => '閘機控制', - 'prohibited_passage' => '違禁通行記錄' + 'prohibited_passage' => '違禁通行記錄', + 'add_enter' => '创建入场记录', + 'add_leave' => '创建离场记录', + 'get_screenshot' => '获取截图' ]; diff --git a/resources/lang/zh-TW/service.php b/resources/lang/zh-TW/service.php index 914d0e8..f7f14f5 100644 --- a/resources/lang/zh-TW/service.php +++ b/resources/lang/zh-TW/service.php @@ -168,8 +168,13 @@ return [ 'synced' => '已同步' ], 'gate_control' => [ - 'automatic' => '自動入場', - 'manual' => '手動入場' + 'automatic' => '自動入場', + 'manual' => '手動入場', + 'cat_exists' => '当前车辆还未离场', + 'cat_not_exists' => '当前车辆未入场', + 'not_reservation' => '无预约', + 'yes_reservation' => '有预约', + 'get_error' => '获取失败' ], 'prohibited_passage' => [ 'remark1' => '無預約,不可進場', diff --git a/resources/lang/zh-TW/validation.php b/resources/lang/zh-TW/validation.php index 9b80af2..856b0fe 100644 --- a/resources/lang/zh-TW/validation.php +++ b/resources/lang/zh-TW/validation.php @@ -178,5 +178,12 @@ return [ 'ids_empty' => 'Please select the data to be deleted', 'ids_array' => 'The selected data must be an array', 'date_error' => 'The start time cannot be greater than the end time' + ], + 'gate_control' => [ + 'n_empty' => '訂單號碼或車牌號碼不能為空', + 'et_empty' => '入場時間不能為空', + 'channel_id' => '通道不能為空', + 'lp_empty' => '車牌號碼不能為空', + 'lt_empty' => '離場時間不能為空' ] ]; diff --git a/routes/admin/api.php b/routes/admin/api.php index 9366e31..b60a28e 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -239,6 +239,10 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/gateControl', [ParkingGateControlController::class, 'index']); Route::get('/gateControl/search', [ParkingGateControlController::class, 'search']); Route::get('/gateControl/show/{id}', [ParkingGateControlController::class, 'show']); + Route::get('/gateControl/enter', [ParkingGateControlController::class, 'getNumber']); + Route::get('/gateControl/getScreenshot', [ParkingGateControlController::class, 'getScreenshot']); + Route::post('/gateControl/enter', [ParkingGateControlController::class, 'enter']); + Route::post('/gateControl/leave', [ParkingGateControlController::class, 'leave']); // 违禁通行记录 Route::get('/prohibitedPassage', [ProhibitedPassageController::class, 'index']); // 系统总配置