fix(sync): truncate fields in import-legacy to match column VARCHAR limits
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+78
-2
@@ -728,8 +728,19 @@ app.put('/api/notificacoes/:id/read', async (req, res) => {
|
||||
// --- PACIENTES ---
|
||||
app.get('/api/pacientes', async (req, res) => {
|
||||
try {
|
||||
const { rows } = await pool.query('SELECT * FROM pacientes');
|
||||
res.json(rows);
|
||||
const { q } = req.query;
|
||||
let text, params;
|
||||
if (q && q.trim()) {
|
||||
const term = `%${q.trim().toUpperCase()}%`;
|
||||
text = `SELECT * FROM pacientes WHERE UPPER(nome) LIKE $1 OR cpf LIKE $1 ORDER BY nome LIMIT 100`;
|
||||
params = [term];
|
||||
} else {
|
||||
text = `SELECT * FROM pacientes ORDER BY nome LIMIT 50`;
|
||||
params = [];
|
||||
}
|
||||
const { rows } = await pool.query(text, params);
|
||||
const { rows: total } = await pool.query('SELECT COUNT(*) as total FROM pacientes');
|
||||
res.json({ data: rows, total: parseInt(total[0].total) });
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
@@ -1492,6 +1503,71 @@ app.post('/api/sync/pull', tenantGuard, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Import patients from Apps Script legacy sheet (PACIENTES-CONSULTT-CLINIC tab)
|
||||
app.post('/api/sync/import-legacy', tenantGuard, async (req, res) => {
|
||||
const logs = [];
|
||||
try {
|
||||
const sheets = await getSheetsClient();
|
||||
logs.push('[←] LENDO ABA PACIENTES-CONSULTT-CLINIC...');
|
||||
const realTab = await ensureSheetTab(sheets, 'PACIENTES-CONSULTT-CLINIC');
|
||||
const resp = await sheets.spreadsheets.values.get({
|
||||
spreadsheetId: SHEETS_BACKUP_ID,
|
||||
range: `${realTab}!A:ZZ`
|
||||
});
|
||||
const sheetRows = resp.data.values || [];
|
||||
if (sheetRows.length < 2) {
|
||||
logs.push('[AVISO] ABA VAZIA OU SEM DADOS.');
|
||||
return res.json({ success: true, logs, imported: 0 });
|
||||
}
|
||||
const headers = sheetRows[0].map(h => h.trim());
|
||||
const dataRows = sheetRows.slice(1).filter(r => r.some(c => c && c.trim() !== ''));
|
||||
logs.push(`[OK] ${dataRows.length} LINHAS ENCONTRADAS`);
|
||||
|
||||
const idx = h => headers.indexOf(h);
|
||||
const iNome = idx('Nome'); const iSobre = idx('SobreNome');
|
||||
const iCpf = idx('CPF'); const iCred = idx('Credenciada');
|
||||
const iNasci = idx('DataNasci'); const iTel = idx('TefefonePrincipal');
|
||||
|
||||
let imported = 0, skipped = 0;
|
||||
for (let i = 0; i < dataRows.length; i++) {
|
||||
const row = dataRows[i];
|
||||
const get = j => (j >= 0 && j < row.length ? (row[j] || '').trim() : '');
|
||||
const nome = [get(iNome), get(iSobre)].filter(Boolean).join(' ').toUpperCase();
|
||||
if (!nome) { skipped++; continue; }
|
||||
const cpfRaw = get(iCpf);
|
||||
const cpfDigits = cpfRaw.replace(/\D/g, '');
|
||||
const id = cpfDigits || `legacy_${i + 1}`;
|
||||
try {
|
||||
const trunc = (v, n) => v ? v.substring(0, n) : null;
|
||||
await pool.query(
|
||||
`INSERT INTO pacientes (id,nome,cpf,telefone,email,ultimotratamento,convenio,datanascimento)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
nome=EXCLUDED.nome,cpf=EXCLUDED.cpf,telefone=EXCLUDED.telefone,
|
||||
convenio=EXCLUDED.convenio,datanascimento=EXCLUDED.datanascimento`,
|
||||
[trunc(id,50), trunc(nome,255), trunc(cpfRaw,20)||null, trunc(get(iTel),20)||null, null, null, trunc(get(iCred),100)||null, trunc(get(iNasci),20)||null]
|
||||
);
|
||||
imported++;
|
||||
} catch (e) {
|
||||
skipped++;
|
||||
if (skipped <= 3) logs.push(`[AVISO] linha ${i + 2}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
logs.push(`[✓] ${imported} PACIENTES IMPORTADOS, ${skipped} IGNORADOS`);
|
||||
if (imported > 0) {
|
||||
await saveSyncStatus({ pacientes: { lastPush: new Date().toISOString(), count: imported, source: 'legacy' } });
|
||||
schedulePush('pacientes');
|
||||
}
|
||||
res.json({ success: true, logs, imported, skipped });
|
||||
} catch (err) {
|
||||
const msg = err.message === 'NO_GOOGLE_TOKEN'
|
||||
? 'NENHUMA CONTA GOOGLE CONECTADA.'
|
||||
: err.message;
|
||||
logs.push(`[ERRO] ${msg}`);
|
||||
res.status(err.message === 'NO_GOOGLE_TOKEN' ? 400 : 500).json({ success: false, logs });
|
||||
}
|
||||
});
|
||||
|
||||
// initTables() was removed as database is native PostgreSQL and schema DDL is maintained externally.
|
||||
async function generateIntelligentNotifications() {
|
||||
if (!pool) return;
|
||||
|
||||
Reference in New Issue
Block a user