Persist document processing outcomes separately from upload success
This commit is contained in:
+20
-2
@@ -743,21 +743,30 @@ const server = http.createServer(async (req, res) => {
|
||||
if (url.pathname === '/api/kalem/cikar' && req.method === 'POST') {
|
||||
const user = userFromAuthHeader(req.headers['authorization']);
|
||||
if (!user) return json(res, 401, { success: false, error: 'oturum yok' });
|
||||
let validatedDocument = null;
|
||||
try {
|
||||
const body = await readBody(req, 4 * 1024 * 1024);
|
||||
if (!body.ikn) return json(res, 400, { success: false, error: 'ikn gerekli' });
|
||||
const sourceDocument = body.documentId && store.getDocument(user.email,String(body.documentId));
|
||||
if (!sourceDocument || sourceDocument.tur !== 'ihale' || sourceDocument.ikn !== String(body.ikn))
|
||||
return json(res,403,{success:false,error:'Kalem aktarımı için bu ihaleye bağlı, size ait ihale dokümanı gerekli. Firma belgeleri ortak havuza aktarılamaz.'});
|
||||
validatedDocument = sourceDocument;
|
||||
if (typeof body.metin !== 'string') throw new Error('Doküman metni gerekli.');
|
||||
const { kalemler, yontem } = kalemleriCikar(body.metin || '');
|
||||
if (!kalemler.length) {
|
||||
store.setDocumentProcessing(user.email,sourceDocument.id,{status:'no_items',count:0});
|
||||
return json(res, 200, { success: true, kalemler: [], yontem, not: 'Metinde teklif cetveli tablosu bulunamadı.' });
|
||||
}
|
||||
kalemStore.kalemYaz(String(body.ikn), kalemler, {
|
||||
dosya: body.dosya ? String(body.dosya).slice(0, 200) : null, yontem, ekleyen: user.email,
|
||||
});
|
||||
store.setDocumentProcessing(user.email,sourceDocument.id,{status:'processed',count:kalemler.length});
|
||||
return json(res, 200, { success: true, kalemler, yontem, sayi: kalemler.length });
|
||||
} catch (e) {
|
||||
if (validatedDocument) {
|
||||
try { store.setDocumentProcessing(user.email,validatedDocument.id,{status:'error',error:'Kalem çıkarımı tamamlanamadı. Doküman metnini kontrol edip yeniden deneyin.'}); }
|
||||
catch (statusError) { console.error('[document-processing] Durum kaydedilemedi:', statusError.message); }
|
||||
}
|
||||
return json(res, 400, { success: false, error: e.message });
|
||||
}
|
||||
}
|
||||
@@ -970,8 +979,9 @@ const server = http.createServer(async (req, res) => {
|
||||
// PDF tarayıcıda okunduğu için istemci ikn'yi kendisi gönderir.
|
||||
let ikn = body.ikn ? String(body.ikn).slice(0, 40) : null;
|
||||
let ofisMetni = null;
|
||||
let readError = null;
|
||||
if (sunucuOkuyabilir(body.ad)) {
|
||||
try { ofisMetni = arsivMetni(String(body.ad), buf); } catch { /* metin çıkmazsa devam */ }
|
||||
try { ofisMetni = arsivMetni(String(body.ad), buf); } catch { readError = 'Dosya metni okunamadı. Dosya biçimini ve bütünlüğünü kontrol edin.'; }
|
||||
if (documentType === 'ihale' && !ikn && body.otoIkn && ofisMetni) ikn = iknCikar(ofisMetni);
|
||||
}
|
||||
const id = store.saveDocumentFile(user.email, {
|
||||
@@ -986,19 +996,27 @@ const server = http.createServer(async (req, res) => {
|
||||
// tıklama beklemez. PDF'ler tarayıcıda çözüldüğü için istemci
|
||||
// metni /api/kalem/cikar'a gönderir.
|
||||
let kalemBilgi = null;
|
||||
let processing = documentType !== 'ihale' ? {status:'not_applicable'}
|
||||
: readError ? {status:'error',error:readError}
|
||||
: /\.(pdf|txt|md)$/i.test(body.ad) ? {status:'awaiting_text'}
|
||||
: !sunucuOkuyabilir(body.ad) ? {status:'unsupported'}
|
||||
: !ikn ? {status:'needs_tender'} : {status:'no_items',count:0};
|
||||
if (documentType === 'ihale' && ikn && ofisMetni) {
|
||||
try {
|
||||
const { kalemler, yontem } = kalemleriCikar(ofisMetni);
|
||||
if (kalemler.length) {
|
||||
kalemStore.kalemYaz(ikn, kalemler, { dosya: String(body.ad), yontem, ekleyen: user.email });
|
||||
kalemBilgi = { sayi: kalemler.length, yontem };
|
||||
processing = {status:'processed',count:kalemler.length};
|
||||
console.log(`[kalem] ${ikn} → ${kalemler.length} kalem (${yontem}, ${body.ad})`);
|
||||
}
|
||||
} catch (e) {
|
||||
processing = {status:'error',error:'Kalem çıkarımı tamamlanamadı; yeniden deneyin.'};
|
||||
console.warn('[kalem] çıkarılamadı:', e.message);
|
||||
}
|
||||
}
|
||||
return json(res, 200, { success: true, id, ikn, kalem: kalemBilgi, belgeler: store.listDocuments(user.email), kullanim: store.documentUsage(user.email) });
|
||||
store.setDocumentProcessing(user.email,id,processing);
|
||||
return json(res, 200, { success: true, id, ikn, processing, kalem: kalemBilgi, belgeler: store.listDocuments(user.email), kullanim: store.documentUsage(user.email) });
|
||||
} catch (e) {
|
||||
return json(res, e.kod === 'KOTA_ASILDI' ? 402 : 400, { success: false, error: e.message, kod: e.kod || null });
|
||||
}
|
||||
|
||||
+10
-2
@@ -98,12 +98,15 @@ export function openDb() {
|
||||
if (!columns.has(column)) db.exec(`ALTER TABLE belgeler ADD COLUMN ${column} TEXT`);
|
||||
}
|
||||
if (!columns.has('tur')) db.exec("ALTER TABLE belgeler ADD COLUMN tur TEXT NOT NULL DEFAULT 'firma'");
|
||||
if (!columns.has('isleme')) db.exec('ALTER TABLE belgeler ADD COLUMN isleme TEXT');
|
||||
db.exec('CREATE INDEX IF NOT EXISTS idx_belge_ikn ON belgeler(email, ikn)');
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS schema_migrations (version TEXT PRIMARY KEY, applied_at TEXT NOT NULL)`);
|
||||
db.prepare('INSERT OR IGNORE INTO schema_migrations VALUES (?,?)')
|
||||
.run('20260906_document_columns', new Date().toISOString());
|
||||
db.prepare('INSERT OR IGNORE INTO schema_migrations VALUES (?,?)')
|
||||
.run('20260906_document_type', new Date().toISOString());
|
||||
db.prepare('INSERT OR IGNORE INTO schema_migrations VALUES (?,?)')
|
||||
.run('20260906_document_processing', new Date().toISOString());
|
||||
db.exec('COMMIT');
|
||||
} catch (error) {
|
||||
try { db.exec('ROLLBACK'); } catch { /* original error is authoritative */ }
|
||||
@@ -269,11 +272,16 @@ export function saveDocumentFile(email, metadata, bytes) {
|
||||
}
|
||||
|
||||
export function listDocuments(email, { ikn } = {}) {
|
||||
const alanlar = 'id, ad, kategori, boyut, mime, son_kullanma, ikn, olusturma, dosya, tur';
|
||||
const alanlar = 'id, ad, kategori, boyut, mime, son_kullanma, ikn, olusturma, dosya, tur, isleme';
|
||||
return withDb((db) => (ikn
|
||||
? db.prepare(`SELECT ${alanlar} FROM belgeler WHERE email=? AND ikn=? ORDER BY olusturma DESC`).all(email, ikn)
|
||||
: db.prepare(`SELECT ${alanlar} FROM belgeler WHERE email=? ORDER BY olusturma DESC`).all(email)
|
||||
).map(({dosya,...record}) => ({...record, erisilebilir: fs.existsSync(path.join(BELGE_DIR,dosya))})), []);
|
||||
).map(({dosya,isleme,...record}) => ({...record, isleme:isleme ? JSON.parse(isleme) : null, erisilebilir: fs.existsSync(path.join(BELGE_DIR,dosya))})), []);
|
||||
}
|
||||
|
||||
export function setDocumentProcessing(email,id,processing) {
|
||||
return withDb(db=>db.prepare('UPDATE belgeler SET isleme=? WHERE id=? AND email=?')
|
||||
.run(JSON.stringify({...processing,updatedAt:now()}),id,email).changes>0);
|
||||
}
|
||||
|
||||
export function getDocument(email, id) {
|
||||
|
||||
Reference in New Issue
Block a user