Merge branch 'develop' into 'main'

Develop

See merge request witelgroup/rms_v2!52
This commit is contained in:
2024-12-28 12:41:52 +00:00
54 changed files with 20451 additions and 23 deletions

View File

@@ -58,3 +58,11 @@ TELESCOPE_RESPONSE_SIZE_LIMIT=128
DEBUGBAR_ENABLED=false
IS_DEVELOPMENT_ENV=
CMMS_MACHINE_INFO_URL=
CMMS_MACHINE_INFO_PASSWORD=
CMMS_MACHINE_INFO_VIEW_NAME=
FMS_VEHICLE_ACTIVITY_URL=
FMS_VEHICLE_ACTIVITY_PASSWORD=
FMS_VEHICLE_ACTIVITY_USERNAME=

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Console\Commands;
use App\Models\CMMSMachine;
use App\Services\CMMS\GetMachinesInfoListService;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use SoapClient;
class GetMachinesInfoListCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'cmms_machines_info:get_list';
/**
* The console command description.
*
* @var string
*/
protected $description = 'receive cmms cars information list and update the corresponding tables';
/**
* Execute the console command.
* @throws Exception
*/
public function handle(GetMachinesInfoListService $getMachinesInfoListService): void
{
$response = $getMachinesInfoListService->run();
$updatedRows = 0;
if (isset($response['vw_MachBankFull'])) {
foreach ($response['vw_MachBankFull'] as $entry) {
// Insert data into the database
CMMSMachine::query()->updateOrCreate(
[
'car_id' => $entry['Id'],
'machine_code' => $entry['MachineCode'],
],
[
'car_name' => $entry['CarName'] == [] ? null : $entry['CarName'],
'car_group' => $entry['CarGroup'] == [] ? null : $entry['CarGroup'],
'machine_code' => $entry['MachineCode'],
'unit_name' => $entry['UnitName'],
'car_status' => $entry['Status'],
'car_id' => $entry['Id'],
'unit_group' => $entry['UnitGroup'] == [] ? null : $entry['UnitGroup'],
'plak_number' => $entry['PlakNumber'] ?? null,
]);
$updatedRows += 1;
}
}
$this->info("{$updatedRows} row's updated successfully");
}
}

View File

@@ -317,7 +317,7 @@ class RoadItemsProjectController extends Controller
$road_item = RoadItemsProject::store(Auth::user(), $attributes, $before_image, $after_image, $request->observed_item_id);
if ($road_item == -1) {
if ($road_item === -1) {
return response()->json([
'message' => 'اقدام مربوطه قبلا رسیدگی شده است.'
], 400);

View File

@@ -329,6 +329,7 @@ class RoadObservationController extends Controller
'road_observeds.id',
'Title',
'road_observeds.created_at',
'road_observeds.StartTime_DateTime',
'lat',
'lng',
'FeatureTypeTitle',
@@ -340,7 +341,7 @@ class RoadObservationController extends Controller
'edarate_shahri.name_fa'
];
$aliases = ['', 'road_observeds_id', '', 'road_observeds_created_at', '', '', '', '', '', 'province_id', '', '', 'edarate_shahri_name_fa'];
$aliases = ['', 'road_observeds_id', '', 'road_observeds_created_at', 'road_observeds_nikarayan_created_at', '', '', '', '', '', 'province_id', '', '', 'edarate_shahri_name_fa'];
$selectRaw = makeSelectQuery($fields, $aliases);

View File

@@ -413,7 +413,7 @@ class RoadPatrolProjectController extends Controller
$road_item = RoadItemsProject::store(auth()->user(), $attributes, $before_image, $after_image, $observed_item->id);
if ($road_item == -1) {
if ($road_item === -1) {
return response()->json([
'message' => 'اقدام مربوطه قبلا رسیدگی شده است.'
], 400);

View File

@@ -36,7 +36,8 @@ class AzmayeshController extends Controller
'project_name',
'updated_at',
'created_at',
'user_name'
'user_name',
'contract_subitem_id'
);
$allowedFilters = $columns;
@@ -80,6 +81,7 @@ class AzmayeshController extends Controller
'province_name' => $province->name_fa,
'user_id' => $user->id,
'user_name' => $user->name,
'contract_subitem_id' => $request->contract_subitem_id
]);
return $this->successResponse();
@@ -117,6 +119,7 @@ class AzmayeshController extends Controller
'applicant' => $request->applicant ?? '-',
'province_id' => $province->id,
'province_name' => $province->name_fa,
'contract_subitem_id' => $request->contract_subitem_id
]);
return $this->successResponse();
@@ -133,7 +136,7 @@ class AzmayeshController extends Controller
return $this->successResponse();
}
catch (QueryException $exception) {
return $this->errorResponse('can not be deleted');
return $this->errorResponse('امکان حذف وجود ندارد');
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Controllers\V3;
use App\Http\Controllers\Controller;
use App\Http\Traits\ApiResponse;
use App\Models\CMMSMachine;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CMMSMachinesController extends Controller
{
use ApiResponse;
public function list(): JsonResponse
{
$machinesList = CMMSMachine::query()->get(['machine_code', 'id']);
return $this->successResponse($machinesList);
}
public function search(Request $request): JsonResponse
{
$matchedSearchedMachines = CMMSMachine::query()
->where('machine_code', 'LIKE', "%{$request->machine_code}%")
->get(['machine_code', 'id']);
return $this->successResponse($matchedSearchedMachines);
}
}

View File

@@ -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();
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Controllers\V3;
use App\Http\Controllers\Controller;
use App\Http\Traits\ApiResponse;
use App\Models\Rahdaran;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class RahdaranController extends Controller
{
use ApiResponse;
public function list(): JsonResponse
{
$rahdaranList = Rahdaran::query()->get();
return $this->successResponse($rahdaranList);
}
public function search(Request $request): JsonResponse
{
$matchedSearchedRahdaran = Rahdaran::query()
->where('code', 'LIKE', "%{$request->code}%")
->get();
return $this->successResponse($matchedSearchedRahdaran);
}
}

View File

@@ -0,0 +1,337 @@
<?php
namespace App\Http\Controllers\V3;
use App\Exports\V2\RoadItems\OperatorCartableExport;
use App\Exports\V2\RoadItems\SupervisorCartableExport;
use App\Facades\DataTable\DataTableFacade;
use App\Http\Controllers\Controller;
use App\Http\Requests\V3\RoadItemsProject\StoreRequest;
use App\Http\Requests\V3\RoadItemsProject\UpdateRequest;
use App\Http\Requests\V3\RoadItemsProject\VerifyBySupervisorRequest;
use App\Http\Traits\ApiResponse;
use App\Models\CMMSMachine;
use App\Models\EdarateShahri;
use App\Models\InfoItem;
use App\Models\Rahdaran;
use App\Models\RoadItemsProject;
use App\Services\NominatimService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class RoadItemsProjectController extends Controller
{
use ApiResponse;
/**
* Display a listing of the resource.
*/
public function supervisorIndex(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','cmmsMachines.machine_code'
);
$allowedFilters = $columns;
$allowedSortings = $columns;
$user = auth()->user();
$query = null;
if ($user->hasPermissionTo('show-road-item-supervise-cartable')) {
$query = RoadItemsProject::query()->where('is_new', 1)->with(['files', 'rahdaran:id,name,code', 'cmmsMachines:id,machine_code,car_name,plak_number']);
}
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', 'rahdaran:id,name,code', 'cmmsMachines:id,machine_code,car_name,plak_number'])->where('province_id', auth()->user()->province_id);
}
$data = DataTableFacade::run(
$query,
$request,
allowedFilters: $allowedFilters,
allowedSortings: $allowedSortings);
foreach ($data['data'] as $road_item) {
if (Gate::allows('gate-supervise-road-item', $road_item)) {
$road_item['can_supervise'] = 1;
} else {
$road_item['can_supervise'] = 0;
}
}
return response()->json($data);
}
public function verifyBySupervisor(VerifyBySupervisorRequest $request, RoadItemsProject $roadItemsProject): JsonResponse
{
$status_fa = $request->verify == 1 ? 'تایید شده' : 'عدم تایید';
$user = auth()->user();
$roadItemsProject->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 $roadItemsProject): JsonResponse
{
if ($roadItemsProject->status == 0) {
return response()->json([
'message' => 'امکان بازگردانی وضعیت این فعالیت وجود ندارد!'
], 400);
}
$roadItemsProject->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 $roadItemsProject): JsonResponse
{
if ($roadItemsProject->files()->exists()) {
Storage::delete('public/'. $roadItemsProject->files[0]->path);
Storage::delete('public/'. $roadItemsProject->files[1]->path);
$roadItemsProject->files()->delete();
}
auth()->user()->addActivityComplete(1151);
$roadItemsProject->delete();
return $this->successResponse();
}
public function supervisorCartableReport(Request $request): BinaryFileResponse
{
$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', 'cmmsMachines.machine_code'
);
$allowedFilters = $columns;
$allowedSortings = $columns;
$query = RoadItemsProject::with(['files', 'rahdaran:id,name,code', 'cmmsMachines:id,machine_code,car_name,plak_number'])
->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::query()->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);
}
$road_item->rahdaran()->attach($request->rahdaran_id);
$road_item->cmmsMachines()->attach($request->machines_id);
auth()->user()->addActivityComplete(1154);
return $this->successResponse();
}
/**
* Update the specified resource in storage.
* @throws ValidationException
*/
public function update(UpdateRequest $request, RoadItemsProject $roadItemsProject): JsonResponse
{
$info_item = InfoItem::query()->where('item', $roadItemsProject->item)
->where('sub_item', $roadItemsProject->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/'. $roadItemsProject->files[0]->path);
$after = $request->file('after_image')->store('road_items_projects_new/after', 'public');
$roadItemsProject->files[0]->update([
'path' => $after
]);
// $roadItemsProject->files()->create(['path' => $after]);
$urlAfter = "/var/www/rms/public/storage/{$after}";
// \App\Helpers\Compress::resize($urlAfter);
}
if ($request->has('before_image')) {
Storage::delete('public/'. $roadItemsProject->files[1]->path);
$before = $request->file('before_image')->store('/road_items_projects_new/before', 'public');
$roadItemsProject->files[1]->update([
'path' => $before
]);
// $roadItemsProject->files()->create(['path' => $before]);
$urlBefore = "/var/www/rms/public/storage/{$before}";
// \App\Helpers\Compress::resize($urlBefore);
}
}
$roadItemsProject->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' => 'در حال بررسی',
]);
$roadItemsProject->rahdaran()->sync($request->rahdaran_id);
$roadItemsProject->cmmsMachines()->sync($request->machines_id);
auth()->user()->addActivityComplete(1155);
return $this->successResponse();
}
public function operatorCartableReport(Request $request): BinaryFileResponse
{
$name = 'گزارش از کارتابل عملیات فعالیت روزانه ' . verta()->now()->format('Y-m-d H:i') . '.xlsx';
return Excel::download(
new OperatorCartableExport($request->id, $request->item, $request->status, $request->fromDate, $request->toDate),
$name
);
}
}

