diff --git a/docs/quality/qa-health-portfolio.json b/docs/quality/qa-health-portfolio.json new file mode 100644 index 0000000..991cafb --- /dev/null +++ b/docs/quality/qa-health-portfolio.json @@ -0,0 +1,17 @@ +{ + "date": "2026-09-06", + "environment": "localhost:5182 synthetic profile and tender", + "checks": { + "saved": true, + "reloadPreserved": true, + "selectedDeclaration": true, + "suitabilityReset": true, + "outputStillBlocked": true, + "draftSelectionPreserved": true + }, + "limits": [ + "Synthetic declarations only, no official UTS check", + "One device portfolio record and one tender row tested", + "Profile later changes do not automatically overwrite the saved tender snapshot" + ] +} diff --git a/docs/quality/uygulama-durumu.md b/docs/quality/uygulama-durumu.md index bfe719d..438365c 100644 --- a/docs/quality/uygulama-durumu.md +++ b/docs/quality/uygulama-durumu.md @@ -897,3 +897,10 @@ Taslak türü seçicisine erişilebilir ad eklendi. Üretim derlemesi geçti. Ö - Sahte ilerleme yüzdeleri, konfeti, doğrulanmış sektör/ÜTS iddiaları kaldırıldı. Modal başlığı/alanlar/kapama etiketlendi; odak geri dönüşü, Escape ve Tab sınırı eklendi. - 202 otomatik test ve derleme geçti. Yerel normal hesapta taramasız ekleme, kaydetmeden kapatma, kayıt onayı, yenileme sonrası kalıcılık, yapılandırılmamış tarama hatası ve mevcut ürünü koruma dahil 6 tarayıcı kontrolü geçti (qa-company-profile.json). Başarılı tarama öneri dönüşümü stub testte doğrulandı; gerçek AI/site taraması yapılmadı. - Marka/model, yapılandırılmış ÜTS durumu ve servis kapasitesi portföyü henüz eklenmedi. Çok cihazlı eşzamanlı profil düzenleme ve başarılı gerçek tarama kabulü açık. Profil kaydı için mevcut hesap veri deposu kullanılır; bu tur yeni sunucu şeması yoktur. + +### D07 — Yapılandırılmış sağlık portföyü ve kalem seçimi — 6 Eylül 2026 +- Firma profilinde kalıcı healthPortfolio kayıtları eklendi: ürün grubu, marka, model/hizmet adı, ÜTS beyanı ve açıklaması, kurulum/bakım/servis kapasitesi. Sarf/test, cihaz/servis ve personelli hizmet kapsamları ayrı seçilir. Tüm alanlar firma beyanı olarak sunulur. +- Web taraması önerileri alınırken elle oluşturulmuş sağlık portföyü korunur. Portföy mevcut açık profil kaydetme akışıyla hesap deposuna yazılır. +- Hazırlık kaleminde portföyden ürün seçilebilir; seçimin kimliği ve o andaki beyan kopyası bidDraft içinde saklanır. Ürün seçimi veya marka/model değişimi önceki teknik kaynak/uygunluk/ÜTS/numune/servis/teslim kontrollerini sıfırlar; uygunluk otomatik verilmez. Yeniden kontrol gerekliliği alanda açıklanır. +- 203 otomatik test ve derleme geçti. Seçilen beyan kopyasının kaynak nesne değişince korunması ve bütün teknik onayların pending kalması test edildi. Yerel cihaz portföyü kaydı/yenileme, kaleme seçim, eski uygunluğu sıfırlama, çıktı engeli ve taslakta seçimin korunması dahil 6 tarayıcı kontrolü geçti (qa-health-portfolio.json). +- Sentetik ÜTS beyanı resmi kayıt doğrulaması değildir. Portföy sonradan değişince mevcut teklifin seçilmiş kopyası otomatik güncellenmez; kullanıcı yeniden seçebilir. Bu tur tek cihaz/tek kalem sınandı; gerçek firma portföyü, beş resmi dosya ve dış çıktı kabulleri açık. diff --git a/src/components/CompanyScannerModal.jsx b/src/components/CompanyScannerModal.jsx index 3c5dec3..172d7bf 100644 --- a/src/components/CompanyScannerModal.jsx +++ b/src/components/CompanyScannerModal.jsx @@ -1,3 +1,4 @@ +import {HealthPortfolioEditor} from './HealthPortfolioEditor'; import React,{useState,useEffect,useRef,useId} from 'react'; import {useApp} from '../context/AppContext'; import {getToken} from '../services/auth'; @@ -24,7 +25,7 @@ function ProfileEditor(){ const scan=e=>{e.preventDefault();void run('scan',async()=>{ controller.current=new AbortController(); const proposal=await scanCompanyWebsite(url,{signal:controller.current.signal}); - if(alive.current){setCaps(proposal);setMessage('Tarama önerileri alındı. Alanları kontrol edip düzenleyin; henüz profilinize kaydedilmedi.');} + if(alive.current){setCaps(previous=>({...proposal,healthPortfolio:previous.healthPortfolio || []}));setMessage('Tarama önerileri alındı. Alanları kontrol edip düzenleyin; henüz profilinize kaydedilmedi.');} });}; const save=()=>run('save',async()=>{ await updateCompanyCapabilities(caps,{website:url,threshold}); @@ -61,6 +62,7 @@ function ProfileEditor(){ )} + edit('healthPortfolio',items)}/>

