[['id'=>1,'name'=>'Administrador','email'=>'admin@local','password'=>password_hash('admin123', PASSWORD_DEFAULT)]], 'clients'=>[], 'equipment'=>[], 'orders'=>[], 'history'=>[], 'next'=>['client'=>1,'equipment'=>1,'order'=>1000,'history'=>1]];
file_put_contents(DATA_FILE, json_encode($seed, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
$data = json_decode((string)file_get_contents(DATA_FILE), true) ?: [];
// Mantém a nova sequência mesmo em instalações que já tenham o arquivo criado.
if (($data['next']['order'] ?? 0) < 1000) $data['next']['order'] = 1000;
return $data;
}
function saveData(array $data): void { file_put_contents(DATA_FILE, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), LOCK_EX); }
function find(array $rows, int $id): ?array { foreach ($rows as $row) if ((int)$row['id'] === $id) return $row; return null; }
function statusClass(string $status): string { return ['Aberta'=>'blue','Em andamento'=>'yellow','Aguardando peça'=>'purple','Concluída'=>'green','Cancelada'=>'red'][$status] ?? 'gray'; }
function layout(string $title, string $content, bool $public = false): void {
$flash = flash(); $active = $_GET['page'] ?? 'dashboard';
?>
=e($title)?> · InfoByte CWB= $flash ? ''.e($flash).'
' : '' ?>= $content ?>= $flash ? ''.e($flash).'
' : '' ?>= $content ?> $id?:$data['next']['client']++,'name'=>trim($_POST['name']),'cpf'=>cpf($_POST['cpf']),'phone'=>trim($_POST['phone']),'email'=>trim($_POST['email']),'address'=>trim($_POST['address'])]; if (!$item['name']||strlen($item['cpf'])!==11){flash('Informe nome e CPF válido.');go('?page=clients');} $found=false; foreach($data['clients'] as &$r)if($r['id']===$item['id']){$r=$item;$found=true;}unset($r);if(!$found)$data['clients'][]=$item;saveData($data);flash('Cliente salvo com sucesso.');go('?page=clients'); }
if ($action === 'save-equipment') { requireLogin(); $id=(int)($_POST['id']??0); $item=['id'=>$id?:$data['next']['equipment']++,'client_id'=>(int)$_POST['client_id'],'type'=>trim($_POST['type']),'brand'=>trim($_POST['brand']),'model'=>trim($_POST['model']),'serial'=>trim($_POST['serial']),'notes'=>trim($_POST['notes'])];$found=false;foreach($data['equipment'] as &$r)if($r['id']===$item['id']){$r=$item;$found=true;}unset($r);if(!$found)$data['equipment'][]=$item;saveData($data);flash('Equipamento salvo com sucesso.');$return=$_POST['return']??'';if($return==='order-form')go('?page=order-form&equipment_id='.$item['id'].'&client_id='.$item['client_id']);go('?page=equipment'); }
if ($action === 'save-order') { requireLogin(); $id=(int)($_POST['id']??0); $old=find($data['orders'],$id); $item=['id'=>$id?:$data['next']['order']++,'client_id'=>(int)$_POST['client_id'],'equipment_id'=>(int)$_POST['equipment_id'],'status'=>$_POST['status'],'priority'=>$_POST['priority'],'technician'=>trim($_POST['technician']),'defect'=>trim($_POST['defect']),'diagnosis'=>trim($_POST['diagnosis']),'service'=>trim($_POST['service']),'parts'=>trim($_POST['parts']),'value'=>(float)str_replace(',','.',$_POST['value']),'warranty'=>trim($_POST['warranty']),'created_at'=>$old['created_at']??date('Y-m-d H:i:s'),'updated_at'=>date('Y-m-d H:i:s')];$found=false;foreach($data['orders'] as &$r)if($r['id']===$item['id']){$r=$item;$found=true;}unset($r);if(!$found)$data['orders'][]=$item;$data['history'][]=['id'=>$data['next']['history']++,'order_id'=>$item['id'],'status'=>$item['status'],'note'=>$old?'Ordem atualizada.':'Ordem criada.','at'=>date('Y-m-d H:i:s')];saveData($data);flash('Ordem de serviço salva.');go('?page=orders'); }
}
if ($action === 'delete-client' || $action === 'delete-equipment') { requireLogin(); $key=$action==='delete-client'?'clients':'equipment';$id=(int)$_GET['id'];$data[$key]=array_values(array_filter($data[$key],fn($r)=>(int)$r['id']!==$id));saveData($data);flash('Registro removido.');go('?page='.($key==='clients'?'clients':'equipment')); }
if ($page === 'login') { if(logged())go('?page=dashboard'); ob_start(); ?>
OFICINA OS
Acesse sua conta
Gestão de ordens de serviço
Primeiro acesso: admin@local / admin123
InfoByte CWB
Acompanhe seu serviço
Informe seu CPF para consultar seus equipamentos e os detalhes das ordens de serviço.
Nenhum cadastro encontrado para este CPF.
=e($clientFound['name'])?>
CPF
=e($clientFound['cpf'])?>
Telefone
=e($clientFound['phone']?:'Não informado')?>
E-mail
=e($clientFound['email']?:'Não informado')?>
Endereço
=e($clientFound['address']?:'Não informado')?>
Nenhuma ordem de serviço encontrada para este cliente.
Ordem de serviço #=$o['id']?>
Aberta em =dateBR($o['created_at'])?> · Atualizada em =dateBR($o['updated_at'])?>=e($o['status'])?>Equipamento
=e(trim(($eq['type']??'').' '.($eq['brand']??'').' '.($eq['model']??'')))?>
Nº de série: =e($eq['serial']??'Não informado')?>
Atendimento
Técnico: =e($o['technician']?:'Não definido')?>
Prioridade: =e($o['priority'])?>
Valor: =money((float)$o['value'])?>
Defeito relatado
=nl2br(e($o['defect']?:'Não informado'))?>
Diagnóstico técnico
=nl2br(e($o['diagnosis']?:'Em análise'))?>
Serviço executado
=nl2br(e($o['service']?:'Em análise'))?>
Peças e garantia
Peças: =nl2br(e($o['parts']?:'Não informado'))?>
Garantia: =e($o['warranty']?:'Não informada')?>
!in_array($o['status'],['Concluída','Cancelada'])));$done=array_filter($data['orders'],fn($o)=>$o['status']==='Concluída');$revenue=array_sum(array_map(fn($o)=>(float)$o['value'],$done));$recent=array_slice(array_reverse($data['orders']),0,6);ob_start();?>
Painel de controle
Visão geral da oficina
+ Nova ordemOrdens cadastradas=$total?>
Concluídas=count($done)?>
Faturamento concluído=money($revenue)?>
Ordens recentes
| OS | Cliente | Serviço | Status | |
|---|
| #=str_pad((string)$o['id'],5,'0',STR_PAD_LEFT)?> | =e($cl['name']??'—')?> | =e($o['service']?:'Em análise')?> | =e($o['status'])?> | Abrir |
| Nenhuma ordem cadastrada. |
=$isClient?'Clientes':'Equipamentos'?>
Cadastre e organize =$isClient?'seus clientes':'os equipamentos recebidos'?>.
+ Novo =$isClient?'cliente':'equipamento'?>=$edit?'Editar':'Novo'?> =$isClient?'cliente':'equipamento'?>
| Nome | CPF | Telefone | E-mail | Equipamento | Cliente | Nº de série | Observações | |
|---|
| =e($r['name'])?> | =e($r['cpf'])?> | =e($r['phone'])?> | =e($r['email'])?> | =e(trim($r['type'].' '.$r['brand'].' '.$r['model']))?> | =e($cl['name']??'—')?> | =e($r['serial'])?> | =e($r['notes'])?> | |
| Nenhum registro encontrado. |
in_array($o['status'],['Concluída','Cancelada']))); if($page==='reports'){$orders=array_values(array_filter($orders,fn($o)=>$o['status']==='Concluída'));}$title=$page==='orders'?'Ordens de serviço':($page==='history'?'Histórico de ordens':'Relatório de serviços executados');ob_start();?>
=$title?>
=$page==='reports'?'Serviços concluídos e faturamento gerado.':($page==='history'?'Consulte as ordens finalizadas ou canceladas.':'Acompanhe todos os atendimentos da oficina.')?>
+ Nova ordem(float)$o['value'],$orders));?>
Serviços executados=count($orders)?>
Valor total=money($sum)?>
| OS | Cliente | Equipamento | Serviço | Status | Valor | Atualização | |
|---|
| #=str_pad((string)$o['id'],5,'0',STR_PAD_LEFT)?> | =e($cl['name']??'—')?> | =e(trim(($eq['type']??'').' '.($eq['brand']??'').' '.($eq['model']??'')))?> | =e($o['service']?:'Em análise')?> | =e($o['status'])?> | =money((float)$o['value'])?> | =dateBR($o['updated_at'])?> | Ver |
| Nenhuma ordem encontrada. |
0,'client_id'=>0,'equipment_id'=>0,'status'=>'Aberta','priority'=>'Normal','technician'=>'','defect'=>'','diagnosis'=>'','service'=>'','parts'=>'','value'=>'','warranty'=>''];ob_start();?>
=$isNew?'Nova ordem de serviço':'OS #'.str_pad((string)$edit['id'],5,'0',STR_PAD_LEFT)?>
Registre o atendimento e o andamento do serviço.
Cliente
=e($cl['name']??'')?>
CPF: =e($cl['cpf']??'')?>
=e($cl['phone']??'')?>
=e($cl['address']??'')?>
Equipamento
=e(trim(($eq['type']??'').' '.($eq['brand']??'').' '.($eq['model']??'')))?>
Nº de série: =e($eq['serial']??'')?>
Entrada: =dateBR($o['created_at'])?>
Técnico: =e($o['technician']?:'Não definido')?>
Defeito relatado
=nl2br(e($o['defect']?:'Não informado'))?>
Diagnóstico técnico
=nl2br(e($o['diagnosis']?:'Não informado'))?>
Serviço =$full?'executado':'previsto'?>
=nl2br(e($o['service']?:'Em análise'))?>
Peças e materiais
=nl2br(e($o['parts']?:'Não informado'))?>
Garantia
=nl2br(e($o['warranty']?:'Não informado'))?>
Valor: =money((float)$o['value'])?>Assinatura do cliente: __________________________