initial: project state before operator dashboard card redesign
This commit is contained in:
commit
e0aed8eed7
113 files changed
+20074
No files matched your search
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ParkingLot extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'address',
|
||||
'total_capacity',
|
||||
'price_per_hour',
|
||||
'pricing_rules',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'working_hours',
|
||||
'is_active',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'latitude' => 'decimal:8',
|
||||
'longitude' => 'decimal:8',
|
||||
'price_per_hour' => 'decimal:2',
|
||||
'total_capacity' => 'integer',
|
||||
'is_active' => 'boolean',
|
||||
'pricing_rules' => 'array',
|
||||
];
|
||||
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('is_active', true);
|
||||
}
|
||||
|
||||
public function scopeWithStatus($query)
|
||||
{
|
||||
return $query->withCount([
|
||||
'carRegistries as active_registries_count' => function ($q) {
|
||||
$q->active();
|
||||
},
|
||||
'bookings as active_bookings_count' => function ($q) {
|
||||
$q->where('status', 'active');
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
public function bookings(): HasMany
|
||||
{
|
||||
return $this->hasMany(Booking::class);
|
||||
}
|
||||
|
||||
public function carRegistries(): HasMany
|
||||
{
|
||||
return $this->hasMany(CarRegistry::class);
|
||||
}
|
||||
|
||||
public function scopeSearch($query, $search)
|
||||
{
|
||||
return $query->where('name', 'like', "%{$search}%")
|
||||
->orWhere('address', 'like', "%{$search}%");
|
||||
}
|
||||
|
||||
public function getAvailableSpacesAttribute()
|
||||
{
|
||||
$activeBookings = $this->bookings()->where('status', 'active')->count();
|
||||
$activeRegistries = $this->carRegistries()->active()->count();
|
||||
$occupied = $activeBookings + $activeRegistries;
|
||||
return max(0, $this->total_capacity - $occupied);
|
||||
}
|
||||
|
||||
public function getOccupiedSpacesAttribute()
|
||||
{
|
||||
$activeBookings = $this->bookings()->where('status', 'active')->count();
|
||||
$activeRegistries = $this->carRegistries()->active()->count();
|
||||
return $activeBookings + $activeRegistries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate fee and per-day breakdown between two timestamps.
|
||||
* Uses pricing_rules (ISO weekday keys 1–7) if set, otherwise price_per_hour.
|
||||
*
|
||||
* Returns ['total' => float, 'details' => [['day','date','hours','rate','subtotal'], ...]]
|
||||
*/
|
||||
public function calculateFee(Carbon $start, Carbon $end): array
|
||||
{
|
||||
$rules = $this->pricing_rules ?? [];
|
||||
$details = [];
|
||||
$total = 0.0;
|
||||
$cursor = $start->copy()->seconds(0);
|
||||
|
||||
while ($cursor < $end) {
|
||||
$dayEnd = $cursor->copy()->endOfDay()->addSecond();
|
||||
$segEnd = ($dayEnd < $end) ? $dayEnd : $end;
|
||||
|
||||
$dow = (int) $cursor->format('N'); // 1=Mon … 7=Sun
|
||||
$rate = isset($rules[$dow]) ? (float) $rules[$dow] : (float) $this->price_per_hour;
|
||||
$hours = round($cursor->diffInMinutes($segEnd) / 60, 4);
|
||||
$subtotal = $hours * $rate;
|
||||
|
||||
$details[] = [
|
||||
'day' => $this->arabicDayName($dow),
|
||||
'date' => $cursor->format('Y/m/d'),
|
||||
'hours' => round($hours, 2),
|
||||
'rate' => $rate,
|
||||
'subtotal' => round($subtotal, 2),
|
||||
];
|
||||
|
||||
$total += $subtotal;
|
||||
$cursor = $segEnd;
|
||||
}
|
||||
|
||||
return ['total' => (float) number_format(ceil($total), 2, '.', ''), 'details' => $details];
|
||||
}
|
||||
|
||||
private function arabicDayName(int $iso): string
|
||||
{
|
||||
return ['الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت', 'الأحد'][$iso - 1] ?? '';
|
||||
}
|
||||
|
||||
public function getUsagePercentageAttribute()
|
||||
{
|
||||
$occupied = $this->occupied_spaces;
|
||||
return $this->total_capacity > 0 ? round(($occupied / $this->total_capacity) * 100, 2) : 0;
|
||||
}
|
||||
}
|
||||
?>
|
||||
Reference in new issue
Block a user