Files
ihaleist/server/document-review.mjs
T

44 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import fs from 'node:fs';
import path from 'node:path';
import {createHash} from 'node:crypto';
import {openDb,BELGE_DIR} from './user-store.mjs';
const hash=value=>createHash('sha256').update(value).digest('hex');
const fail=(status,message)=>Object.assign(new Error(message),{status});
function source(db,email,id) {
const record=db.prepare('SELECT * FROM belgeler WHERE id=? AND email=?').get(id,email);
if(!record || record.tur !== 'ihale') throw fail(404,'İhale dokümanı bulunamadı.');
let bytes;
try {bytes=fs.readFileSync(path.join(BELGE_DIR,record.dosya));}
catch {throw fail(409,'Kaynak dosya okunamıyor; inceleme kaydedilemez.');}
return hash(bytes);
}
function latest(db,email,id) {
return db.prepare('SELECT revision,file_hash,text_hash,corrected_text,review_note,reviewed_at FROM document_text_reviews WHERE document_id=? AND email=? ORDER BY revision DESC LIMIT 1').get(id,email) || null;
}
export function documentReview(email,id) {
const db=openDb();
try {
const fileHash=source(db,email,id), review=latest(db,email,id);
return {documentId:id,fileHash,review,stale:Boolean(review && review.file_hash!==fileHash)};
} finally {db.close();}
}
export function saveDocumentReview(email,id,input) {
if(typeof input.correctedText !== 'string' || input.correctedText.trim().length<40 || Buffer.byteLength(input.correctedText)>1024*1024)
throw fail(400,'Kontrol edilen metin 40 karakter ile 1 MB arasında olmalı.');
if(typeof input.note !== 'string' || input.note.trim().length<20 || input.note.length>2000)
throw fail(400,'Karşılaştırılan sayfaları ve yapılan düzeltmeleri en az 20 karakterle açıklayın.');
if(input.allPagesCompared !== true) throw fail(400,'Tüm kaynak sayfalarıyla karşılaştırma gerekli.');
if(!Number.isInteger(input.expectedRevision) || input.expectedRevision<0) throw fail(400,'Geçerli inceleme sürümü gerekli.');
const db=openDb();
try {
db.exec('BEGIN IMMEDIATE');
const fileHash=source(db,email,id), previous=latest(db,email,id);
if(input.fileHash!==fileHash || input.expectedRevision!==(previous?.revision || 0)) throw fail(409,'Dosya veya inceleme sürümü değişti. Güncel kaydı yeniden açın.');
const text=input.correctedText.trim();
db.prepare('INSERT INTO document_text_reviews VALUES (?,?,?,?,?,?,?,?)').run(id,email,input.expectedRevision+1,fileHash,hash(text),text,input.note.trim(),new Date().toISOString());
const review=latest(db,email,id);
db.exec('COMMIT');return {documentId:id,fileHash,review,stale:false};
} catch(error) {try {db.exec('ROLLBACK');} catch {} throw error;}
finally {db.close();}
}