diff --git a/docs/quality/evidence/qa-browser-acceptance-runtime.json b/docs/quality/evidence/qa-browser-acceptance-runtime.json index c35bf52..63e0704 100644 --- a/docs/quality/evidence/qa-browser-acceptance-runtime.json +++ b/docs/quality/evidence/qa-browser-acceptance-runtime.json @@ -56,6 +56,7 @@ "printButtonHidden": true, "overviewStatus": 200, "overviewFrames": 3, + "documentOwnerInPreparationOverview": true, "mobileStatus": 200, "mobileOverflow": { "viewport": 390, diff --git a/src/components/BidPackageBuilder.jsx b/src/components/BidPackageBuilder.jsx index 0e93c6f..1c3c972 100644 --- a/src/components/BidPackageBuilder.jsx +++ b/src/components/BidPackageBuilder.jsx @@ -38,7 +38,7 @@ const firmaAnahtari = email => `${FIRMA_ANAHTAR}:${encodeURIComponent(String(ema const bosFirma = () => Object.fromEntries(ALANLAR.map((a) => [a.k, ''])); -export const BidPackageBuilder = ({ results, tender: selectedTender, initialFocus }) => { +export const BidPackageBuilder = ({ results, tender: selectedTender, initialFocus, now = null }) => { const { userProfile, mutateTender, savingCount, authUser, tenders } = useApp(); const tender = resolveCurrentTender(selectedTender,tenders); const storedDraft = tender?.bidDraft || {}; @@ -148,9 +148,13 @@ export const BidPackageBuilder = ({ results, tender: selectedTender, initialFocu const kalemEksik = teklifTuru === 'birim' && validateBidRows(satirlar).length > 0; const turCeliskisi = !['birim','goturu'].includes(teklifTuru) || kaynakTeklifTuru.status === 'conflict' || (kaynakTeklifTuru.type && teklifTuru !== kaynakTeklifTuru.type); const sureEksik = !Number.isInteger(Number(gecerlilikGun)) || !(Number(gecerlilikGun) > 0) || kaynakGecerlilik.status === 'conflict' || (kaynakGecerlilik.days && Number(gecerlilikGun) < kaynakGecerlilik.days); - const [deadlineNow,setDeadlineNow] = useState(() => new Date()); - useEffect(() => {const timer=setInterval(()=>setDeadlineNow(new Date()),30000);return ()=>clearInterval(timer);},[]); - const deadlineProblem = preparationDeadlineProblem(tender,deadlineNow); + const [deadlineNow,setDeadlineNow] = useState(() => now || new Date()); + useEffect(() => { + if (now) { setDeadlineNow(now); return undefined; } + const timer=setInterval(()=>setDeadlineNow(new Date()),30000); + return ()=>clearInterval(timer); + },[now]); + const deadlineProblem = preparationDeadlineProblem(tender,now || deadlineNow); const kontrolEksikleri = preparationBlockers(lotSelection.rows, documents, checks, {...vault,healthPortfolio:userProfile.scrapedCapabilities?.healthPortfolio || [],deadlineDate:tenderDateKey(tender),tenderIkn:tender.ikn}); const analizEksik = analysisStatusBlocksPreparation(effectiveResults.sourceReview?.status); const hazir = !deadlineProblem && eksikler.length === 0 && toplam > 0 && !kalemEksik && !turCeliskisi && !sureEksik && !kaynakKontrolGerekli && kontrolEksikleri.length === 0 && lotSelection.errors.length === 0 && !analizEksik && !sourceOptions.needsSelection; @@ -189,7 +193,7 @@ export const BidPackageBuilder = ({ results, tender: selectedTender, initialFocu const session = getToken(); setHata(null); try { - const initialDeadlineProblem=preparationDeadlineProblem(tender); + const initialDeadlineProblem=preparationDeadlineProblem(tender,now || new Date()); if(initialDeadlineProblem)throw new Error(initialDeadlineProblem); if (!hazir) throw new Error('Kalem, miktar, birim, fiyat, firma ve geçerlilik süresindeki eksikleri giderin.'); // Open during the click; async validation must not lose popup activation. @@ -206,7 +210,7 @@ export const BidPackageBuilder = ({ results, tender: selectedTender, initialFocu setVault(currentVault); const fileErrors = preparationBlockers(lotSelection.rows, documents, checks, currentVault); if (fileErrors.length) throw new Error(fileErrors.join(' ')); - const currentDeadlineProblem=preparationDeadlineProblem(tender); + const currentDeadlineProblem=preparationDeadlineProblem(tender,now || new Date()); if(currentDeadlineProblem)throw new Error(currentDeadlineProblem); const f = formVerisi(); if (tip === 'excel') { @@ -219,7 +223,7 @@ export const BidPackageBuilder = ({ results, tender: selectedTender, initialFocu setVault(finalVault); const finalErrors=preparationBlockers(lotSelection.rows,documents,checks,finalVault); if(finalErrors.length)throw new Error(finalErrors.join(' ')); - const finalDeadlineProblem=preparationDeadlineProblem(tender); + const finalDeadlineProblem=preparationDeadlineProblem(tender,now || new Date()); if(finalDeadlineProblem)throw new Error(finalDeadlineProblem); downloadBidWorkbook(buffer,tender.ikn); printWindow.current?.close(); diff --git a/tests/browser-acceptance.mjs b/tests/browser-acceptance.mjs index ac0d4da..f116af6 100644 --- a/tests/browser-acceptance.mjs +++ b/tests/browser-acceptance.mjs @@ -27,6 +27,8 @@ try { evidence.checks.signInStatus = response?.status(); await page.getByRole('button', { name: 'Test hesabıyla gir' }).click(); await page.waitForLoadState('networkidle'); + const hideExpired = page.getByLabel('Süresi geçenleri gizle', { exact: true }); + if (await hideExpired.isChecked()) await hideExpired.uncheck(); evidence.checks.visibleCities = await Promise.all(['Giresun', 'Kayseri', 'Akdeniz', 'Aksaray', 'Tepecik'].map(async city => ({ city, count: await page.getByText(city, { exact: false }).count() }))); if (evidence.checks.visibleCities.some(item => item.count < 1)) throw new Error('Beş sentetik şehirden biri görünmedi.'); await page.getByRole('button', { name: 'Günlük Bülten', exact: true }).click(); diff --git a/tests/browser-qa.mjs b/tests/browser-qa.mjs index c2d915e..7817613 100644 --- a/tests/browser-qa.mjs +++ b/tests/browser-qa.mjs @@ -167,7 +167,7 @@ const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{targ const query=new URL(req.url,'http://localhost').searchParams; qaFiles=query.has('file')?[{...qaFile}]:null; const selected=query.has('ready')?readyBid(tenders[0],qaFiles?.[0]):tenders[0]; - if(selected.bidDraft){const summary=preparationSummary(selected,{loading:false,error:null,documents:qaFiles || []});if(summary.issues.length)throw new Error('QA ready fixture: '+JSON.stringify(summary.issues));} + if(selected.bidDraft){const summary=preparationSummary(selected,{loading:false,error:null,documents:qaFiles || []},new Date('2026-09-06T09:00:00Z'));if(summary.issues.length)throw new Error('QA ready fixture: '+JSON.stringify(summary.issues));} const html=`
`; res.setHeader('Content-Type','text/html; charset=utf-8');res.end(await server.transformIndexHtml('/qa-source-update',html));return;