fix: invalidate pending bid output when preparation changes
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { getToken } from '../services/auth';
|
||||
import { listDocuments, downloadDocument } from '../services/account';
|
||||
import { tenderDateKey } from '../services/tenderCalendar';
|
||||
import React, { useState, useMemo, useEffect } from 'react';
|
||||
import React, { useState, useMemo, useEffect, useRef } from 'react';
|
||||
import { bidRowTotal, validateBidRows, roundMoney, parseBidPrice } from '../services/bidValidation';
|
||||
import { sourceRows, bidSourceSnapshot, restoreBidPrices } from '../services/bidSource';
|
||||
import { rowLot, selectBidLots } from '../services/bidLots';
|
||||
@@ -100,9 +101,16 @@ export const BidPackageBuilder = ({ results, tender: selectedTender }) => {
|
||||
);
|
||||
|
||||
const kalemToplami = useMemo(() => roundMoney(satirlar.reduce((t,r) => t + (bidRowTotal(r) ?? 0),0)), [satirlar]);
|
||||
const latestDraft = useRef('');
|
||||
latestDraft.current = JSON.stringify([firma,teklifTuru,gecerlilikGun,kisim,goturuBedel,fiyatlar,sourceSnapshot,reviewedSource,checks,manualDocuments,partialBid]);
|
||||
const mounted = useRef(true);
|
||||
const printWindow = useRef(null);
|
||||
const [printing,setPrinting] = useState(false);
|
||||
useEffect(()=>{mounted.current=true;return ()=>{mounted.current=false;printWindow.current?.close();};},[]);
|
||||
const saveDraft = async () => {
|
||||
const submitted = latestDraft.current;
|
||||
const saved = await mutateTender(tender.id, {bidDraft:{firma,teklifTuru,gecerlilikGun,kisim,goturuBedel,priceSchema:1,pricesBySource:fiyatlar,sourceSnapshot,reviewedSource,checks,manualDocuments,partialBid,analysisSource:{itemsAndSpecs:effectiveResults.itemsAndSpecs || [],documentChecklist:effectiveResults.documentChecklist || [],documentVersion:effectiveResults.documentVersion || null}}});
|
||||
if (saved) { setDirty(false); setHata(null); }
|
||||
if (saved && mounted.current) { setDirty(latestDraft.current !== submitted); setHata(null); }
|
||||
else setHata('Taslak kaydedilemedi. Tekrar deneyin.');
|
||||
};
|
||||
|
||||
@@ -127,21 +135,32 @@ export const BidPackageBuilder = ({ results, tender: selectedTender }) => {
|
||||
});
|
||||
|
||||
const uret = async (tip) => {
|
||||
if (printWindow.current) return;
|
||||
const submitted = latestDraft.current;
|
||||
const session = getToken();
|
||||
setHata(null);
|
||||
try {
|
||||
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.
|
||||
printWindow.current = belgeYazdir('Dosya kontrolü', '<p>Belgeler kontrol ediliyor…</p>');
|
||||
setPrinting(true);
|
||||
const currentFiles = await listDocuments();
|
||||
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.');
|
||||
const currentVault = {loading:false,error:null,documents:currentFiles.belgeler || [],deadlineDate:tenderDateKey(tender)};
|
||||
setVault(currentVault);
|
||||
const fileErrors = preparationBlockers(lotSelection.rows, documents, checks, currentVault);
|
||||
if (fileErrors.length) throw new Error(fileErrors.join(' '));
|
||||
const f = formVerisi();
|
||||
if (tip === 'mektup') belgeYazdir('Teklif Mektubu', teklifMektubuHtml(f, toplam));
|
||||
if (tip === 'cetvel') belgeYazdir('Birim Fiyat Teklif Cetveli', teklifCetveliHtml(f, satirlar, toplam));
|
||||
if (tip === 'liste') belgeYazdir('Evrak Kontrol Listesi', evrakListesiHtml(f, documents));
|
||||
if (tip === 'mektup') belgeYazdir('Teklif Mektubu', teklifMektubuHtml(f, toplam), printWindow.current);
|
||||
if (tip === 'cetvel') belgeYazdir('Birim Fiyat Teklif Cetveli', teklifCetveliHtml(f, satirlar, toplam), printWindow.current);
|
||||
if (tip === 'liste') belgeYazdir('Evrak Kontrol Listesi', evrakListesiHtml(f, documents), printWindow.current);
|
||||
printWindow.current = null;
|
||||
} catch (e) {
|
||||
setHata(e.message);
|
||||
}
|
||||
printWindow.current?.close();
|
||||
printWindow.current = null;
|
||||
if(mounted.current) setHata(e.message);
|
||||
} finally { if(mounted.current) setPrinting(false); }
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -389,7 +408,7 @@ export const BidPackageBuilder = ({ results, tender: selectedTender }) => {
|
||||
<button
|
||||
key={b.t}
|
||||
type="button"
|
||||
disabled={!hazir}
|
||||
disabled={!hazir || printing}
|
||||
onClick={() => uret(b.t)}
|
||||
className="text-left bg-white border border-slate-300 hover:border-emerald-500 hover:bg-emerald-50/50 disabled:opacity-40 disabled:hover:border-slate-300 disabled:hover:bg-white rounded-xl p-3 transition-colors"
|
||||
>
|
||||
|
||||
@@ -84,9 +84,11 @@ const STIL = `
|
||||
`;
|
||||
|
||||
/** Belgeyi kendi penceresinde açıp yazdırma diyaloğunu tetikler. */
|
||||
export function belgeYazdir(baslik, govde) {
|
||||
const w = window.open('', '_blank', 'width=900,height=1000');
|
||||
export function belgeYazdir(baslik, govde, existingWindow) {
|
||||
const w = existingWindow || window.open('', '_blank', 'width=900,height=1000');
|
||||
if (!w) throw new Error('Tarayıcı yeni pencereyi engelledi. Açılır pencere iznini verip tekrar deneyin.');
|
||||
if(w.closed) throw new Error('Çıktı penceresi kapatıldı. Yeniden deneyin.');
|
||||
w.document.open();
|
||||
w.document.write(`<!doctype html><html lang="tr"><head><meta charset="utf-8">
|
||||
<title>${kacir(baslik)}</title><style>${STIL}</style></head><body>${govde}
|
||||
<div class="yazdirma" style="text-align:center;margin-top:10mm">
|
||||
|
||||
Reference in New Issue
Block a user