diff --git a/.env.example b/.env.example index 79b288cd..3ebfeaa3 100644 --- a/.env.example +++ b/.env.example @@ -90,3 +90,7 @@ HARIM_EDIT_ACCESS_USERNAME= HARIM_NEED_GUARANTEE_LETTER_URL= HARIM_NEED_GUARANTEE_LETTER_PASSWORD= HARIM_NEED_GUARANTEE_LETTER_USERNAME= + +BACKUP_TARGET_DIR= +BACKUP_USER= +BACKUP_PASSWORD= \ No newline at end of file diff --git a/app/Console/Commands/BackupDatabaseCommand.php b/app/Console/Commands/BackupDatabaseCommand.php new file mode 100644 index 00000000..1d0d6ca8 --- /dev/null +++ b/app/Console/Commands/BackupDatabaseCommand.php @@ -0,0 +1,51 @@ +forever()->run("sudo mariadb-backup --backup --target-dir={$path}/{$time} --user={$user} --password={$password}"); + + if ($backup->failed()) { + Log::channel('mariadb-backup')->info("Backup failed at {$time}"); + } + + $prepare = Process::path($path)->forever()->run("sudo mariadb-backup --prepare --target-dir={$path}/{$time}"); + + if ($prepare->failed()) { + Log::channel('mariadb-backup')->info("Preparation failed at {$time}"); + } + + Log::channel('mariadb-backup')->info("Backup successful at {$time}"); + + $this->info('done'); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f1f2d616..815e0d20 100755 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -39,6 +39,9 @@ class Kernel extends ConsoleKernel $schedule->command("webservice:roadobserved --daily-mode") ->dailyAt('00:45')->appendOutputTo(storage_path('logs/nikarayan.log')); + + $schedule->command("db:backup") + ->weekly()->at('03:00')->appendOutputTo(storage_path('logs/mariadb-backup.log')); } /** diff --git a/app/Enums/FMSResultCode.php b/app/Enums/FMSResultCode.php new file mode 100644 index 00000000..af8d06a9 --- /dev/null +++ b/app/Enums/FMSResultCode.php @@ -0,0 +1,27 @@ + "اﺟﺮاي ﺗﺎﺑﻊ ﻣﻮﻓﻘﯿﺖ آﻣﯿﺰ ﺑﻮد.", + 1 => "نام ﮐﺎرﺑﺮي ﯾﺎ ﮐﻠﻤﻪ ﻋﺒﻮر ﺻﺤﯿﺢ ﻧﯿﺴﺖ.", + 2 => "خودرو با کد مورد نظر وجود ندارد یا دستگاه ردیاب به آن متصل نیست.", + 3 => "کاربر به خودرو مورد نظر دسترسی ندارد.", + 4 => "ﺗﻌﺪاد دﻓﻌﺎت ﺟﺮاي ﺗﺎﺑﻊ ﺑﯿﺶ از ﺣﺪ ﻣﺠﺎز اﺳﺖ(اﯾﻦ ﺳﺮوﯾﺲ را در ﻫﺮ ثاﻧﯿﻪ ﻓﻘﻂ ﯾﮏ ﺑﺎر ﻣﯽﺗﻮان اﺟﺮاﮐﺮد)", + 5 => "پارامتر های داده شده صحیح نیستند", + ]; + + return $mapArray[$state]; + } +} diff --git a/app/Exports/V3/Damage/DamageCartableReport.php b/app/Exports/V3/Damage/DamageCartableReport.php new file mode 100644 index 00000000..dac30525 --- /dev/null +++ b/app/Exports/V3/Damage/DamageCartableReport.php @@ -0,0 +1,67 @@ + $this->data + ]); + } + + public function registerEvents(): array + { + return [ + AfterSheet::class => function (AfterSheet $event) { + $event->sheet->getDelegate()->setRightToLeft(true); + $event->sheet->getDelegate()->getStyle('A:U')->getFont()->setName('Arial'); + $event->sheet->getDelegate()->getStyle('A:U') + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_CENTER); + + $event->sheet->getDelegate()->getStyle('A:U') + ->getAlignment() + ->setVertical(Alignment::VERTICAL_CENTER); + } + ]; + } + + public function drawings(): array + { + $drawing = new Drawing(); + $drawing->setName('Logo'); + $drawing->setDescription('This is my logo'); + $drawing->setPath(public_path('/dist/logo.png')); + $drawing->setWidth(50); + $drawing->setHeight(50); + $drawing->setOffsetX(5); + $drawing->setOffsetY(5); + $drawing->setCoordinates('A1'); + + $drawing2 = new Drawing(); + $drawing2->setName('Logo'); + $drawing2->setDescription('This is my logo'); + $drawing2->setPath(public_path('/dist/141icon.png')); + $drawing2->setWidth(50); + $drawing2->setHeight(50); + $drawing2->setOffsetX(5); + $drawing2->setOffsetY(5); + $drawing2->setCoordinates('f1'); + return [$drawing, $drawing2]; + } +} \ No newline at end of file diff --git a/app/Exports/V3/RoadObservation/CountryCartableReport.php b/app/Exports/V3/RoadObservation/CountryCartableReport.php new file mode 100644 index 00000000..e46a48ac --- /dev/null +++ b/app/Exports/V3/RoadObservation/CountryCartableReport.php @@ -0,0 +1,70 @@ + $this->data, + ]); + } + + public function registerEvents(): array + { + return [ + AfterSheet::class => function (AfterSheet $event) { + $event->sheet->getDelegate()->setRightToLeft(true); + $event->sheet->getDelegate()->getStyle('A:U')->getFont()->setName('Arial'); + $event->sheet->getDelegate()->getStyle('A:U') + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_CENTER); + + $event->sheet->getDelegate()->getStyle('A:U') + ->getAlignment() + ->setVertical(Alignment::VERTICAL_CENTER); + } + ]; + } + + public function drawings(): array + { + $drawing = new Drawing(); + $drawing->setName('Logo'); + $drawing->setDescription('This is my logo'); + $drawing->setPath(public_path('/dist/logo.png')); + $drawing->setWidth(50); + $drawing->setHeight(50); + $drawing->setOffsetX(5); + $drawing->setOffsetY(5); + $drawing->setCoordinates('A1'); + + $drawing2 = new Drawing(); + $drawing2->setName('Logo'); + $drawing2->setDescription('This is my logo'); + $drawing2->setPath(public_path('/dist/141icon.png')); + $drawing2->setWidth(50); + $drawing2->setHeight(50); + $drawing2->setOffsetX(5); + $drawing2->setOffsetY(5); + $drawing2->setCoordinates('j1'); + return [$drawing, $drawing2]; + } + +} diff --git a/app/Exports/V3/RoadObservation/ProvinceCartableReport.php b/app/Exports/V3/RoadObservation/ProvinceCartableReport.php new file mode 100644 index 00000000..57daad87 --- /dev/null +++ b/app/Exports/V3/RoadObservation/ProvinceCartableReport.php @@ -0,0 +1,70 @@ + $this->data, + ]); + } + + public function registerEvents(): array + { + return [ + AfterSheet::class => function (AfterSheet $event) { + $event->sheet->getDelegate()->setRightToLeft(true); + $event->sheet->getDelegate()->getStyle('A:U')->getFont()->setName('Arial'); + $event->sheet->getDelegate()->getStyle('A:U') + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_CENTER); + + $event->sheet->getDelegate()->getStyle('A:U') + ->getAlignment() + ->setVertical(Alignment::VERTICAL_CENTER); + } + ]; + } + + public function drawings(): array + { + $drawing = new Drawing(); + $drawing->setName('Logo'); + $drawing->setDescription('This is my logo'); + $drawing->setPath(public_path('/dist/logo.png')); + $drawing->setWidth(50); + $drawing->setHeight(50); + $drawing->setOffsetX(5); + $drawing->setOffsetY(5); + $drawing->setCoordinates('A1'); + + $drawing2 = new Drawing(); + $drawing2->setName('Logo'); + $drawing2->setDescription('This is my logo'); + $drawing2->setPath(public_path('/dist/141icon.png')); + $drawing2->setWidth(50); + $drawing2->setHeight(50); + $drawing2->setOffsetX(5); + $drawing2->setOffsetY(5); + $drawing2->setCoordinates('j1'); + return [$drawing, $drawing2]; + } + +} diff --git a/app/Http/Controllers/V3/DamageManagementController.php b/app/Http/Controllers/V3/DamageManagementController.php index 53047e18..dc075c61 100644 --- a/app/Http/Controllers/V3/DamageManagementController.php +++ b/app/Http/Controllers/V3/DamageManagementController.php @@ -2,14 +2,19 @@ namespace App\Http\Controllers\V3; +use App\Exports\V3\Damage\DamageCartableReport; use App\Facades\DataTable\DataTableFacade; use App\Http\Controllers\Controller; use App\Http\Requests\V3\Damage\StoreRequest; use App\Http\Requests\V3\Damage\UpdateRequest; use App\Http\Traits\ApiResponse; use App\Models\Damage; +use App\Services\Cartables\Damage\DamageService; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Maatwebsite\Excel\Facades\Excel; +use PhpOffice\PhpSpreadsheet\Exception; +use Symfony\Component\HttpFoundation\BinaryFileResponse; class DamageManagementController extends Controller { @@ -17,20 +22,9 @@ class DamageManagementController extends Controller /** * Display a listing of the resource. */ - public function index(Request $request): JsonResponse + public function index(Request $request ,DamageService $damageService): JsonResponse { - $allowedFilters = ['*']; - $allowedSortings = ['*']; - - $query = Damage::query(); - - $data = DataTableFacade::run( - $query, - $request, - allowedFilters: $allowedFilters, - allowedSortings: $allowedSortings); - - + $data = $damageService->dataTable($request); return response()->json($data); } @@ -71,7 +65,6 @@ class DamageManagementController extends Controller */ public function update(UpdateRequest $request, Damage $damage): JsonResponse - { $damage->update([ 'title' => $request->title, @@ -92,4 +85,15 @@ class DamageManagementController extends Controller return $this->successResponse(); } + + /** + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception + */ + public function excel(Request $request, DamageService $damageService): BinaryFileResponse + { + $name = 'آیتم خسارات وارده بر ابنیه فنی' . verta()->now()->format('Y-m-d H-i') . '.xlsx'; + $data = $damageService->datatable($request); + return Excel::download(new DamageCartableReport($data['data']), $name); + } } diff --git a/app/Http/Controllers/V3/Dashboard/Accident/AccidentReceiptController.php b/app/Http/Controllers/V3/Dashboard/Accident/AccidentReceiptController.php index 8107a951..eeece69e 100644 --- a/app/Http/Controllers/V3/Dashboard/Accident/AccidentReceiptController.php +++ b/app/Http/Controllers/V3/Dashboard/Accident/AccidentReceiptController.php @@ -256,22 +256,18 @@ class AccidentReceiptController extends Controller $final_amount = $accident->driver_share_amount - ($accident->deposit_insurance_amount + $accident->deposit_daghi_amount); - if ($final_amount > 0) { - $status = AccidentStates::SABT_FISH->value; - $status_fa = AccidentStates::name($status); - } - elseif ($final_amount == 0) { - $status = AccidentStates::PARDAKHT_FACTOR->value; - $status_fa = AccidentStates::name($status); - } + throw_if($final_amount < 0, new ProhibitedAction('مبالغ داغی و بیمه از مبلغ کل بیشتر می باشد.')); + + $status = $final_amount > 0 ? AccidentStates::SABT_FISH->value : AccidentStates::PARDAKHT_FACTOR->value; $accident->update([ + 'final_amount' => $final_amount, 'deposit_insurance_image' => $request->has('deposit_insurance_image') ? FileFacade::save($request->deposit_insurance_image, "receipts_files/{$accident->id}/deposit_insurance") : null, 'deposit_insurance_amount' => $request->deposit_insurance_amount ?? 0, 'deposit_daghi_image' => $request->has('deposit_daghi_image') ? FileFacade::save($request->deposit_daghi_image, "receipts_files/{$accident->id}/deposit_daghi") : null, 'deposit_daghi_amount' => $request->deposit_daghi_amount ?? 0, 'status' => $status, - 'status_fa' => $status_fa, + 'status_fa' => AccidentStates::name($status), ]); auth()->user()->addActivityComplete(1132); @@ -288,16 +284,13 @@ class AccidentReceiptController extends Controller $lock = Cache::lock("accidentPayment-{$accident->id}", 10); throw_if(!$lock->get(), new ProhibitedAction('امکان درخواست مجدد تا 10 ثانیه دیگر وجود ندارد')); - $final_amount = $accident->driver_share_amount - ($accident->deposit_insurance_amount + $accident->deposit_daghi_amount); - - throw_if($final_amount < 0, new ProhibitedAction('مبالغ داغی و بیمه از مبلغ کل بیشتر می باشد.')); + $final_amount = $accident->final_amount; $bill_code = $paymentService->invoiceBillApi($accident->driver_national_code, $final_amount); DB::transaction(function () use ($bill_code, $final_amount, $accident) { $accident->update([ - 'final_amount' => $final_amount, 'bill_code' => $bill_code, 'status' => AccidentStates::SODOR_FACTOR->value, 'status_fa' => AccidentStates::name(AccidentStates::SODOR_FACTOR->value), @@ -318,26 +311,15 @@ class AccidentReceiptController extends Controller public function checkPaymentStatus(Accident $accident, PaymentService $paymentService): JsonResponse { DB::transaction(function () use ($accident, $paymentService) { - if ($accident->final_amount > 0) { - $response = json_decode($paymentService->callPaymentStatusBillApi(explode("/", $accident->bill_code)[0])); + $response = json_decode($paymentService->callPaymentStatusBillApi(explode("/", $accident->bill_code)[0])); - throw_if(!$response->isPayed, new ProhibitedAction('پرداخت انجام نشده است')); + throw_if(!$response->isPayed, new ProhibitedAction('پرداخت انجام نشده است')); - if ($response->isPayed) { - $accident->update([ - 'status' => AccidentStates::PARDAKHT_FACTOR->value, - 'status_fa' => AccidentStates::name(AccidentStates::PARDAKHT_FACTOR->value), - ]); - } - } - else - { - $accident->update([ - 'status' => AccidentStates::PARDAKHT_FACTOR->value, - 'status_fa' => AccidentStates::name(AccidentStates::PARDAKHT_FACTOR->value), - ]); - } + $accident->update([ + 'status' => AccidentStates::PARDAKHT_FACTOR->value, + 'status_fa' => AccidentStates::name(AccidentStates::PARDAKHT_FACTOR->value), + ]); auth()->user()->addActivityComplete(1130); }); diff --git a/app/Http/Controllers/V3/Dashboard/Mission/ControlUnitController.php b/app/Http/Controllers/V3/Dashboard/Mission/ControlUnitController.php index 506861fe..d9ca292f 100644 --- a/app/Http/Controllers/V3/Dashboard/Mission/ControlUnitController.php +++ b/app/Http/Controllers/V3/Dashboard/Mission/ControlUnitController.php @@ -57,7 +57,8 @@ class ControlUnitController extends Controller $mission->update([ 'state_id' => $state, 'state_name' => MissionStates::name($state), - 'finish_time' => now() + 'finish_time' => now(), + 'mission_duration' => strtotime(now()) - strtotime($mission->start_time), ]); }); diff --git a/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php b/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php index 74ec9be3..f5dc950c 100644 --- a/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php +++ b/app/Http/Controllers/V3/Dashboard/Mission/RequestPortalController.php @@ -9,6 +9,7 @@ use App\Enums\MissionZones; use App\Http\Controllers\Controller; use App\Http\Controllers\V3\Dashboard\RoadPatrol\OperatorController; use App\Http\Requests\V3\Mission\RequestPortal\NoProcessRequest; +use App\Http\Requests\V3\Mission\RequestPortal\ContinueMissionRequest; use App\Http\Requests\V3\Mission\RequestPortal\StoreRequest; use App\Http\Requests\V3\Mission\RequestPortal\UpdateRequest; use App\Http\Traits\ApiResponse; @@ -33,6 +34,7 @@ class RequestPortalController extends Controller { DB::transaction(function () use ($request) { $user = auth()->user(); + $state = MissionStates::REQUEST_CREATED->value; $category = $request->category_id; @@ -80,6 +82,56 @@ class RequestPortalController extends Controller return $this->successResponse($mission); } + public function continueMission(ContinueMissionRequest $request , Mission $mission): JsonResponse + { + DB::transaction(function () use ($request, $mission) { + $user = auth()->user(); + + $mission->update(['finish_time' => now()]); + + $state = MissionStates::REQUEST_CREATED->value; + $category = $request->category_id; + + $newMission = Mission::query()->create([ + 'user_id' => $user->id, + 'username' => $user->username, + 'province_id' => $user->province_id, + 'province_name' => $user->province_fa, + 'edare_shahri_id' => $user->edarate_shahri_id ?? null, + 'edare_shahri_name' => $user->edarate_shahri_name ?? null, + 'state_id' => $state, + 'state_name' => MissionStates::name($state), + 'type' => $request->type, + 'type_fa' => MissionTypes::name($request->type), + 'zone' => $request->zone, + 'zone_fa' => MissionZones::name($request->zone), + 'start_date' => $request->start_date, + 'end_date' => $request->end_date, + 'request_date' => now(), + 'description' => $request->description, + 'end_point' => $request->end_point, + 'area' => json_encode($request->area), + 'category_id' => $category, + 'category_name' => MissionCategory::name($category), + 'explanation' => $request->explanation, + 'start_time' => now() + ]); + + $newMission->rahdaran()->sync($request->rahdaran); + $newMission->machines()->attach($request->machines); + $newMission->rahdaran()->attach($request->driver, ['is_driver' => true]); + + if ($category == 3){ + RoadObserved::query() + ->find($request->road_observed_id) + ->missions() + ->attach( $newMission->id); + } + }); + + return $this->successResponse(); + } + public function update(UpdateRequest $request, Mission $mission): JsonResponse { DB::transaction(function () use ($mission, $request) { diff --git a/app/Http/Controllers/V3/Dashboard/RoadObservation/ReportController.php b/app/Http/Controllers/V3/Dashboard/RoadObservation/ReportController.php index db11136c..4b00f238 100644 --- a/app/Http/Controllers/V3/Dashboard/RoadObservation/ReportController.php +++ b/app/Http/Controllers/V3/Dashboard/RoadObservation/ReportController.php @@ -3,10 +3,15 @@ namespace App\Http\Controllers\V3\Dashboard\RoadObservation; use App\Exports\V2\RoadObservation\ReportComplaintsExport; +use App\Exports\V3\RoadObservation\CountryCartableReport; +use App\Exports\V3\RoadObservation\ProvinceCartableReport; use App\Facades\DataTable\DataTableFacade; use App\Http\Traits\ApiResponse; +use App\Models\EdarateShahri; +use App\Models\Province; use App\Models\RoadObserved; use App\Services\Cartables\RoadObservation\ReportService; +use App\Services\Cartables\SafetyAndPrivacy\OperatorService; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Maatwebsite\Excel\Facades\Excel; @@ -39,4 +44,37 @@ class ReportController allowedSelects: ['id', 'lat', 'lng', 'status'] )); } -} \ No newline at end of file + + public function countryActivity(Request $request, ReportService $reportService): JsonResponse + { + $data = $reportService->countryActivity($request); + return $this->successResponse($data); + } + + public function provinceActivity(Request $request, ReportService $reportService): JsonResponse + { + $data = $reportService->provinceActivity( + province_id: $request->input('province_id') + ); + + return $this->successResponse([ + 'activities' => $data, + 'edarateShahri' => EdarateShahri::where('province_id', $request->province_id)->get(['id', 'name_fa']), + ]); + } + public function countryActivityExcel(Request $request, OperatorService $operatorService): BinaryFileResponse + { + $data = $operatorService->countryActivity($request); + $name = 'گزارش رسیدگی به شکایات واکنش سریع' . verta()->now()->format('Y-m-d H-i') . '.xlsx'; + return Excel::download(new CountryCartableReport($data), $name); + } + + public function provinceActivityExcel(Request $request, OperatorService $operatorService): BinaryFileResponse + { + $data = $operatorService->provinceActivity( + province_id: $request->input('province_id') + ); + $name = 'گزارش رسیدگی به شکایات واکنش سریع' . verta()->now()->format('Y-m-d H-i') . '.xlsx'; + return Excel::download(new ProvinceCartableReport($data, $request), $name); + } +} diff --git a/app/Http/Requests/V3/Mission/RequestPortal/ContinueMissionRequest.php b/app/Http/Requests/V3/Mission/RequestPortal/ContinueMissionRequest.php new file mode 100644 index 00000000..345f2505 --- /dev/null +++ b/app/Http/Requests/V3/Mission/RequestPortal/ContinueMissionRequest.php @@ -0,0 +1,66 @@ +mission->edare_shahri_id == auth()->user()->edarate_shahri_id && $this->mission->state_id == MissionStates::START_MISSION->value; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules(): array + { + return [ + 'rahdaran' => 'array', + 'rahdaran.*' => 'exists:rahdaran,id', + 'machines' => 'required|array', + 'machines.*' => 'required|integer|exists:cmms_machines,id', + 'driver' => 'required|integer|exists:rahdaran,id', + 'type' => 'required|in:1,2', + 'zone' => 'required|in:1,2,3', + 'start_date' => 'required|date', + 'end_date' => 'required|date', + 'description' => 'string', + 'end_point' => 'required|string', + 'area' => 'required|array', + 'area.type' => 'required|string', + 'area.coordinates' => 'required|array', + 'explanation' => 'required|string', + 'category_id' => 'required|in:1,2,3', + 'road_observed_id' => 'required_if:category_id,3|exists:road_observeds,id', + ]; + } + public function after(): array + { + return [ + function (Validator $validator) { + if ($this->type == 1){ + $start = Carbon::parse($this->start_date); + $end = Carbon::parse($this->end_date); + + if ($start->diffInMinutes($end) > 480){ + $validator->errors()->add( + 'end_date', + 'مدت زمان مأموریت ساعتی نباید بیشتر از ۸ ساعت باشد.' + ); + } + } + } + ]; + } +} diff --git a/app/Listeners/V3/Dashboard/Mission/SendDataToFMSListener.php b/app/Listeners/V3/Dashboard/Mission/SendDataToFMSListener.php index 500f1ed1..1d0b249b 100644 --- a/app/Listeners/V3/Dashboard/Mission/SendDataToFMSListener.php +++ b/app/Listeners/V3/Dashboard/Mission/SendDataToFMSListener.php @@ -2,6 +2,7 @@ namespace App\Listeners\V3\Dashboard\Mission; +use App\Enums\FMSResultCode; use App\Events\V3\Dashboard\Mission\SendDataToFMSEvent; use App\Services\FMS\GetErrorRateService; use Exception; @@ -28,12 +29,24 @@ class SendDataToFMSListener implements ShouldQueue $mission = $event->mission; $this->getErrorRateService->setInputParameters([ - 'area' => $mission->area, - 'start_date' => $mission->start_date, - 'end_date' => $mission->end_date, - 'machine_code' => $mission->machines()->first('cmms_machines.machine_code') + 'url' => config('fms_web_services.Error_Rate.url'), + 'password' => config('fms_web_services.Error_Rate.password'), + 'missionArea' => $mission->area['coordinates'], + 'missionStartDT' => $mission->start_time->format('Y-m-d\TH:i:s'), + 'missionEndDT' => $mission->finish_time->format('Y-m-d\TH:i:s'), + 'machineCode' => $mission->machines()->first()->value('machine_code'), + 'areaType' => $mission->area['type'] === 'polygon' ? 1 : 2, ]); - $this->getErrorRateService->run(); + $responseData = $this->getErrorRateService->run(); + + $mission->update([ + 'in_area_duration' => $responseData['timeInAreaSeconds'], + 'first_enter' => $responseData['firstEnter'], + 'last_exit' => $responseData['lastExit'], + 'point_number_sent' => $responseData['noOfPointsInMission'], + 'fms_result_code' => $responseData['resultCode'], + 'fms_result_message' => FMSResultCode::name($responseData['resultCode']), + ]); } } diff --git a/app/Models/Accident.php b/app/Models/Accident.php index aec15bce..f9ef31e5 100644 --- a/app/Models/Accident.php +++ b/app/Models/Accident.php @@ -126,4 +126,18 @@ class Accident extends Model get: fn ($value) => env("PAYMENT_LINK")."/#/pay/".explode("/", $this->bill_code)[0]."/{$this->final_amount}", ); } + + protected function depositInsuranceImage(): Attribute + { + return Attribute::make( + get: fn($value) => $value == null ? null : Storage::disk('public')->url($value) + ); + } + + protected function depositIdaghiImage(): Attribute + { + return Attribute::make( + get: fn($value) => $value == null ? null : Storage::disk('public')->url($value) + ); + } } diff --git a/app/Models/Mission.php b/app/Models/Mission.php index 347c738d..9d85a9bc 100644 --- a/app/Models/Mission.php +++ b/app/Models/Mission.php @@ -15,6 +15,10 @@ class Mission extends Model protected $guarded = []; protected $hidden = ['pivot']; + protected $casts = [ + 'start_time' => 'datetime', + 'finish_time' => 'datetime', + ]; protected function requestedMachines(): Attribute { @@ -26,7 +30,7 @@ class Mission extends Model protected function area(): Attribute { return Attribute::make( - get: fn($value) => json_decode($value) + get: fn($value) => json_decode($value, true) ); } diff --git a/app/Services/Cartables/Damage/DamageService.php b/app/Services/Cartables/Damage/DamageService.php new file mode 100644 index 00000000..6e3efe08 --- /dev/null +++ b/app/Services/Cartables/Damage/DamageService.php @@ -0,0 +1,24 @@ + $toDate, ]; } + public function countryActivity(Request $request): array + { + return DB::select(" + SELECT + p.id AS province_id, + p.name_fa AS province_name, + SUM(t.rms_status = 0 ) AS residegiShode, + SUM(t.rms_status = 1 ) AS egdamshode, + SUM(t.rms_status = 2) AS egdamnashodeh, + SUM(t.status = 0 ) AS darhalbarasi, + SUM(t.status = 1 ) AS taayidshode, + SUM(t.status = 2 ) AS adamtaayid, + SUM(t.rms_status = 0 ) + SUM(t.rms_status = 1) + SUM(t.rms_status = 2) AS total + FROM + provinces p + LEFT JOIN + + road_observeds t ON t.province_id = p.id + GROUP BY + p.id, p.name_fa + + UNION ALL + + SELECT + -1 AS province_id, + 'کل کشور' AS province_name, + SUM(t.rms_status = 0 ) AS residegiShode, + SUM(t.rms_status = 1 ) AS egdamshode, + SUM(t.rms_status = 2) AS egdamnashodeh, + SUM(t.status = 0 ) AS darhalbarasi, + SUM(t.status = 1 ) AS taayidshode, + SUM(t.status = 2 ) AS adamtaayid, + SUM(t.rms_status = 0 ) + SUM(t.rms_status = 1) + SUM(t.rms_status = 2) AS total + FROM + provinces p + LEFT JOIN + + road_observeds t ON t.province_id = p.id + ORDER BY + province_id + "); + } + + public function provinceActivity(int $province_id): array + { + return DB::select(" + SELECT + e.id AS edare_id, + e.name_fa AS edare_name, + COALESCE(SUM(t.rms_status = 0 ),0) AS residegiShode, + COALESCE(SUM(t.rms_status = 1),0) AS egdamshode, + COALESCE(SUM(t.rms_status = 2),0) AS egdamnashodeh, + COALESCE(SUM(t.status = 0 ),0) AS darhalbarasi, + COALESCE(SUM(t.status = 1 ),0) AS taayidshode, + COALESCE(SUM(t.status = 2 ),0) AS adamtaayid, + COALESCE(SUM(t.rms_status = 0 ) + SUM(t.rms_status = 1) + SUM(t.rms_status = 2),0)AS total + FROM + edarate_shahri e + LEFT JOIN + road_observeds t ON t.edarate_shahri_id = e.id AND t.province_id = e.province_id + WHERE + e.province_id = :provinceId + GROUP BY + e.id, e.name_fa + + UNION ALL + + SELECT + -1 AS edare_id, + 'کل استان' AS edare_name, + COALESCE(SUM(t.rms_status = 0 ),0) AS residegiShode, + COALESCE(SUM(t.rms_status = 1),0) AS egdamshode, + COALESCE(SUM(t.rms_status = 2),0) AS egdamnashodeh, + COALESCE(SUM(t.status = 0 ),0) AS darhalbarasi, + COALESCE(SUM(t.status = 1 ),0) AS taayidshode, + COALESCE(SUM(t.status = 2 ),0) AS adamtaayid, + COALESCE(SUM(t.rms_status = 0 ) + SUM(t.rms_status = 1) + SUM(t.rms_status = 2),0)AS total + FROM + edarate_shahri e + LEFT JOIN + road_observeds t ON t.edarate_shahri_id = e.id AND t.province_id = e.province_id + ORDER BY + edare_id + ", [ + 'provinceId' => $province_id, + ]); + } } \ No newline at end of file diff --git a/app/Services/FMS/GetErrorRateService.php b/app/Services/FMS/GetErrorRateService.php index aa86d83c..bf2f699c 100644 --- a/app/Services/FMS/GetErrorRateService.php +++ b/app/Services/FMS/GetErrorRateService.php @@ -16,8 +16,6 @@ class GetErrorRateService public function __construct() { - $this->url = config('fms_web_services.Error_Rate.url'); - $this->password = config('fms_web_services.Error_Rate.password'); $this->username = config('fms_web_services.Error_Rate.username'); $this->channelName = 'fms_error_rate'; } @@ -49,23 +47,10 @@ class GetErrorRateService public function sendRequest(): array { - $inputData = $this->makeInputParameters(); - - return Http::withBody($inputData) + return Http::withHeaders(['Content-Type' => 'application/json']) ->throw() ->withoutVerifying() - ->post($this->url) + ->post($this->url, $this->inputParameters) ->json(); } - - private function makeInputParameters(): string - { - $inputData = $this->inputParameters + array( - "username" => $this->username, - "password" => $this->password, - "minStopDuration" => 1, - ); - - return json_encode($inputData); - } } diff --git a/app/Services/PaymentService.php b/app/Services/PaymentService.php index bb5d2e68..cfe90719 100644 --- a/app/Services/PaymentService.php +++ b/app/Services/PaymentService.php @@ -23,7 +23,7 @@ class PaymentService 'type' => 1, 'instanceid' => 123, 'ownerid' => $driver_national_code, - 'calculationBox' => "{\"rows\":[{\"amount\":" . $final_amount . ",\"code\":\"7070021060000015\"}]}" + 'calculationBox' => "{\"rows\":[{\"amount\":" . $final_amount . ",\"code\":\"7070011026200593\"}]}" ); $ch = curl_init(); diff --git a/config/global_variables.php b/config/global_variables.php index cc7b9df3..886160ad 100644 --- a/config/global_variables.php +++ b/config/global_variables.php @@ -2,4 +2,7 @@ return [ 'IS_DEVELOPMENT_ENV' => env('IS_DEVELOPMENT_ENV', false), + "BACKUP_TARGET_DIR" => env('BACKUP_TARGET_DIR'), + "BACKUP_USER" => env('BACKUP_USER'), + "BACKUP_PASSWORD" => env('BACKUP_PASSWORD'), ]; diff --git a/config/logging.php b/config/logging.php index dced418b..3a6fc052 100644 --- a/config/logging.php +++ b/config/logging.php @@ -135,6 +135,11 @@ return [ 'path' => storage_path('logs/fms/error_rate_service.log'), 'level' => 'info', ], - ], + 'mariadb-backup' => [ + 'driver' => 'single', + 'path' => storage_path('logs/mariadb-backup.log'), + 'level' => 'info', + ], + ], ]; diff --git a/database/migrations/2025_09_08_104123_add_mission_id_to_road_items_projects_table.php b/database/migrations/2025_09_08_104123_add_mission_id_to_road_items_projects_table.php index 62d511c4..e874b73e 100644 --- a/database/migrations/2025_09_08_104123_add_mission_id_to_road_items_projects_table.php +++ b/database/migrations/2025_09_08_104123_add_mission_id_to_road_items_projects_table.php @@ -12,7 +12,7 @@ return new class extends Migration public function up(): void { Schema::table('road_items_projects', function (Blueprint $table) { - $table->foreignId('mission_id')->nullable()->constrained('missions'); + $table->unsignedBigInteger('mission_id')->nullable(); }); } @@ -22,7 +22,6 @@ return new class extends Migration public function down(): void { Schema::table('road_items_projects', function (Blueprint $table) { - $table->dropForeign('road_items_projects_mission_id_foreign'); $table->dropColumn('mission_id'); }); } diff --git a/database/migrations/2025_09_23_095848_add_column_to_missions_table.php b/database/migrations/2025_09_23_095848_add_column_to_missions_table.php new file mode 100644 index 00000000..a69e92dc --- /dev/null +++ b/database/migrations/2025_09_23_095848_add_column_to_missions_table.php @@ -0,0 +1,38 @@ +bigInteger('mission_duration')->nullable(); + $table->bigInteger('in_area_duration')->nullable(); + $table->timestamp('first_enter')->nullable(); + $table->timestamp('last_exit')->nullable(); + $table->integer('point_number_sent')->nullable(); + $table->smallInteger('fms_result_code')->nullable(); + $table->string('fms_result_message')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('missions', function (Blueprint $table) { + $table->dropColumn([ + 'mission_duration', 'in_area_duration', + 'first_enter', 'last_exit', 'point_number_sent', + 'fms_result_code', 'fms_result_message', + ]); + }); + } +}; diff --git a/resources/views/v3/Reports/Damage/DamageCartableReport.blade.php b/resources/views/v3/Reports/Damage/DamageCartableReport.blade.php new file mode 100644 index 00000000..0219c627 --- /dev/null +++ b/resources/views/v3/Reports/Damage/DamageCartableReport.blade.php @@ -0,0 +1,77 @@ + + + + + + + + مدریت سامانه + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @foreach ($data as $item) + + + + + + + + + @endforeach + +
+ تاریخ دریافت گزارش: {{ verta()->now()->format('Y/m/d H:i') }} +
+
+ آیتم خسارت وارده بر ابنیه فنی +
کد + یکتا + عنوان + واحد + فی(ریال) + وضعیت + بروزرسانی
{{ $item['id'] ?? '-' }}{{ $item['title'] ?? '-' }}{{ $item['unit'] ?? '-' }}{{ $item['base_price'] ?? '-' }}{{ $item['status'] ?? '-' }}{{ $item['update_time'] ?? '-' }}
+ + + diff --git a/resources/views/v3/Reports/RoadObservation/CountryReport.blade.php b/resources/views/v3/Reports/RoadObservation/CountryReport.blade.php new file mode 100644 index 00000000..55ee1ea9 --- /dev/null +++ b/resources/views/v3/Reports/RoadObservation/CountryReport.blade.php @@ -0,0 +1,68 @@ + + + + + + + + گزارش واکنش سریع + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @foreach ($data as $item) + + + + + + + + + + + @endforeach + +
+ تاریخ دریافت گزارش: {{ verta()->now()->format('Y/m/d H:i') }} +
+
+ گزارش رسیدگی به شکایات واکنش سریع +
کد یکتاجمع کلرسیدگی نشدهاقدام شده اقدام نشده درحال بررسیتائید شدهعدم تائید
{{ $item['id'] ?? '-' }}{{ $item['total'] ?? '-' }}{{ $item['resideginaShode'] ?? '-' }}{{ $item['egdamshode'] ?? '-' }}{{ $item['egdamnashodeh'] ?? '-' }}{{ $item['darhalbarasi'] ?? '-' }}{{ $item['taayidshode'] ?? '-' }}{{ $item['adamtaayid'] ?? '-' }}
+ + diff --git a/resources/views/v3/Reports/RoadObservation/ProvinceReport.blade.php b/resources/views/v3/Reports/RoadObservation/ProvinceReport.blade.php new file mode 100644 index 00000000..a8eb7e03 --- /dev/null +++ b/resources/views/v3/Reports/RoadObservation/ProvinceReport.blade.php @@ -0,0 +1,68 @@ + + + + + + + + گزارش واکنش سریع + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @foreach ($data as $item) + + + + + + + + + + + @endforeach + +
+ تاریخ دریافت گزارش: {{ verta()->now()->format('Y/m/d H:i') }} +
+
+ گزارش رسیدگی به شکایات واکنش سریع +
کد یکتاجمع کلرسیدگی نشدهاقدام شده اقدام نشده درحال بررسیتائید شدهعدم تائید
{{ $item['id'] ?? '-' }}{{ $item['total'] ?? '-' }}{{ $item['resideginaShode'] ?? '-' }}{{ $item['egdamshode'] ?? '-' }}{{ $item['egdamnashodeh'] ?? '-' }}{{ $item['darhalbarasi'] ?? '-' }}{{ $item['taayidshode'] ?? '-' }}{{ $item['adamtaayid'] ?? '-' }}
+ + diff --git a/routes/v3.php b/routes/v3.php index 8a0bebed..37496c5c 100644 --- a/routes/v3.php +++ b/routes/v3.php @@ -270,6 +270,7 @@ Route::prefix('damages') Route::get('/', 'index')->name('index'); Route::get('/list', 'list')->name('list')->withoutMiddleware('permission:manage-damage'); Route::post('/', 'store')->name('store'); + Route::get('/excel', 'excel')->name('excel'); Route::get('/{damage}', 'show')->name('show'); Route::post('/{damage}', 'update')->name('update'); Route::post('/activate/{damage}', 'activate')->name('activate'); @@ -350,6 +351,10 @@ Route::prefix('road_observations') Route::get('/index', 'index')->name('index')->middleware('permission:show-fast-react-province|show-fast-react'); Route::get('/excel', 'excel')->name('excel')->middleware('permission:show-fast-react-province|show-fast-react'); Route::get('/map', 'map')->name('map'); + Route::get('/country_activity', 'countryActivity')->name('countryActivity'); + Route::get('/province_activity', 'provinceActivity')->name('provinceActivity'); + Route::get('/country_activity_excels', 'countryActivityExcel')->name('countryExcelActivity'); + Route::get('/province_activity_excel', 'provinceActivityExcel')->name('provinceExcelActivity'); }); }); @@ -483,6 +488,7 @@ Route::prefix('missions') Route::get('/', 'index')->name('index'); Route::post('/', 'store')->name('store'); Route::post('/no_process','noProcess')->name('noProcess'); + Route::post('/continue','continueMission')->name('continueMission'); Route::get('/{mission}', 'show')->name('show'); Route::post('/{mission}', 'update')->name('update'); Route::delete('/{mission}', 'destroy')->name('destroy'); @@ -568,7 +574,7 @@ Route::prefix('harim') ->group(function () { Route::post('/receive_new_request', 'receiveNewRequest')->name('receiveNewRequest'); Route::post('/receive_access_road','getAccessRoad')->name('getAccessRoad'); - Route::post('/get_reject_request','getRejectRequest')->name('getRejectRequest'); + Route::post('/get_status_request','getRejectRequest')->name('getRejectRequest'); Route::post('/get_final_polygons','getFinalPolygons')->name('getFinalPolygons'); }); });