View File

@@ -0,0 +1,409 @@
<?php
namespace App\Http\Controllers\V3;
use App\Exports\V2\RoadPatrol\OperatorCartableExport;
use App\Exports\V2\RoadPatrol\SupervisorCartableExport;
use App\Facades\DataTable\DataTableFacade;
use App\Facades\Sms\Sms;
use App\Http\Controllers\Controller;
use App\Http\Requests\V3\RoadPatrolProject\DeleteRequest;
use App\Http\Requests\V3\RoadPatrolProject\StoreRequest;
use App\Http\Traits\ApiResponse;
use App\Models\EdarateShahri;
use App\Models\InfoItem;
use App\Models\RoadItemsProject;
use App\Models\RoadObserved;
use App\Models\RoadPatrol;
use App\Services\NominatimService;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class RoadPatrolProjectController extends Controller
{
use ApiResponse;
public function supervisorIndex(Request $request): JsonResponse
{
$columns = array(
'id', 'start_lat', 'start_lon', 'end_lat', 'end_lon', 'operator_id',
'operator_name', 'officer_plaque', 'officer_phone_number', 'officer_name',
'supervisor_description', 'supervising_time', 'supervisor_name', 'status',
'status_fa', 'distance', 'province_id', 'province_fa', 'edare_id', 'edare_name',
'start_time', 'end_time','description'
);
$allowedFilters = $columns;
$allowedSortings = $columns;
$user = auth()->user();
$query = null;
if ($user->hasPermissionTo('show-road-patrol-supervise-cartable')) {
$query = RoadPatrol::query();
}
elseif ($user->hasPermissionTo('show-road-patrol-supervise-cartable-province')) {
if (is_null($user->province_id)) {
return $this->errorResponse('استانی برای شما در سامانه ثبت نشده است!');
}
$query = RoadPatrol::query()->where('province_id', '=', $user->province_id);
}
$data = DataTableFacade::run(
$query,
$request,
allowedFilters: $allowedFilters,
allowedSortings: $allowedSortings);
foreach ($data['data'] as $road_patrol) {
if (Gate::allows('gate-supervise-road-item', $road_patrol)) {
$road_patrol['can_supervise'] = 1;
} else {
$road_patrol['can_supervise'] = 0;
}
}
return response()->json($data);
}
public function delete(DeleteRequest $request, RoadPatrol $roadPatrol): JsonResponse
{
if ($request->type == 1) {
DB::transaction(function () use ($roadPatrol) {
$roadPatrol->observedItems()->delete();
$roadPatrol->delete();
});
} else {
DB::transaction(function () use ($roadPatrol) {
if ($roadPatrol->observedItems) {
foreach ($roadPatrol->observedItems as $index => $observed_item) {
if ($observed_item->roadItemProject) {
$road_item = $observed_item->roadItemProject;
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();
}
$road_item->delete();
}
$observed_item->delete();
}
}
auth()->user()->addActivityComplete(1144);
$roadPatrol->delete();
});
}
return $this->successResponse();
}
public function supervisorCartableReport(Request $request): BinaryFileResponse
{
$name = 'گزارش از کارتابل ارزیابی گشت راهداری ' . verta()->now()->format('Y-m-d H:i') . '.xlsx';
return Excel::download(
new SupervisorCartableExport($request->id, $request->fromDate,
$request->toDate, $request->province_id, $request->edare_id
), $name
);
}
public function operatorIndex(Request $request): JsonResponse
{
$columns = array(
'id', 'start_lat', 'start_lon', 'end_lat', 'end_lon', 'officer_plaque',
'officer_phone_number', 'officer_name', 'supervisor_description', 'supervising_time',
'supervisor_name', 'status', 'status_fa', 'distance', 'start_time', 'end_time'
);
$allowedFilters = $columns;
$allowedSortings = $columns;
$query = RoadPatrol::query()->where('operator_id', '=', auth()->user()->id);
$data = DataTableFacade::run(
$query,
$request,
allowedFilters: $allowedFilters,
allowedSortings: $allowedSortings);
return response()->json($data);
}
public function store(StoreRequest $request, NominatimService $nominatimService)
{
$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);
}
$start_coordinates = explode(',', $request->start_point);
$end_coordinates = explode(',', $request->end_point);
$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 = DB::transaction(function () use ($request, $start_coordinates,
$end_coordinates, $edare_id,
$edare_name, $nominatimService, $user) {
$road_patrol = RoadPatrol::query()->create([
'start_lat' => $start_coordinates[0],
'start_lon' => $start_coordinates[1],
'end_lat' => $end_coordinates[0],
'end_lon' => $end_coordinates[1],
'officer_name' => $request->officer_name,
'officer_phone_number' => $request->officer_phone_number,
'officer_plaque' => $request->officer_plaque,
'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,
'start_way_id' => $nominatimService->get_way_id_from_nominatim($start_coordinates[0], $start_coordinates[1]),
'end_way_id' => $nominatimService->get_way_id_from_nominatim($end_coordinates[0], $end_coordinates[1]),
'status' => 0,
'status_fa' => 'در حال بررسی',
'distance' => $request->distance,
'start_time' => $request->start_time,
'end_time' => $request->end_time,
'description' => $request->description ?? null,
]);
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) {
$observed_item->priority = $item['priority'];
$observed_item->priority_fa = $item['priority_fa'];
$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 response()->json([
'message' => 'اقدام مربوطه قبلا رسیدگی شده است.'
], 400);
}
}
}
}
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;
});
return response()->json([
'road_patrol_id' => $road_patrol->id,
'message' => 'succussful'
]);
}
public function getReport(RoadPatrol $roadPatrol): JsonResponse
{
$data = [
'serial_no' => $roadPatrol->id,
'province_fa' => $roadPatrol->province_fa,
'edare_name' => $roadPatrol->edare_name,
'start_time' => $roadPatrol->start_time,
'end_time' => $roadPatrol->end_time,
'officer_name' => $roadPatrol->officer_name,
'officer_plaque' => $roadPatrol->officer_plaque,
'officer_phone_number' => $roadPatrol->officer_phone_number,
'created_at' => $roadPatrol->created_at
];
$observed_items = array();
if($roadPatrol->observedItems) {
foreach ($roadPatrol->observedItems as $index => $observed_item) {
$observed_items[] = [
'item' => $observed_item->item_name,
'sub_item' => $observed_item->sub_item_name,
'local_name' => $observed_item->local_name,
'description' => $observed_item->description,
'priority_fa' => $observed_item->priority_fa,
];
}
}
$data['observed_items'] = $observed_items;
return $this->successResponse($data);
}
public function getAllDataToMap(Request $request): JsonResponse
{
$date_from = $request->date_from ? $request->date_from .' 00:00:00' : Date('Y-m-d') .' 00:00:00';
$date_to = $request->date_to ? $request->date_to.' 23:59:59' : (new \DateTime('tomorrow'))->format('Y-m-d').' 23:59:59';
$data = RoadPatrol::query()->when($request->province_id, function ($query, $province) {
return $query->where('province_id', '=', $province);
})
->when($request->edare_id, function ($query, $edare_id) {
return $query->where('edare_id', '=', $edare_id);
})
->whereBetween('created_at', [
$date_from,
$date_to,
])
->select('id', 'start_lat', 'start_lon')
->get();
return $this->successResponse($data);
}
public function map(Request $request): JsonResponse
{
$province = $request->province_id;
$edare_shahri = $request->edare_shahri_id;
$status = $request->status;
$rms_status = $request->rms_status;
if ($request->date_from && $request->date_to) {
$date_from = $request->date_from.' 00:00:00';
$date_to = $request->date_to.' 23:59:59';
} else {
$date_from = Date('Y-m-d');
$date_to = new \DateTime('tomorrow');
$date_to = $date_to->format('Y-m-d');
}
$projects = RoadObserved::query()->select(['id', 'lng', 'lat','status'])
->whereBetween('created_at', [$date_from, $date_to])
->when($province, function ($query) use ($province) {
return $query->where('province_id', '=', $province);
})
->when($rms_status, function ($query) use ($rms_status) {
if ($rms_status == 2) {
return $query->where('rms_status', '<>', 0);
} else {
return $query->where('rms_status', '=', 0);
}
})
->when($edare_shahri, function ($query) use ($edare_shahri) {
return $query->where('edarate_shahri_id', '=', $edare_shahri);
})
->when($status, function ($query) use ($status) {
return $query->where('status', '=', $status);
})
->get();
return $this->successResponse($projects);
}
public function show(RoadPatrol $roadPatrol): JsonResponse
{
return $this->successResponse($roadPatrol);
}
public function operatorCartableReport(Request $request): BinaryFileResponse
{
$name = 'گزارش از کارتابل عملیات گشت راهداری ' . verta()->now()->format('Y-m-d H:i') . '.xlsx';
return Excel::download(
new OperatorCartableExport($request->id, $request->status, $request->officer_name, $request->fromDate, $request->toDate),
$name
);
}
}

