feat: track document and health product preparation checks
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { bidRowTotal, validateBidRows, roundMoney } from '../services/bidValidation';
|
||||
import { sourceRows, bidSourceSnapshot, restoreBidPrices } from '../services/bidSource';
|
||||
import { PreparationChecks } from './PreparationChecks';
|
||||
import { preparationBlockers, documentKey } from '../services/preparationChecks';
|
||||
import { useApp } from '../context/AppContext';
|
||||
import {
|
||||
FolderCheck, ChevronDown, ChevronUp, FileSignature, Table2, ListChecks,
|
||||
@@ -59,8 +61,12 @@ export const BidPackageBuilder = ({ results, tender }) => {
|
||||
const [kisim, setKisim] = useState(storedDraft.kisim || '');
|
||||
const [goturuBedel, setGoturuBedel] = useState(storedDraft.goturuBedel || '');
|
||||
|
||||
const kalemler = sourceRows(tender, results);
|
||||
const sourceSnapshot = bidSourceSnapshot(tender, results, kalemler);
|
||||
const effectiveResults = results || storedDraft.analysisSource || {};
|
||||
const [manualDocuments, setManualDocuments] = useState(storedDraft.manualDocuments || []);
|
||||
const [checks, setChecks] = useState(storedDraft.checks || {});
|
||||
const documents = [...new Map([...(effectiveResults.documentChecklist || []), ...manualDocuments].map(d => [documentKey(d),d])).values()];
|
||||
const kalemler = sourceRows(tender, effectiveResults);
|
||||
const sourceSnapshot = bidSourceSnapshot(tender, {...effectiveResults, documentChecklist:documents}, kalemler);
|
||||
const [reviewedSource, setReviewedSource] = useState(storedDraft.reviewedSource || null);
|
||||
const [fiyatlar, setFiyatlar] = useState(() => restoreBidPrices(storedDraft));
|
||||
const kaynakKontrolGerekli = reviewedSource !== sourceSnapshot;
|
||||
@@ -79,7 +85,7 @@ export const BidPackageBuilder = ({ results, tender }) => {
|
||||
|
||||
const kalemToplami = useMemo(() => roundMoney(satirlar.reduce((t,r) => t + (bidRowTotal(r) ?? 0),0)), [satirlar]);
|
||||
const saveDraft = async () => {
|
||||
const saved = await mutateTender(tender.id, {bidDraft:{firma,teklifTuru,gecerlilikGun,kisim,goturuBedel,priceSchema:1,pricesBySource:fiyatlar,sourceSnapshot,reviewedSource}});
|
||||
const saved = await mutateTender(tender.id, {bidDraft:{firma,teklifTuru,gecerlilikGun,kisim,goturuBedel,priceSchema:1,pricesBySource:fiyatlar,sourceSnapshot,reviewedSource,checks,manualDocuments,analysisSource:{itemsAndSpecs:effectiveResults.itemsAndSpecs || [],documentChecklist:effectiveResults.documentChecklist || [],documentVersion:effectiveResults.documentVersion || null}}});
|
||||
if (saved) { setDirty(false); setHata(null); }
|
||||
else setHata('Taslak kaydedilemedi. Tekrar deneyin.');
|
||||
};
|
||||
@@ -90,7 +96,8 @@ export const BidPackageBuilder = ({ results, tender }) => {
|
||||
const kalemEksik = teklifTuru === 'birim' && validateBidRows(satirlar).length > 0;
|
||||
const turCeliskisi = teklifTuru === 'goturu' && /birim fiyat/i.test(tender?.aciklama || '');
|
||||
const sureEksik = !(Number(gecerlilikGun) > 0) || (kaynakGecerlilik && Number(gecerlilikGun) < Number(kaynakGecerlilik[1]));
|
||||
const hazir = eksikler.length === 0 && toplam > 0 && !kalemEksik && !turCeliskisi && !sureEksik && !kaynakKontrolGerekli;
|
||||
const kontrolEksikleri = preparationBlockers(kalemler, documents, checks);
|
||||
const hazir = eksikler.length === 0 && toplam > 0 && !kalemEksik && !turCeliskisi && !sureEksik && !kaynakKontrolGerekli && kontrolEksikleri.length === 0;
|
||||
|
||||
const formVerisi = () => ({
|
||||
...firma,
|
||||
@@ -110,7 +117,7 @@ export const BidPackageBuilder = ({ results, tender }) => {
|
||||
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, results?.documentChecklist || []));
|
||||
if (tip === 'liste') belgeYazdir('Evrak Kontrol Listesi', evrakListesiHtml(f, documents));
|
||||
} catch (e) {
|
||||
setHata(e.message);
|
||||
}
|
||||
@@ -297,6 +304,13 @@ export const BidPackageBuilder = ({ results, tender }) => {
|
||||
</p>
|
||||
)}
|
||||
|
||||
<PreparationChecks rows={kalemler} documents={documents} manualDocuments={manualDocuments}
|
||||
setManualDocuments={value => {setManualDocuments(value);setDirty(true);}} checks={checks} setChecks={setChecks}/>
|
||||
{kontrolEksikleri.length > 0 && <details className="bg-amber-50 border border-amber-300 rounded-xl p-3">
|
||||
<summary className="text-xs font-bold cursor-pointer">{kontrolEksikleri.length} belge/uygunluk kontrolü tamamlanmalı</summary>
|
||||
<ul className="text-xs list-disc pl-5 mt-2 space-y-1">{kontrolEksikleri.map((message,i)=><li key={i}>{message}</li>)}</ul>
|
||||
</details>}
|
||||
|
||||
{/* Toplam */}
|
||||
<div className="bg-slate-900 text-white rounded-xl p-4 space-y-1">
|
||||
<div className="flex items-baseline justify-between gap-3 flex-wrap">
|
||||
@@ -327,7 +341,7 @@ export const BidPackageBuilder = ({ results, tender }) => {
|
||||
{[
|
||||
{ t: 'mektup', ad: 'Teklif Mektubu', ikon: FileSignature, aciklama: 'Rakam ve yazı ile bedel' },
|
||||
{ t: 'cetvel', ad: 'Birim Fiyat Teklif Cetveli', ikon: Table2, aciklama: `${kalemler.length} kalem` },
|
||||
{ t: 'liste', ad: 'Evrak Kontrol Listesi', ikon: ListChecks, aciklama: `${(results?.documentChecklist || []).length} belge` },
|
||||
{ t: 'liste', ad: 'Evrak Kontrol Listesi', ikon: ListChecks, aciklama: `${documents.length} belge` },
|
||||
].map((b) => (
|
||||
<button
|
||||
key={b.t}
|
||||
@@ -349,7 +363,7 @@ export const BidPackageBuilder = ({ results, tender }) => {
|
||||
<p className="text-[11px] text-slate-500">
|
||||
{eksikler.length > 0
|
||||
? 'Yukarıdaki zorunlu alanları doldurun.'
|
||||
: 'Belgeleri hazırlamak için teklif tutarını girin.'}
|
||||
: 'Tutar, kaynak, belge ve ürün uygunluğu kontrollerini tamamlayın.'}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user