Uyum skoru terim eşleşmesi ve varsa anlamsal yakınlık girdisidir; başvuru yeterliliği değildir.

diff --git a/src/components/HealthPortfolioEditor.jsx b/src/components/HealthPortfolioEditor.jsx new file mode 100644 index 0000000..a6fcea2 --- /dev/null +++ b/src/components/HealthPortfolioEditor.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import {portfolioFields} from '../services/healthPortfolio'; +export function HealthPortfolioEditor({items,onChange,disabled}){ + const patch=(id,change)=>onChange(items.map(item=>item.id===id?{...item,...change}:item)); + return
+ Sağlık ürün ve hizmet portföyü +

Firma beyanıdır; resmi kayıt veya teknik uygunluk doğrulaması değildir. İhale hazırlığında seçilen ürünün bu sürümü taslakta tutulur.

+ {items.map((item,index)=>
+

Portföy kaydı {index+1}

+ {portfolioFields.map(([key,label])=>)} + + + +
)} + +
; +} diff --git a/src/components/PreparationChecks.jsx b/src/components/PreparationChecks.jsx index 1b9b7cf..8a0746e 100644 --- a/src/components/PreparationChecks.jsx +++ b/src/components/PreparationChecks.jsx @@ -1,3 +1,5 @@ +import {useApp} from '../context/AppContext'; +import {portfolioProductText,selectPortfolioProduct} from '../services/healthPortfolio'; import React, {useState} from 'react'; import {HEALTH_CHECKS, documentKey, documentRevision, documentScopeProblem} from '../services/preparationChecks'; const fieldClass = 'w-full border border-slate-300 rounded-lg p-2 text-xs bg-white'; @@ -6,6 +8,8 @@ const Status = ({value, onChange, optional = true}) => ; export function PreparationChecks({rows, documents, manualDocuments, setManualDocuments, checks, setChecks, vault, refreshVault, downloadFile}) { + const {userProfile}=useApp(); + const portfolio=userProfile.scrapedCapabilities?.healthPortfolio || []; const eligibleFiles = vault.documents.filter(file => !documentScopeProblem(file,vault.tenderIkn)); const [name,setName] = useState(''); const [clause,setClause] = useState(''); @@ -56,7 +60,16 @@ export function PreparationChecks({rows, documents, manualDocuments, setManualDo return
{row.name} — ürün/hizmet ve yükümlülük kontrolü
- +

Ürün seçimini veya marka/model metnini değiştirirseniz teknik kontroller ve kaynak açıklamaları yeniden doldurulmalıdır.

+ + {c.portfolioSnapshot&&

Seçim anındaki firma beyanı: {c.portfolioSnapshot.kind==='device'?'Cihaz ve servis':c.portfolioSnapshot.kind==='staffedService'?'Personelli hizmet':'Sarf / test ürünü'} · ÜTS: {{declared:'Kayıt mevcut — firma beyanı',notApplicable:'Uygulanmıyor — firma beyanı',unknown:'Kontrol gerekli'}[c.portfolioSnapshot.utsStatus] || 'Kontrol gerekli'} · {c.portfolioSnapshot.utsReference || 'Kayıt açıklaması yok'} · Servis: {c.portfolioSnapshot.serviceCapacity || 'Belirtilmedi'}. İhale koşullarını aşağıda ayrıca doğrulayın.

} +