extract exchange amount validation
This commit is contained in:
@@ -2006,3 +2006,9 @@ Doğrulama: 287 test geçti, üretim derlemesi başarılı.
|
|||||||
İhale kartı ve detay görünümündeki şirket uyum skoru rozetleri artık yüzde değerini ve eşleşme nedenlerine nasıl erişileceğini ARIA etiketiyle bildiriyor; skor yalnızca görsel rozet veya masaüstü tooltip’ine bağlı değil.
|
İhale kartı ve detay görünümündeki şirket uyum skoru rozetleri artık yüzde değerini ve eşleşme nedenlerine nasıl erişileceğini ARIA etiketiyle bildiriyor; skor yalnızca görsel rozet veya masaüstü tooltip’ine bağlı değil.
|
||||||
|
|
||||||
Doğrulama: 287 test geçti, üretim derlemesi başarılı.
|
Doğrulama: 287 test geçti, üretim derlemesi başarılı.
|
||||||
|
|
||||||
|
### 2026-09-06 · Kur tutarı doğrulama servisleştirildi
|
||||||
|
|
||||||
|
Kur hesaplayıcısının tutar sınırı bileşen içinden çıkarılıp saf doğrulama servisine taşındı; boş, negatif, sonlu olmayan ve sınır dışı değerler için bağımsız regresyon testi eklendi.
|
||||||
|
|
||||||
|
Doğrulama: 288 test geçti, üretim derlemesi başarılı.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
import { acknowledgeNoteDraft, editNoteDraft } from '../services/noteDrafts';
|
import { acknowledgeNoteDraft, editNoteDraft } from '../services/noteDrafts';
|
||||||
import { tenderStateKey } from '../services/tenderState';
|
import { tenderStateKey } from '../services/tenderState';
|
||||||
import { createTenderICS } from '../services/tenderCalendar';
|
import { createTenderICS } from '../services/tenderCalendar';
|
||||||
|
import { validateExchangeAmount, MAX_EXCHANGE_AMOUNT } from '../services/exchangeAmount';
|
||||||
|
|
||||||
export const TenderDetailModal = () => {
|
export const TenderDetailModal = () => {
|
||||||
const { activeTenderDetail, setActiveTenderDetail, toggleTrackTender, userProfile, setIsAiSpecAnalyzerOpen, gorevAc, gorevKontrol, aiAnalysisResults, tenders, mutateTender, savingCount, saveError, authUser, detailLoad, retryTenderDetail } = useApp();
|
const { activeTenderDetail, setActiveTenderDetail, toggleTrackTender, userProfile, setIsAiSpecAnalyzerOpen, gorevAc, gorevKontrol, aiAnalysisResults, tenders, mutateTender, savingCount, saveError, authUser, detailLoad, retryTenderDetail } = useApp();
|
||||||
@@ -49,7 +50,7 @@ export const TenderDetailModal = () => {
|
|||||||
const usdRate = fx?.rates?.USD;
|
const usdRate = fx?.rates?.USD;
|
||||||
const eurRate = fx?.rates?.EUR;
|
const eurRate = fx?.rates?.EUR;
|
||||||
const fxIsStale = Boolean(fx?.refreshError);
|
const fxIsStale = Boolean(fx?.refreshError);
|
||||||
const bidAmountValid = Number.isFinite(bidAmount) && bidAmount >= 0 && bidAmount <= 1e12;
|
const bidAmountValid = validateExchangeAmount(bidAmount);
|
||||||
|
|
||||||
if (!activeTenderDetail) return null;
|
if (!activeTenderDetail) return null;
|
||||||
// Havuzdaki güncel kayıt: takip/görev değişince düğme etiketleri de değişsin.
|
// Havuzdaki güncel kayıt: takip/görev değişince düğme etiketleri de değişsin.
|
||||||
@@ -385,7 +386,7 @@ export const TenderDetailModal = () => {
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = Number(e.target.value);
|
const value = Number(e.target.value);
|
||||||
setBidAmount(value);
|
setBidAmount(value);
|
||||||
setBidAmountError(Number.isFinite(value) && value >= 0 && value <= 1e12 ? null : 'Tutar 0 ile 1.000.000.000.000 TL arasında olmalıdır.');
|
setBidAmountError(validateExchangeAmount(value) ? null : `Tutar 0 ile ${MAX_EXCHANGE_AMOUNT.toLocaleString('tr-TR')} TL arasında olmalıdır.`);
|
||||||
}}
|
}}
|
||||||
className="w-full bg-white/10 border border-white/20 rounded-lg px-3 py-1.5 text-xs text-white"
|
className="w-full bg-white/10 border border-white/20 rounded-lg px-3 py-1.5 text-xs text-white"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
const MAX_EXCHANGE_AMOUNT = 1e12;
|
||||||
|
|
||||||
|
export function validateExchangeAmount(value) {
|
||||||
|
if (value === null || value === undefined || (typeof value === 'string' && !value.trim())) return false;
|
||||||
|
const amount = Number(value);
|
||||||
|
return Number.isFinite(amount) && amount >= 0 && amount <= MAX_EXCHANGE_AMOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { MAX_EXCHANGE_AMOUNT };
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { test } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { validateExchangeAmount, MAX_EXCHANGE_AMOUNT } from '../src/services/exchangeAmount.js';
|
||||||
|
|
||||||
|
test('exchange amount validator accepts finite non-negative amounts within limit', () => {
|
||||||
|
assert.equal(validateExchangeAmount(0), true);
|
||||||
|
assert.equal(validateExchangeAmount('125,50'), false);
|
||||||
|
assert.equal(validateExchangeAmount(125.5), true);
|
||||||
|
assert.equal(validateExchangeAmount(MAX_EXCHANGE_AMOUNT), true);
|
||||||
|
for (const value of [-1, Infinity, NaN, MAX_EXCHANGE_AMOUNT + 1, null, '']) assert.equal(validateExchangeAmount(value), false);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user