diff --git a/app/Http/Controllers/V3/ProfileController.php b/app/Http/Controllers/V3/ProfileController.php index 4ba5d36b..b5841811 100644 --- a/app/Http/Controllers/V3/ProfileController.php +++ b/app/Http/Controllers/V3/ProfileController.php @@ -78,4 +78,10 @@ class ProfileController extends Controller return $this->successResponse(); } + + public function addActivity(Request $request): JsonResponse + { + auth()->user()->addActivityComplete($request->query('activityCode')); + return $this->successResponse(); + } } diff --git a/app/Http/Controllers/V3/RoadItemsProjectController.php b/app/Http/Controllers/V3/RoadItemsProjectController.php new file mode 100644 index 00000000..a4318e6f --- /dev/null +++ b/app/Http/Controllers/V3/RoadItemsProjectController.php @@ -0,0 +1,314 @@ +user(); + $query = null; + + if ($user->hasPermissionTo('show-road-item-supervise-cartable')) { + $query = RoadItemsProject::query()->where('is_new', 1)->with('files'); + } + elseif ($user->hasPermissionTo('show-road-item-supervise-cartable-province')) { + if (is_null($user->province_id)) { + return $this->errorResponse('استانی برای شما در سامانه ثبت نشده است!'); + } + $query = RoadItemsProject::query()->where('is_new', 1) + ->with('files')->where('province_id', auth()->user()->province_id); + } + + $data = DataTableFacade::run( + $query, + $request, + allowedFilters: $allowedFilters, + allowedSortings: $allowedSortings); + + return response()->json($data); + } + + public function verifyBySupervisor(VerifyBySupervisorRequest $request, RoadItemsProject $road_item): JsonResponse + { + $status_fa = $request->verify == 1 ? 'تایید شده' : 'عدم تایید'; + $user = auth()->user(); + + $road_item->update([ + 'status' => $request->verify, + 'status_fa' => $status_fa, + 'supervisor_id' => $user->id, + 'supervisor_name' => $user->name, + 'supervisor_description' => $request->description, + 'supervising_time' => now(), + ]); + + $user->addActivityComplete(1149); + + return $this->successResponse(); + } + + public function restore(RoadItemsProject $road_item): JsonResponse + { + if ($road_item->status == 0) { + return response()->json([ + 'message' => 'امکان بازگردانی وضعیت این فعالیت وجود ندارد!' + ], 400); + } + + $road_item->update([ + 'status' => 0, + 'status_fa' => 'در حال بررسی', + 'supervisor_id' => null, + 'supervisor_description' => null, + 'supervising_time' => null, + 'supervisor_name' => null, + ]); + auth()->user()->addActivityComplete(1150); + + return $this->successResponse(); + } + + public function delete(RoadItemsProject $road_item): JsonResponse + { + if ($road_item->files()->exists()) { + Storage::delete('public/'. $road_item->files[0]->path); + Storage::delete('public/'. $road_item->files[1]->path); + $road_item->files()->delete(); + } + auth()->user()->addActivityComplete(1151); + + $road_item->delete(); + + return $this->successResponse(); + } + + + public function supervisorCartableReport(Request $request) + { + $name = 'گزارش از کارتابل ارزیابی فعالیت روزانه ' . verta()->now()->format('Y-m-d H:i') . '.xlsx'; + return Excel::download(new SupervisorCartableExport($request->id, $request->item, $request->status, + $request->fromDate, $request->toDate, $request->province_id, $request->edarat_id), $name); + } + + public function operatorIndex(Request $request): JsonResponse + { + $columns = array( + 'id', 'user_id', 'start_lat', 'start_lng', 'end_lat', + 'end_lng', 'project_distance', 'item', 'item_fa', 'sub_item_fa', + 'sub_item_data', 'created_at', 'updated_at', 'province_id', 'province_fa', + 'unit_fa', 'status', 'status_fa', 'supervisor_description', 'supervising_time', + 'supervisor_name', 'edarat_id', 'edarat_name', 'activity_date_time' + ); + + $allowedFilters = $columns; + $allowedSortings = $columns; + + $query = RoadItemsProject::with('files') + ->where('is_new', 1) + ->where('user_id', auth()->user()->id); + + $data = DataTableFacade::run( + $query, + $request, + allowedFilters: $allowedFilters, + allowedSortings: $allowedSortings); + + return response()->json($data); + } + + /** + * Store a newly created resource in storage. + * @throws ValidationException + */ + public function store(StoreRequest $request, NominatimService $nominatimService): JsonResponse + { + $user = auth()->user(); + + if ($user->edarate_ostani_id || is_null($user->city_id)) { + return response()->json([ + 'message' => 'امکان ثبت فعالیت برای ادارات استانی و ستادی وجود ندارد!' + ], 400); + } + + if (is_null($user->edarate_shahri_id)) { + return response()->json([ + 'message' => 'اداره شهری برای شما در سامانه ثبت نشده است!' + ], 400); + } + + $info_item = InfoItem::where('item', $request->item_id) + ->where('sub_item', $request->sub_item_id) + ->firstOrFail(); + + if ($info_item->needs_end_point && !$request->end_point) { + throw ValidationException::withMessages([ + 'end_point' => __('validation.required', ['attribute' => 'end_point']), + ]); + } + + if ((!$request->before_image || !$request->after_image) && $info_item->needs_image) { + throw ValidationException::withMessages([ + 'before_image' => __('validation.required', ['attribute' => 'before_image']), + 'after_image' => __('validation.required', ['attribute' => 'after_image']), + ]); + } + + $start_coordinates = explode(',', $request->start_point); + $end_coordinates = $info_item->needs_end_point ? explode(',', $request->end_point) : null; + + $attributes = [ + 'start_lat' => $start_coordinates[0], + 'start_lng' => $start_coordinates[1], + 'end_lat' => $end_coordinates ? $end_coordinates[0] : null, + 'end_lng' => $end_coordinates ? $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' => $request->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($start_coordinates[0], $start_coordinates[1]), + 'end_way_id' => $end_coordinates ? $nominatimService->get_way_id_from_nominatim($end_coordinates[0], $end_coordinates[1]) : null, + 'unit_fa' => $info_item->sub_item_unit, + 'created_at_fa' => verta(\Carbon\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' => $request->activity_date, + 'activity_time' => $request->activity_time, + ]; + + $after_image = ($request->has('after_image') && $info_item->needs_image) ? + $request->file('after_image') : + null; + + $before_image = ($request->has('before_image') && $info_item->needs_image) ? + $request->file('before_image') : + null; + + $road_item = RoadItemsProject::store($user, $attributes, $before_image, $after_image, $request->observed_item_id); + + if ($road_item == -1) { + return response()->json([ + 'message' => 'اقدام مربوطه قبلا رسیدگی شده است.' + ], 400); + } + auth()->user()->addActivityComplete(1154); + + return $this->successResponse(); + } + + /** + * Display the specified resource. + */ + public function show(string $id) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, RoadItemsProject $road_item) + { + $info_item = InfoItem::where('item', $road_item->item) + ->where('sub_item', $road_item->sub_item) + ->firstOrFail(); + + $start_coordinates = explode(',', $request->start_point); + $end_coordinates = null; + + if ($info_item->needs_end_point) { + if (!$request->end_point) { + throw ValidationException::withMessages([ + 'end_point' => __('validation.required', ['attribute' => 'end_point']), + ]); + } + + $end_coordinates = explode(',', $request->end_point); + } + + if ($info_item->needs_image) { + if ($request->has('after_image')) { + + Storage::delete('public/'. $road_item->files[0]->path); + + $after = $request->file('after_image')->store('road_items_projects_new/after', 'public'); + $road_item->files[0]->update([ + 'path' => $after + ]); + // $road_item->files()->create(['path' => $after]); + $urlAfter = "/var/www/rms/public/storage/{$after}"; + \App\Helpers\Compress::resize($urlAfter); + } + if ($request->has('before_image')) { + Storage::delete('public/'. $road_item->files[1]->path); + + $before = $request->file('before_image')->store('/road_items_projects_new/before', 'public'); + $road_item->files[1]->update([ + 'path' => $before + ]); + // $road_item->files()->create(['path' => $before]); + $urlBefore = "/var/www/rms/public/storage/{$before}"; + \App\Helpers\Compress::resize($urlBefore); + } + } + + $road_item->update([ + 'start_lat' => $start_coordinates[0], + 'start_lng' => $start_coordinates[1], + 'end_lat' => $end_coordinates ? $end_coordinates[0] : null, + 'end_lng' => $end_coordinates ? $end_coordinates[1] : null, + 'sub_item_data' => $request->amount, + 'status' => 0, + 'status_fa' => 'در حال بررسی', + ]); + + + auth()->user()->addActivityComplete(1155); + + return $this->successResponse(); + } +} diff --git a/app/Http/Requests/V3/RoadItemsProject/StoreRequest.php b/app/Http/Requests/V3/RoadItemsProject/StoreRequest.php new file mode 100644 index 00000000..62a6055f --- /dev/null +++ b/app/Http/Requests/V3/RoadItemsProject/StoreRequest.php @@ -0,0 +1,73 @@ +|string> + */ + public function rules(): array + { + return [ + 'start_point' => 'required', + 'item_id' => 'required|integer', + 'sub_item_id' => 'required|integer', + 'amount' => 'required|numeric', + 'observed_item_id' => 'integer|exists:observed_items,id', + 'activity_date' => 'required|date_format:Y-m-d', + 'activity_time' => 'required|date_format:H:i', + 'before_image' => 'image|max:4096', + 'after_image' => 'image|max:4096', + ]; + } + + public function attributes(): array + { + return [ + 'activity_date' => 'تاریخ فعالیت', + 'activity_time' => 'ساعت فعالیت', + ]; + } + +// public function after(): array +// { +// return [ +// function (Validator $validator) { +// if ($this->has(['item_id', 'sub_item_id'])) { +// +// $info_item = InfoItem::query() +// ->where('item', $this->item_id) +// ->where('sub_item', $this->sub_item_id) +// ->firstOrFail(); +// +// if ($info_item->needs_end_point && !$this->filled('end_point')) { +// $validator->errors()->add('end_point', __('validation.required')); +// } +// +// if ($info_item->needs_image) { +// if (!$this->hasFile('before_image')) { +// $validator->errors()->add('before_image', __('validation.required')); +// } +// if (!$this->hasFile('after_image')) { +// $validator->errors()->add('after_image', __('validation.required')); +// } +// } +// } +// } +// ]; +// } +} diff --git a/app/Http/Requests/V3/RoadItemsProject/UpdateRequest.php b/app/Http/Requests/V3/RoadItemsProject/UpdateRequest.php new file mode 100644 index 00000000..b8b0363f --- /dev/null +++ b/app/Http/Requests/V3/RoadItemsProject/UpdateRequest.php @@ -0,0 +1,36 @@ +road_item->user_id != auth()->user()->id || $this->road_item->status != 2); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + return [ + 'start_point' => 'required', + 'amount' => 'required|numeric', + 'before_image' => 'image|max:4096', + 'after_image' => 'image|max:4096', + ]; + } +} diff --git a/app/Http/Requests/V3/RoadItemsProject/VerifyBySupervisorRequest.php b/app/Http/Requests/V3/RoadItemsProject/VerifyBySupervisorRequest.php new file mode 100644 index 00000000..c360df47 --- /dev/null +++ b/app/Http/Requests/V3/RoadItemsProject/VerifyBySupervisorRequest.php @@ -0,0 +1,35 @@ +road_item); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + return [ + 'verify' => 'required|in:1,2', + 'description' => 'nullable|string', + ]; + } +} diff --git a/routes/v3.php b/routes/v3.php index 53978a75..25ed2e24 100644 --- a/routes/v3.php +++ b/routes/v3.php @@ -6,6 +6,7 @@ use App\Http\Controllers\V3\Azmayesh\AzmayeshSampleController; use App\Http\Controllers\V3\Azmayesh\AzmayeshTypeController; use App\Http\Controllers\V3\Harim\DivarkeshiController; use App\Http\Controllers\V3\ProfileController; +use App\Http\Controllers\V3\RoadItemsProjectController; use Illuminate\Support\Facades\Route; Route::prefix('harim')->name('harim')->group(function () { @@ -35,6 +36,7 @@ Route::prefix('profile') Route::get('info', 'info')->name('info'); Route::post('edit', 'edit')->name('edit'); Route::post('change_password', 'changePassword')->name('changePassword'); + Route::post('add_activity', 'addActivity')->name('addActivity'); }); Route::prefix('azmayesh_types') @@ -43,7 +45,7 @@ Route::prefix('azmayesh_types') ->controller(AzmayeshTypeController::class) ->group(function () { Route::get('/', 'index')->name('index'); - Route::get('/list', 'list')->name('list'); + Route::get('/list', 'list')->name('list')->middleware('can:azmayesh-management'); Route::get('/fields/{azmayeshType}', 'fields')->name('fields'); Route::get('/{azmayeshType}', 'show')->name('show'); Route::post('/store', 'store')->name('store'); @@ -76,3 +78,28 @@ Route::prefix('azmayesh_samples') }); Route::post('logout', LogoutController::class)->name('logout'); + +Route::prefix('road_items') + ->name('road_items.') + ->controller(RoadItemsProjectController::class) + ->group(function () { + Route::get('/supervisor_index', 'supervisorIndex') + ->middleware(['can:show-road-item-supervise-cartable', 'can:show-road-item-supervise-cartable-province']) + ->name('supervisorIndex'); + Route::post('/verify_by_supervisor/{$road_item}', 'VerifyBySupervisor') + ->name('VerifyBySupervisor'); + Route::post('/restore/{$road_item}', 'restore') + ->middleware('can:restore-road-item') + ->name('restore'); + Route::post('/delete/{$road_item}', 'delete') + ->middleware('can:delete-road-item') + ->name('delete'); + Route::get('/operator_index', 'operatorIndex') + ->middleware('can:create-road-item') + ->name('operatorIndex'); + Route::post('/store', 'store') + ->middleware('can:create-road-item') + ->name('store'); + Route::post('/', 'update')->name('update'); + Route::post('/', 'destroy')->name('delete'); + }); diff --git a/tests/Feature/V3/RoadItemsProject/StoreTest.php b/tests/Feature/V3/RoadItemsProject/StoreTest.php new file mode 100644 index 00000000..fdc4710e --- /dev/null +++ b/tests/Feature/V3/RoadItemsProject/StoreTest.php @@ -0,0 +1,582 @@ +create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store')); + + $response->assertForbidden(); + } + + public function test_start_point_is_required(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'start_point' => __('validation.required', ['attribute' => 'start point']) + ]); + } + + public function test_item_id_is_required(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'item_id' => __('validation.required', ['attribute' => 'item id']) + ]); + } + + public function test_item_id_should_be_integer(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'item_id' => $this->faker->name + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'item_id' => __('validation.integer', ['attribute' => 'item id']) + ]); + } + + public function test_sub_item_id_is_required(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'sub_item_id' => __('validation.required', ['attribute' => 'sub item id']) + ]); + } + + public function test_sub_item_id_should_be_integer(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'sub_item_id' => $this->faker->name + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'sub_item_id' => __('validation.integer', ['attribute' => 'sub item id']) + ]); + } + + public function test_amount_is_required(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'amount' => __('validation.required', ['attribute' => 'amount']) + ]); + } + + public function test_amount_should_be_numeric(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'amount' => $this->faker->name + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'amount' => __('validation.numeric', ['attribute' => 'amount']) + ]); + } + + public function test_observed_item_id_should_be_integer(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'observed_item_id' => $this->faker->name + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'observed_item_id' => __('validation.integer', ['attribute' => 'observed item id']) + ]); + } + + public function test_observed_item_id_should_be_existed_in_db(): void + { + $observedItem = ObservedItem::factory()->create(); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'observed_item_id' => $this->faker->numberBetween(10, 20) + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'observed_item_id' => __('validation.exists', ['attribute' => 'observed item id']) + ]); + } + + public function test_activity_date_is_required(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'activity_date' => __('validation.required', ['attribute' => 'تاریخ فعالیت']) + ]); + } + + public function test_activity_date_should_match_the_format(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'activity_date' => $this->faker->date('d-m-Y-H-i-s') + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'activity_date' => __('validation.date_format', ['attribute' => 'تاریخ فعالیت', 'format' => 'Y-m-d']) + ]); + } + + public function test_activity_time_is_required(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'activity_time' => __('validation.required', ['attribute' => 'ساعت فعالیت']) + ]); + } + + public function test_activity_time_should_match_the_format(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'activity_time' => $this->faker->date('d-m-Y-H-i-s') + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'activity_time' => __('validation.date_format', ['attribute' => 'ساعت فعالیت', 'format' => 'H:i']) + ]); + } + + public function test_before_image_should_be_image(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'before_image' => $this->faker->name + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'before_image' => __('validation.image', ['attribute' => 'before image']) + ]); + } + + public function test_before_image_should_be_less_than_4096kb(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $image = UploadedFile::fake()->create('image.jpg', 5096); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'before_image' => $image + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'before_image' => __('validation.max.file', ['attribute' => 'before image', 'max' => 4096]) + ]); + } + + public function test_after_image_should_be_image(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'after_image' => $this->faker->randomNumber() + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'after_image' => __('validation.image', ['attribute' => 'after image']) + ]); + } + + public function test_after_image_should_be_less_than_4096kb(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create(); + + $image = UploadedFile::fake()->create('image.jpg', 5096); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [ + 'after_image' => $image + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'after_image' => __('validation.max.file', ['attribute' => 'after image', 'max' => 4096]) + ]); + } + + public function test_province_user_is_prohibited_to_access(): void + { + $edarateOstani = EdarateOstani::factory()->create(); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create([ + 'edarate_ostani_id' => $edarateOstani->id + ]); + + $data = [ + 'start_point' => '12,12', + 'item_id' => $this->faker->numberBetween(1, 10), + 'sub_item_id' => $this->faker->numberBetween(1, 10), + 'amount' => $this->faker->numberBetween(1, 10), + 'activity_date' => $this->faker->date(), + 'activity_time' => $this->faker->date('H:i'), + 'before_image' => UploadedFile::fake()->create('image.jpg', 10), + 'after_image' => UploadedFile::fake()->create('image.jpg', 10) + ]; + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), $data); + + $response->assertStatus(400) + ->assertExactJson([ + 'message' => 'امکان ثبت فعالیت برای ادارات استانی و ستادی وجود ندارد!' + ]); + } + + public function test_user_should_have_edarate_shahri_id(): void + { + $city = City::factory()->create(); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create([ + 'city_id' => $city->id + ]); + + $data = [ + 'start_point' => '12,12', + 'item_id' => $this->faker->numberBetween(1, 10), + 'sub_item_id' => $this->faker->numberBetween(1, 10), + 'amount' => $this->faker->numberBetween(1, 10), + 'activity_date' => $this->faker->date(), + 'activity_time' => $this->faker->date('H:i'), + 'before_image' => UploadedFile::fake()->create('image.jpg', 10), + 'after_image' => UploadedFile::fake()->create('image.jpg', 10) + ]; + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), $data); + + $response->assertStatus(400) + ->assertExactJson([ + 'message' => 'اداره شهری برای شما در سامانه ثبت نشده است!' + ]); + } + + public function test_end_point_required_when_info_item_needs_end_point(): void + { + $city = City::factory()->create(); + $edarateShari = EdarateShahri::factory()->create(); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create([ + 'city_id' => $city->id, + 'edarate_shahri_id' => $edarateShari->id + ]); + + $data = [ + 'start_point' => '12,12', + 'item_id' => $this->faker->numberBetween(1, 10), + 'sub_item_id' => $this->faker->numberBetween(1, 10), + 'amount' => $this->faker->numberBetween(1, 10), + 'activity_date' => $this->faker->date(), + 'activity_time' => $this->faker->date('H:i'), + 'before_image' => UploadedFile::fake()->create('image.jpg', 10), + 'after_image' => UploadedFile::fake()->create('image.jpg', 10) + ]; + + InfoItem::factory()->create([ + 'item' => $data['item_id'], + 'sub_item' => $data['sub_item_id'], + 'needs_end_point' => 1 + ]); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), $data); + + $response->assertUnprocessable() + ->assertInvalid([ + 'end_point' => __('validation.required', ['attribute' => 'end_point']) + ]); + } + + public function test_before_image_required_when_info_item_needs_image(): void + { + $city = City::factory()->create(); + $edarateShari = EdarateShahri::factory()->create(); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create([ + 'city_id' => $city->id, + 'edarate_shahri_id' => $edarateShari->id + ]); + + $data = [ + 'start_point' => '12,12', + 'item_id' => $this->faker->numberBetween(1, 10), + 'sub_item_id' => $this->faker->numberBetween(1, 10), + 'amount' => $this->faker->numberBetween(1, 10), + 'activity_date' => $this->faker->date(), + 'activity_time' => $this->faker->date('H:i'), + ]; + + InfoItem::factory()->create([ + 'item' => $data['item_id'], + 'sub_item' => $data['sub_item_id'], + 'needs_image' => 1 + ]); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), $data); + + $response->assertUnprocessable() + ->assertInvalid([ + 'before_image' => __('validation.required', ['attribute' => 'before_image']) + ]); + } + + public function test_after_image_required_when_info_item_needs_image(): void + { + $city = City::factory()->create(); + $edarateShari = EdarateShahri::factory()->create(); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create([ + 'city_id' => $city->id, + 'edarate_shahri_id' => $edarateShari->id + ]); + + $data = [ + 'start_point' => '12,12', + 'item_id' => $this->faker->numberBetween(1, 10), + 'sub_item_id' => $this->faker->numberBetween(1, 10), + 'amount' => $this->faker->numberBetween(1, 10), + 'activity_date' => $this->faker->date(), + 'activity_time' => $this->faker->date('H:i'), + ]; + + InfoItem::factory()->create([ + 'item' => $data['item_id'], + 'sub_item' => $data['sub_item_id'], + 'needs_image' => 1 + ]); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), $data); + + $response->assertUnprocessable() + ->assertInvalid([ + 'after_image' => __('validation.required', ['attribute' => 'after_image']) + ]); + } + + public function test_can_store_a_new_road_item_project(): void + { + $city = City::factory()->create(); + $province = Province::factory()->create(); + $edarateShari = EdarateShahri::factory()->create(); + + LogList::factory()->create([ + 'log_unique_code' => 1154 + ]); + UserActivityLog::factory()->create(); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'create-road-item' + ])) + ->create([ + 'city_id' => $city->id, + 'province_id' => $province->id, + 'edarate_shahri_id' => $edarateShari->id + ]); + + Storage::fake('public'); + + $this->mock(NominatimService::class, function (MockInterface $mock) { + $mock->shouldReceive('get_way_id_from_nominatim') + ->once() + ->andReturn(0); + }); + + $data = [ + 'start_point' => '12,12', + 'item_id' => $this->faker->numberBetween(1, 10), + 'sub_item_id' => $this->faker->numberBetween(1, 10), + 'amount' => $this->faker->numberBetween(1, 10), + 'activity_date' => $this->faker->date(), + 'activity_time' => $this->faker->date('H:i'), + 'before_image' => UploadedFile::fake()->create('image.jpg', 10), + 'after_image' => UploadedFile::fake()->create('image.jpg', 10) + ]; + + $infoItem = InfoItem::factory()->create([ + 'item' => $data['item_id'], + 'sub_item' => $data['sub_item_id'], + 'needs_image' => 1 + ]); + + $response = $this->actingAs($user)->postJson(route('v3.road_items.store'), $data); + + $response->assertOk() + ->assertExactJson([ + 'message' => __('messages.successful') + ]); + + $this->assertDatabaseHas('road_items_projects', [ + 'start_lat' => 12, + 'start_lng' => 12, + 'item' => $data['item_id'], + 'sub_item' => $data['sub_item_id'], + 'province_id' => $province->id, + 'city_id' => $city->id, + 'user_name' => $user->name, + 'start_way_id' => 0, + 'info_id' => $infoItem->id, + 'status' => 0, + 'status_fa' => 'در حال بررسی', + 'edarat_id' => $user->edarate_shahri_id, + ]); + } +}