Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> git-subtree-dir: gti-maquina-comercial git-subtree-mainline:93ca82979egit-subtree-split:b77484946f
73 lines
2.5 KiB
JavaScript
73 lines
2.5 KiB
JavaScript
import fs from 'node:fs';
|
|
import { paths } from '../../env.mjs';
|
|
import { UF_NAMES } from '../../sources/common.mjs';
|
|
import { resolveZipReader } from '../../extract/rfb-extractor.mjs';
|
|
|
|
export function registerExtractionRoutes(router, { db, jobs }) {
|
|
router.add('POST', '/api/extractions', async (req, res, { json, body }) => {
|
|
const uf = String(body?.uf || '').toUpperCase();
|
|
if (!UF_NAMES[uf]) {
|
|
json(400, { erro: 'informe uma UF valida' });
|
|
return;
|
|
}
|
|
|
|
if (!fs.existsSync(paths.rfbRaw)) {
|
|
json(409, { erro: `zips da Receita Federal nao encontrados em ${paths.rfbRaw}. Rode scripts/baixar-base-rfb.sh primeiro.` });
|
|
return;
|
|
}
|
|
|
|
try {
|
|
resolveZipReader();
|
|
} catch (error) {
|
|
json(409, { erro: error.message });
|
|
return;
|
|
}
|
|
|
|
const running = db.prepare(
|
|
"SELECT id, uf FROM extractions WHERE status IN ('pending','running')"
|
|
).get();
|
|
if (running) {
|
|
json(409, { erro: `ja existe uma extracao em andamento (${running.uf}). Aguarde terminar.` });
|
|
return;
|
|
}
|
|
|
|
const inserted = db.prepare("INSERT INTO extractions (uf, status) VALUES (?, 'pending')").run(uf);
|
|
const extractionId = Number(inserted.lastInsertRowid);
|
|
|
|
const jobId = jobs.startJob({
|
|
type: 'extracao',
|
|
script: 'src/extract/extract-job.mjs',
|
|
args: [`--extraction-id=${extractionId}`],
|
|
meta: { extractionId, uf }
|
|
});
|
|
db.prepare('UPDATE extractions SET job_id = ? WHERE id = ?').run(jobId, extractionId);
|
|
|
|
json(202, { extractionId, jobId });
|
|
});
|
|
|
|
router.add('GET', '/api/extractions', async (req, res, { json }) => {
|
|
const rows = db.prepare(
|
|
`SELECT id, job_id, uf, status, csv_path, total_rows, with_phone, municipios_count,
|
|
progress_json, error, started_at, finished_at, created_at
|
|
FROM extractions ORDER BY id DESC LIMIT 20`
|
|
).all();
|
|
json(200, {
|
|
extractions: rows.map((row) => ({
|
|
...row,
|
|
progress: JSON.parse(row.progress_json || 'null'),
|
|
progress_json: undefined
|
|
}))
|
|
});
|
|
});
|
|
|
|
router.add('POST', '/api/extractions/:id/cancel', async (req, res, { json, params }) => {
|
|
const row = db.prepare('SELECT job_id, status FROM extractions WHERE id = ?').get(Number(params.id));
|
|
if (!row) {
|
|
json(404, { erro: 'extracao nao encontrada' });
|
|
return;
|
|
}
|
|
const ok = row.job_id ? jobs.cancelJob(row.job_id) : false;
|
|
json(ok ? 202 : 409, ok ? { cancelando: true } : { erro: `nao ha job ativo para cancelar (status: ${row.status})` });
|
|
});
|
|
}
|