feat: isola as configuracoes de IA em tabela especifica configuracoes_ia no PostgreSQL, removendo-as do JSON de school_data
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 2m24s Details

This commit is contained in:
Sidney 2026-07-17 22:28:33 -03:00
parent 25377a9bc7
commit 3a953a7e41
1 changed files with 103 additions and 1 deletions

View File

@ -22,6 +22,48 @@ pool.on('error', (err) => {
console.error('[PostgreSQL] Erro inesperado no pool:', err);
});
// Inicializar a tabela configuracoes_ia se não existir
export async function verificarEInicializarTabelaIA() {
const client = await pool.connect();
try {
await client.query(`
CREATE TABLE IF NOT EXISTS configuracoes_ia (
id INT PRIMARY KEY DEFAULT 1,
active_provider VARCHAR(50) DEFAULT 'gemini',
gemini_key TEXT,
openai_key TEXT,
claude_key TEXT,
openrouter_key TEXT,
gemini_model VARCHAR(100) DEFAULT 'gemini-1.5-flash',
openai_model VARCHAR(100) DEFAULT 'gpt-4o-mini',
claude_model VARCHAR(100) DEFAULT 'claude-3-5-sonnet-20241022',
openrouter_model VARCHAR(100) DEFAULT 'google/gemini-2.5-flash',
active_image_provider VARCHAR(50) DEFAULT 'gemini',
openai_image_model VARCHAR(100) DEFAULT 'dall-e-3',
gemini_image_model VARCHAR(100) DEFAULT 'imagen-3.0-generate-002',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT single_row CHECK (id = 1)
)
`);
await client.query(`
INSERT INTO configuracoes_ia (id)
VALUES (1)
ON CONFLICT (id) DO NOTHING
`);
} catch (err) {
console.error('[PostgreSQL] Erro ao inicializar configuracoes_ia:', err.message);
} finally {
client.release();
}
}
// Chamar inicialização
verificarEInicializarTabelaIA().catch(err => {
console.error('[PostgreSQL] Erro na inicialização da tabela de IA:', err);
});
// ============================================================
// HELPER: Buscar school_data JSON blob (compatibilidade legada)
// ============================================================
@ -29,7 +71,32 @@ export async function getSchoolData() {
const { rows } = await pool.query(
'SELECT data FROM school_data WHERE id = 1'
);
return rows[0]?.data || {};
const data = rows[0]?.data || {};
try {
const aiRes = await pool.query('SELECT * FROM configuracoes_ia WHERE id = 1');
if (aiRes.rows[0]) {
const dbConfig = aiRes.rows[0];
data.aiConfig = {
activeProvider: dbConfig.active_provider,
geminiKey: dbConfig.gemini_key || '',
openaiKey: dbConfig.openai_key || '',
claudeKey: dbConfig.claude_key || '',
openrouterKey: dbConfig.openrouter_key || '',
geminiModel: dbConfig.gemini_model || 'gemini-1.5-flash',
openaiModel: dbConfig.openai_model || 'gpt-4o-mini',
claudeModel: dbConfig.claude_model || 'claude-3-5-sonnet-20241022',
openrouterModel: dbConfig.openrouter_model || 'google/gemini-2.5-flash',
activeImageProvider: dbConfig.active_image_provider || 'gemini',
openaiImageModel: dbConfig.openai_image_model || 'dall-e-3',
geminiImageModel: dbConfig.gemini_image_model || 'imagen-3.0-generate-002'
};
}
} catch (err) {
console.warn('[Database] Erro ao mesclar configuracoes_ia no school_data:', err.message);
}
return data;
}
/**
@ -126,6 +193,41 @@ export async function saveSchoolData(data) {
// Aplicar fechamento de pauta automático antes de salvar
const dataWithAbsences = await processAutoAbsences(data);
if (dataWithAbsences.aiConfig) {
const c = dataWithAbsences.aiConfig;
try {
await pool.query(
`INSERT INTO configuracoes_ia
(id, active_provider, gemini_key, openai_key, claude_key, openrouter_key,
gemini_model, openai_model, claude_model, openrouter_model,
active_image_provider, openai_image_model, gemini_image_model, updated_at)
VALUES (1, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, NOW())
ON CONFLICT (id) DO UPDATE SET
active_provider = EXCLUDED.active_provider,
gemini_key = EXCLUDED.gemini_key,
openai_key = EXCLUDED.openai_key,
claude_key = EXCLUDED.claude_key,
openrouter_key = EXCLUDED.openrouter_key,
gemini_model = EXCLUDED.gemini_model,
openai_model = EXCLUDED.openai_model,
claude_model = EXCLUDED.claude_model,
openrouter_model = EXCLUDED.openrouter_model,
active_image_provider = EXCLUDED.active_image_provider,
openai_image_model = EXCLUDED.openai_image_model,
gemini_image_model = EXCLUDED.gemini_image_model,
updated_at = NOW()`,
[
c.activeProvider, c.geminiKey || '', c.openaiKey || '', c.claudeKey || '', c.openrouterKey || '',
c.geminiModel, c.openaiModel, c.claudeModel, c.openrouterModel,
c.activeImageProvider, c.openaiImageModel, c.geminiImageModel
]
);
} catch (err) {
console.error('[Database] Erro ao salvar na tabela configuracoes_ia:', err.message);
}
delete dataWithAbsences.aiConfig;
}
await pool.query(
`INSERT INTO school_data (id, data, updated_at)
VALUES (1, $1, NOW())