View File

@@ -73,7 +73,10 @@ class Kernel extends HttpKernel
'confirmUser' => \App\Http\Middleware\ConfirmUserMiddleware::class,
'randd' => \App\Http\Middleware\RandDRedirectMiddleware::class,
'log.route' => \App\Http\Middleware\LogRoute::class,
'test' => \App\Http\Middleware\CsrfLoginDev::class
'test' => \App\Http\Middleware\CsrfLoginDev::class,
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
/**

View File

@@ -35,6 +35,7 @@ class StoreRequest extends FormRequest
'consultant' => 'string',
'applicant' => 'string',
'province_id' => 'required|exists:provinces,id',
'contract_subitem_id' => 'required|exists:contract_subitems,id',
];
}
}

View File

@@ -35,6 +35,7 @@ class UpdateRequest extends FormRequest
'consultant' => 'string',
'applicant' => 'string',
'province_id' => 'required|exists:provinces,id',
'contract_subitem_id' => 'required|exists:contract_subitems,id',
];
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace App\Http\Requests\V3\RoadItemsProject;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|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',
'machines_id' => 'required|array',
'machines_id.*' => 'required|exists:cmms_machines,id',
'rahdaran_id' => 'required|array',
'rahdaran_id.*' => 'required|exists:rahdaran,id',
];
}
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'));
// }
// }
// }
// }
// ];
// }
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Http\Requests\V3\RoadItemsProject;
use App\Models\InfoItem;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Symfony\Component\Finder\Exception\AccessDeniedException;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return !($this->roadItemsProject->user_id != auth()->user()->id || $this->roadItemsProject->status != 2);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'start_point' => 'required',
'amount' => 'required|numeric',
'before_image' => 'image|max:4096',
'after_image' => 'image|max:4096',
'machines_id' => 'required|array',
'machines_id.*' => 'required|exists:cmms_machines,id',
'rahdaran_id' => 'required|array',
'rahdaran_id.*' => 'required|exists:rahdaran,id',
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Requests\V3\RoadItemsProject;
use App\Models\InfoItem;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
use Symfony\Component\Finder\Exception\AccessDeniedException;
class VerifyBySupervisorRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return Gate::allows('gate-supervise-road-item', $this->roadItemsProject);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'verify' => 'required|in:1,2',
'description' => 'nullable|string',
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Http\Requests\V3\RoadPatrolProject;
use Illuminate\Foundation\Http\FormRequest;
class DeleteRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'type' => 'required|in:1,2' // {1 = > partial , 2 => complete}
];
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Http\Requests\V3\RoadPatrolProject;
use Illuminate\Foundation\Http\FormRequest;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'start_point' => 'required',
'end_point' => 'required',
'distance' => 'numeric',
'officer_name' => 'required',
'officer_plaque' => 'required',
'officer_phone_number' => 'required|digits:11',
'start_time' => 'required|date_format:Y-m-d H:i',
'end_time' => 'required|date_format:Y-m-d H:i|after:start_time',
'observed_items' => 'array',
'observed_items.*.item_id' => 'required|integer',
'observed_items.*.sub_item_id' => 'required|integer',
'observed_items.*.local_name' => 'required',
'observed_items.*.description' => '',
'observed_items.*.instant_action' => 'required|in:0,1',
// road item projects fields
'observed_items.*.start_point' => 'required',
'observed_items.*.end_point' => '',
'observed_items.*.amount' => 'numeric|required_if: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:instant_action,0',
'observed_items.*.priority_fa' => 'string|required_if:instant_action,0',
'description' => 'string|required_with:observed_items',
'start_time' => 'ساعت شروع گشت',
'end_time' => 'ساعت پایان گشت',
];
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CMMSMachine extends Model
{
use HasFactory;
protected $table = 'cmms_machines';
protected $hidden = ['pivot'];
protected $guarded = [];
}

21
app/Models/Rahdaran.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Rahdaran extends Model
{
use HasFactory;
protected $guarded = [];
protected $table = 'rahdaran';
protected $hidden = ['pivot'];
public function roadItemsProject(): BelongsToMany
{
return $this->belongsToMany(RoadItemsProject::class,'rahdaran_road_items_project');
}
}

View File

@@ -3,8 +3,11 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Http\UploadedFile;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class RoadItemsProject extends Model
{
@@ -127,7 +130,6 @@ class RoadItemsProject extends Model
'activity_time' => $attributes['activity_time'],
'activity_date_time' => $attributes['activity_date']." ".$attributes['activity_time'],
'is_new' => 1,
]);
// if ($info_item->needs_image) {
@@ -157,7 +159,7 @@ class RoadItemsProject extends Model
]);
}
return 1;
return $road_item;
});
return $road_item;
@@ -165,4 +167,24 @@ class RoadItemsProject extends Model
throw $th;
}
}
public function cmmsMachines(): MorphToMany
{
return $this->morphToMany(CMMSMachine::class,
'machinable',
'machinables',
'machinable_id',
'machine_id'
);
}
public function rahdaran(): MorphToMany
{
return $this->morphToMany(Rahdaran::class,
'rahdarable',
'rahdarables',
'rahdarable_id',
'rahdar_id',
);
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Services\CMMS;
use Exception;
use Illuminate\Support\Facades\Log;
use SoapClient;
class GetMachinesInfoListService
{
protected string $url;
protected string $channelName;
protected string $password;
protected string $viewName;
public function __construct()
{
$this->url = config('cmms_web_services.MACHINE_INFO.url');
$this->password = config('cmms_web_services.MACHINE_INFO.password');
$this->viewName = config('cmms_web_services.MACHINE_INFO.ViewName');
$this->channelName = 'cmms_machines_info';
ini_set('memory_limit', '512M');
}
/**
* @throws Exception
*/
public function run(): array
{
try {
$xmlResponse = $this->sendRequest();
return $this->xmlToArray($xmlResponse);
}
catch (Exception $e) {
Log::channel($this->channelName)
->error(get_class($this),
[
'message' => $e->getMessage(),
]
);
throw $e;
}
}
public function sendRequest()
{
$client = new SoapClient($this->url);
return $client->GetView([
'ViewName' => $this->viewName,
'Password' => $this->password,
])->GetViewResult;
}
public function xmlToArray($xmlString)
{
$xmlObject = simplexml_load_string($xmlString);
$json = json_encode($xmlObject);
return json_decode($json, true);
}
}

