177 lines
4.1 KiB
PHP
Executable File
177 lines
4.1 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Carbon\Carbon;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
class Cita extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $table = 'citas';
|
|
|
|
protected $fillable = [
|
|
'mensaje_id',
|
|
'nombre_cliente',
|
|
'email_cliente',
|
|
'telefono_cliente',
|
|
'servicio',
|
|
'fecha',
|
|
'hora_inicio',
|
|
'hora_fin',
|
|
'duracion',
|
|
'estado',
|
|
'notas',
|
|
];
|
|
|
|
protected $casts = [
|
|
'fecha' => 'date',
|
|
'hora_inicio' => 'datetime:H:i',
|
|
'hora_fin' => 'datetime:H:i',
|
|
'duracion' => 'integer',
|
|
];
|
|
|
|
/**
|
|
* Relación con Mensaje
|
|
*/
|
|
public function mensaje(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Mensaje::class);
|
|
}
|
|
|
|
/**
|
|
* Scope para filtrar citas pendientes
|
|
*/
|
|
public function scopePendiente(Builder $query): Builder
|
|
{
|
|
return $query->where('estado', 'pendiente');
|
|
}
|
|
|
|
/**
|
|
* Scope para filtrar citas confirmadas
|
|
*/
|
|
public function scopeConfirmada(Builder $query): Builder
|
|
{
|
|
return $query->where('estado', 'confirmada');
|
|
}
|
|
|
|
/**
|
|
* Scope para filtrar citas completadas
|
|
*/
|
|
public function scopeCompletada(Builder $query): Builder
|
|
{
|
|
return $query->where('estado', 'completada');
|
|
}
|
|
|
|
/**
|
|
* Scope para filtrar citas canceladas
|
|
*/
|
|
public function scopeCancelada(Builder $query): Builder
|
|
{
|
|
return $query->where('estado', 'cancelada');
|
|
}
|
|
|
|
/**
|
|
* Scope para filtrar citas por fecha específica
|
|
*/
|
|
public function scopePorFecha(Builder $query, $fecha): Builder
|
|
{
|
|
return $query->whereDate('fecha', $fecha);
|
|
}
|
|
|
|
/**
|
|
* Scope para filtrar citas entre dos fechas
|
|
*/
|
|
public function scopeEntreFechas(Builder $query, $inicio, $fin): Builder
|
|
{
|
|
return $query->whereBetween('fecha', [$inicio, $fin]);
|
|
}
|
|
|
|
/**
|
|
* Calcular hora_fin basado en hora_inicio + duracion
|
|
*/
|
|
public function calcularHoraFin(): string
|
|
{
|
|
$horaInicio = Carbon::parse($this->hora_inicio);
|
|
$horaFin = $horaInicio->addMinutes($this->duracion);
|
|
|
|
$this->hora_fin = $horaFin->format('H:i:s');
|
|
|
|
return $this->hora_fin;
|
|
}
|
|
|
|
/**
|
|
* Obtener estado formateado para mostrar
|
|
*/
|
|
public function getEstadoFormateadoAttribute(): string
|
|
{
|
|
$estados = [
|
|
'pendiente' => 'Pendiente',
|
|
'confirmada' => 'Confirmada',
|
|
'completada' => 'Completada',
|
|
'cancelada' => 'Cancelada',
|
|
];
|
|
|
|
return $estados[$this->estado] ?? $this->estado;
|
|
}
|
|
|
|
/**
|
|
* Obtener hora de inicio formateada
|
|
*/
|
|
public function getHoraInicioFormatAttribute(): string
|
|
{
|
|
return Carbon::parse($this->hora_inicio)->format('H:i');
|
|
}
|
|
|
|
/**
|
|
* Obtener hora de fin formateada
|
|
*/
|
|
public function getHoraFinFormatAttribute(): string
|
|
{
|
|
return Carbon::parse($this->hora_fin)->format('H:i');
|
|
}
|
|
|
|
/**
|
|
* Obtener duración formateada (horas y minutos)
|
|
*/
|
|
public function getDuracionFormatAttribute(): string
|
|
{
|
|
$horas = floor($this->duracion / 60);
|
|
$minutos = $this->duracion % 60;
|
|
|
|
if ($horas > 0 && $minutos > 0) {
|
|
return "{$horas}h {$minutos}min";
|
|
} elseif ($horas > 0) {
|
|
return "{$horas}h";
|
|
} else {
|
|
return "{$minutos}min";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verificar si la cita está activa (no cancelada ni completada)
|
|
*/
|
|
public function isActiva(): bool
|
|
{
|
|
return in_array($this->estado, ['pendiente', 'confirmada']);
|
|
}
|
|
|
|
/**
|
|
* Cambiar estado de la cita
|
|
*/
|
|
public function cambiarEstado(string $nuevoEstado): bool
|
|
{
|
|
$estadosValidos = ['pendiente', 'confirmada', 'completada', 'cancelada'];
|
|
|
|
if (! in_array($nuevoEstado, $estadosValidos)) {
|
|
return false;
|
|
}
|
|
|
|
return $this->update(['estado' => $nuevoEstado]);
|
|
}
|
|
}
|