From 91b8ea94b843b10eeeebedb02a939fc5ba7cbf06 Mon Sep 17 00:00:00 2001 From: ht Date: Fri, 4 Sep 2026 00:16:58 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20sinir=20deger=20hesaplayici=20=E2=80=94?= =?UTF-8?q?=20Tebli=C4=9F=20md.=2079/45=20formulleri,=202026=20R=20katsayi?= =?UTF-8?q?lari?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Formuller kaynagindan alindi (mevzuat.gov.tr Kamu Ihale Genel Tebligi, kullanicinin Chrome'u uzerinden okundu; formuller Teblig'de gorsel oldugu icin ekran goruntusunden): - Md. 79.1.2 hizmet (personel dayali olmayan): SD = ((YM + ΣT)/(n+1)) × R, YM'nin %60 alti ve YM ustu teklifler haric - Md. 79.1.1 personel calistirmaya dayali: SD = kar haric YM - Md. 62/A.1 (RG 9/4/2026): mal aliminda 79 uygulanir - Md. 45.1.1 yapim: Tort1/σ/Tort2, C = Tort2/YM, K parcali, SD = K×Tort2/(C×N); N 1,00 (B/C/D/E gruplari) veya 1,20 (45.1.1.1) - R katsayilari: KIK Kurul karari 21.01.2026 (.doc'tan okundu): arac kiralama 0,77, bilgisayar 0,87, yemek 0,77, muhendislik 0,72, sigorta 0,74, tasima 0,78, diger 0,78 Dogrulama: Teblig'in kendi 45.2 ornegi (YM 100.000, N 1,20, 12 teklif) ile birebir — Tort1 66.270,00, σ 20.317,05, Tort2 63.237,50, C 0,632, K 0,627, SD 52.281,00. Yuvarlama kurallari ornekteki gibi (2/3 ondalik). Arac: ust menude "Sinir Deger"; alim turu, YM, teklif listesi, R/N secimi, "benim teklifim sinirin altinda mi" uyarisi, adim adim hesap. Co-Authored-By: Claude Fable 5.1 --- src/App.jsx | 2 + src/components/TopNavigation.jsx | 1 + src/components/tools/SinirDeger.jsx | 156 ++++++++++++++++++++++++++++ src/services/sinirDeger.js | 105 +++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 src/components/tools/SinirDeger.jsx create mode 100644 src/services/sinirDeger.js diff --git a/src/App.jsx b/src/App.jsx index 01875de..8ff6c65 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -21,6 +21,7 @@ import { ResultSearch } from './components/tools/ResultSearch'; import { TenderCalendar } from './components/tools/TenderCalendar'; import { ContractSearch } from './components/tools/ContractSearch'; import { VatCalculator } from './components/tools/VatCalculator'; +import { SinirDeger } from './components/tools/SinirDeger'; import { PriceAnalysis } from './components/tools/PriceAnalysis'; import { CompetitorRadar } from './components/tools/CompetitorRadar'; import { DocumentVault } from './components/tools/DocumentVault'; @@ -61,6 +62,7 @@ const MainContent = () => { {activeTab === 'takvim' && } {activeTab === 'sozlesme' && } {activeTab === 'kdv' && } + {activeTab === 'sinir' && } {activeTab === 'fiyat' && } {activeTab === 'kanban' && } {activeTab === 'rakip_radar' && } diff --git a/src/components/TopNavigation.jsx b/src/components/TopNavigation.jsx index 08d12a7..ab53125 100644 --- a/src/components/TopNavigation.jsx +++ b/src/components/TopNavigation.jsx @@ -25,6 +25,7 @@ export const TopNavigation = () => { { id: 'takvim', label: 'İhale Takvimi', icon: CalendarDays }, { id: 'sozlesme', label: 'Sözleşme Sorgula', icon: FileCheck2 }, { id: 'kdv', label: 'KDV Hesapla', icon: Calculator }, + { id: 'sinir', label: 'Sınır Değer', icon: Calculator }, { id: 'fiyat', label: 'Fiyat Analizi', icon: TrendingUp }, { id: 'kanban', label: 'Kanban Pano', icon: Kanban, badge: 'Sürükle Takip' }, { id: 'rakip_radar', label: 'Rakip Radar', icon: Radar, badge: 'Canlı Uyar' }, diff --git a/src/components/tools/SinirDeger.jsx b/src/components/tools/SinirDeger.jsx new file mode 100644 index 0000000..e9359b5 --- /dev/null +++ b/src/components/tools/SinirDeger.jsx @@ -0,0 +1,156 @@ +import React, { useMemo, useState } from 'react'; +import { Scale, AlertTriangle, CheckCircle2, Info } from 'lucide-react'; +import { sinirDegerHizmet, sinirDegerPersonel, sinirDegerYapim, teklifleriAyir, R_2026, R_KAYNAK } from '../../services/sinirDeger'; + +/** + * Aşırı düşük teklif sınır değeri hesaplayıcı. + * Formüller Kamu İhale Genel Tebliği md. 79 (hizmet/mal) ve 45 (yapım), + * R katsayıları KİK 21.01.2026 Kurul kararı — kaynaklar services/sinirDeger.js'de. + * Teklifçinin sorusu: "Teklifim sınırın altında kalıp aşırı düşük sorgusuna girer mi?" + */ +const tl = (n) => (Number.isFinite(n) ? n.toLocaleString('tr-TR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' TL' : '—'); + +export const SinirDeger = () => { + const [tur, setTur] = useState('hizmet'); // hizmet | mal | personel | yapim + const [ym, setYm] = useState(''); + const [tekliflerMetin, setTekliflerMetin] = useState(''); + const [rSecim, setRSecim] = useState(String(R_2026[6].r)); + const [rOzel, setROzel] = useState(''); + const [nKat, setNKat] = useState('1.2'); + const [benimTeklif, setBenimTeklif] = useState(''); + + const teklifler = useMemo(() => teklifleriAyir(tekliflerMetin), [tekliflerMetin]); + const r = rSecim === 'ozel' ? Number(String(rOzel).replace(',', '.')) : Number(rSecim); + + const sonuc = useMemo(() => { + if (tur === 'personel') return ym ? sinirDegerPersonel({ karHaricYm: ym }) : null; + if (!ym || !teklifler.length) return null; + if (tur === 'yapim') return sinirDegerYapim({ ym, teklifler, n: Number(nKat) }); + return sinirDegerHizmet({ ym, teklifler, r }); + }, [tur, ym, teklifler, r, nKat]); + + const benim = teklifleriAyir(benimTeklif)[0]; + const altinda = sonuc?.sd != null && Number.isFinite(benim) ? benim < sonuc.sd : null; + + return ( +
+
+
+
+
+

Sınır Değer Hesaplayıcı

+

Teklifiniz aşırı düşük teklif sorgusuna girer mi? Kamu İhale Genel Tebliği md. 79 / 45 formülleriyle.

+
+
+
+ +
+
+
+ Alım türü +
+ {[['hizmet', 'Hizmet (personel dayalı olmayan)'], ['mal', 'Mal alımı'], ['personel', 'Hizmet (personel çalıştırmaya dayalı)'], ['yapim', 'Yapım işi']].map(([k, ad]) => ( + + ))} +
+ {tur === 'mal' &&

Md. 62/A.1 (RG 9/4/2026): mal alımında aşırı düşük değerlendirmesi 79 uncu maddeye göre yapılır — hizmet formülü uygulanır.

} +
+ + + + {tur !== 'personel' && ( +