View File

@@ -57,12 +57,17 @@ class DataTableInput
}
/**
* @return Sort|null
* @return array
*/
public function getSorting(): ?Sort
public function getSorting(): ?array
{
return !empty($this->sorting) ?
new Sort($this->sorting[0]->id, $this->sorting[0]->desc, $this->allowedSortings) : null;
$sorts = [];
if (!empty($this->sorting)){
foreach ($this->sorting as $sort) {
$sorts[] = new Sort($sort->id, $sort->desc, $this->allowedSortings);
}
}
return $sorts;
}
public function getRelations(): array

View File

@@ -83,7 +83,10 @@ class DataTableService
}
$sorting = $this->dataTableInput->getSorting();
$query = (new ApplySort($query, $sorting))->apply();
foreach ($sorting as $sort){
$query = (new ApplySort($query, $sort))->apply();
}
return $query;
}

View File

@@ -0,0 +1,70 @@
<?php
namespace App\Services\FMS;
use Exception;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class GetVehicleActivityService
{
protected string $url;
protected string $channelName;
protected string $password;
protected string $username;
protected array $inputParameters;
public function __construct()
{
$this->url = config('fms_web_services.Vehicle_Activity.url');
$this->password = config('fms_web_services.Vehicle_Activity.password');
$this->username = config('fms_web_services.Vehicle_Activity.username');
$this->channelName = 'fms_vehicle_activity';
}
public function setInputParameters(array $inputs): void
{
$this->inputParameters = $inputs;
}
/**
* @throws Exception
*/
public function run(): array
{
try {
return $this->sendRequest();
}
catch (Exception $e) {
Log::channel($this->channelName)
->error(get_class($this),
[
'message' => $e->getMessage(),
]
);
throw $e;
}
}
public function sendRequest(): array
{
$inputData = $this->makeInputParameters();
return Http::withBody($inputData)
->throw()
->withoutVerifying()
->post($this->url)
->json();
}
private function makeInputParameters(): string
{
$inputData = $this->inputParameters + array(
"username" => $this->username,
"password" => $this->password,
);
return json_encode($inputData);
}
}

