Verify current document review before bid outputs
This commit is contained in:
@@ -373,3 +373,9 @@ Bu yalnız sunucu altyapısıdır. Metin düzenleme arayüzü, bu kaydın analiz
|
|||||||
Hazırlık formu inceleme kaynağını gösterir. İnceleme sürümü kaynak snapshot'ına katıldı; aynı kalemlerle yeni inceleme sonucu geldiğinde eski kaynak kontrolü geçersizleşir.
|
Hazırlık formu inceleme kaynağını gösterir. İnceleme sürümü kaynak snapshot'ına katıldı; aynı kalemlerle yeni inceleme sonucu geldiğinde eski kaynak kontrolü geçersizleşir.
|
||||||
|
|
||||||
79 mevcut test ve ek snapshot testi geçti (80 ayrı test); üretim derlemesi geçti. Kaynak çözümleme testleri başka hesap/İKN, eski revizyon ve değişmiş dosyayı reddediyor. Gerçek AI sağlayıcısıyla tarayıcı kabulü ve çıktı anında sunucudan incelemenin hâlâ güncel olduğunun doğrulanması henüz açık. İnceleme kullanıcı beyanıdır, resmi doğruluk garantisi değildir.
|
79 mevcut test ve ek snapshot testi geçti (80 ayrı test); üretim derlemesi geçti. Kaynak çözümleme testleri başka hesap/İKN, eski revizyon ve değişmiş dosyayı reddediyor. Gerçek AI sağlayıcısıyla tarayıcı kabulü ve çıktı anında sunucudan incelemenin hâlâ güncel olduğunun doğrulanması henüz açık. İnceleme kullanıcı beyanıdır, resmi doğruluk garantisi değildir.
|
||||||
|
|
||||||
|
### İnceleme güncelliğinin çıktı öncesi doğrulanması
|
||||||
|
|
||||||
|
PDF/yazdırma akışı, canlı belge listesi kontrolüne ek olarak analizdeki humanReview kaydını sunucuda doğruluyor. İKN, sahiplik, son revizyon, gerçek dosya SHA256 ve düzeltilmiş metin SHA256 eşleşmeden çıktı ilerlemiyor. Excel oluşturma asenkron olduğu için dosya hazırlanırken oluşabilecek inceleme değişikliği indirmeden önce tekrar kontrol ediliyor. API yanıtı düzeltme metninin tamamını taşımıyor; ağ/sürüm hatasında çıktı penceresi kapanıyor ve hata gösteriliyor.
|
||||||
|
|
||||||
|
80 test ve üretim derlemesi geçti. HTTP doğrulama testinde güncel kayıt kabul edildi; başka hesap, yanlış İKN, yanlış metin özeti ve sonradan oluşturulan yeni revizyon karşısındaki eski kayıt reddedildi. Gerçek tarayıcıda çıktı sırasında inceleme değiştirme kabulü hâlâ açık. Bu kontrol çıktı anına aittir; çıktı alındıktan sonra resmi belge değişirse önceden indirilen dosya otomatik geri alınamaz.
|
||||||
|
|||||||
@@ -1065,6 +1065,17 @@ const server = http.createServer(async (req, res) => {
|
|||||||
return json(res, 200, { success: true, belgeler: store.listDocuments(user.email) });
|
return json(res, 200, { success: true, belgeler: store.listDocuments(user.email) });
|
||||||
} catch (e) { return json(res, 400, { success: false, error: e.message }); }
|
} catch (e) { return json(res, 400, { success: false, error: e.message }); }
|
||||||
}
|
}
|
||||||
|
if (url.pathname === '/api/me/documents/text-review/validate' && req.method === 'POST') {
|
||||||
|
const user=userFromAuthHeader(req.headers['authorization']);
|
||||||
|
if(!user) return json(res,401,{success:false,error:'oturum yok'});
|
||||||
|
try {
|
||||||
|
const body=await readBody(req,8192);
|
||||||
|
const resolved=reviewedAnalysisSource(user.email,body.review,body.ikn);
|
||||||
|
if(body.review.fileHash!==resolved.humanReview.fileHash || body.review.textHash!==resolved.humanReview.textHash)
|
||||||
|
return json(res,409,{success:false,error:'Analizin dayandığı metin incelemesi güncel değil. Analizi yenileyin.'});
|
||||||
|
return json(res,200,{success:true,review:resolved.humanReview});
|
||||||
|
} catch(error) {return json(res,error.status || 500,{success:false,error:error.message});}
|
||||||
|
}
|
||||||
if (url.pathname === '/api/me/documents/text-review') {
|
if (url.pathname === '/api/me/documents/text-review') {
|
||||||
const user=userFromAuthHeader(req.headers['authorization']);
|
const user=userFromAuthHeader(req.headers['authorization']);
|
||||||
if(!user) return json(res,401,{success:false,error:'oturum yok'});
|
if(!user) return json(res,401,{success:false,error:'oturum yok'});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bidValidityForForm, bidTypeForForm } from '../services/bidTerms';
|
import { bidValidityForForm, bidTypeForForm } from '../services/bidTerms';
|
||||||
import { createBidWorkbook, downloadBidWorkbook } from '../services/bidWorkbook';
|
import { createBidWorkbook, downloadBidWorkbook } from '../services/bidWorkbook';
|
||||||
import { getToken } from '../services/auth';
|
import { getToken } from '../services/auth';
|
||||||
import { listDocuments, downloadDocument } from '../services/account';
|
import { listDocuments, downloadDocument, validateDocumentTextReview } from '../services/account';
|
||||||
import { tenderDateKey } from '../services/tenderCalendar';
|
import { tenderDateKey } from '../services/tenderCalendar';
|
||||||
import React, { useState, useMemo, useEffect, useRef } from 'react';
|
import React, { useState, useMemo, useEffect, useRef } from 'react';
|
||||||
import { bidRowTotal, validateBidRows, roundMoney, parseBidPrice } from '../services/bidValidation';
|
import { bidRowTotal, validateBidRows, roundMoney, parseBidPrice } from '../services/bidValidation';
|
||||||
@@ -153,6 +153,8 @@ export const BidPackageBuilder = ({ results, tender: selectedTender }) => {
|
|||||||
printWindow.current = belgeYazdir('Dosya kontrolü', '<p>Belgeler kontrol ediliyor…</p>');
|
printWindow.current = belgeYazdir('Dosya kontrolü', '<p>Belgeler kontrol ediliyor…</p>');
|
||||||
setPrinting(true);
|
setPrinting(true);
|
||||||
const currentFiles = await listDocuments();
|
const currentFiles = await listDocuments();
|
||||||
|
const reviewedText = effectiveResults.sourceReview?.humanReview;
|
||||||
|
if (reviewedText) await validateDocumentTextReview(reviewedText,tender.ikn);
|
||||||
if (!mounted.current || session !== getToken() || submitted !== latestDraft.current)
|
if (!mounted.current || session !== getToken() || submitted !== latestDraft.current)
|
||||||
throw new Error('Form, kaynak veya oturum değişti. Güncel bilgilerle yeniden çıktı oluşturun.');
|
throw new Error('Form, kaynak veya oturum değişti. Güncel bilgilerle yeniden çıktı oluşturun.');
|
||||||
const currentVault = {loading:false,error:null,documents:currentFiles.belgeler || [],deadlineDate:tenderDateKey(tender)};
|
const currentVault = {loading:false,error:null,documents:currentFiles.belgeler || [],deadlineDate:tenderDateKey(tender)};
|
||||||
@@ -162,6 +164,7 @@ export const BidPackageBuilder = ({ results, tender: selectedTender }) => {
|
|||||||
const f = formVerisi();
|
const f = formVerisi();
|
||||||
if (tip === 'excel') {
|
if (tip === 'excel') {
|
||||||
const buffer = await createBidWorkbook(f,satirlar);
|
const buffer = await createBidWorkbook(f,satirlar);
|
||||||
|
if (reviewedText) await validateDocumentTextReview(reviewedText,tender.ikn);
|
||||||
if (!mounted.current || session !== getToken() || submitted !== latestDraft.current)
|
if (!mounted.current || session !== getToken() || submitted !== latestDraft.current)
|
||||||
throw new Error('Form veya oturum değişti; Excel çıktısını yeniden oluşturun.');
|
throw new Error('Form veya oturum değişti; Excel çıktısını yeniden oluşturun.');
|
||||||
downloadBidWorkbook(buffer,tender.ikn);
|
downloadBidWorkbook(buffer,tender.ikn);
|
||||||
|
|||||||
@@ -119,3 +119,7 @@ export const getDocumentTextReview = (id) => iste(`/api/me/documents/text-review
|
|||||||
export const saveDocumentTextReview = (id, data) => iste('/api/me/documents/text-review', {
|
export const saveDocumentTextReview = (id, data) => iste('/api/me/documents/text-review', {
|
||||||
method:'POST', body:JSON.stringify({id,...data}),
|
method:'POST', body:JSON.stringify({id,...data}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const validateDocumentTextReview = (review, ikn) => iste('/api/me/documents/text-review/validate', {
|
||||||
|
method:'POST', body:JSON.stringify({review,ikn}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -117,9 +117,18 @@ test('shared item extraction requires an owned tender document and matching tend
|
|||||||
assert.equal((await request('/api/me/documents/text-review','POST',correction,other)).status,404);
|
assert.equal((await request('/api/me/documents/text-review','POST',correction,other)).status,404);
|
||||||
const savedReview=await request('/api/me/documents/text-review','POST',correction);
|
const savedReview=await request('/api/me/documents/text-review','POST',correction);
|
||||||
assert.equal(savedReview.status,200);assert.equal(savedReview.data.review.revision,1);
|
assert.equal(savedReview.status,200);assert.equal(savedReview.data.review.revision,1);
|
||||||
|
const verification={ikn:body.ikn,review:{documentId:tender.data.id,revision:1,fileHash:savedReview.data.fileHash,textHash:savedReview.data.review.text_hash}};
|
||||||
|
assert.equal((await request('/api/me/documents/text-review/validate','POST',verification)).status,200);
|
||||||
|
assert.equal((await request('/api/me/documents/text-review/validate','POST',verification,other)).status,404);
|
||||||
|
assert.equal((await request('/api/me/documents/text-review/validate','POST',{...verification,review:{...verification.review,textHash:'wrong'}})).status,409);
|
||||||
|
assert.equal((await request('/api/me/documents/text-review/validate','POST',{...verification,ikn:'2026/999'})).status,409);
|
||||||
|
|
||||||
assert.equal((await request(reviewUrl)).data.review.corrected_text,correction.correctedText);
|
assert.equal((await request(reviewUrl)).data.review.corrected_text,correction.correctedText);
|
||||||
assert.equal((await request('/api/me/documents/text-review','POST',correction)).status,409);
|
assert.equal((await request('/api/me/documents/text-review','POST',correction)).status,409);
|
||||||
assert.equal((await request('/api/me/documents/text-review','POST',{...correction,expectedRevision:1,fileHash:'old-hash'})).status,409);
|
assert.equal((await request('/api/me/documents/text-review','POST',{...correction,expectedRevision:1,fileHash:'old-hash'})).status,409);
|
||||||
|
assert.equal((await request('/api/me/documents/text-review','POST',{...correction,expectedRevision:1,correctedText:correction.correctedText+' İkinci inceleme.'})).status,200);
|
||||||
|
assert.equal((await request('/api/me/documents/text-review/validate','POST',verification)).status,409);
|
||||||
|
|
||||||
|
|
||||||
assert.equal((await request('/api/kalem/cikar','POST',{ikn:body.ikn,metin:'test'})).status,403);
|
assert.equal((await request('/api/kalem/cikar','POST',{ikn:body.ikn,metin:'test'})).status,403);
|
||||||
await request('/api/me/documents?id='+company.data.id,'DELETE');
|
await request('/api/me/documents?id='+company.data.id,'DELETE');
|
||||||
|
|||||||
Reference in New Issue
Block a user