diff --git a/app/Http/Controllers/Admin/ActivityLogController.php b/app/Http/Controllers/Admin/ActivityLogController.php
new file mode 100644
index 0000000..1c47d6e
--- /dev/null
+++ b/app/Http/Controllers/Admin/ActivityLogController.php
@@ -0,0 +1,23 @@
+with('causer')
+ ->when($request->filled('log_name'), function ($query) use ($request) {
+ $query->where('log_name', $request->input('log_name'));
+ })
+ ->latest('created_at')
+ ->paginate(20);
+
+ return view('admin.activity-logs.index', compact('logs'));
+ }
+}
diff --git a/app/Http/Controllers/Admin/FlightController.php b/app/Http/Controllers/Admin/FlightController.php
index 3d03c87..94f32de 100644
--- a/app/Http/Controllers/Admin/FlightController.php
+++ b/app/Http/Controllers/Admin/FlightController.php
@@ -169,7 +169,7 @@ class FlightController extends Controller
$fileId = $uploadedFile->id;
}
- Flight::create([
+ $flight = Flight::create([
'title' => $request->input('title'),
'file_id' => $fileId,
'airline_id' => $request->input('airline_id'),
@@ -183,8 +183,12 @@ class FlightController extends Controller
'views' => 0,
'description' => $request->input('description'),
'status' => $request->input('status'),
+ 'created_by' => auth('admin')->id(),
+ 'updated_by' => auth('admin')->id(),
]);
+ logActivity('flights', $flight->id, 'created');
+
DB::commit();
} catch (\Exception $exception) {
@@ -227,6 +231,12 @@ class FlightController extends Controller
public function update(Request $request, Flight $flight)
{
+ $before = $flight->only([
+ 'title', 'airline_id', 'flight_type', 'departure_time',
+ 'departure_airport_id', 'arrival_airport_id', 'price',
+ 'summary', 'capacity', 'description', 'status',
+ ]);
+
$request->validate([
'title' => [
'required',
@@ -327,6 +337,12 @@ class FlightController extends Controller
'capacity' => $request->input('capacity'),
'description' => $request->input('description'),
'status' => $request->input('status'),
+ 'updated_by' => auth('admin')->id(),
+ ]);
+
+ logActivity('flights', $flight->id, 'updated', [
+ 'before' => $before,
+ 'after' => $flight->only(array_keys($before)),
]);
DB::commit();
@@ -357,6 +373,7 @@ class FlightController extends Controller
]);
}
+ logActivity('flights', $flight->id, 'deleted');
$flight->delete();
return redirect()->route('admin.flights.index')->withErrors([
diff --git a/app/Http/Controllers/Admin/TourController.php b/app/Http/Controllers/Admin/TourController.php
index f6cd011..15b704c 100644
--- a/app/Http/Controllers/Admin/TourController.php
+++ b/app/Http/Controllers/Admin/TourController.php
@@ -107,28 +107,24 @@ class TourController extends Controller
$fileId = $uploadedFile->id;
}
- Tour::create([
+ $tour = Tour::create([
'title' => $request->input('title'),
-
'summary' => $request->input('summary'),
-
'description' => $request->input('description'),
-
'origin' => $request->input('origin'),
-
'destination' => $request->input('destination'),
-
'file_id' => $fileId,
-
'duration' => $request->input('duration'),
-
'departure_time' => $request->input('departure_time'),
-
'price' => $request->input('price'),
-
'status' => $request->input('status'),
+ 'created_by' => auth('admin')->id(),
+ 'updated_by' => auth('admin')->id(),
]);
+ logActivity('tours', $tour->id, 'created');
+
+
DB::commit();
} catch (\Exception $exception) {
@@ -160,9 +156,16 @@ class TourController extends Controller
}
- public function update(tourUpdateRequest $request, Tour $tour) {
+ public function update(tourUpdateRequest $request, Tour $tour)
+ {
try {
+ $before = $tour->only([
+ 'title', 'summary', 'description', 'origin',
+ 'destination', 'file_id', 'duration', 'price',
+ 'departure_time', 'status',
+ ]);
+
DB::beginTransaction();
$fileId = $tour->file_id;
@@ -193,26 +196,21 @@ class TourController extends Controller
$tour->update([
'title' => $request->input('title'),
-
'summary' => $request->input('summary'),
-
'description' => $request->input('description'),
-
'origin' => $request->input('origin'),
-
'destination' => $request->input('destination'),
-
'file_id' => $fileId,
-
'duration' => $request->input('duration'),
-
- 'views' => 0,
-
'departure_time' => $request->input('departure_time'),
-
'price' => $request->input('price'),
-
'status' => $request->input('status'),
+ 'updated_by' => auth('admin')->id(),
+ ]);
+
+ logActivity('tours', $tour->id, 'updated', [
+ 'before' => $before,
+ 'after' => $tour->only(array_keys($before)),
]);
DB::commit();
@@ -237,15 +235,16 @@ class TourController extends Controller
]);
}
-
public function destroy(Tour $tour)
{
+ if ($tour->bookings()->exists()) {
+ return back()->withErrors(['error' => 'این پرواز دارای رزرو است و قابل حذف نیست.']);
+ }
+
+ logActivity('flights', $tour->id, 'deleted');
+
$tour->delete();
- return redirect()
- ->route('admin.tours.index')
- ->withErrors([
- 'success' => 'تور با موفقیت حذف شد'
- ]);
+ return redirect()->route('admin.flights.index')->withErrors(['success'=> 'پرواز با موفقیت حذف شد']);
}
}
diff --git a/app/Http/Controllers/FlightController.php b/app/Http/Controllers/FlightController.php
index 4612bce..8d8b33f 100644
--- a/app/Http/Controllers/FlightController.php
+++ b/app/Http/Controllers/FlightController.php
@@ -49,7 +49,7 @@ class FlightController extends Controller
public function show(Flight $flight)
{
- abort_if($flight->status !== FlightStatus::ENABLE->value, 404);
+ abort_if($flight->status !== FlightStatus::ENABLE, 404);
$flight->increment('views');
diff --git a/app/Http/Controllers/TourController.php b/app/Http/Controllers/TourController.php
index 90b5293..e3ce53a 100644
--- a/app/Http/Controllers/TourController.php
+++ b/app/Http/Controllers/TourController.php
@@ -23,7 +23,7 @@ class TourController extends Controller
public function show(Tour $tour)
{
- abort_if($tour->status !== TourStatus::ENABLE->value, 404);
+ abort_if($tour->status !== TourStatus::ENABLE, 404);
$tour->increment('views');
diff --git a/app/Models/ActivityLog.php b/app/Models/ActivityLog.php
new file mode 100644
index 0000000..9fa8883
--- /dev/null
+++ b/app/Models/ActivityLog.php
@@ -0,0 +1,37 @@
+ 'array',
+ 'created_at' => 'datetime',
+ ];
+
+ protected static function boot()
+ {
+ parent::boot();
+
+ static::creating(function ($log) {
+ $log->created_at = now();
+ });
+ }
+
+ public function causer()
+ {
+ return $this->belongsTo(Admin::class, 'causer_id');
+ }
+}
diff --git a/app/Models/File.php b/app/Models/File.php
index 859477f..3ebe9f4 100644
--- a/app/Models/File.php
+++ b/app/Models/File.php
@@ -36,12 +36,14 @@ class File extends Model
];
protected $fillable = [
- 'name',
- 'extension',
- 'size',
- 'original_name',
- 'path'
- ];
+ 'name',
+ 'extension',
+ 'size',
+ 'original_name',
+ 'path',
+ 'created_by',
+ 'updated_by'
+ ];
public function flights()
{
diff --git a/app/Models/Flight.php b/app/Models/Flight.php
index 269c549..608cc55 100644
--- a/app/Models/Flight.php
+++ b/app/Models/Flight.php
@@ -41,64 +41,73 @@ use Illuminate\Database\Eloquent\Model;
*/
class Flight extends Model
{
- protected $table = 'flights';
+ protected $table = 'flights';
- protected $casts = [
- 'file_id' => 'int',
- 'airline_id' => 'int',
- 'flight_type' => 'int',
- 'departure_time' => 'datetime',
- 'departure_airport_id' => 'int',
- 'arrival_airport_id' => 'int',
- 'price' => 'float',
- 'capacity' => 'int',
+ protected $casts = [
+ 'file_id' => 'int',
+ 'airline_id' => 'int',
+ 'flight_type' => 'int',
+ 'departure_time' => 'datetime',
+ 'departure_airport_id' => 'int',
+ 'arrival_airport_id' => 'int',
+ 'price' => 'float',
+ 'capacity' => 'int',
'views' => 'int',
'status' => FlightStatus::class
];
- protected $fillable = [
- 'title',
- 'file_id',
- 'airline_id',
- 'flight_type',
- 'departure_time',
- 'departure_airport_id',
- 'arrival_airport_id',
- 'price',
- 'summary',
- 'capacity',
- 'description',
+ protected $fillable = [
+ 'title',
+ 'file_id',
+ 'airline_id',
+ 'flight_type',
+ 'departure_time',
+ 'departure_airport_id',
+ 'arrival_airport_id',
+ 'price',
+ 'summary',
+ 'capacity',
+ 'description',
'views',
- 'status'
- ];
+ 'status',
+ 'created_by',
+ 'updated_by',
+ ];
- public function airline()
- {
- return $this->belongsTo(Airline::class);
- }
+ protected $hidden = [
+ 'created_by',
+ 'updated_by',
+ ];
+ public function airline()
+ {
+ return $this->belongsTo(Airline::class);
+ }
- public function file()
- {
- return $this->belongsTo(File::class);
- }
+ public function file()
+ {
+ return $this->belongsTo(File::class);
+ }
- public function airport()
- {
- return $this->belongsTo(Airport::class, 'departure_airport_id');
- }
+ public function airport()
+ {
+ return $this->belongsTo(Airport::class, 'departure_airport_id');
+ }
+
+ public function bookings()
+ {
+ return $this->hasMany(Booking::class);
+ }
- public function bookings()
- {
- return $this->hasMany(Booking::class);
- }
public function arrivalAirport()
{
return $this->belongsTo(Airport::class, 'arrival_airport_id');
}
+
public function departureAirport()
{
return $this->belongsTo(Airport::class, 'departure_airport_id');
}
+
public function comments()
{
return $this->hasMany(Comment::class, 'flight_id');
@@ -113,4 +122,14 @@ class Flight extends Model
$query->where('flight_type', $request->input('flight_type'));
}
}
+
+ public function creator()
+ {
+ return $this->belongsTo(Admin::class, 'created_by');
+ }
+
+ public function updater()
+ {
+ return $this->belongsTo(Admin::class, 'updated_by');
+ }
}
diff --git a/app/Models/Tour.php b/app/Models/Tour.php
index b8a247d..9e17627 100644
--- a/app/Models/Tour.php
+++ b/app/Models/Tour.php
@@ -35,6 +35,8 @@ class Tour extends Model
'departure_time',
'status',
'created_at',
+ 'created_by',
+ 'updated_by',
];
public function file()
@@ -51,4 +53,19 @@ class Tour extends Model
{
return $this->hasMany(Comment::class, 'tour_id');
}
+
+ protected $hidden = [
+ 'created_by',
+ 'updated_by',
+ ];
+
+ public function creator()
+ {
+ return $this->belongsTo(Admin::class, 'created_by');
+ }
+
+ public function updater()
+ {
+ return $this->belongsTo(Admin::class, 'updated_by');
+ }
}
diff --git a/app/helpers/helpers.php b/app/helpers/helpers.php
index 05bad26..851c888 100644
--- a/app/helpers/helpers.php
+++ b/app/helpers/helpers.php
@@ -1,4 +1,7 @@
$logName,
+ 'subject_id' => $subjectId,
+ 'causer_id' => auth('admin')->id(),
+ 'event' => $event,
+ 'changes' => $changes,
+ ]);
+ }
+ }
}
diff --git a/config/database.php b/config/database.php
index 64709ce..9c6eda5 100644
--- a/config/database.php
+++ b/config/database.php
@@ -139,7 +139,7 @@ return [
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer body of commands than a typical key-value system
- | such as Memcached. You may define your connection settings here.
+ | such as Memcached. You may define your connection activity-logs here.
|
*/
diff --git a/public/assets/admin/css/styles.css b/public/assets/admin/css/styles.css
index 1aa50ea..28b22ee 100644
--- a/public/assets/admin/css/styles.css
+++ b/public/assets/admin/css/styles.css
@@ -24828,7 +24828,7 @@ ul.files-main-nav li div.filemanager-upgrade-storage img {
}
/* End:: mail-app */
-/* Start:: mail-settings */
+/* Start:: mail-activity-logs */
.mail-notification-settings, .mail-security-settings {
width: 60%;
}
@@ -24896,7 +24896,7 @@ ul.files-main-nav li div.filemanager-upgrade-storage img {
}
}
-/* End:: mail-settings */
+/* End:: mail-activity-logs */
/* Start:: task */
/* Start::task-kanboard-board */
.Meno-kanban-board {
diff --git a/resources/views/admin/activity-logs/index.blade.php b/resources/views/admin/activity-logs/index.blade.php
index eb1612b..f05e422 100644
--- a/resources/views/admin/activity-logs/index.blade.php
+++ b/resources/views/admin/activity-logs/index.blade.php
@@ -1,3 +1,107 @@
@extends('admin.layouts.app')
-@section('breadcrumb')
لاگ تغییرات
ثبت چه کسی، چه زمانی و چه تغییری روی اطلاعات پرواز و تور@endsection
-@section('content')| مدیر | بخش | عملیات | شرح تغییر | تاریخ |
@forelse(($logs ?? []) as $log)| {{ $log->admin->first_name ?? '-' }} {{ $log->admin->last_name ?? '' }} | {{ $log->subject_type ?? '-' }} | {{ $log->action ?? '-' }} | {{ $log->description ?? '-' }} | {{ isset($log->created_at) ? $log->created_at->toJalali()->format('Y/m/d H:i') : '-' }} |
@empty| لاگی برای نمایش وجود ندارد. |
@endforelse
{{ ($logs ?? collect())->links() }}
@endsection
+
+@section('content')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | کاربر |
+ عملیات |
+ مربوط به |
+ تغییرات |
+ زمان |
+
+
+
+ @forelse($logs as $log)
+
+ |
+ {{ optional($log->causer)->first_name ?? 'نامشخص' }}
+ |
+
+
+ @switch($log->event)
+ @case('created')
+ ایجاد
+ @break
+
+ @case('updated')
+ ویرایش
+ @break
+
+ @case('deleted')
+ حذف
+ @break
+
+ @default
+ {{ $log->event }}
+ @endswitch
+ |
+
+
+ {{ $log->log_name === 'flights' ? 'پرواز' : 'تور' }}
+ #{{ $log->subject_id }}
+ |
+
+
+ @if($log->event === 'updated' && $log->changes)
+
+ @foreach($log->changes['after'] as $field => $newValue)
+ @if(($log->changes['before'][$field] ?? null) != $newValue)
+ -
+ {{ $field }}:
+ «{{ $log->changes['before'][$field] ?? '—' }}»
+ ←
+ «{{ $newValue }}»
+
+ @endif
+ @endforeach
+
+ @elseif($log->event === 'created')
+ ایجاد رکورد جدید
+ @else
+ حذف رکورد
+ @endif
+ |
+
+
+ {{ verta($log->created_at)->format('Y/m/d H:i') }}
+ |
+
+ @empty
+
+ |
+ لاگی ثبت نشده است
+ |
+
+ @endforelse
+
+
+
+
+ {{ $logs->links() }}
+
+
+
+
+
+
+
+
+
+@endsection
diff --git a/resources/views/admin/products/create.blade.php b/resources/views/admin/products/create.blade.php
deleted file mode 100644
index 609db57..0000000
--- a/resources/views/admin/products/create.blade.php
+++ /dev/null
@@ -1,141 +0,0 @@
-@extends('admin.layouts.app')
-
-@section('content')
-
-@endsection