View File

@@ -0,0 +1,9 @@
<?php
return [
'MACHINE_INFO' => [
'url' => env('CMMS_MACHINE_INFO_URL'),
'password' => env('CMMS_MACHINE_INFO_PASSWORD'),
'ViewName' => env('CMMS_MACHINE_INFO_VIEW_NAME'),
],
];

View File

@@ -0,0 +1,9 @@
<?php
return [
'Vehicle_Activity' => [
'url' => env('FMS_VEHICLE_ACTIVITY_URL'),
'password' => env('FMS_VEHICLE_ACTIVITY_PASSWORD'),
'username' => env('FMS_VEHICLE_ACTIVITY_USERNAME'),
],
];

View File

@@ -99,6 +99,18 @@ return [
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
'cmms_machines_info' => [
'driver' => 'single',
'path' => storage_path('logs/cmms/machines_info_list_service.log'),
'level' => 'info',
],
'fms_vehicle_activity' => [
'driver' => 'single',
'path' => storage_path('logs/fms/vehicle_activity_service.log'),
'level' => 'info',
],
],
];

View File

@@ -0,0 +1,30 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\CMMSMachine>
*/
class CMMSMachineFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'car_name' => $this->faker->name,
'car_group' => $this->faker->name,
'car_id' => $this->faker->numberBetween(1, 10),
'car_status' => $this->faker->lexify,
'machine_code' => $this->faker->numerify,
'unit_name' => $this->faker->name,
'unit_group' => $this->faker->name,
'plak_number' => $this->faker->numerify,
];
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Rahdaran>
*/
class RahdaranFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name,
'code' => fake()->numerify,
];
}
}

View File

