diff --git a/GEMINI.md b/GEMINI.md index 7220c46..5b454ea 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -71,4 +71,6 @@ 42. **Cronological Display Standard**: Consultas a cadastros secundários (como Disciplinas e Categorias) DEVEM utilizar `ORDER BY created_at ASC` no SQL para manter a mesma ordem de listagem original do sistema (evitando reordenação alfabética não-intencional). 43. **Mass Contracts Update**: A edição de um "Modelo de Contrato" dispara atualizações em massa (PUT `/api/contratos/:id`) recalcularizando as variáveis de todos os contratos já emitidos para os alunos vinculados àquele modelo, garantindo atualização em tempo real no Portal do Aluno via SQL. 44. **Biometria SQL-First Parcial**: A biometria (faceDescriptor) já está preparada para persistência nativa na coluna jsonb 'face_descriptor' do PostgreSQL (com mapeamento camelCase na API). Contudo, o cadastro de alunos via Manager ainda não utiliza a API SQL em sua plenitude no handleSave. Até a refatoração do Students.tsx, os alunos novos continuarão dependendo do fallback do school_data.json. +45. **Forçar Fuso Horário Brasileiro na Origem**: Ao gerar datas ou horários locais no frontend para envio ao banco PostgreSQL (como registros de biometria ou ponto), é OBRIGATÓRIO forçar o cálculo no fuso 'America/Sao_Paulo' (ex: \ +ew Date().toLocaleString('en-US', { timeZone: 'America/Sao_Paulo' })\). Isso evita que instâncias rodando em UTC no Windows Server ou celulares com fuso errado enviem horários defasados, o que causaria quebra em lógicas de restrição de janela de tempo (ex: horário de aula). \ No newline at end of file diff --git a/manager/components/AttendanceCapture.tsx b/manager/components/AttendanceCapture.tsx index 6dec72e..8c900d1 100644 --- a/manager/components/AttendanceCapture.tsx +++ b/manager/components/AttendanceCapture.tsx @@ -252,13 +252,17 @@ const AttendanceCapture: React.FC = ({ data, updateData return; } - // Gerar string de data local para o banco de dados - const localDateStr = nowLocal.getFullYear() + '-' + - String(nowLocal.getMonth() + 1).padStart(2, '0') + '-' + - String(nowLocal.getDate()).padStart(2, '0') + 'T' + - String(nowLocal.getHours()).padStart(2, '0') + ':' + - String(nowLocal.getMinutes()).padStart(2, '0') + ':' + - String(nowLocal.getSeconds()).padStart(2, '0'); + // Gerar string de data local forçando o fuso horário de Brasília (America/Sao_Paulo) + // Isso evita que dispositivos em UTC (como o servidor Windows) salvem horários +3 horas + const brtString = new Date().toLocaleString('en-US', { timeZone: 'America/Sao_Paulo' }); + const brtDate = new Date(brtString); + + const localDateStr = brtDate.getFullYear() + '-' + + String(brtDate.getMonth() + 1).padStart(2, '0') + '-' + + String(brtDate.getDate()).padStart(2, '0') + 'T' + + String(brtDate.getHours()).padStart(2, '0') + ':' + + String(brtDate.getMinutes()).padStart(2, '0') + ':' + + String(brtDate.getSeconds()).padStart(2, '0'); // Limpar qualquer falta auto-gerada para o mesmo aluno nesta mesma aula/dia const filteredAttendance = (data.attendance || []).filter(a => { diff --git a/manager/services/database.js b/manager/services/database.js index 86fd13b..385d54d 100644 --- a/manager/services/database.js +++ b/manager/services/database.js @@ -835,7 +835,7 @@ export async function getFrequencias() { classId: r.turma_id, lessonId: r.aula_id, date: r.formatted_data || r.data, - photo: r.foto, + photo: r.foto_url || r.foto, verified: r.verificado, type: r.tipo, justification: r.justificativa,