feat: ihale dokümanları + OKAS kalem verisi + doğrudan temin (Playwright) + kalıcı arşiv

1) İhale evrakları (yeni)
   - server/documents.mjs: EKAP doküman URL üretimi (imzalı), ilan metni +
     OKAS kalem çıkarımı, Playwright ile doküman metni (varsa)
   - /api/documents/url · /ilan · /text · /config uçları
   - TenderDocuments paneli: 'EKAP Dokümanlarını Aç' + 'İlan Metnini AI ile
     Analiz Et' (11K+ karakter gerçek ilan metni doğrudan AI'ya gider)
   - NOT: eski EKAP host'u bot isteklerine bağlantı kesiyor; bağlantı
     kullanıcının tarayıcısında açılır, sunucu tarafı metin için Chromium gerekir

2) Kalem verisi gerçek oldu
   - ekap-scan: her ihale için IhaleDetay'dan OKAS ihtiyaç kalemleri çekilir
   - history-store: okas_kalemler kolonu + otomatik şema geçişi
   - --kalem-doldur modu: mevcut kayıtlara IKN'den çözerek kalem ekler
   - scheduler: tarama sonrası kalem doldurmayı zincirler
   - PriceAnalysis: yöntem şeffaflığı notu (birim fiyatlar kamuya açık değil;
     kategori bazlı yaklaşık değer olduğu açıkça yazıyor)

3) Doğrudan temin (Playwright)
   - Dockerfile: node:22-slim + nginx + Playwright/Chromium
   - scheduler: DT worker periyodik (DT_INTERVAL_SAAT, varsayılan 4 saat)
   - Bellek koruması: boş bellek DT_MIN_BOS_MB altındaysa tarama atlanır ve
     uyarı loglanır; DT_ENABLED=0 ile tamamen kapatılabilir

4) Kalıcı arşiv
   - Coolify'da /app/server/data volume bağlandı; arşiv artık deploy'lar
     arası korunuyor

Ayrıca: TenderDetailModal'daki sabit '3-5 Firma' tahmini kaldırıldı, yerine
gerçek geçerli teklif sayısı gösteriliyor.
This commit is contained in:
2026-08-28 22:31:40 +03:00
parent e2512be9f7
commit 1838de95f5
9 changed files with 500 additions and 25 deletions
+23 -13
View File
@@ -1,32 +1,42 @@
# Stage 1: Vite SPA build
FROM node:22-alpine AS build
FROM node:22-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: nginx (frontend) + node (canlı veri backend) tek container'da
FROM node:22-alpine
RUN apk add --no-cache nginx
# Stage 2: nginx (frontend) + node (canlı veri backend) + Playwright/Chromium
# NOT: Chromium yalnızca doğrudan temin (EKAP anti-bot) ve ihale dokümanı
# indirme için gerekli. Sunucu darlığında DT_ENABLED=0 ile kapatılabilir;
# uygulama ve diğer tüm veri kaynakları Chromium olmadan da çalışır.
FROM node:22-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends nginx ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Playwright + Chromium (yalnızca chromium; sistem bağımlılıklarıyla)
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
RUN npm init -y >/dev/null \
&& npm i --omit=dev playwright@1.62.1 \
&& npx playwright install --with-deps chromium \
&& npm cache clean --force
# Frontend
COPY --from=build /app/dist /usr/share/nginx/html
COPY --from=build /app/nginx.conf /etc/nginx/http.d/default.conf
COPY --from=build /app/nginx.conf /etc/nginx/sites-available/default
# Backend (yalnızca Node builtin'leri kullanır — npm bağımlılığı yok)
WORKDIR /app
# Backend (Node builtin'leri + playwright)
COPY --from=build /app/server ./server
# Geçmiş sonuç veritabanı (SQLite). Deploy'lar arası kalıcılık için Coolify'da
# /app/server/data yoluna bir volume bağlanmalı; bağlanmazsa tarayıcı veriyi
# her yeniden dağıtımdan sonra yeniden biriktirir.
# Kalıcı veri (Coolify'da /app/server/data volume olarak bağlı)
RUN mkdir -p /app/server/data
VOLUME ["/app/server/data"]
# Başlangıç: Node backend'i (sabit 3001) arka planda + nginx (80) ön planda.
# Coolify container'a PORT=80 verir; backend'i 3001'e sabitleyip nginx ile
# çakışmasını önlüyoruz (nginx /api → 127.0.0.1:3001 proxy'ler).
# Başlangıç: Node backend (3001) arka planda + nginx (80) ön planda.
RUN printf '#!/bin/sh\nset -e\nPORT=3001 node /app/server/index.js &\nexec nginx -g "daemon off;"\n' > /start.sh \
&& chmod +x /start.sh