@@ -24,6 +24,7 @@ return new class extends Migration
public function down(): void
{
Schema::table('azmayeshes', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->dropColumn('user_id');
$table->dropColumn('user_name');
});

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cmms_machines', function (Blueprint $table) {
$table->id();
$table->string('car_name')->nullable();
$table->string('car_group')->nullable();
$table->unsignedBigInteger('car_id')->nullable();
$table->string('car_status')->nullable();
$table->string('machine_code')->nullable();
$table->string('unit_name')->nullable();
$table->string('unit_group')->nullable();
$table->string('plak_number')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cmms_machines');
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('rahdaran', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('code');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('rahdaran');
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('rahdaran_road_items_project', function (Blueprint $table) {
$table->id();
$table->foreignId('rahdaran_id')->constrained('rahdaran')->onDelete('cascade');
$table->unsignedBigInteger('road_items_project_id');
$table->foreign('road_items_project_id')->references('id')->on('road_items_projects')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('rahdaran_road_items_project');
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cmms_machine_road_items_project', function (Blueprint $table) {
$table->id();
$table->foreignId('machine_id')->constrained('cmms_machines')->onDelete('cascade');
$table->unsignedBigInteger('road_items_project_id');
$table->foreign('road_items_project_id')->references('id')->on('road_items_projects')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cmms_machine_road_items_project');
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('azmayeshes', function (Blueprint $table) {
$table->foreignId('contract_subitem_id')->nullable()->constrained('contract_subitems')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('azmayeshes', function (Blueprint $table) {
$table->dropForeign('contract_subitem_id');
$table->dropColumn(['contract_subitem_id']);
});
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('machinables', function (Blueprint $table) {
$table->id();
$table->foreignId('machine_id')->constrained('cmms_machines')->noActionOnDelete();
$table->morphs('machinable');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('machinable');
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('rahdarables', function (Blueprint $table) {
$table->id();
$table->foreignId('rahdar_id')->constrained('rahdaran')->noActionOnDelete();
$table->morphs('rahdarable');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('rahdarables');
}
};

View File

@@ -0,0 +1,20 @@
<?php
namespace Database\Seeders;
use App\Models\CMMSMachine;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class CMMSMachineSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$sqlFile = file_get_contents(storage_path('/sql-files/cmms_machines.sql'));
DB::unprepared($sqlFile);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Database\Seeders;
use App\Models\Rahdaran;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class RahdaranSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Rahdaran::factory(5)->create();
}
}

View File

@@ -200,5 +200,7 @@ return [
'fields.*.unit' => 'واحد فیلد',
'fields.*.type' => 'نوع فیلد',
'fields.*.option' => 'گزینه های فیلد',
'cmms_machine_id' => 'کد یکتا ماشین',
'contract_subitem_id' => 'کد یکتای پروژه',
],
];

View File

@@ -4,8 +4,12 @@ use App\Http\Controllers\V3\Auth\LogoutController;
use App\Http\Controllers\V3\Azmayesh\AzmayeshController;
use App\Http\Controllers\V3\Azmayesh\AzmayeshSampleController;
use App\Http\Controllers\V3\Azmayesh\AzmayeshTypeController;
use App\Http\Controllers\V3\CMMSMachinesController;
use App\Http\Controllers\V3\Harim\DivarkeshiController;
use App\Http\Controllers\V3\ProfileController;
use App\Http\Controllers\V3\RahdaranController;
use App\Http\Controllers\V3\RoadItemsProjectController;
use App\Http\Controllers\V3\RoadPatrolProjectController;
use Illuminate\Support\Facades\Route;
Route::prefix('harim')->name('harim')->group(function () {
@@ -35,25 +39,25 @@ 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')
->name('azmayesh_types.')
->middleware('can:azmayesh-type-management')
->controller(AzmayeshTypeController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('/list', 'list')->name('list');
Route::get('/fields/{azmayeshType}', 'fields')->name('fields');
Route::get('/{azmayeshType}', 'show')->name('show');
Route::post('/store', 'store')->name('store');
Route::post('/update/{azmayeshType}', 'update')->name('update');
Route::post('/delete/{azmayeshType}', 'destroy')->name('delete');
Route::get('/', 'index')->middleware('permission:azmayesh-type-management')->name('index');
Route::get('/list', 'list')->middleware(['permission:azmayesh-type-management|azmayesh-management'])->name('list');
Route::get('/fields/{azmayeshType}', 'fields')->middleware('permission:azmayesh-type-management')->name('fields');
Route::get('/{azmayeshType}', 'show')->middleware('permission:azmayesh-type-management')->name('show');
Route::post('/store', 'store')->middleware('permission:azmayesh-type-management')->name('store');
Route::post('/update/{azmayeshType}', 'update')->middleware('permission:azmayesh-type-management')->name('update');
Route::post('/delete/{azmayeshType}', 'destroy')->middleware('permission:azmayesh-type-management')->name('delete');
});
Route::prefix('azmayesh_samples')
->name('azmayesh_samples.')
->middleware('can:azmayesh-management')
->middleware('permission:azmayesh-management')
->controller(AzmayeshSampleController::class)
->group(function () {
Route::get('/index/{azmayesh_id}', 'index')->name('index');
@@ -65,7 +69,7 @@ Route::prefix('azmayesh_samples')
Route::prefix('azmayeshes')
->name('azmayeshes.')
->middleware('can:azmayesh-management')
->middleware('permission:azmayesh-management')
->controller(AzmayeshController::class)
->group(function () {
Route::get('/', 'index')->name('index');
@@ -76,3 +80,93 @@ 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(['permission:show-road-item-supervise-cartable|show-road-item-supervise-cartable-province'])
->name('supervisorIndex');
Route::post('/verify_by_supervisor/{roadItemsProject}', 'VerifyBySupervisor')
->name('VerifyBySupervisor');
Route::post('/restore/{roadItemsProject}', 'restore')
->middleware('permission:restore-road-item')
->name('restore');
Route::post('/delete/{roadItemsProject}', 'delete')
->middleware('permission:delete-road-item')
->name('delete');
Route::get('/supervisor_report', 'supervisorCartableReport')
->name('supervisorCartableReport');
Route::get('/operator_index', 'operatorIndex')
->middleware('permission:create-road-item')
->name('operatorIndex');
Route::post('/store', 'store')
->middleware('permission:create-road-item')
->name('store');
Route::post('/update/{roadItemsProject}', 'update')->name('update');
Route::get('/operator_report', 'operatorCartableReport')
->name('operatorCartableReport');
});
Route::prefix('road_patrols')
->name('road_patrols.')
->controller(RoadPatrolProjectController::class)
->group(function () {
Route::get('/supervisor_index', 'supervisorIndex')
->middleware(['permission:show-road-patrol-supervise-cartable|show-road-patrol-supervise-cartable-province'])
->name('supervisorIndex');
Route::post('/delete/{roadPatrol}', 'delete')
->middleware('permission:partial-delete-road-patrol|complete-delete-road-patrol')
->name('delete');
Route::get('/supervisor_report', 'supervisorCartableReport')
->name('supervisorCartableReport');
Route::get('/operator_index', 'operatorIndex')
->middleware('permission:add-road-patrol')
->name('operatorIndex');
Route::post('/store', 'store')
->middleware('permission:add-road-patrol')
->name('store');
Route::get('/operator_report', 'operatorCartableReport')
->name('operatorCartableReport');
Route::get('/operator/report/{roadPatrol}', 'getReport')
->name('getReport');
Route::get('/operator/map_data', 'getAllDataToMap')
->name('getAllDataToMap');
Route::get('/detail/{roadPatrol}', 'show')
->name('show');
});
Route::prefix('cmms_machines')
->name('cmms_machines.')
->controller(CMMSMachinesController::class)
->group(function () {
Route::get('/list', 'list')->name('list');
Route::get('/search', 'search')->name('search');
});
Route::prefix('rahdaran')
->name('rahdaran.')
->controller(RahdaranController::class)
->group(function () {
Route::get('/list', 'list')->name('list');
Route::get('/search', 'search')->name('search');
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
<?php
namespace Tests\Feature\Console\CMMS;
use App\Models\CMMSMachine;
use App\Services\CMMS\GetMachinesInfoListService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Mockery\MockInterface;
use Tests\TestCase;
class GetMachinesInfoListTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
protected function setUp(): void
{
parent::setUp();
CMMSMachine::factory()->create();
}
public function test_get_machines_info_list_console_command_work_properly(): void
{
$this->withoutExceptionHandling();
$data = [
"Id" => $this->faker->numberBetween(1, 10),
"PlakNumber" => $this->faker->numerify,
"CarName" => $this->faker->name,
"CarGroup" => $this->faker->name,
"MachineCode" => $this->faker->numerify,
"UnitName" => $this->faker->name,
"Status" => $this->faker->numberBetween(1, 10),
"UnitGroup" => $this->faker->name,
];
$cmmsMachine = CMMSMachine::factory()->create([
"Id" => $data['Id'],
]);
$serviceResult = [
'vw_MachBankFull' => [
[
"Id" => $data['Id'],
"PlakNumber" => $data['PlakNumber'],
"CarName" => $data['CarName'],
"CarGroup" => $data['CarGroup'],
"MachineCode" => $data['MachineCode'],
"UnitName" => $data['UnitName'],
"Status" => $data['Status'],
"UnitGroup" => $data['UnitGroup'],
],
[
"Id" => 3232,
"PlakNumber" => $data['PlakNumber'],
"CarName" => $data['CarName'],
"CarGroup" => $data['CarGroup'],
"MachineCode" => $data['MachineCode'],
"UnitName" => $data['UnitName'],
"Status" => $data['Status'],
"UnitGroup" => $data['UnitGroup'],
],
]
];
$this->mock(GetMachinesInfoListService::class, function (MockInterface $mock) use($serviceResult) {
$mock->shouldReceive('run')
->andReturn($serviceResult);
});
$this->artisan('cmms_machines_info:get_list');
$this->assertDatabaseHas('cmms_machines', [
'car_name' => $data['CarName'],
'car_group' => $data['CarGroup'],
'machine_code' => $data['MachineCode'],
'unit_name' => $data['UnitName'],
'car_status' => $data['Status'],
'car_id' => $data['Id'],
'unit_group' => $data['UnitGroup'],
'plak_number' => $data['PlakNumber'],
]);
$this->assertDatabaseHas('cmms_machines', [
'car_name' => $data['CarName'],
'car_group' => $data['CarGroup'],
'machine_code' => $data['MachineCode'],
'unit_name' => $data['UnitName'],
'car_status' => $data['Status'],
'car_id' => 3232,
'unit_group' => $data['UnitGroup'],
'plak_number' => $data['PlakNumber'],
]);
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace Tests\Feature\Services\CMMS;
use App\Services\CMMS\GetMachinesInfoListService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Mockery;
use Mockery\MockInterface;
use SoapClient;
use Tests\TestCase;
class GetMachinesInfoListTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
public function test_data_returned_properly(): void
{
$data = [
"Id" => $this->faker->numberBetween(1, 10),
"PlakNumber" => $this->faker->numerify,
"CarName" => $this->faker->name,
"CarGroup" => $this->faker->name,
"MachineCode" => $this->faker->numerify,
"UnitName" => $this->faker->name,
"Status" => $this->faker->numberBetween(1, 10),
"UnitGroup" => $this->faker->name,
];
$expected_response = [
'vw_MachBankFull' => [
[
"Id" => $data['Id'],
"PlakNumber" => $data['PlakNumber'],
"CarName" => $data['CarName'],
"CarGroup" => $data['CarGroup'],
"MachineCode" => $data['MachineCode'],
"UnitName" => $data['UnitName'],
"Status" => $data['Status'],
"UnitGroup" => $data['UnitGroup'],
],
[
"Id" => $data['Id'],
"PlakNumber" => $data['PlakNumber'],
"CarName" => $data['CarName'],
"CarGroup" => $data['CarGroup'],
"MachineCode" => $data['MachineCode'],
"UnitName" => $data['UnitName'],
"Status" => $data['Status'],
"UnitGroup" => $data['UnitGroup'],
],
]
];
$mockStdClass = Mockery::mock('stdClass');
$mockResultObject = $mockStdClass->GetViewResult->NewDataSet->vw_MachBankFull;
$mockResultObject->CarName = $data['CarName'];
$mockResultObject->CarGroup = $data['CarGroup'];
$mockResultObject->PlakNumber = $data['PlakNumber'];
$mockResultObject->MachineCode = $data['MachineCode'];
$mockResultObject->UnitName = $data['UnitName'];
$mockResultObject->Status = $data['Status'];
$mockResultObject->Id = $data['Id'];
$mockResultObject->UnitGroup = $data['UnitGroup'];
$this->mock(SoapClient::class, function (MockInterface $mock) use ($mockStdClass) {
$mock->shouldReceive('GetView')
->andReturn($mockStdClass);
});
$service = new GetMachinesInfoListService();
$actual_response = $service->run();
$this->assertEquals($expected_response, $actual_response);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Tests\Feature\V3\CMMSMachine;
use App\Models\CMMSMachine;
use App\Models\Permission;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class ListTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
public function test_machine_code_list_return_successfully(): void
{
$user = User::factory()->create();
CMMSMachine::factory(5)->create();
$response = $this->actingAs($user)->getJson(route('v3.cmms_machines.list'));
$response->assertOk();
$response->assertJsonStructure([
'data' => [
'*' => [
"machine_code",
],
]
]);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Tests\Feature\V3\CMMSMachine;
use App\Models\CMMSMachine;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class SearchTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
public function test_user_can_search_through_machine_codes(): void
{
$user = User::factory()->create();
$machine = CMMSMachine::factory()->create();
$response = $this->actingAs($user)->getJson(route('v3.cmms_machines.search', [$machine->machine_code]));
$response->assertOk();
$response->assertJsonStructure([
'data' => [
'*' => [
"machine_code",
],
]
]);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Tests\Feature\V3\Rahdaran;
use App\Models\Rahdaran;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class ListTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
public function test_machine_code_list_return_successfully(): void
{
$user = User::factory()->create();
Rahdaran::factory(5)->create();
$response = $this->actingAs($user)->getJson(route('v3.rahdaran.list'));
$response->assertOk();
$response->assertJsonStructure([
'data' => [
'*' => [
"name",
"code",
],
]
]);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Tests\Feature\V3\Rahdaran;
use App\Models\Rahdaran;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class SearchTest extends TestCase
{
use RefreshDatabase;
/**
* A basic feature test example.
*/
public function test_user_can_search_through_rahdaran_codes(): void
{
$user = User::factory()->create();
$rahdar = Rahdaran::factory()->create();
$response = $this->actingAs($user)->getJson(route('v3.cmms_machines.search', [$rahdar->code]));
$response->assertOk();
$response->assertJsonStructure([
'data' => [
'*' => [
"name",
"code",
],
]
]);
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace Tests\Feature\V3\RoadItemsProject;
use App\Models\Permission;
use App\Models\RoadItemsProject;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class OperatorIndexTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
public function test_user_should_have_create_road_item_permission(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->getJson(route('v3.road_items.operatorIndex'));
$response->assertForbidden();
}
public function test_operator_can_see_the_data_table(): void
{
$user = User::factory()
->has(Permission::factory([
'name' => 'create-road-item'
]))
->create();
RoadItemsProject::factory(10)->create();
$response = $this->actingAs($user)->getJson(route('v3.road_items.operatorIndex', [
'size' => 10,
'start' => 0,
'sorting' => json_encode([]),
'filters' => json_encode([]),
]));
$response->assertOk();
$response->assertJsonStructure([
'data' => [
'*' => [
"id",
"user_id",
"start_lat",
"start_lng",
"end_lat",
"end_lng",
"project_distance",
"item",
"item_fa",
"sub_item",
"sub_item_fa",
"sub_item_data",
"sub_items",
"sub_items_data",
"created_at",
"updated_at",
"province_id",
"province_fa",
"city_id",
"city_fa",
"is_new",
"parent_id",
"start_way_id",
"end_way_id",
"unit_fa",
"user_name",
"created_at_fa",
"info_id",
"status",
"status_fa",
"edarat_id",
"edarat_name",
"edarat_type",
"activity_date",
"activity_time",
"activity_date_time",
"supervisor_id",
"supervisor_name",
"supervisor_description",
"supervising_time",
"cmms_machine_id",
"cmms_machine_code",
"rahdar_id",
"rahdar_code",
],
]
]);
}
}

View File

@@ -0,0 +1,686 @@
<?php
namespace Tests\Feature\V3\RoadItemsProject;
use App\Models\City;
use App\Models\CMMSMachine;
use App\Models\EdarateOstani;
use App\Models\EdarateShahri;
use App\Models\InfoItem;
use App\Models\LogList;
use App\Models\ObservedItem;
use App\Models\Permission;
use App\Models\Province;
use App\Models\Rahdaran;
use App\Models\User;
use App\Models\UserActivityLog;
use App\Services\NominatimService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Mockery\MockInterface;
use Symfony\Component\Finder\Exception\AccessDeniedException;
use Tests\TestCase;
class StoreTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
public function test_user_should_have_create_road_item_permission(): void
{
$user = User::factory()->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_cmms_machine_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([
'cmms_machine_id' => __('validation.required', ['attribute' => 'کد یکتا ماشین'])
]);
}
public function test_cmms_machine_id_should_already_exists_on_the_table(): void
{
$user = User::factory()
->has(Permission::factory([
'name' => 'create-road-item'
]))
->create();
$response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [
'cmms_machine_id' => $this->faker->numberBetween(10, 100)
]);
$response->assertUnprocessable()
->assertInvalid([
'cmms_machine_id' => __('validation.exists', ['attribute' => 'کد یکتا ماشین'])
]);
}
public function test_rahdar_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([
'rahdar_id' => __('validation.required', ['attribute' => 'rahdar id'])
]);
}
public function test_rahdar_id_should_already_exists_on_the_table(): void
{
$user = User::factory()
->has(Permission::factory([
'name' => 'create-road-item'
]))
->create();
$response = $this->actingAs($user)->postJson(route('v3.road_items.store'), [
'rahdar_id' => $this->faker->numberBetween(10, 100)
]);
$response->assertUnprocessable()
->assertInvalid([
'rahdar_id' => __('validation.exists', ['attribute' => 'rahdar id'])
]);
}
public function test_province_user_is_prohibited_to_access(): void
{
$edarateOstani = EdarateOstani::factory()->create();
$cmmsMachine = CMMSMachine::factory()->create();
$rahdar = Rahdaran::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),
'cmms_machine_id' => $cmmsMachine->id,
'rahdar_id' => $rahdar->id,
];
$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();
$cmmsMachine = CMMSMachine::factory()->create();
$rahdar = Rahdaran::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),
'cmms_machine_id' => $cmmsMachine->id,
'rahdar_id' => $rahdar->id,
];
$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();
$cmmsMachine = CMMSMachine::factory()->create();
$rahdar = Rahdaran::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),
'cmms_machine_id' => $cmmsMachine->id,
'rahdar_id' => $rahdar->id,
];
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();
$cmmsMachine = CMMSMachine::factory()->create();
$rahdar = Rahdaran::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'),
'cmms_machine_id' => $cmmsMachine->id,
'rahdar_id' => $rahdar->id,
];
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();
$cmmsMachine = CMMSMachine::factory()->create();
$rahdar = Rahdaran::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'),
'cmms_machine_id' => $cmmsMachine->id,
'rahdar_id' => $rahdar->id,
];
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();
$cmmsMachine = CMMSMachine::factory()->create();
$rahdar = Rahdaran::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),
'cmms_machine_id' => $cmmsMachine->id,
'rahdar_id' => $rahdar->id,
];
$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,
'cmms_machine_id' => $cmmsMachine->id,
'cmms_machine_code' => $cmmsMachine->machine_code,
'rahdar_id' => $rahdar->id,
'rahdar_code' => $rahdar->code
]);
$this->assertDatabaseHas('user_activity_logs', [
'user_id' => $user->id,
'username' => $user->username,
'log_unique_code' => 1154,
]);
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace Tests\Feature\V3\RoadItemsProject;
use App\Models\Permission;
use App\Models\RoadItemsProject;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class SupervisorIndexTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* A basic feature test example.
*/
public function test_user_should_have_show_road_item_supervise_cartable_permission(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->getJson(route('v3.road_items.supervisorIndex'));
$response->assertForbidden();
}
public function test_supervisor_can_see_the_data_table(): void
{
$user = User::factory()
->has(Permission::factory([
'name' => 'show-road-item-supervise-cartable'
]))
->create();
RoadItemsProject::factory(10)->create();
$response = $this->actingAs($user)->getJson(route('v3.road_items.supervisorIndex', [
'size' => 10,
'start' => 0,
'sorting' => json_encode([]),
'filters' => json_encode([]),
]));
$response->assertOk();
$response->assertJsonStructure([
'data' => [
'*' => [
"id",
"user_id",
"start_lat",
"start_lng",
"end_lat",
"end_lng",
"project_distance",
"item",
"item_fa",
"sub_item",
"sub_item_fa",
"sub_item_data",
"sub_items",
"sub_items_data",
"created_at",
"updated_at",
"province_id",
"province_fa",
"city_id",
"city_fa",
"is_new",
"parent_id",
"start_way_id",
"end_way_id",
"unit_fa",
"user_name",
"created_at_fa",
"info_id",
"status",
"status_fa",
"edarat_id",
"edarat_name",
"edarat_type",
"activity_date",
"activity_time",
"activity_date_time",
"supervisor_id",
"supervisor_name",
"supervisor_description",
"supervising_time",
"cmms_machine_id",
"cmms_machine_code",
"rahdar_id",
"rahdar_code",
"can_supervise",
],
]
]);
}
}

View File

@@ -0,0 +1,317 @@
<?php
namespace Tests\Feature\V3\RoadItemsProject;
use App\Models\City;
use App\Models\CMMSMachine;
use App\Models\EdarateShahri;
use App\Models\InfoItem;
use App\Models\LogList;
use App\Models\Permission;
use App\Models\Province;
use App\Models\Rahdaran;
use App\Models\RoadItemsProject;
use App\Models\User;
use App\Models\UserActivityLog;
use App\Services\NominatimService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Mockery\MockInterface;
use Tests\TestCase;
class UpdateTest extends TestCase
{
use RefreshDatabase, WithFaker;
public function test_road_item_should_belong_to_the_user()
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route("v3.road_items.update", [$road_item->id]));
$response->assertForbidden();
}
public function test_road_item_status_must_be_2()
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 3
]);
$response = $this->actingAs($user)->postJson(route("v3.road_items.update", [$road_item->id]));
$response->assertForbidden();
}
public function test_start_point_is_required(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route("v3.road_items.update", [$road_item->id]));
$response->assertUnprocessable()
->assertInvalid([
'start_point' => __('validation.required', ['attribute' => 'start point'])
]);
}
public function test_amount_is_required(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]));
$response->assertUnprocessable()
->assertInvalid([
'amount' => __('validation.required', ['attribute' => 'amount'])
]);
}
public function test_amount_should_be_numeric(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), [
'amount' => $this->faker->name
]);
$response->assertUnprocessable()
->assertInvalid([
'amount' => __('validation.numeric', ['attribute' => 'amount'])
]);
}
public function test_before_image_should_be_image(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), [
'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()->create();
$image = UploadedFile::fake()->create('image.jpg', 5096);
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), [
'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()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), [
'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()->create();
$image = UploadedFile::fake()->create('image.jpg', 5096);
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), [
'after_image' => $image
]);
$response->assertUnprocessable()
->assertInvalid([
'after_image' => __('validation.max.file', ['attribute' => 'after image', 'max' => 4096])
]);
}
public function test_cmms_machine_id_is_required(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]));
$response->assertUnprocessable()
->assertInvalid([
'cmms_machine_id' => __('validation.required', ['attribute' => 'کد یکتا ماشین'])
]);
}
public function test_cmms_machine_id_should_already_exists_on_the_table(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), [
'cmms_machine_id' => $this->faker->numberBetween(10, 100)
]);
$response->assertUnprocessable()
->assertInvalid([
'cmms_machine_id' => __('validation.exists', ['attribute' => 'کد یکتا ماشین'])
]);
}
public function test_rahdar_id_is_required(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]));
$response->assertUnprocessable()
->assertInvalid([
'rahdar_id' => __('validation.required', ['attribute' => 'rahdar id'])
]);
}
public function test_rahdar_id_should_already_exists_on_the_table(): void
{
$user = User::factory()->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), [
'rahdar_id' => $this->faker->numberBetween(10, 100)
]);
$response->assertUnprocessable()
->assertInvalid([
'rahdar_id' => __('validation.exists', ['attribute' => 'rahdar id'])
]);
}
public function test_can_update_the_road_item_project(): void
{
$cmmsMachine = CMMSMachine::factory()->create();
$rahdar = Rahdaran::factory()->create();
LogList::factory()->create([
'log_unique_code' => 1155
]);
UserActivityLog::factory()->create();
$user = User::factory()
->has(Permission::factory([
'name' => 'create-road-item'
]))
->create();
$road_item = RoadItemsProject::factory()->create([
'user_id' => $user->id,
'status' => 2,
'item' => $this->faker->numberBetween(1, 10),
'sub_item' => $this->faker->numberBetween(1, 10),
]);
Storage::fake('public');
$data = [
'start_point' => '12,12',
'amount' => $this->faker->numberBetween(1, 10),
'cmms_machine_id' => $cmmsMachine->id,
'rahdar_id' => $rahdar->id,
];
$infoItem = InfoItem::factory()->create([
'item' => $road_item ->item,
'sub_item' => $road_item ->sub_item,
]);
$response = $this->actingAs($user)->postJson(route('v3.road_items.update', [$road_item->id]), $data);
$response->assertOk()
->assertExactJson([
'message' => __('messages.successful')
]);
$this->assertDatabaseHas('road_items_projects', [
'start_lat' => 12,
'start_lng' => 12,
'cmms_machine_id' => $cmmsMachine->id,
'cmms_machine_code' => $cmmsMachine->machine_code,
'rahdar_id' => $rahdar->id,
'rahdar_code' => $rahdar->code
]);
$this->assertDatabaseHas('user_activity_logs', [
'user_id' => $user->id,
'username' => $user->username,
'log_unique_code' => 1155,
]);
}
}