File manager - Edit - /var/www/html/portal/app/Models/IndicadoresTi/Chamado.php
Back
<?php namespace App\Models\IndicadoresTi; use App\Models\UnidadeOrganizacional; use App\Models\User; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; class Chamado extends Model { protected $table = 'chamados_ti'; public const STATUS = [ 'em_andamento' => 'Em Andamento', 'pendente' => 'Pendente', 'atendido' => 'Atendido', 'cancelado' => 'Cancelado / Finalizado', ]; public const PRIORIDADE = [ 'baixa' => 'Baixa', 'media' => 'Média', 'alta' => 'Alta', 'critica' => 'Crítica', ]; public const TIPO = [ 'incidente' => 'Incidente', 'requisicao' => 'Requisição', 'problema' => 'Problema', 'melhoria' => 'Melhoria', 'help_desk' => 'Help Desk', ]; public const CANAL = [ 'portal' => 'Portal', 'telefone' => 'Telefone', 'email' => 'E-mail', 'presencial' => 'Presencial', ]; protected $fillable = [ 'numero', 'data_abertura', 'data_fechamento', 'data_reabertura', 'tempo_atendimento', 'tempo_acumulado', 'descricao', 'setor_id', 'setor_nome', 'assunto_id', 'assunto_nome', 'subassunto_id', 'subassunto_nome', 'cliente_id', 'user_id', 'atendente_id', 'status', 'prioridade', 'tipo', 'canal', 'unidade_organizacional_id', ]; protected $casts = [ 'data_abertura' => 'datetime', 'data_fechamento' => 'datetime', 'data_reabertura' => 'datetime', ]; // ========================= // RELACIONAMENTOS // ========================= public function setor(): BelongsTo { return $this->belongsTo(Setor::class); } public function assunto(): BelongsTo { return $this->belongsTo(Assunto::class); } public function subassunto(): BelongsTo { return $this->belongsTo(Subassunto::class); } public function cliente(): BelongsTo { return $this->belongsTo(Cliente::class); } // 👇 Usuário que abriu o chamado public function solicitante(): BelongsTo { return $this->belongsTo(User::class, 'user_id'); } // 👇 Usuário que atende o chamado public function atendente(): BelongsTo { return $this->belongsTo(User::class, 'atendente_id'); } public function unidade(): BelongsTo { return $this->belongsTo(UnidadeOrganizacional::class, 'unidade_organizacional_id'); } public function participantes(): BelongsToMany { return $this->belongsToMany(User::class, 'chamado_participantes_ti', 'chamado_id', 'user_id') ->withTimestamps(); } public function logs(): HasMany { return $this->hasMany(ChamadoLog::class)->orderBy('created_at', 'asc'); } public function isParticipante(string $userId): bool { return $this->atendente_id === $userId || $this->participantes->contains('id', $userId); } // ========================= // ACCESSORS (INTELIGENTES) // ========================= public function getSolicitanteNomeAttribute(): string { if ($this->user_id && $this->solicitante) { return $this->solicitante->name; } if ($this->cliente) { return $this->cliente->nome; } return '—'; } public function getSolicitanteTipoAttribute(): string { if ($this->user_id) { return 'usuario'; } if ($this->cliente_id) { return 'cliente'; } return 'desconhecido'; } // ========================= // LÓGICA DE NEGÓCIO // ========================= public static function gerarNumero(): string { $year = now()->year; $ultimoId = (int) static::max('id') + 1; return sprintf('CHM-%d-%05d', $year, $ultimoId); } public function atualizarTempoAtendimento(): void { if (!$this->data_abertura || !$this->data_fechamento) { return; } // Início do período atual: reopen date if exists, otherwise original opening $inicio = Carbon::parse($this->data_reabertura ?? $this->data_abertura); $fim = Carbon::parse($this->data_fechamento); $segmentoSegundos = max(0, $inicio->diffInSeconds($fim)); $this->tempo_acumulado = ($this->tempo_acumulado ?? 0) + $segmentoSegundos; $this->tempo_atendimento = (int) ceil($this->tempo_acumulado / 60); } private function totalSegundos(): int { $acumulado = (int) ($this->tempo_acumulado ?? 0); if ($this->data_fechamento) { return $acumulado; } // Open: add seconds since the current period started $inicio = Carbon::parse($this->data_reabertura ?? $this->data_abertura); return $acumulado + max(0, $inicio->diffInSeconds(now())); } public function getTempoAtendimentoFormatado(): string { if (!$this->data_abertura) { return '—'; } $total = $this->totalSegundos(); $d = floor($total / 86400); $h = floor(($total % 86400) / 3600); $m = floor(($total % 3600) / 60); $s = $total % 60; $partes = []; if ($d > 0) $partes[] = $d . 'd'; if ($h > 0) $partes[] = $h . 'h'; if ($m > 0) $partes[] = $m . 'min'; if ($s > 0 || empty($partes)) $partes[] = $s . 's'; return implode(' ', $partes); } public function getTempoAtendimentoDetalhado(): array { if (!$this->data_abertura) { return [ 'dias' => 0, 'horas' => 0, 'minutos' => 0, 'segundos' => 0, 'total_segundos' => 0, 'total_minutos' => 0, 'formatado' => '—', 'em_andamento' => false, ]; } $total = $this->totalSegundos(); $d = floor($total / 86400); $h = floor(($total % 86400) / 3600); $m = floor(($total % 3600) / 60); $s = $total % 60; return [ 'dias' => $d, 'horas' => $h, 'minutos' => $m, 'segundos' => $s, 'total_segundos' => $total, 'total_minutos' => (int) ceil($total / 60), 'formatado' => $this->getTempoAtendimentoFormatado(), 'em_andamento' => is_null($this->data_fechamento), ]; } public function isEmAndamento(): bool { return in_array($this->status, ['pendente', 'em_andamento']); } public function getTempoAtendimentoLegivelAttribute(): string { if (!$this->tempo_atendimento) { return '—'; } $minutos = $this->tempo_atendimento; $dias = floor($minutos / 1440); $horas = floor(($minutos % 1440) / 60); $mins = $minutos % 60; $partes = []; if ($dias > 0) $partes[] = $dias . 'd'; if ($horas > 0) $partes[] = $horas . 'h'; if ($mins > 0 || empty($partes)) $partes[] = $mins . 'min'; return implode(' ', $partes); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.07 |
proxy
|
phpinfo
|
Settings