Files
COMERCIAL-GTI/gti-maquina-comercial/src/server/routes/extractions.mjs
T
GustavoandClaude Sonnet 5 f5af038e19 chore: import gti-maquina-comercial history via subtree
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

git-subtree-dir: gti-maquina-comercial
git-subtree-mainline: 93ca82979e
git-subtree-split: b77484946f
2026-09-28 15:50:08 -03:00

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})` });
});
}