diff --git a/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php b/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php index 2aba04b8..9f6cb7ef 100644 --- a/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php +++ b/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php @@ -7,6 +7,7 @@ use App\Enums\MissionStates; use App\Enums\MissionTypes; use App\Enums\MissionZones; use App\Http\Controllers\Controller; +use App\Http\Controllers\V3\Dashboard\RoadPatrol\OperatorController; use App\Http\Requests\V3\Mission\RequestPortal\StoreRequest; use App\Http\Requests\V3\Mission\RequestPortal\UpdateRequest; use App\Http\Traits\ApiResponse; @@ -59,6 +60,12 @@ class RequestPortalController extends Controller ]); $mission->rahdaran()->attach($request->rahdaran); + + if ($request->category_id == 2) { + $rpc = new OperatorController(); + $rpc->store($mission); + } + if ($request->category_id == 3){ RoadObserved::query() ->find($request->road_observed_id) diff --git a/app/Http/Controllers/V3/Dashboard/Mission/TransportationUnitController.php b/app/Http/Controllers/V3/Dashboard/Mission/TransportationUnitController.php index 6e96d81b..e15cdccc 100644 --- a/app/Http/Controllers/V3/Dashboard/Mission/TransportationUnitController.php +++ b/app/Http/Controllers/V3/Dashboard/Mission/TransportationUnitController.php @@ -27,6 +27,7 @@ class TransportationUnitController extends Controller { DB::transaction(function () use ($request, $mission) { $mission->machines()->attach($request->machines); + $mission->rahdaran()->attach($request->driver, ['is_driver'=>true]); $mission->histories()->create([ 'user_id' => auth()->user()->id, diff --git a/app/Http/Controllers/V3/Dashboard/ObservedItemController.php b/app/Http/Controllers/V3/Dashboard/ObservedItemController.php index 5018fb5f..78c099b1 100644 --- a/app/Http/Controllers/V3/Dashboard/ObservedItemController.php +++ b/app/Http/Controllers/V3/Dashboard/ObservedItemController.php @@ -4,10 +4,14 @@ namespace App\Http\Controllers\V3\Dashboard; use App\Facades\DataTable\DataTableFacade; use App\Http\Controllers\Controller; +use App\Http\Requests\V3\ObservedItem\StoreRequest; use App\Http\Traits\ApiResponse; +use App\Models\InfoItem; use App\Models\ObservedItem; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; +use Illuminate\Validation\ValidationException; class ObservedItemController extends Controller { @@ -37,4 +41,59 @@ class ObservedItemController extends Controller return response()->json($dataTable); } + + /** + * @throws ValidationException + */ + public function store(StoreRequest $request): jsonResponse + { + foreach ($request->observed_items as $index => $item) { + $info_item = InfoItem::query()->where('item', $item['item_id']) + ->where('sub_item', $item['sub_item_id']) + ->firstOrFail(); + + $start = explode(',', $item['start_point']); + $priority = [ + 1 => 'عادی', + 2 => 'فوری', + 3 => 'آنی', + ]; + + $data = [ + 'road_patrol_id' => $request->road_patrol_id, + 'item_id' => $info_item->item, + 'item_name' => $info_item->item_str, + 'sub_item_id' => $info_item->sub_item, + 'sub_item_name' => $info_item->sub_item_str, + 'local_name' => $item['local_name'], + 'description' => $item['description'] ?? null, + 'start_lat' => $start[0], + 'start_lon' => $start[1], + 'priority' => $item['instant_action'] == 0 ? $item['priority'] : null, + 'priority_fa' => $item['instant_action'] ? $priority[$item['priority']] : null, + ]; + + if ($item['instant_action'] == 1) { + $item_end_coordinates = null; + + if ($info_item->needs_end_point) { + if (!isset($item['end_point'])) { + throw ValidationException::withMessages([ + "observed_items.$index.end_point" => __('validation.required', ['attribute' => 'end_point']), + ]); + } + + $item_end_coordinates = explode(',', $item['end_point']); + + $data['end_lat'] = $item_end_coordinates[0]; + $data['end_lon'] = $item_end_coordinates[1]; + } + } + DB::transaction(function () use ($data) { + ObservedItem::query()->create($data); + }); + } + + return $this->successResponse(); + } } diff --git a/app/Http/Controllers/V3/Dashboard/RoadPatrol/OperatorController.php b/app/Http/Controllers/V3/Dashboard/RoadPatrol/OperatorController.php index bdb4964a..e57e4c0d 100644 --- a/app/Http/Controllers/V3/Dashboard/RoadPatrol/OperatorController.php +++ b/app/Http/Controllers/V3/Dashboard/RoadPatrol/OperatorController.php @@ -3,26 +3,18 @@ namespace App\Http\Controllers\V3\Dashboard\RoadPatrol; -use App\Enums\MissionStates; use App\Exports\V3\RoadPatrols\OperatorCartableReport; use App\Facades\Sms\Sms; use App\Http\Controllers\Controller; use App\Http\Requests\V3\RoadPatrol\DeleteRequest; -use App\Http\Requests\V3\RoadPatrol\StoreRequest; use App\Http\Traits\ApiResponse; -use App\Models\EdarateShahri; -use App\Models\InfoItem; use App\Models\Mission; -use App\Models\RoadItemsProject; use App\Models\RoadPatrol; use App\Services\Cartables\RoadPatrol\OperatorService; -use App\Services\NominatimService; -use Carbon\Carbon; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; -use Illuminate\Validation\ValidationException; use Maatwebsite\Excel\Facades\Excel; use Symfony\Component\HttpFoundation\BinaryFileResponse; @@ -43,158 +35,16 @@ class OperatorController extends Controller return Excel::download(new OperatorCartableReport($data['data']), $name); } - public function store(StoreRequest $request, NominatimService $nominatimService): JsonResponse + public function store(Mission $mission): JsonResponse { - $user = auth()->user(); + $road_patrol = RoadPatrol::query()->create([ + 'status' => 0, + 'status_fa' => 'در حال بررسی', + ]); - $edare_id = $user->edarate_shahri_id ?? $user->edarate_ostani_id; - $edare_name = $user->edarate_shahri_id ? $user->edarate_shahri_name : $user->edarate_ostani_name; + $road_patrol->mission()->attach($mission->id); - $road_patrol = DB::transaction(function () use ( - $request, $edare_id, - $edare_name, $nominatimService, $user - ) { - $mission = Mission::query()->findOrFail($request->mission_id); - - if ($mission->status !== MissionStates::START_MISSION->value) { - throw ValidationException::withMessages([ - 'mission_id' => 'ماموریت انتخاب شده هنوز شروع نشده است.', - ]); - } - - $road_patrol = RoadPatrol::query()->create([ - 'operator_id' => $user->id, - 'operator_name' => $user->name, - 'province_id' => $user->province_id, - 'province_fa' => $user->province_fa, - 'city_id' => $user->city_id, - 'city_fa' => $user->city_fa, - 'edare_id' => $edare_id, - 'edare_name' => $edare_name, - 'status' => 0, - 'status_fa' => 'در حال بررسی', - 'distance' => $request->distance, - 'start_time' => $request->start_time, - 'end_time' => $request->end_time, - 'description' => $request->description ?? null, - 'fuel_consumption' => $request->fuel_consumption, - 'vehicle_runtime' => $request->vehicle_runtime, - 'stop_points' => json_encode($request->stop_points), - ]); - - $road_patrol->rahdaran()->attach($request->road_patrol_rahdaran_id); - $road_patrol->cmmsMachines()->attach($request->road_patrol_machines_id); - - if ($request->observed_items) { - foreach ($request->observed_items as $index => $item) { - $info_item = InfoItem::where('item', $item['item_id']) - ->where('sub_item', $item['sub_item_id']) - ->firstOrFail(); - - $item_start_coordinates = explode(',', $item['start_point']); - - $observed_item = $road_patrol->observedItems()->create([ - 'item_id' => $info_item->item, - 'item_name' => $info_item->item_str, - 'sub_item_id' => $info_item->sub_item, - 'sub_item_name' => $info_item->sub_item_str, - 'local_name' => $item['local_name'], - 'description' => $item['description'] ?? null, - 'start_lat' => $item_start_coordinates[0], - 'start_lon' => $item_start_coordinates[1], - ]); - - $item_end_coordinates = null; - if ($item['instant_action'] == 0) { - $priority = [ - 1 => 'عادی', - 2 => 'فوری', - 3 => 'آنی', - ]; - $observed_item->priority = $item['priority']; - $observed_item->priority_fa = $priority[$item['priority']]; - $observed_item->save(); - } elseif ($item['instant_action'] == 1) { - if ($info_item->needs_end_point) { - if (!isset($item['end_point'])) { - throw ValidationException::withMessages([ - "observed_items.$index.end_point" => __('validation.required', ['attribute' => 'end_point']), - ]); - } - - $item_end_coordinates = explode(',', $item['end_point']); - } - - $before_image = null; - $after_image = null; - if ($info_item->needs_image) { - if (!isset($item['before_image'])) { - throw ValidationException::withMessages([ - "observed_items.$index.before_image" => __('validation.required', ['attribute' => 'before_image']), - ]); - } - if (!isset($item['after_image'])) { - throw ValidationException::withMessages([ - "observed_items.$index.after_image" => __('validation.required', ['attribute' => 'after_image']), - ]); - } - - $before_image = $item['before_image']; - $after_image = $item['after_image']; - } - - $start_time = Carbon::createFromFormat('Y-m-d H:i', $request->start_time); - $end_time = Carbon::createFromFormat('Y-m-d H:i', $request->end_time); - $activity_date = $start_time->average($end_time); - - $attributes = [ - 'start_lat' => $item_start_coordinates[0], - 'start_lng' => $item_start_coordinates[1], - 'end_lat' => $item_end_coordinates ? $item_end_coordinates[0] : null, - 'end_lng' => $item_end_coordinates ? $item_end_coordinates[1] : null, - 'item' => $info_item->item, - 'item_fa' => $info_item->item_str, - 'sub_item' => $info_item->sub_item, - 'sub_item_fa' => $info_item->sub_item_str, - 'sub_item_data' => $item['amount'], - 'province_id' => $user->province_id, - 'province_fa' => $user->province_fa, - 'city_id' => $user->city_id, - 'city_fa' => $user->city_fa, - 'user_name' => $user->name, - 'start_way_id' => $nominatimService->get_way_id_from_nominatim($item_start_coordinates[0], $item_start_coordinates[1]), - 'end_way_id' => $item_end_coordinates ? $nominatimService->get_way_id_from_nominatim($item_end_coordinates[0], $item_end_coordinates[1]) : null, - 'unit_fa' => $info_item->sub_item_unit, - 'created_at_fa' => verta(Carbon::now())->format('Y-m-d H:i:s'), - 'info_id' => $info_item->id, - 'status' => 0, - 'status_fa' => 'در حال بررسی', - 'edarat_id' => $user->edarate_shahri_id, - 'edarat_type' => EdarateShahri::class, - 'edarat_name' => $user->edarate_shahri_name, - 'activity_date' => $activity_date->format('Y-m-d'), - 'activity_time' => $activity_date->format('H:i:s'), - ]; - - $road_item = RoadItemsProject::store($user, $attributes, $before_image, $after_image, $observed_item->id); - - if ($road_item === -1) { - return $this->errorResponse('اقدام مربوطه قبلا رسیدگی شده است.'); - } - - $road_item->rahdaran()->attach($item['road_item_rahdaran_id']); - $road_item->cmmsMachines()->attach($item['road_item_machines_id']); - } - } - } - - auth()->user()->addActivityComplete(1147); - - Sms::sendSms($request->officer_phone_number, - "گشت راهداری با کد یکتای $road_patrol->id در تاریخ " . verta(\Carbon\Carbon::now())->format('Y-m-d H:i:s') . " با شماره شما در سامانه RMS ثبت شد. \n لینک دریافت گزارش : \n https://rms.rmto.ir/v2/road_patrols/operator/report/$road_patrol->id" - ); - return $road_patrol; - }); + auth()->user()->addActivityComplete(1147); return $this->successResponse(); } diff --git a/app/Http/Requests/V3/Mission/TransportaionUnit/AllocateRequest.php b/app/Http/Requests/V3/Mission/TransportaionUnit/AllocateRequest.php index 5cff54a5..4c744cba 100644 --- a/app/Http/Requests/V3/Mission/TransportaionUnit/AllocateRequest.php +++ b/app/Http/Requests/V3/Mission/TransportaionUnit/AllocateRequest.php @@ -25,6 +25,7 @@ class AllocateRequest extends FormRequest return [ 'machines' => 'required|array', 'machines.*' => 'required|integer|exists:cmms_machines,id', + 'driver' => 'required|integer|exists:rahdaran,id' ]; } } diff --git a/app/Http/Requests/V3/ObservedItem/StoreRequest.php b/app/Http/Requests/V3/ObservedItem/StoreRequest.php new file mode 100644 index 00000000..9d5e2593 --- /dev/null +++ b/app/Http/Requests/V3/ObservedItem/StoreRequest.php @@ -0,0 +1,40 @@ +|string> + */ + public function rules(): array + { + return [ + 'road_patrol_id' => 'required|integer|exists:road_patrols,id', + 'observed_items' => 'required|array|min:1', + + 'observed_items.*.item_id' => 'required|integer|exists:info_items,item', + 'observed_items.*.sub_item_id' => 'required|integer', + 'observed_items.*.start_point' => 'required|string', + + 'observed_items.*.local_name' => 'nullable|string', + 'observed_items.*.description' => 'nullable|string', + + 'observed_items.*.instant_action' => 'required|in:0,1', + 'observed_items.*.priority' => 'required_if:observed_items.*.instant_action,0|in:1,2,3', + 'observed_items.*.end_point' => 'required_if:observed_items.*.instant_action,1|string', + ]; + } +} diff --git a/app/Http/Requests/V3/RoadPatrol/StoreRequest.php b/app/Http/Requests/V3/RoadPatrol/StoreRequest.php deleted file mode 100644 index 30c4d899..00000000 --- a/app/Http/Requests/V3/RoadPatrol/StoreRequest.php +++ /dev/null @@ -1,68 +0,0 @@ -|string> - */ - public function rules(): array - { - return [ - 'verification_code' => ['required', 'string', new VerificationCode($this->phone_number)], - 'distance' => 'numeric', - 'start_time' => 'required|date_format:Y-m-d H:i', - 'end_time' => 'required|date_format:Y-m-d H:i|after:start_time', - 'fuel_consumption' => 'required|numeric', - 'vehicle_runtime' => 'required|integer', - 'stop_points' => 'required|array', - 'road_patrol_machines_id' => 'required|array', - 'road_patrol_machines_id.*' => 'required|exists:cmms_machines,id', - 'road_patrol_rahdaran_id' => 'required|array', - 'road_patrol_rahdaran_id.*' => 'required|exists:rahdaran,id', - - 'observed_items' => 'array', - 'observed_items.*.item_id' => 'required|integer', - 'observed_items.*.sub_item_id' => 'required|integer', - 'observed_items.*.description' => '', - 'observed_items.*.instant_action' => 'required|in:0,1', - 'observed_items.*.local_name' => 'required_if:observed_items.*.instant_action,0', - - // road item projects fields - 'observed_items.*.start_point' => 'required', - 'observed_items.*.end_point' => '', - 'observed_items.*.amount' => 'numeric|required_if:observed_items.*.instant_action,1', - 'observed_items.*.before_image' => 'image|max:4096', - 'observed_items.*.after_image' => 'image|max:4096', - 'observed_items.*.priority' => 'integer|in:1,2,3|required_if:observed_items.*.instant_action,0', - 'description' => 'string', - - 'observed_items.*.road_item_machines_id' => 'required_if:observed_items.*.instant_action,1|array', - 'observed_items.*.road_item_machines_id.*' => 'required_if:observed_items.*.instant_action,1|exists:cmms_machines,id', - 'observed_items.*.road_item_rahdaran_id' => 'required_if:observed_items.*.instant_action,1|array', - 'observed_items.*.road_item_rahdaran_id.*' => 'required_if:observed_items.*.instant_action,1|exists:rahdaran,id', - ]; - } - - public function attributes(): array - { - return [ - 'start_time' => 'ساعت شروع گشت', - 'end_time' => 'ساعت پایان گشت', - ]; - } -} diff --git a/app/Models/Accident.php b/app/Models/Accident.php index f1495dce..aec15bce 100644 --- a/app/Models/Accident.php +++ b/app/Models/Accident.php @@ -14,6 +14,7 @@ class Accident extends Model use ReceiptReportAble, HasFactory; protected $guarded = []; + protected $appends = ['link']; public static function boot() { @@ -118,4 +119,11 @@ class Accident extends Model get: fn($value) => $value == null ? null : Storage::disk('public')->url($value) ); } + + protected function link(): Attribute + { + return Attribute::make( + get: fn ($value) => env("PAYMENT_LINK")."/#/pay/".explode("/", $this->bill_code)[0]."/{$this->final_amount}", + ); + } } diff --git a/database/migrations/2024_12_25_133822_create_machinables_table.php b/database/migrations/2024_12_25_133822_create_machinables_table.php index 4e81635b..31c4e9f4 100644 --- a/database/migrations/2024_12_25_133822_create_machinables_table.php +++ b/database/migrations/2024_12_25_133822_create_machinables_table.php @@ -24,6 +24,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('machinable'); + Schema::dropIfExists('machinables'); } }; diff --git a/database/migrations/2025_07_21_095907_add_one_column_to_rahdarables_table.php b/database/migrations/2025_07_21_095907_add_one_column_to_rahdarables_table.php new file mode 100644 index 00000000..6dbc833b --- /dev/null +++ b/database/migrations/2025_07_21_095907_add_one_column_to_rahdarables_table.php @@ -0,0 +1,28 @@ +boolean('is_driver')->nullable()->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('rahdarables', function (Blueprint $table) { + $table->dropColumn('is_driver'); + }); + } +}; diff --git a/database/migrations/2025_07_22_162735_make_columns_name_nullable_on_road_patrols.php b/database/migrations/2025_07_22_162735_make_columns_name_nullable_on_road_patrols.php new file mode 100644 index 00000000..4ac40ee8 --- /dev/null +++ b/database/migrations/2025_07_22_162735_make_columns_name_nullable_on_road_patrols.php @@ -0,0 +1,30 @@ +timestamp('start_time')->nullable()->change(); + $table->timestamp('end_time')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('road_patrols', function (Blueprint $table) { + $table->timestamp('start_time')->change(); + $table->timestamp('end_time')->change(); + }); + } +}; diff --git a/routes/v3.php b/routes/v3.php index a12dcfab..294a407f 100644 --- a/routes/v3.php +++ b/routes/v3.php @@ -199,6 +199,7 @@ Route::prefix('observed_items') ->name('observedItem.') ->controller(ObservedItemController::class) ->group(function () { + Route::post('/', 'store')->name('store'); Route::get('/filter', 'filter')->name('filter'); Route::get('/{observedItem}', 'show')->name('show'); });