1235 lines
74 KiB
Markdown
1235 lines
74 KiB
Markdown
# Sozsoft Platform
|
||
|
||
**Çalışma zamanında yapılandırılabilen, çok kiracılı (multi-tenant) low-code uygulama motoru.**
|
||
|
||
Sozsoft Platform, klasik bir "kod yaz–derle–yayınla" uygulaması değildir. Ekranlar, menüler,
|
||
route'lar, yetkiler, veri kaynakları, iş akışları ve hatta API endpoint'leri **veritabanındaki
|
||
konfigürasyon kayıtlarından** üretilir. Yeni bir modül veya ekran eklemek çoğu durumda tek satır
|
||
React/C# kodu yazmadan, yalnızca konfigürasyon ile mümkündür.
|
||
|
||
> **Temel ilke:** Configuration first, code last.
|
||
> Bu ilkenin operasyonel karşılığı ve yapay zeka ajanları için bağlayıcı kurallar
|
||
> [`.github/instructions/ai.instructions.md`](.github/instructions/ai.instructions.md) dosyasındadır.
|
||
|
||
---
|
||
|
||
## İçindekiler
|
||
|
||
1. [Platform Ne Yapar?](#1-platform-ne-yapar)
|
||
2. [Mimari Genel Bakış](#2-mimari-genel-bakış)
|
||
3. [Teknoloji Yığını](#3-teknoloji-yığını)
|
||
4. [Depo Yapısı](#4-depo-yapısı)
|
||
5. [Hızlı Başlangıç](#5-hızlı-başlangıç)
|
||
6. [Yapılandırma (Configuration)](#6-yapılandırma-configuration)
|
||
7. [Low-Code Motoru: ListForm Ekosistemi](#7-low-code-motoru-listform-ekosistemi)
|
||
8. [Developer Kit](#8-developer-kit)
|
||
9. [Dinamik Menü, Route ve Yetki Modeli](#9-dinamik-menü-route-ve-yetki-modeli)
|
||
10. [Modül Kataloğu](#10-modül-kataloğu)
|
||
11. [Kimlik, Oturum ve Güvenlik](#11-kimlik-oturum-ve-güvenlik)
|
||
12. [Çok Kiracılılık (Multi-Tenancy)](#12-çok-kiracılılık-multi-tenancy)
|
||
13. [Bildirim ve Entegrasyonlar](#13-bildirim-ve-entegrasyonlar)
|
||
14. [Arka Plan İşleri](#14-arka-plan-işleri)
|
||
15. [Raporlama](#15-raporlama)
|
||
16. [Dosya Yönetimi ve CDN](#16-dosya-yönetimi-ve-cdn)
|
||
17. [Gerçek Zamanlı Özellikler](#17-gerçek-zamanlı-özellikler)
|
||
18. [Frontend Mimarisi](#18-frontend-mimarisi)
|
||
19. [API ve Swagger](#19-api-ve-swagger)
|
||
20. [Dağıtım (Deployment)](#20-dağıtım-deployment)
|
||
21. [Geliştirme Standartları ve Sık Kullanılan Komutlar](#21-geliştirme-standartları-ve-sık-kullanılan-komutlar)
|
||
22. [Sorun Giderme](#22-sorun-giderme)
|
||
23. [Bilinen Sınırlar ve Notlar](#23-bilinen-sınırlar-ve-notlar)
|
||
|
||
---
|
||
|
||
## 1. Platform Ne Yapar?
|
||
|
||
| Yetenek | Açıklama |
|
||
| --- | --- |
|
||
| **Dinamik liste/form ekranları** | `ListForm` + `ListFormField` kayıtlarıyla tanımlanan; grid, pivot, ağaç, grafik, gantt, scheduler, kart ve todo görünümlerini destekleyen ekranlar. |
|
||
| **Dinamik menü ve route** | Menüler ve route'lar veritabanından okunur; frontend bunları çalışma zamanında React Router'a bağlar. |
|
||
| **Yetki tabanlı görünürlük** | Menü, ekran, sütun ve buton seviyesinde ABP permission kontrolü. |
|
||
| **SQL Query Manager** | Tarayıcı içinden SQL nesne gezgini, sorgu editörü, sonuç grid'i ve tablo tasarımcısı. |
|
||
| **Custom / CRUD Endpoint** | Kod yazmadan, SQL veya tablo tanımından REST endpoint üretimi. |
|
||
| **Dynamic Service** | Roslyn ile çalışma zamanında derlenen ve controller olarak kaydedilen C# ApplicationService'ler. |
|
||
| **Custom Component** | Babel ile tarayıcıda derlenen, veritabanında saklanan React bileşenleri ve bunların route'ları. |
|
||
| **İş akışı / onay** | ListForm üzerinde görsel workflow tasarımcısı, koşullu dallanma ve çok kişili onay adımları. |
|
||
| **Çok kiracılılık** | Tenant başına ayrı bağlantı dizesi (ayrı veritabanı) desteği, şube (branch) ve organizasyon birimi kırılımı. |
|
||
| **Bildirim ve entegrasyon** | SMS, e-posta, WhatsApp, Rocket.Chat, masaüstü ve UI kanallarına kural tabanlı bildirim. |
|
||
| **Raporlama** | DevExpress Report Designer/Viewer + ListForm'dan otomatik üretilen dinamik raporlar. |
|
||
| **Arka plan işleri** | Hangfire + ABP Background Worker; zamanlanmış SQL, mail kuyruğu, yedekleme, oturum temizliği. |
|
||
| **Gerçek zamanlı** | SignalR tabanlı messenger ve video oda (WebRTC/TURN) altyapısı. |
|
||
| **Intranet & Forum** | Duyuru, anket, sosyal duvar, etkinlik; kategori/konu/gönderi tabanlı forum. |
|
||
| **Public web sitesi** | Ana sayfa, hakkımızda, hizmetler, ürün, ödeme, blog, demo ve iletişim içerikleri (tasarımcı ekranlarıyla düzenlenebilir). |
|
||
| **PWA** | Service worker ile offline kabuk, kontrollü sürüm güncellemesi ve changelog bildirimi. |
|
||
|
||
---
|
||
|
||
## 2. Mimari Genel Bakış
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────┐
|
||
│ UI — React 19 + Vite + TypeScript + DevExtreme + Tailwind (PWA) │
|
||
│ ├─ DynamicRouter (route kayıtlarından React Router üretimi) │
|
||
│ ├─ ListForm runtime (Grid / Pivot / Tree / Chart / Gantt / ...) │
|
||
│ ├─ Form runtime (DevExtreme Form, metadata ile alan üretimi)│
|
||
│ ├─ Developer Kit UI (SQL, endpoint, component, dynamic service) │
|
||
│ └─ easy-peasy store + React Query + SignalR │
|
||
└───────────────┬──────────────────────────────────────────────────────┘
|
||
│ HTTPS / OAuth2 (OpenIddict) / SignalR
|
||
┌───────────────▼──────────────────────────────────────────────────────┐
|
||
│ API — ASP.NET Core (.NET 10) + ABP Framework 10 │
|
||
│ ├─ HttpApi.Host : Swagger, OpenIddict, Hangfire, SignalR Hub, │
|
||
│ │ DevExpress Reporting, Setup/Migration akışı │
|
||
│ ├─ Application : ListForms, DeveloperKit, Identity, Tenants, │
|
||
│ │ Menu, Routes, DataSource, FileManagement, ... │
|
||
│ ├─ Domain : Entity'ler, dinamik veri erişimi, seed'ler │
|
||
│ └─ EF Core : Migration'lar, dinamik DbContext, tenant DB │
|
||
│ │
|
||
│ Modüller: Languages · Settings · Notifications · MailQueue · │
|
||
│ Sender · SqlQueryManager │
|
||
└───────────────┬──────────────────────────────────────────────────────┘
|
||
│
|
||
┌───────────────▼──────────────────────────────────────────────────────┐
|
||
│ Veri ve Altyapı │
|
||
│ SQL Server / PostgreSQL · Redis (cache + SignalR backplane) · │
|
||
│ Hangfire (job storage) · Dosya sistemi tabanlı BLOB/CDN · │
|
||
│ coturn (TURN) · nginx · Elasticsearch (opsiyonel) │
|
||
└──────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Akışın özeti:** Kullanıcı giriş yapar → ABP `application-configuration` yanıtına
|
||
`PlatformApplicationConfigurationContributor` menü, route ve yetkileri ekler → `DynamicRouter`
|
||
route kayıtlarını React bileşenlerine bağlar → `/admin/list/{ListFormCode}` gibi bir ekran
|
||
açıldığında `ListFormsAppService` metadata'yı, `ListFormDataAppService` ise veriyi döner →
|
||
DevExtreme bileşenleri bu metadata'ya göre kendini kurar.
|
||
|
||
---
|
||
|
||
## 3. Teknoloji Yığını
|
||
|
||
### Backend
|
||
|
||
| Bileşen | Sürüm / Notlar |
|
||
| --- | --- |
|
||
| .NET | `net10.0` (SDK 10.0.300, `global.json` ile sabit) |
|
||
| ABP Framework | 10.0.0 (Identity, TenantManagement, PermissionManagement, AuditLogging, OpenIddict, BlobStoring, BackgroundWorkers) |
|
||
| Veritabanı | SQL Server 2022 veya PostgreSQL 17 (`PlatformConsts.DefaultDatabaseProvider`) |
|
||
| ORM | Entity Framework Core |
|
||
| Kimlik | OpenIddict (password + refresh token, `/connect/token`) |
|
||
| Cache | Redis (opsiyonel; `Redis:IsEnabled`) |
|
||
| Job | Hangfire (`default`, `platform` kuyrukları) + ABP Background Workers |
|
||
| Raporlama | DevExpress Reporting (Web Document Viewer + Report Designer) |
|
||
| Log | Serilog |
|
||
| Dinamik derleme | Roslyn (`DynamicServiceCompiler`) |
|
||
| Şablon | Scriban (mail şablonları), MailKit/MimeKit |
|
||
| Gerçek zamanlı | SignalR (Redis backplane destekli) |
|
||
|
||
### Frontend
|
||
|
||
| Bileşen | Sürüm / Notlar |
|
||
| --- | --- |
|
||
| React | 19.2 |
|
||
| Build | Vite 8 + TypeScript 5.9 |
|
||
| UI kütüphaneleri | DevExtreme 26.1 (React), Tailwind CSS 3.4, kendi `components/ui` tasarım sistemi |
|
||
| Routing | react-router-dom 7 (dinamik route üretimi) |
|
||
| State | easy-peasy (global store) + @tanstack/react-query |
|
||
| Form | Formik + Yup, DevExtreme Form |
|
||
| Kod editörü | Monaco Editor |
|
||
| Runtime derleme | @babel/standalone (Custom Component) |
|
||
| Takvim/Gantt | FullCalendar, DevExtreme Scheduler/Gantt |
|
||
| Gerçek zamanlı | @microsoft/signalr |
|
||
| PWA | vite-plugin-pwa (Workbox) |
|
||
| Node | 24.13 / npm 11 (`volta` ile sabitlenmiş) |
|
||
|
||
---
|
||
|
||
## 4. Depo Yapısı
|
||
|
||
```
|
||
sozsoft-platform/
|
||
├── api/ # .NET çözümü (Sozsoft.Platform.sln)
|
||
│ ├── src/
|
||
│ │ ├── Sozsoft.Platform.Domain.Shared/ # Sabitler, enum'lar, permission kodları (AppCodes)
|
||
│ │ ├── Sozsoft.Platform.Domain/ # Entity'ler, dinamik veri erişimi, repository'ler
|
||
│ │ ├── Sozsoft.Platform.Application.Contracts/ # DTO'lar, servis arayüzleri, permission tanımları
|
||
│ │ ├── Sozsoft.Platform.Application/ # Uygulama servisleri (iş mantığı)
|
||
│ │ ├── Sozsoft.Platform.EntityFrameworkCore/ # DbContext, migration'lar, dinamik veri katmanı
|
||
│ │ ├── Sozsoft.Platform.HttpApi/ # Controller'lar (conventional)
|
||
│ │ ├── Sozsoft.Platform.HttpApi.Client/ # HTTP istemci proxy'leri
|
||
│ │ ├── Sozsoft.Platform.HttpApi.Host/ # Host: Swagger, auth, Hangfire, SignalR, raporlama
|
||
│ │ └── Sozsoft.Platform.DbMigrator/ # Migration + seed uygulaması
|
||
│ ├── modules/ # Bağımsız ABP modülleri
|
||
│ │ ├── Sozsoft.Languages/ # Dil, dil anahtarı, çeviri metinleri
|
||
│ │ ├── Sozsoft.Settings/ # Ayar tanımları ve ayar UI'ı
|
||
│ │ ├── Sozsoft.Notifications/ # Bildirim tipleri, kuralları, kullanıcı bildirimleri
|
||
│ │ ├── Sozsoft.MailQueue/ # Şablonlu mail kuyruğu ve ekleri
|
||
│ │ ├── Sozsoft.Sender/ # Mail (SES), SMS, WhatsApp, Rocket.Chat göndericileri
|
||
│ │ └── Sozsoft.SqlQueryManager/ # SQL nesne yönetimi ve sorgu çalıştırma
|
||
│ └── test/ # Test projeleri
|
||
├── ui/ # React uygulaması
|
||
│ └── src/
|
||
│ ├── routes/ # dynamicRouter, dynamicRouteLoader, route.constant
|
||
│ ├── views/ # list, form, admin, developerKit, public, intranet, forum, report, auth, setup
|
||
│ ├── components/ # ui (tasarım sistemi), template (layout), importManager, visualDesigner, componentEditor
|
||
│ ├── services/ # API istemcileri (her modül için ayrı servis dosyası)
|
||
│ ├── store/ # easy-peasy modelleri (auth, theme, locale, abpConfig, admin)
|
||
│ ├── contexts/ # ComponentContext (runtime bileşenler), Dialog, Scroll
|
||
│ └── utils/ # editorScriptRuntime, workflow, hooks, hoc, biçimlendirme yardımcıları
|
||
├── configs/
|
||
│ ├── docker/ # Yerel geliştirme için veri katmanı compose dosyaları ve scriptler
|
||
│ ├── deployment/ # Dev/Prod compose dosyaları, nginx/redis/turn konfigürasyonu, deploy scriptleri
|
||
│ ├── seeds/ # Runtime'da düzenlenebilen seed'ler; CDN ile aynı kapsam düzeni
|
||
│ │ # host/{crud,custom,wizard,sql,postgres}
|
||
│ │ # tenants/{tenantId}/{crud,custom,wizard,sql,postgres}
|
||
│ │ # {sql|postgres}/{object,execute}
|
||
│ └── ai/ # AI entegrasyonu (n8n akış tanımları)
|
||
├── .github/instructions/ # ai.instructions.md (bağlayıcı platform kuralları)
|
||
│ # lowcode.instructions.md (artefakt üretim referansı: şemalar, örnekler)
|
||
│ # dotnet.instructions.md (api/ için bağlayıcı .NET/ABP kod standardı)
|
||
│ # list.instructions.md (modül/liste ekleme prosedürü)
|
||
├── CLAUDE.md # Claude Code için operasyon kuralları
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Hızlı Başlangıç
|
||
|
||
### 5.1. Önkoşullar
|
||
|
||
- .NET SDK **10.0.300+**
|
||
- Node.js **24.x** ve npm **11.x** (Volta önerilir)
|
||
- Docker Desktop (veritabanı ve Redis için)
|
||
- DevExpress lisansı (`api/DevExpress_License.txt`) ve DevExtreme npm erişimi
|
||
|
||
### 5.2. Veri katmanını ayağa kaldırma
|
||
|
||
```powershell
|
||
# SQL Server + Redis
|
||
.\configs\docker\start_sql.bat
|
||
|
||
# veya PostgreSQL + Redis
|
||
.\configs\docker\start_postgres.bat
|
||
```
|
||
|
||
Compose dosyaları `configs/docker/docker-compose-data.yml` içindedir; `sql` ve `postgres`
|
||
profilleri ile hangi veritabanının kalkacağı seçilir. Redis her iki profilde de çalışır.
|
||
|
||
### 5.3. Backend
|
||
|
||
```powershell
|
||
cd api
|
||
dotnet restore
|
||
dotnet run --project src/Sozsoft.Platform.HttpApi.Host
|
||
```
|
||
|
||
Uygulama `https://localhost:44344` adresinde açılır. Swagger UI kök adreste yayınlanır.
|
||
|
||
**Veritabanı ilk kurulum:** Veritabanı yoksa host, tam ABP yığını yerine minimal bir
|
||
"setup" uygulaması ile açılır (`DbStartup/SetupAppRunner`). Bu durumda:
|
||
|
||
- `GET /api/setup/application-status` — veritabanının hazır olup olmadığını döner (anonim).
|
||
- UI tarafında `/setup` route'u (`views/setup/DatabaseSetup.tsx`) migration'ı tetikleyen ekranı gösterir.
|
||
- Migration için `Setup:MigrationPassword` yapılandırması veya `App.Setup.Migrate` yetkisi gerekir.
|
||
|
||
Alternatif olarak migration + seed'i doğrudan çalıştırabilirsiniz:
|
||
|
||
```powershell
|
||
dotnet run --project api/src/Sozsoft.Platform.DbMigrator
|
||
```
|
||
|
||
DbMigrator; şema migration'larını uygular ve ardından menü, route, permission, dil,
|
||
host ayarları, ülke/şehir/ilçe verileri ile seed edilmiş ListForm ekranlarını yükler
|
||
(kodla versiyonlanan sabit seed'ler `api/src/Sozsoft.Platform.DbMigrator/Migrations/`,
|
||
runtime'da düzenlenebilen seed'ler `configs/seeds/` altındadır — bkz. `App:SeedsPath`).
|
||
|
||
`configs/seeds` altında en üst seviye kapsamdır (CDN klasörleriyle aynı mantık): host
|
||
veritabanı için `host/`, her tenant için `tenants/{tenantId}/`. Kapsamın altında içerik
|
||
türüne göre `crud/`, `custom/`, `wizard/`, `data/`, `sql/`, `postgres/` klasörleri bulunur:
|
||
|
||
```
|
||
configs/seeds/
|
||
host/
|
||
crud/ custom/ wizard/ data/
|
||
sql/ { object/ execute/ }
|
||
postgres/ { object/ execute/ }
|
||
tenants/
|
||
{tenantId}/
|
||
crud/ custom/ wizard/ data/
|
||
sql/ { object/ execute/ }
|
||
postgres/ { object/ execute/ }
|
||
```
|
||
|
||
Aktif veritabanı sağlayıcısına göre `sql/` (SQL Server) ya da `postgres/` okunur. Her
|
||
`.sql` dosyası amacını belirten bir klasörün altındadır; klasör köklerinde dosya bulunmaz:
|
||
|
||
| Klasör | Ne zaman çalışır |
|
||
| --- | --- |
|
||
| `{sql\|postgres}/object` | Seed sırasında nesneyi oluşturur/günceller. SqlTableDesigner ve SqlQueryManager, deploy ettiği script'i çalıştığı kapsamın bu klasörüne yazar (host bağlamı → `host/`, tenant seçiliyken → `tenants/{tenantId}/`). |
|
||
| `{sql\|postgres}/execute` | Nesneyi oluşturur; ayrıca tüm migration ve seed'ler bittikten sonra `AfterAllMigrationsSqlExecutor` dosya adından türettiği procedure'ü çalıştırır (dosya adı = procedure adı, `schema.Procedure.sql` de olur). |
|
||
| `wizard` | ListForm Wizard'ın ürettiği `.json` konfigürasyonları; `WizardDataSeeder` kendi kapsamındaki dosyaları okur. |
|
||
| `crud` | CrudEndpoint konfigürasyonları; `CrudDataSeeder` kendi kapsamındaki dosyaları okur. |
|
||
| `custom` | Custom Component konfigürasyonları (`{Name}.json`); Component Manager kaydetme/silme sırasında dosyayı senkronlar, `CustomComponentDataSeeder` kendi kapsamındaki dosyaları okuyup veritabanına uygular. |
|
||
| `data` | Ekranlardan girilen listelerin veri aynası (`{ListFormCode}.json`). `ListForm.SeedFilePath` dolu olan ekranda `SeedSyncInsert/Update/Delete` bayraklarından işaretli olan işlemler dosyaya yansır (`ListFormSeedDataSynchronizer`); migrate/seed sırasında bütün contributor'lar bittikten sonra `ListFormSeedDataApplier` dosyayı geri uygular: anahtarı veritabanında **olmayan** satırları ekler, var olanlara dokunmaz. |
|
||
|
||
Klasör kökünde kalmış eski `.sql` dosyaları geriye dönük uyumluluk için hâlâ işlenir,
|
||
fakat `SqlDataSeeder` bunları uyarı ile loglar — ilgili klasöre taşınmaları beklenir.
|
||
|
||
### 5.4. Frontend
|
||
|
||
```powershell
|
||
cd ui
|
||
npm install
|
||
npm start # vite dev server (http://localhost:3000)
|
||
```
|
||
|
||
Visual Designer ve Custom Component altyapısının kullandığı bileşen kataloğu
|
||
`src/components/visualDesigner/generated/componentProps.json` dosyasında tutulur ve repoya
|
||
dahildir. `src/components/ui` altındaki bileşen prop'ları değiştiğinde bu dosya elle
|
||
güncellenmelidir.
|
||
|
||
### 5.5. İlk giriş
|
||
|
||
Seed edilen host yöneticisi ile `/login` üzerinden giriş yapılır (kullanıcı bilgileri
|
||
`PlatformIdentityDataSeeder` ve `HostData.json` ile belirlenir; ortam bazlı değerler
|
||
`HostData.Dev.json` / `HostData.Production.json` dosyalarındadır). Giriş sonrası
|
||
`/admin/dashboard` açılır.
|
||
|
||
---
|
||
|
||
## 6. Yapılandırma (Configuration)
|
||
|
||
### 6.1. Backend (`appsettings.json`)
|
||
|
||
| Anahtar | Açıklama |
|
||
| --- | --- |
|
||
| `App:SelfUrl` | API'nin kendi adresi (OpenIddict authority ile uyumlu olmalı). |
|
||
| `App:ClientUrl` | React uygulamasının kök adresi (mail linkleri bu adresi kullanır). |
|
||
| `App:CorsOrigins` | Virgülle ayrılmış izinli origin listesi; wildcard subdomain destekli. |
|
||
| `App:RedirectAllowedUrls` | OAuth yönlendirme için izinli adresler. |
|
||
| `App:CdnUrl` / `App:CdnPath` | Dosya servisinin adresi ve BLOB kök dizini. |
|
||
| `App:AttachmentsPath` | Mail kuyruğu eklerinin yazıldığı dizin. |
|
||
| `App:BackupPath` | Veritabanı yedek dizini (BackupWorker kullanır). |
|
||
| `App:Version` | Uygulama sürümü (UI sürüm kontrolü ile eşleşir). |
|
||
| `ConnectionStrings:SqlServer` / `PostgreSql` | Host veritabanı bağlantıları. |
|
||
| `Redis:IsEnabled` / `Redis:Configuration` | Dağıtık cache ve SignalR backplane. |
|
||
| `AuthServer:Authority` / `SwaggerClientId` | OpenIddict authority ve Swagger istemcisi. |
|
||
| `OpenIddict:TokenLifetimes:*` | Access/refresh token ömrü (dakika). |
|
||
| `Setup:MigrationPassword` | Setup ekranından migration tetiklemek için parola. |
|
||
| `StringEncryption:DefaultPassPhrase` | ABP string şifreleme anahtarı. |
|
||
| `Serilog:MinimumLevel` | Log seviyeleri. |
|
||
|
||
> **Güvenlik:** Depodaki `appsettings.json` dosyaları geliştirme değerleri içerir.
|
||
> Üretimde bağlantı dizeleri, `MigrationPassword`, `DefaultPassPhrase` ve entegrasyon
|
||
> anahtarları **ortam değişkeni veya secret yöneticisi** ile verilmelidir; repoya yazılmamalıdır.
|
||
|
||
### 6.2. Frontend (`ui/.env`, `.env.dev`, `.env.production`)
|
||
|
||
| Değişken | Açıklama |
|
||
| --- | --- |
|
||
| `VITE_API_URL` | API kök adresi. |
|
||
| `VITE_CDN_URL` | Dosya/CDN kök adresi. |
|
||
| `VITE_REACT_APP_VERSION` | `package.json` sürümünden beslenir. |
|
||
| `VITE_AI_URL` | AI asistanının n8n webhook kökü. |
|
||
| `VITE_USE_POLLING` | Dosya izlemede polling (WSL/Docker senaryoları). |
|
||
| `VITE_PWA_DEV` | Geliştirmede service worker'ı açar (varsayılan kapalı). |
|
||
|
||
### 6.3. Uygulama içi ayarlar
|
||
|
||
Çalışma zamanı ayarları veritabanında tutulur ve **Ayarlar** ekranından (`/admin/settings`)
|
||
yönetilir. `Sozsoft.Settings` modülü ayar tanımlarını, `SettingUiAppService` ise bu tanımların
|
||
UI gösterimini yönetir. Şifre politikası, oturum kuralları, gönderici kimlik bilgileri (SMS,
|
||
mail, WhatsApp, Rocket) ve AI bot yapılandırması bu yolla değiştirilir — kod dağıtımı gerekmez.
|
||
|
||
---
|
||
|
||
## 7. Low-Code Motoru: ListForm Ekosistemi
|
||
|
||
Platformun kalbi budur. Bir iş ekranı; bir `ListForm` kaydı, ona bağlı `ListFormField`
|
||
kayıtları ve bir menü/route/permission üçlüsünden oluşur.
|
||
|
||
### 7.1. Kavramlar
|
||
|
||
| Varlık | Rolü |
|
||
| --- | --- |
|
||
| `DataSource` | Hedef veritabanı bağlantısı (MSSQL / PostgreSQL). Ekranlar `DataSourceCode` ile bağlanır. |
|
||
| `ListForm` | Ekranın tüm davranışı: veri kaynağı, sütun/filtre/sayfalama/düzenleme ayarları, yetkiler, alt formlar, iş akışı, grafik ayarları. |
|
||
| `ListFormField` | Tek bir sütun/alanın davranışı: başlık, tip, genişlik, editör, lookup, doğrulama, biçim, yetki. |
|
||
| `ListFormCustomization` | Kullanıcı bazlı kişiselleştirme: kayıtlı filtre, grid state, sunucu tarafı join/where. |
|
||
| `ListFormWorkflow` | Onay ve koşul düğümlerinden oluşan iş akışı grafiği. |
|
||
| `ListFormImport` / `ImportLog` | Excel/CSV içe aktarma tanımı ve satır bazlı sonuç günlüğü. |
|
||
|
||
### 7.2. `ListForm` anatomisi
|
||
|
||
Ekran davranışı büyük ölçüde JSON kolonlarında saklanır. Öne çıkanlar:
|
||
|
||
| Alan | İşlevi |
|
||
| --- | --- |
|
||
| `SelectCommandType` + `SelectCommand` | Veri kaynağı türü: `Table`, `View`, `TableValuedFunction`, `Query`, `StoredProcedure`. |
|
||
| `KeyFieldName` / `KeyFieldDbSourceType` | Birincil anahtar alanı ve tipi. |
|
||
| `PermissionJson` | Ekranın create/read/update/delete/export/import/note yetki eşlemesi. |
|
||
| `EditingOptionJson` / `EditingFormJson` | Düzenleme modu (row/cell/batch/form/popup) ve düzenleme formu düzeni. |
|
||
| `FilterRowJson`, `HeaderFilterJson`, `FilterPanelJson`, `SearchPanelJson`, `GroupPanelJson` | Filtreleme, arama ve gruplama davranışı. |
|
||
| `ColumnOptionJson`, `PagerOptionJson`, `SelectionJson`, `StateStoringJson` | Sütun, sayfalama, seçim ve durum saklama ayarları. |
|
||
| `Insert/Update/DeleteCommand` (+ `Before` / `After`) | CRUD komutları ve öncesi/sonrası çalışacak SQL kancaları. |
|
||
| `Insert/Update/DeleteServiceAddress` | Varsayılan olarak `list-form-data/*`; özel endpoint'e yönlendirilebilir. |
|
||
| `SeedFilePath` | Doluysa seed sırasında listenin verisi kapsam klasöründeki bu JSON dosyasından geri yüklenir (`data/{ListFormCode}.json`). |
|
||
| `SeedSyncInsert` / `SeedSyncUpdate` / `SeedSyncDelete` | Ekranda yapılan hangi işlemin seed dosyasına yansıyacağı; kapalıysa o işlem dosyaya dokunmaz. |
|
||
| `SubFormsJson` | Ana-detay ilişkisi (ParentFieldName → ChildFieldName eşlemesi). |
|
||
| `WidgetsJson` | Ekranın üstünde gösterilecek KPI kartları. |
|
||
| `WorkflowJson` | İş akışı bağlaması. |
|
||
| `ExtraFilterJson` | Ekrana özel ek filtre araç çubuğu. |
|
||
| `PivotOptionJson`, `TreeOptionJson`, `GanttOptionJson`, `SchedulerOptionJson`, `TodoOptionJson` | Alternatif görünümlerin ayarları. |
|
||
| Grafik alanları (`SeriesJson`, `LegendJson`, `ArgumentAxisJson`, `ValueAxisJson`, `TooltipJson`, `ZoomAndPanJson`, …) | DevExtreme Chart yapılandırması. |
|
||
| `CustomJsSourcesJson` / `CustomStyleSourcesJson` | Ekran yüklendiğinde çalışacak JS/CSS. |
|
||
| `IsTenant`, `IsBranch`, `IsOrganizationUnit` | Otomatik tenant/şube/organizasyon birimi filtrelemesi. |
|
||
| `UserId`, `RoleId`, `CultureName` | Aynı ekranın kullanıcı, rol veya dil bazlı varyantları. |
|
||
|
||
### 7.3. Görünüm tipleri
|
||
|
||
Aynı `ListForm` tanımı, aynı veri hattı üzerinden birden fazla görünümle sunulabilir:
|
||
|
||
`Grid` · `Pivot` · `Tree` · `Chart` · `Gantt` · `Scheduler` · `CardView` · `TodoBoard (Kanban)` ·
|
||
`Widget Group`
|
||
|
||
Kullanıcı görünümler arasında geçiş yapabilir; grid durumu (sütun sırası, genişlik, filtre,
|
||
gruplama) kullanıcı bazlı saklanır ve sıfırlanabilir.
|
||
|
||
**TodoBoard artık bir Kanban panosudur:** kolonlar `TodoOptionJson` içindeki `statusExpr`
|
||
değerlerinden üretilir, kartlar kolonlar arasında sürüklenerek durum değiştirir ve panodan yeni
|
||
kolon (durum) eklenebilir. Kart içeriği `titleExpr`, `descriptionExpr`, `dueDateExpr`, `tagExpr`
|
||
ve atanan kullanıcı alanlarından kurulur.
|
||
|
||
### 7.4. Alan (field) davranışı
|
||
|
||
- **Editör tipleri:** `dxTextBox`, `dxTextArea`, `dxNumberBox`, `dxDateBox`, `dxDateRangeBox`,
|
||
`dxCalendar`, `dxCheckBox`, `dxSwitch`, `dxRadioGroup`, `dxSelectBox`, `dxTagBox`, `dxLookup`,
|
||
`dxDropDownBox`, `dxGridBox`, `dxAutocomplete`, `dxColorBox`, `dxHtmlEditor`, `dxSlider`,
|
||
`dxRangeSlider` — ayrıca görsel yükleme/görüntüleme editörleri.
|
||
- **Lookup kaynakları:** `StaticData`, `Query`, `WebService`; ebeveyn–çocuk (cascade) desteklidir.
|
||
- **Doğrulama:** `ValidationRuleJson` ile required/range/pattern/custom kuralları.
|
||
- **Editör script:** `EditorScript` alanı ile alan değişiminde çalışan JS (örn. tarih farkından
|
||
gün hesaplama, miktar × birim fiyat toplamı). Çalıştırma `utils/editorScriptRuntime.ts` üzerinden yapılır.
|
||
- **Editör seçenekleri:** `EditorOptions` alanı DevExtreme editörüne geçirilen JSON'dur
|
||
(format, maske, placeholder, yükseklik, buton görünürlüğü, platform editörlerinin tipli
|
||
ayarları). Elle JSON yazmak zorunlu değildir; bkz. 7.4.1.
|
||
- **Koşullu biçimlendirme:** `ColumnStylingJson`, `ColumnCssClass`/`ColumnCssValue`.
|
||
- **Alan bazlı yetki:** `PermissionJson` ile sütun düzeyinde okuma/yazma/dışa aktarma kontrolü.
|
||
|
||
#### 7.4.1. Script Builder ve Editor Options Builder
|
||
|
||
`EditorScript` ve `EditorOptions` alanları hem görsel olarak hem de seeder kodundan üretilir;
|
||
**iki tarafın çıktısı birebir aynı olmak zorundadır.**
|
||
|
||
**Editor Script Builder** (`json-row-operations/editor-script/`)
|
||
|
||
- Kural sözlüğü `scriptRecipes.ts` içindedir; her tarif (recipe) tek satırlık runtime çağrısı üretir.
|
||
Gruplar: hesap (`calc`), veri (`data`), görünüm (`view`), bildirim, API.
|
||
- Üretilen script'in ilk satırındaki `// @builder {...}` başlığı kuralları saklar. Dialog script'i
|
||
regex ile çözmeye çalışmaz, bu başlıktan geri okur; başlık bozulursa/elle düzenlenirse script
|
||
"manuel" sayılır ve kural editörü kapanır.
|
||
- Kural tetikleyicileri: `change` (varsayılan), `open` (form açılışında — varsayılan değer üretmek
|
||
için, script başına `// @runOnOpen` direktifi eklenir), `both`.
|
||
- Koşullar `and`/`or` ile birleşir: `equals`, `notEquals`, `contains`, `empty`, `notEmpty`,
|
||
`greaterThan`, `lessThan`, `isTrue`, `isFalse`, `always`.
|
||
- Dialog'un kendisi ortaktır (`components/scriptBuilder/ScriptBuilderDialog.tsx` + IntelliSense);
|
||
ListForm lehçesi `formScriptDialect.ts`, Visual Designer lehçesi `designerScriptDialect.ts`
|
||
ile aynı sözleşmeye bağlanır.
|
||
|
||
**Seeder tarafı (C#)** — `Sozsoft.Platform.Domain.Shared/Editors/`
|
||
|
||
`scriptRecipes.ts` ve editorOptions sözlüğünün C# portudur. Seeder ile basılan script/JSON,
|
||
dialogda açılıp görsel olarak düzenlenebilir kalır. Bir tarif TypeScript tarafında değişirse
|
||
buradaki karşılığı da güncellenmelidir.
|
||
|
||
| Tip | Kullanım |
|
||
| --- | --- |
|
||
| `EditorScript` | `Multiply`, `Subtract`, `Percent`, `Sum`, `Formula`, `Today`, `Days`, `Hours`, `Copy`, `SetValue`, `Clear`, `ReadOnly`, `Notify`, `Ask`, `OpenUrl`, `ApiToField`, `Custom` → `EditorScript.Build(rules)` |
|
||
| `EditorScriptRule` | `.When(...)` / `.WhenAny(...)` koşulları, `.OnChange()` / `.OnOpen()` / `.OnOpenAndChange()` tetikleyicisi; `string`'e örtük dönüşür |
|
||
| `EditorScriptCondition` | `Is`, `IsNot`, `Contains`, `IsEmpty`, `IsNotEmpty`, `GreaterThan`, `LessThan`, `IsTrue`, `IsFalse`, `Always` |
|
||
| `EditorOptions` | Hazır başlangıçlar: `Disabled()`, `ReadOnly()`, `ShowClearButton()`, `Multiline(h)`, `Number(precision)`, `Percent()`, `Date()`, `DateTime()`, `Time(interval)`, `Phone()`, `Slider()`, `ImageUpload()`, `Html(h)` |
|
||
| `EditorOptionsBuilder` | Akıcı ekleme: `.Placeholder()`, `.MaxLength()`, `.Height()`, `.Width()`, `.Format()`, `.Mask()`, `.Flag()`, `.Text()`, `.Number()`, `.Json()`; `string`'e örtük dönüşür |
|
||
|
||
```csharp
|
||
EditorOptions = EditorOptions.Number(4).ShowClearButton(),
|
||
EditorOptions = EditorOptions.Multiline(60).Placeholder("Açıklama"),
|
||
EditorScript = EditorScript.Build(
|
||
EditorScript.Multiply("Quantity", "UnitPrice", "Total"),
|
||
EditorScript.Percent("Total", "VatRate", "VatAmount", mode: EditorScriptPercentMode.Add)
|
||
.When(EditorScriptCondition.IsNotEmpty("VatRate"))),
|
||
```
|
||
|
||
**Editor Options Builder** (`json-row-operations/editor-options/`)
|
||
|
||
- UI tamamen `optionSpecs.ts` veri sözlüğünden üretilir; yeni bir ayar eklemek için oraya tek
|
||
satır yazmak yeterlidir. Her ayar `path` (örn. `format.precision`), tip (`boolean` üç durumlu /
|
||
`number` / `text` / `select` / `size` / `stringList` / `json`), grup ve hangi editörlerde
|
||
anlamlı olduğu bilgisini taşır.
|
||
- `platform: true` işaretli ayarlar backend'in tipli DTO'ya (`GridBoxOptionsDto`,
|
||
`TagBoxOptionsDto`, `ImageUploadOptionsDto`) deserialize ettiği alanlardır; yanlış tipte
|
||
yazılırsa sessizce yok sayılır.
|
||
- `presets.ts` hazır kalıplar sunar (HTML editör tam araç çubuğu, telefon maskesi, tarih/saat…);
|
||
kalıp mevcut JSON ile **birleştirilir**, diğer ayarları silmez.
|
||
|
||
### 7.5. İş akışı ve onay
|
||
|
||
`FormTabWorkflow` ve `views/admin/listForm/workflow/WorkflowDesigner.tsx` üzerinden görsel
|
||
tasarlanır. Düğüm türleri koşul karşılaştırması (`CompareColumn`/`CompareOperator`/`CompareValue`)
|
||
ve onay adımlarıdır; her adım için `NextOnTrue`, `NextOnFalse`, `NextOnApprove`, `NextOnReject`
|
||
geçişleri tanımlanır. Onaycı birden fazla kişi olabilir. Formlar içinde iş akışına bağlı özel
|
||
butonlar gösterilebilir.
|
||
|
||
### 7.6. Yeni ekran ekleme akışı (Wizard)
|
||
|
||
`/admin/listform/wizard` altındaki sihirbaz, aşağıdaki artefaktları tek akışta üretir:
|
||
|
||
1. **ListForm** kaydı (kod, ad, başlık, veri kaynağı, select komutu, anahtar alan)
|
||
2. **ListFormField** kümesi (sütunlar, editörler, lookup'lar, doğrulamalar)
|
||
3. **Route** kaydı (`key`, `path`, `componentPath`, `routeType`, `authority`)
|
||
4. **Menu** kaydı (`ParentCode`, `Code`, `DisplayName`, `Url`, `Icon`, `RequiredPermissionName`, `Order`)
|
||
5. **Permission** kayıtları (`.Default`, `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note`)
|
||
6. **Dil anahtarları** (menü, başlık, açıklama; EN + TR)
|
||
7. Gerekiyorsa **ayar/entegrasyon** bağımlılıkları
|
||
8. **Seed dosyası** — `configs/seeds/{host|tenants/{tenantId}}/wizard/{Ad}.json` (wizard cevapları + üretilen `ListForm`/`Fields` sözleşmesi)
|
||
9. **Doğrulama ve geri alma** notları
|
||
|
||
**Adım bileşenleri.** Adımlar numaralı dosya adları yerine işlevleriyle adlandırılır ve
|
||
`React.lazy` ile yüklenir; aynı anda yalnızca görünen adım indirilir, sihirbazın açılış maliyeti
|
||
adım sayısından bağımsızdır.
|
||
|
||
| Adım | Dosya | İçerik |
|
||
| --- | --- | --- |
|
||
| Menü ve kimlik | `WizardStepMenu.tsx` | Wizard adı, ListForm kodu, menü ağacı/üst menü, ikon, sıra, izin grubu, dil metinleri |
|
||
| Veri ayarları | `WizardStepDataSettings.tsx` | Veri kaynağı, select komutu tipi, anahtar alan, CRUD endpoint diyaloğu |
|
||
| Alanlar | `WizardStepFields.tsx` | Sütun grupları, editör tipleri, lookup, doğrulama |
|
||
| Alt formlar | `WizardStepSubForms.tsx` | Ana–detay ilişki eşlemesi |
|
||
| Widget'lar | `WizardStepWidgets.tsx` | KPI kartları |
|
||
| İş akışı | `WizardStepWorkflow.tsx` | Onay/koşul grafiği |
|
||
| Düzen adımları | `WizardStepTodoLayout` · `WizardStepTreeLayout` · `WizardStepGanttLayout` · `WizardStepSchedulerLayout` | Yalnızca ilgili görünüm açıksa görünür |
|
||
| Bileşen | `WizardStepComponent.tsx` · `WizardStepCustomComponent.tsx` | Custom yolunda bağlanacak bileşen |
|
||
| Yayınlama | `WizardStepDeploy.tsx` | Özet, doğrulama ve seed dosyasının üretimi |
|
||
|
||
Menü ağacı yardımcıları (`menuTree.ts`) adım bileşenlerinden ayrı bir modüldedir; böylece Wizard
|
||
ve `SqlTableDesignerDialog` bu fonksiyonları kullanırken adım bileşenlerini pakete çekmez.
|
||
|
||
**Seed dosyası ekranın kendisini taşır.** Dosya `Wizard` bölümünün yanında ekranın
|
||
`GridOptionsEditDto` sözleşmesini (`ListForm`) ve alanların `ColumnFormatEditDto` sözleşmesini
|
||
(`Fields`) tutar; `WizardDataSeeder` ekranı bu iki bölümden kurar. Böylece Wizard ile ListForm
|
||
detayı aynı veri yapısını konuşur ve tasarımcıdaki değişiklikler wizard'a geri yazılabilir.
|
||
`Wizard` bölümü yalnızca ekrandan üretilemeyen bilgileri (menü, yetki, dil metinleri, bileşen
|
||
yolu, alan başlıklarının dil karşılıkları) taşır; `ListForm`/`Fields` içinde karşılığı olan alanlar
|
||
dosyaya yazılmaz, okuma sırasında geri doldurulur. Kalanlar dosyada `Menu`, `Language` ve `Groups`
|
||
başlıkları altında toplanır (`WizardSeedFileDto.ToSeedJson` / `FromSeedJson`). Dosya adı `{Ad}.json`'dır (zaman damgası yok);
|
||
uygulama sırası `Wizard.SeededAt` damgasından gelir.
|
||
|
||
**İki yol: `ComponentKind`.** `ListFormWizardDto.ComponentKind` sihirbazın yol ayrımıdır ve seed
|
||
dosyasında ilk alandır. Varsayılan `List` olduğu için bu alanı taşımayan eski seed dosyaları
|
||
eskisi gibi çalışır.
|
||
|
||
| `ComponentKind` | Üretilen | Menü URL'i | Yetkiler |
|
||
| --- | --- | --- | --- |
|
||
| `List` | ListForm + ListFormField + Route + Menu + Permission + dil anahtarları | `/admin/list/{ListFormCode}` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||
| `Custom` | Menü + Permission + dil anahtarları; ekran seçilen Custom Component'tir | Component'in `RoutePath` değeri | Yalnızca `.Create`, `.Update`, `.Delete` (Export/Import/Note ListForm'a özgüdür) |
|
||
|
||
**Menüsüz wizard (`CreateMenu = false`).** Menü (ve gerekiyorsa üst menü) kaydı hiç üretilmez;
|
||
ListForm, permission ve dil anahtarları her iki durumda da üretilir. Menüsüz wizard'lar başka bir
|
||
ekranda SubGrid/parça olarak kullanılmak üzere tanımlanır. Alan varsayılanı `true` olduğundan bu
|
||
alanı taşımayan eski seed dosyaları etkilenmez.
|
||
|
||
**İzin grubu seçimi.** Menü adımında izin grubu bir seçim listesinden gelir
|
||
(`GetWizardPermissionGroups`). Görünen adlar, grup adıyla aynı olan dil anahtarının metinlerinden
|
||
okunur; seçim yapıldığında `PermissionGroupEn/Tr` forma doldurulur. Yeni bir grup
|
||
tanımlanırsa grup adıyla aynı dil anahtarına bu metinler yazılır; mevcut grup seçilip alanlar boş
|
||
bırakılırsa sunucu veritabanındaki değeri geri yazar. Böylece seed dosyası her durumda iki dilli
|
||
görünen adı taşır.
|
||
|
||
Dinamik liste ekranlarının route deseni `/admin/list/{ListFormCode}` biçimindedir; form
|
||
görünümleri `/admin/form/{listFormCode}/:id`, grafik `/admin/chart/{listFormCode}`, pivot
|
||
`/admin/pivot/{listFormCode}` yollarını kullanır.
|
||
|
||
Var olan bir ekranı düzenlemek için `/admin/listform/edit/{listFormCode}` — tüm JSON
|
||
yapılandırması sekmeli bir editörde yönetilir (Veritabanı, Sütunlar, Filtreler, Düzenleme,
|
||
Yetkiler, Alt Form, Pivot, Tree, Gantt, Scheduler, Todo, Widget, Workflow, Durum, Grafik sekmeleri).
|
||
|
||
**Wizard File Manager** (`/admin/listform/wizard` liste ekranı) üretilmiş seed dosyalarını yönetir:
|
||
liste/kart görünümü arasında geçiş (tercih diğer listelerle aynı yerde, `admin.lists.states`
|
||
altında saklanır), arama, düzenleme (dosyanın yerine geçen yeni bir çalıştırma), silme, veritabanı
|
||
migrate tetikleme, dışa aktarma ve içe aktarma. Butonlar `App.Listforms.Wizard.*` yetkileriyle
|
||
gizlenir; asıl kontrol `ListFormWizardAppService` üzerindedir.
|
||
|
||
### 7.7. İçe/dışa aktarma
|
||
|
||
**Veri (ekran içi)**
|
||
|
||
- **Dışa aktarma:** xlsx, csv, pdf (grid durumuna ve görünür sütunlara saygı duyar).
|
||
- **İçe aktarma:** `components/importManager` altındaki dosya yükleme → önizleme → ilerleme →
|
||
sonuç akışı; sonuçlar `ListFormImportLog` üzerinde satır bazında raporlanır. Şablon dosyası
|
||
ekran tanımından üretilir.
|
||
|
||
**Ekran tanımı (wizard seed paketi)**
|
||
|
||
Bir ekranın tanımı, bağımlılıklarıyla birlikte tek bir zip olarak taşınır. Zip içindeki yollar seed
|
||
kapsam klasörü (`host` / `tenants/{tenantId}`) kökü baz alınarak yazılır; arşiv başka bir ortamda
|
||
aynı klasör düzenine doğrudan açılabilir.
|
||
|
||
| Yol | İçerik |
|
||
| --- | --- |
|
||
| `wizard/{dosya}.json` | Wizard tanımının kendisi |
|
||
| `custom/{component}.json` | Custom yolunda bağlı component ve bağımlılıkları |
|
||
| `crud/{entity}.json` | Component'lerin/nesnenin kullandığı CRUD endpoint tanımları |
|
||
| `{sql\|postgres}/{object\|execute}/{nesne}.sql` | List yolunda `SelectCommand`'a karşılık gelen SQL nesnesi |
|
||
|
||
**İçe aktarma iki adımlıdır** (`WizardImportDialog`):
|
||
|
||
1. **Analiz** (`AnalyzeImport`) — zip, seed kökü altındaki `.imports/{importId}/staged` klasörüne
|
||
açılır (nokta ile başladığı için seeder taramalarına girmez) ve her dosya hedefteki karşılığıyla
|
||
karşılaştırılır: `New` (hedefte yok), `Identical` (aynı, sorulmaz), `Conflict` (farklı).
|
||
Çakışan dosyalar Monaco `DiffEditor` ile karşılaştırılıp birleştirilir.
|
||
2. **Uygulama** (`ApplyImport`) — dosyalar tek tek yazılır, ilerleme satır satır gösterilir. Yazılan
|
||
her dosyanın önceki hâli `.imports/{importId}/backup` altına alındığı için hata durumunda
|
||
`RollbackImport` ile toplu işlem geri alınabilir; `CompleteImport` oturumu kapatır.
|
||
|
||
Güvenlik sınırları: yalnızca `wizard`, `crud`, `custom`, `sql`, `postgres` kök klasörleri
|
||
(SQL sağlayıcı klasörlerinin altında yalnızca `object` ve `execute`) kabul edilir; dosya başına
|
||
5 MB, arşiv başına 50 MB, en çok 500 girdi. Kabul edilmeyen girdiler analiz sonucunda uyarı
|
||
olarak listelenir. Yetkiler: `App.Listforms.Wizard.Export` / `App.Listforms.Wizard.Import`.
|
||
|
||
---
|
||
|
||
## 8. Developer Kit
|
||
|
||
Teknik kullanıcılar için `/admin/developerkit` altında toplanan araçlar:
|
||
|
||
| Araç | Route | Ne işe yarar |
|
||
| --- | --- | --- |
|
||
| **SQL Query Manager** | `/admin/sqlQueryManager` | Nesne gezgini, Monaco tabanlı SQL editörü, sonuç grid'i, **tablo tasarımcısı**, **view tasarımcısı** ve **CRUD endpoint yönetimi**. |
|
||
| **Custom Endpoint** | `/admin/list/App.DeveloperKit.CustomEndpoints` | SQL veya servis tanımından REST endpoint üretimi; GET/POST/PUT/DELETE için ayrı yetki kapıları (`App.DeveloperKit.CustomEndpoints.*`) ve kullanıcı/rol/global erişim kuralları. |
|
||
| **CRUD Endpoint** | SQL Query Manager içinde | Tablo tanımından tam CRUD endpoint kümesi üretimi. Ayrı ekranı yoktur; bkz. aşağıdaki not. |
|
||
| **Dynamic Service** | `/admin/list/App.DeveloperKit.DynamicServices` | Liste bir ListForm ekranıdır (KPI şeridi, Swagger butonu, kart/ızgara görünümü); kod yazma listeden açılan `DynamicServiceEditor` diyalogundadır: Monaco editörü, Roslyn ile derleme (`TestCompile`), yayınlama (`Publish`) ve çalışan uygulamaya controller olarak kaydetme. Yetkiler: Create/Edit/Delete/Manage/TestCompile/Publish/ViewCode. |
|
||
| **Custom Component** | `/admin/developerkit/components` | React bileşenini veritabanında saklama; `@babel/standalone` ile tarayıcıda derleyip route'a bağlama. Liste/kart görünümü, arama; yetkiler `App.DeveloperKit.Components{,.Create,.Update,.Delete}`. |
|
||
| **Visual Designer** | Component editörü içinde | Sürükle-bırak kanvas ile bileşen üretimi ve kod üretimi (`visualDesigner/codeGenerator.ts`). |
|
||
| **ListForm** | `/admin/list/App.Listforms.Listform` | Var olan ekranların ham tanım listesi; buradan `/admin/listform/edit/{kod}` sekmeli editörüne geçilir. |
|
||
| **Wizard Manager** | `/admin/listform/wizardManager` | Üretilmiş wizard seed dosyalarının listesi/kartı, düzenleme, silme, DB migrate, export/import. Yetki `App.Listforms.Wizard{,.Create,.Update,.Delete,.Export,.Import}`. |
|
||
|
||
> Bu ekranların artefakt şemaları, enum değerleri ve çalışan örnekleri
|
||
> [`.github/instructions/lowcode.instructions.md`](.github/instructions/lowcode.instructions.md)
|
||
> dosyasındadır.
|
||
|
||
### 8.1. SQL View Designer
|
||
|
||
`SqlViewDesignerDialog` (+ `sqlViewDesigner/`), SSMS Query Designer düzeninde görsel view
|
||
oluşturma aracıdır. Üç panel:
|
||
|
||
- **Diagram** (`DiagramPane.tsx`) — `ViewSource` kutuları (x/y konumlu, daraltılabilir, yalnızca
|
||
seçili kolonları gösterebilir) ve aralarındaki JOIN okları. Kaynak bir tablo/view olabileceği
|
||
gibi `CROSS/OUTER APPLY` ya da türetilmiş bir alt sorgu da olabilir; alt sorgunun gövdesi
|
||
olduğu gibi saklanır. JOIN türleri: `INNER`, `LEFT`, `RIGHT`, `FULL`, `CROSS`; koşul
|
||
operatörleri `=`, `<>`, `>`, `>=`, `<`, `<=`.
|
||
- **Criteria grid** (`CriteriaGrid.tsx`) — Column / Alias / Output / Group By / Sort / Filter /
|
||
Or… satırları. Bir satır ya `sourceId + columnName` referansıdır ya da serbest bir SQL
|
||
ifadesidir. Group By sütunu `GroupBy`, `Where` (satır çıktıya girmez, yalnızca filtre taşır) ve
|
||
`SUM`/`COUNT`/`COUNT_DISTINCT`/`AVG`/`MIN`/`MAX` değerlerini alır. Filtre hücreleri SSMS'teki
|
||
gibi serbest yüklemdir (`> 100`, `LIKE '%abc%'`, `IS NULL`).
|
||
- **T-SQL önizleme** — model → SQL üretimi (`generateViewSql`).
|
||
|
||
Tasarımcı tek yönlü çalışır: **model → T-SQL**. Mevcut bir view açılırken `parseViewSql` ile geri
|
||
okunmaya çalışılır; üretilen kanonik şekle uymayan bir tanım gelirse dialog **ham SQL moduna**
|
||
düşer ve kullanıcı Query Editor'dan devam eder (`onOpenInEditor`). PostgreSQL bağlantılarında
|
||
`isPostgreSql` bayrağı ile söz dizimi buna göre üretilir.
|
||
|
||
> **CRUD Endpoint, SQL Query Manager ile birleştirildi.** Ayrı `/admin/developerkit/endpoints`
|
||
> ekranı ve menüsü kaldırıldı. Endpoint üretme, aktif/pasif etme, test etme ve silme işlemleri
|
||
> artık iki yerden yapılır: SQL Query Manager nesne gezgininde tablo satırının **CRUD Endpoints**
|
||
> aksiyonu (ve seçili tablolar için toolbar'daki toplu üretim butonu), ayrıca ListForm
|
||
> sihirbazının **Adım 2 – Veri Kaynağı** ekranındaki aynı diyalog. Ayrıca **tablo
|
||
> tasarımcısında deploy öncesi bir adım** vardır: endpoint üretilip üretilmeyeceği ve
|
||
> hangi operasyonların (GetList/GetById/Create/Update/Delete) aktif başlayacağı seçilir
|
||
> ("tümünü seç" destekli); seçilmeyenler pasif olarak kaydedilir, sonradan diyalogdan
|
||
> açılabilir. Hepsi `CrudEndpointDialog` bileşenini kullanır. Yetki `App.SqlQueryManager` altındaki
|
||
> `App.SqlQueryManager.CrudEndpoints`'tir; izin verilmemişse butonlar görünmez ve
|
||
> `crud-endpoint-generate` uçlarının tamamı (base CRUD metotları dahil) reddedilir.
|
||
> Üretilen endpoint'ler `configs/seeds/{host|tenants/{tenantId}}/crud/{EntityName}.json` olarak
|
||
> seed dosyasına yazılır; `CrudDataSeeder` aynı dosyaları okuyup endpoint'leri geri yükler.
|
||
|
||
> **Tablo tasarımı varsayılanı:** Yeni tablo oluştururken tenant ve tam denetim (audit) kolonları
|
||
> varsayılan olarak eklenir: `Id`, `TenantId`, `CreationTime`, `CreatorId`, `LastModificationTime`,
|
||
> `LastModifierId`, `IsDeleted`, `DeletionTime`, `DeleterId`. Kullanıcı açıkça istemedikçe bu
|
||
> kolonlar çıkarılmaz.
|
||
|
||
### 8.2. Custom Component ve Visual Designer
|
||
|
||
**Saklanan tanım.** Bir custom component `Name`, `RoutePath`, `Code` (JSX), `Props`,
|
||
`Dependencies` ve `DataSources` alanlarından oluşur. Görsel tasarımcı dokümanı iki yerde tutulur:
|
||
`Props.visualDesigner` içinde (nodes, canvas, lifecycle, dataSources) ve üretilen kodun ilk
|
||
satırındaki `/*__SOZSOFT_VISUAL_DESIGNER__…__*/` yorumunda. Böylece yalnızca kod elinizdeyse bile
|
||
tasarımcı dokümanı geri okunabilir. `sourceMode` alanı `visual` ya da `code` olur; kod moduna
|
||
geçilen bir bileşen kanvasa geri dönmez.
|
||
|
||
**Seed senkronizasyonu.** Component Manager üzerinden kaydedilen/silinen her bileşen
|
||
`configs/seeds/{host|tenants/{tenantId}}/custom/{Name}.json` olarak yazılır;
|
||
`CustomComponentDataSeeder` veritabanı silinip yeniden oluşturulduğunda aynı dosyaları okuyup geri
|
||
yükler. Dosya düzeni bilinçli olarak `TenantData.json` içindeki `CustomComponents` bloğuyla
|
||
aynıdır. `DataSources` sütunu tasarımcı dokümanından türetilir
|
||
(`CustomComponentDataSourceResolver`): Data sekmesindeki her endpoint `method + path` ile CRUD
|
||
endpoint kataloğunda aranır, eşleşenler `EntityName` + `crud/{EntityName}.json` referansını taşır,
|
||
elle yazılmış olanlar listede kalır ama bu alanları boş gelir. Aynı çözüm hem kaydetmede (katalog
|
||
veritabanından) hem seed'de (katalog `crud/*.json` dosyalarından) kullanıldığı için sütun iki
|
||
yolda da aynı üretilir.
|
||
|
||
**Toolbox.** Kanvasa bırakılabilecekler beş aileye ayrılır:
|
||
|
||
| Aile | İçerik |
|
||
| --- | --- |
|
||
| `layout` | `PageContainer`, `FlexRow` (kolon sayısı, ilk kolon genişliği, hizalama, gap, wrap), `Spacer` |
|
||
| `data` | `Form` — ASP.NET'in Form + FormView karşılığı; dört CRUD endpoint'ini sahiplenen kapsayıcı |
|
||
| `platform` | `ListView`, `DataGridView`, `TreeView`, `GanttView`, `TodoBoard`, `CardView`, `SchedulerView`, `PivotView`, `ChartView` — hepsi `listFormCode` ile bir ListForm ekranını gömer |
|
||
| `html` / `ui` | Ham HTML etiketleri ve `components/ui` tasarım sistemi bileşenleri (sözleşmeleri metadata'dan okunur) |
|
||
| `custom` | Başka custom component'ler (bağımlılık olarak kaydedilir) |
|
||
|
||
**Form bileşeni.** `selectEndpoint` / `insertEndpoint` / `updateEndpoint` / `deleteEndpoint`,
|
||
`keyFieldName`, `collectionPath`, `keySource` + `keyParamName`, `previewKeyValue`, `autoLoad`,
|
||
`showToolbar`, `columnCount`, `gap` özellikleriyle yapılandırılır. İçine bırakılan her bileşen
|
||
Select sonucunun bir kolonuna bağlanır ve Save/Delete üzerinden geri yazar.
|
||
|
||
**Veri bağlama.** `DesignerBinding` bir kaynağa (`sourceId`) ve yola (`path`) bağlanır; `labelPath`
|
||
/ `valuePath` seçim bileşenleri içindir. `columns` ile ekranda görünmeyen ek sütunlar da taşınır
|
||
ve script'ten `refs.<ad>.getColumn('sutun')` ile okunup başka bir bileşenin değerine ya da Form
|
||
kaydına yazılır. Filtreler CrudEndpoint `GetList` sözleşmesine göre üretilir: `eq` çıplak query
|
||
parametresi (`?RoleId=…`), diğerleri son ek taşır (`?Name.contains=…`). Operatörler: `eq`, `ne`,
|
||
`contains`, `startswith`, `endswith`, `gt`, `gte`, `lt`, `lte`, `in`, `isnull`, `notnull`.
|
||
|
||
**Yetki modeli.** İki katmanlıdır:
|
||
|
||
- **Node görünürlüğü** — `designerPermission` prop'u dolu olan bir düğüm, yetki verilmemişse
|
||
render edilmez.
|
||
- **Form komutları** — her komut (`selectPermission`, `insertPermission`, `updatePermission`,
|
||
`deletePermission`) ya serbesttir (boş) ya da bir yetkiye bağlıdır. `Otomatik` modda temel,
|
||
Wizard'ın bu bileşen için ürettiği okuma yetkisidir (menü kaydının korunduğu yetkinin aynısı) ve
|
||
komutlara `''` / `.Create` / `.Update` / `.Delete` son ekleri eklenir. `Özel` modda yetki adı
|
||
elle yazılır.
|
||
|
||
**Script.** Tasarımcı, ListForm Editor Script ile aynı ortak dialog'u kullanır
|
||
(`designerScriptDialect.ts` + `designerScriptRecipes.ts`); tarif grupları bileşen erişimi, API
|
||
çağrıları, form ve olay/sayfa başlıkları altında toplanır.
|
||
|
||
**Diğer notlar.** `PlatformIcon` tasarımcı dokümanındaki ikon adını çözer; `selectComponents.ts`
|
||
`Select.componentAs` için saklanan adı (`ReactSelect`, `CreatableSelect`, `AsyncSelect`) gerçek
|
||
bileşene çevirir — kanvas ve üretilen bileşenin aynı adı aynı şekilde yorumlamasını sağlayan tek
|
||
nokta budur. Yeni bileşen `configs/seeds/host/custom/NewComponent.json` şablonundan başlar.
|
||
|
||
**Dinamik servis yaşam döngüsü:** `DynamicServiceCompiler` kodu derler →
|
||
`DynamicAssemblyRegistrationService` assembly'yi tenant bağlamıyla kaydeder →
|
||
`ActionDescriptorChangeProvider` MVC'ye route tablosunun değiştiğini bildirir →
|
||
`DynamicControllerActivator` bağımlılıkları enjekte eder. Uygulama yeniden başlatılmaz.
|
||
|
||
---
|
||
|
||
## 9. Dinamik Menü, Route ve Yetki Modeli
|
||
|
||
```
|
||
Permission (ABP) ──┐
|
||
├──► Menu.RequiredPermissionName ──► menüde görünürlük
|
||
Route.Authority ──┘ └► PermissionGuard ile erişim
|
||
```
|
||
|
||
- **Route** (`Entities/Tenant/Administration/Route.cs`): `Key`, `Path`, `ComponentType`,
|
||
`ComponentPath`, `RouteType` (`public` / `protected`), `Authority[]`.
|
||
- **Menu** (`Menu.cs`): `Code`, `ParentCode`, `DisplayName`, `Url`, `Icon`, `Order`,
|
||
`RequiredPermissionName`, `Target`, `IsDisabled`, ayrıca `UserId` / `RoleId` / `CultureName`
|
||
ile kullanıcı, rol ve dil bazlı menü varyantları.
|
||
- **Menü yöneticisi** (`/admin/menuManager`): sürükle-bırak ağaç ile menü düzenleme.
|
||
- Frontend'de `dynamicRoutesContext` route'ları çeker, `dynamicRouteLoader` bunları fiziksel
|
||
view'lara veya runtime derlenmiş Custom Component'lere eşler, `DynamicRouter` React Router
|
||
ağacını kurar; her korumalı route `ProtectedRoute` + `PermissionGuard` ile sarılır.
|
||
|
||
**Yetki kodları** `PlatformConsts.AppCodes` içinde merkezî olarak tanımlıdır ve
|
||
`PermissionsData.json` ile seed edilir. Ana gruplar: `App.Saas`, `App.Branches`, `App.Intranet.*`,
|
||
`App.Definitions.*`, `App.Restrictions.*`, `App.Languages.*`, `App.Listforms.*`,
|
||
`App.Notifications.*`, `App.BackgroundWorkers.*`, `App.Menus.*`, `App.DeveloperKit.*`,
|
||
`App.SqlQueryManager.*`,
|
||
`App.Orders.*`, `App.BlogManagement.*`, `App.IdentityManagement.*`, `App.Reports.*`,
|
||
`App.Administration`, `App.Setting`, `App.Setup.Migrate`.
|
||
|
||
Aksiyon yetkisi olan alt gruplar (UI tarafındaki karşılıkları `constants/permission.constant.ts`
|
||
içindedir; oradaki kontroller yalnızca butonları gizler, asıl kontrol AppService'lerdedir):
|
||
|
||
| Grup | Alt yetkiler |
|
||
| --- | --- |
|
||
| `App.Listforms.Wizard` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import` |
|
||
| `App.DeveloperKit.Components` | `.Create`, `.Update`, `.Delete` |
|
||
| `App.DeveloperKit.CustomEndpoints` | `.Get`, `.Post`, `.Put`, `.Remove` (dispatcher üzerinden çağrı kapısı; endpoint bazlı User/Role/Global kuralları bunun üstünde denetlenir) |
|
||
| `App.DeveloperKit.DynamicServices` | `.Create`, `.Edit`, `.Delete`, `.Manage`, `.TestCompile`, `.Publish`, `.ViewCode` |
|
||
| `App.SqlQueryManager` | `.CrudEndpoints` |
|
||
| `App.Setup.Migrate` | Migration + seed tetikleme (host tarafı) |
|
||
| `App.{Home,About,Services,Contact}.Design` | Public site sayfa tasarım modu (`?design=1`) |
|
||
|
||
> **Kural:** Yetki sözleşmesi olmayan menü/route önerilmez ve eklenmez.
|
||
|
||
---
|
||
|
||
## 10. Modül Kataloğu
|
||
|
||
### 10.1. Backend modülleri (`api/modules`)
|
||
|
||
| Modül | Kapsam |
|
||
| --- | --- |
|
||
| **Sozsoft.Languages** | Dil tanımları, dil anahtarları, çeviri metinleri; tenant bazlı lokalizasyon (`TenantLocalizationMiddleware`). |
|
||
| **Sozsoft.Settings** | Ayar tanımları, sağlayıcılar, şifreleme bayrakları ve ayar ekranı metadata'sı. |
|
||
| **Sozsoft.Notifications** | Bildirim tipleri, kuralları ve kullanıcı bildirimleri; kanal bazlı yönlendirme. |
|
||
| **Sozsoft.MailQueue** | Şablon (Scriban) tabanlı gövde üretimi, ek dosya yaşam döngüsü, kuyruk çalıştırma ve günlükleme. |
|
||
| **Sozsoft.Sender** | Amazon SES (mail), Posta Güvercini (SMS), WhatsApp Cloud API, Rocket.Chat göndericileri. |
|
||
| **Sozsoft.SqlQueryManager** | SQL nesne yönetimi, sorgu çalıştırma, tablo/kolon metadata'sı. |
|
||
|
||
### 10.2. Uygulama servisleri (`api/src/Sozsoft.Platform.Application`)
|
||
|
||
`AiBots` · `AuditLogs` · `BackgroundWorker` · `Blog` · `Branch` · `Dashboard` · `DataSource` ·
|
||
`DeveloperKit` · `FileManagement` · `Forum` · `GlobalSearch` · `Hr` · `Identity` · `Intranet` ·
|
||
`ListForms` (+ `Administration`) · `Menu` · `Messenger` · `Note` · `OrgChart` ·
|
||
`OrganizationUnits` · `Public` · `Routes` · `Tenants` · `Videoroom`
|
||
|
||
### 10.3. Yönetim ekranları (UI)
|
||
|
||
| Alan | Route | Açıklama |
|
||
| --- | --- | --- |
|
||
| Dashboard | `/admin/dashboard` | Widget tabanlı özet ekran. |
|
||
| Kullanıcı / Rol | `/admin/list/...`, `/admin/users/detail/:userId` | Kullanıcı, rol ve permission atamaları. |
|
||
| Organizasyon birimleri | `/admin/ous` | OU ağacı ve üyelik yönetimi. |
|
||
| Tenant yönetimi | ListForm ekranları | Tenant kayıtları, bağlantı dizeleri, siparişten otomatik tenant açma. |
|
||
| Ayarlar | `/admin/settings` | Sistem ve entegrasyon ayarları. |
|
||
| Menü yöneticisi | `/admin/menuManager` | Menü ağacı düzenleme. |
|
||
| Dosya yöneticisi | `/admin/files` | Klasör/dosya işlemleri. |
|
||
| Aktivite ve denetim kaydı | `/admin/activityLog`, `/admin/changeLog` | Kullanıcı hareketleri ve ABP audit log detayı. |
|
||
| Bildirimler | `/admin/profile/notification-settings`, bildirim ekranları | Kanal tercihleri ve bildirim oluşturma. |
|
||
| Forum | `/admin/forum` | Forum kullanımı; yönetim `App.ForumManagement` altındaki ListForm ekranlarıyla yapılır. |
|
||
| Intranet | Intranet dashboard ve widget'ları | Duyuru, anket, sosyal duvar, etkinlik. Hangi widget'ın hangi kolonda, hangi sırada ve hangi yetkiyle yayınlandığı `Adm_T_IntranetWidget` kaydından gelir; kayıtlar `configs/seeds/{kapsam}/data/App.DeveloperKit.IntranetWidgets.json` ile senkron tutulur. |
|
||
| Video oda | `/admin/videoroom/*` | Oda listesi, detay, planlama, katılımcı ve ekran paylaşımı. |
|
||
| Raporlar | `/admin/reports/:report/view|design/...` | DevExpress rapor görüntüleyici ve tasarımcı. |
|
||
| AI asistanı | `/admin/ai` | n8n webhook üzerinden sohbet arayüzü. |
|
||
| Profil | `/admin/profile/*` | Genel bilgiler, şifre, bildirim ayarları. |
|
||
|
||
### 10.4. Public site
|
||
|
||
`/home` · `/about` · `/services` · `/products` · `/checkout` · `/payment` · `/success` ·
|
||
`/blog` · `/blog/:id` · `/demo` · `/contact` — içerikler veritabanından yönetilir;
|
||
`/about/designer` ve `/services/designer` sayfa tasarımcılarıdır.
|
||
|
||
---
|
||
|
||
## 11. Kimlik, Oturum ve Güvenlik
|
||
|
||
### 11.1. Kimlik doğrulama
|
||
|
||
- **OpenIddict** password + refresh token akışı. Token uç noktası: `POST /connect/token`
|
||
(`grant_type=password`, `client_id=Platform_PublicApi`, `scope=offline_access Platform`).
|
||
- Token ömürleri `OpenIddict:TokenLifetimes` ile yapılandırılır (varsayılan 60 dk access, 90 dk refresh).
|
||
- Swagger için ayrı istemci: `AuthServer:SwaggerClientId`.
|
||
- İki aşamalı doğrulama (2FA) ve hesap doğrulama (e-posta/telefon) desteklenir.
|
||
- Kayıt ve iletişim formlarında Cloudflare Turnstile tabanlı captcha (`CaptchaMiddleware`).
|
||
|
||
### 11.2. Oturum yönetimi
|
||
|
||
- `PlatformSessionValidationMiddleware` her istekte oturumun hâlâ geçerli olduğunu doğrular.
|
||
- `PlatformSessionRevocationHandler` token iptalinde oturumu sonlandırır.
|
||
- `PlatformSessionCleanupWorker` süresi dolmuş oturumları temizler.
|
||
- Eş zamanlı kullanıcı limiti aşıldığında giriş reddedilir.
|
||
|
||
### 11.3. Giriş engelleri
|
||
|
||
`UserCannotSignInErrors` altında tanımlı, kullanıcıya lokalize mesajla dönen durumlar:
|
||
|
||
| Kod | Anlamı |
|
||
| --- | --- |
|
||
| `LoginNotAllowed_NotVerified` | Hesap doğrulanmamış. |
|
||
| `LoginNotAllowed_NotAllowedIp` | IP kısıtlaması (`IpRestriction`). |
|
||
| `LoginNotAllowed_WorkHour` | Çalışma saati kısıtlaması (`WorkHour`). |
|
||
| `LoginNotAllowed_LoginEndDateDue` | Kullanıcının giriş yetki süresi dolmuş. |
|
||
| `ShouldChangePasswordOnNextLogin` / `ShouldChangePasswordPeriodic` | Zorunlu şifre değişimi. |
|
||
| `LoginNotAllowed_TenantIsPassive` / `TenantNotFound` | Tenant pasif veya bulunamadı. |
|
||
| `LoginNotAllowed_BranchLimit` | Şube lisans limiti aşıldı. |
|
||
| `LoginNotAllowed_ConcurrentUserLimit` | Eş zamanlı kullanıcı limiti aşıldı. |
|
||
|
||
### 11.4. Güvenlik kuralları
|
||
|
||
- Tüm katmanlarda RBAC ve yetki tabanlı görünürlük zorunludur.
|
||
- Dinamik SQL'de **yalnızca parametreli** desenler kullanılır; kullanıcı girdisi string birleştirme ile sorguya eklenmez.
|
||
- Her sorgu ve eylemde tenant izolasyonu korunur (`IsTenant`, `IsBranch`, `IsOrganizationUnit` bayrakları ve ABP tenant filtreleri).
|
||
- Gerçek kimlik bilgileri, token ve anahtarlar örneklerde/dokümanda yer almaz; yer tutucu kullanılır.
|
||
- Denetim: kritik işlemler ABP Audit Log'a yazılır; yüksek frekanslı `list-form-customization` çağrıları denetim dışı bırakılmıştır.
|
||
|
||
---
|
||
|
||
## 12. Çok Kiracılılık (Multi-Tenancy)
|
||
|
||
- `PlatformConsts.IsMultiTenant = true`.
|
||
- Tenant çözümleme host adı (subdomain) ve ABP tenant resolver'ları ile yapılır (`utils/subdomain.ts`).
|
||
- **Tenant başına ayrı veritabanı:** `TenantConnectionString` kayıtları ile her tenant kendi
|
||
veritabanına yönlendirilebilir; migration'lar `DatabaseMigrationEventHandlerBase` üzerinden
|
||
tenant oluşturulduğunda otomatik uygulanır.
|
||
- **Şube (Branch):** Tenant altındaki fiziksel/örgütsel kırılım; kullanıcı–şube eşlemesi
|
||
`BranchUsers` ile tutulur, lisans limiti girişte kontrol edilir.
|
||
- **Organizasyon birimi:** ABP `OrganizationUnit` ağacı; ListForm'lar OU bazlı filtrelenebilir.
|
||
- Tenant bazlı lokalizasyon: `TenantLocalizationInitializer` + `TenantLocalizationMiddleware`.
|
||
|
||
---
|
||
|
||
## 13. Bildirim ve Entegrasyonlar
|
||
|
||
### 13.1. Kanallar
|
||
|
||
`Sms` · `Mail` · `Rocket` · `Desktop` · `UiActivity` · `UiToast` · `WhatsApp` (`Telegram` altyapıda tanımlı, UI'da kapalı)
|
||
|
||
### 13.2. Yönlendirme modeli
|
||
|
||
Bildirim **tip + kanal** eşleşmesiyle yönlendirilir. Alıcı hedefleme seçenekleri:
|
||
`All`, `User`, `Role`, `OrganizationUnit`, `Custom`. Kullanıcılar kendi bildirim tercihlerini
|
||
`/admin/profile/notification-settings` üzerinden kanal bazında yönetir.
|
||
|
||
### 13.3. Göndericiler (`Sozsoft.Sender`)
|
||
|
||
| Kanal | Sağlayıcı |
|
||
| --- | --- |
|
||
| E-posta | ABP Emailing + Amazon SES (`AmazonSesEmailSender`), arka plan iş kuyruğu ile |
|
||
| SMS | Posta Güvercini HTTP API |
|
||
| WhatsApp | WhatsApp Cloud API (şablon tabanlı) |
|
||
| Rocket.Chat | Rocket.Chat HTTP API |
|
||
|
||
Tüm sağlayıcı kimlik bilgileri ayar ekranından yönetilir (`App.Settings.*` anahtarları);
|
||
koda gömülmez.
|
||
|
||
### 13.4. Mail kuyruğu
|
||
|
||
`Sozsoft.MailQueue`; şablondan gövde üretir, PDF/XLS/TXT çıktıları ve ek dosyaları yönetir,
|
||
kuyruğu arka plan işçisiyle çalıştırır ve sonuçları günlükler.
|
||
|
||
### 13.5. AI entegrasyonu
|
||
|
||
`AiBot` kayıtları tenant bazlıdır; n8n webhook üzerinden LangChain ajanı + bellek penceresi ve
|
||
Gemini sohbet modeli bağlanır (`configs/ai/Chat.json`). UI tarafında `/admin/ai` ve header'daki
|
||
asistan bileşeni bu uç noktayı kullanır.
|
||
|
||
---
|
||
|
||
## 14. Arka Plan İşleri
|
||
|
||
İki motor birlikte kullanılır: **Hangfire** (kalıcı iş deposu, `default` ve `platform` kuyrukları)
|
||
ve **ABP Background Workers** (yinelenen işler). Yönetim `/admin` altındaki Background Worker
|
||
ekranlarından yapılır; yetkiler `App.BackgroundWorkers.RecurringJobs` ve `.Jobs`.
|
||
|
||
| Worker tipi | İşlevi |
|
||
| --- | --- |
|
||
| `MailQueueWorker` | Mail kuyruğunu işler. |
|
||
| `SqlWorker` | Zamanlanmış SQL çalıştırır. |
|
||
| `NotificationWorker` | Bildirim kurallarını değerlendirir ve gönderir. |
|
||
| `SessionCleanupWorker` | Süresi dolmuş oturumları temizler. |
|
||
| `BackupWorker` | Veritabanı yedeği alır ve eski yedekleri temizler. |
|
||
|
||
Hangfire panosu geliştirmede serbest, üretimde `AbpHangfireAuthorizationFilter` ile korumalıdır
|
||
(`/hangfire`).
|
||
|
||
---
|
||
|
||
## 15. Raporlama
|
||
|
||
- **DevExpress Reporting**: Web Document Viewer (`/admin/reports/:report/view/...`) ve
|
||
Report Designer (`/admin/reports/:report/design/...`).
|
||
- **Rapor deposu**: `ReportTemplate` ve `ReportCategory` varlıkları; `CustomReportStorageWebExtension`
|
||
ile veritabanı üzerinden okuma/yazma.
|
||
- **Dinamik raporlar** (`HttpApi.Host/PredefinedReports`): ListForm tanımından otomatik üretilen
|
||
grid, form ve ağaç raporları — grid durumunu (sütun sırası, gruplama, filtre) rapora yansıtır.
|
||
- Linux konteynerlerde font sorunlarını önlemek için `DevExpressFontConfiguration` devrededir.
|
||
|
||
---
|
||
|
||
## 16. Dosya Yönetimi ve CDN
|
||
|
||
- ABP BlobStoring, dosya sistemi sağlayıcısıyla `App:CdnPath` altına yazar; dosyalar `App:CdnUrl`
|
||
üzerinden servis edilir.
|
||
- `FileManagementAppService`: listeleme, yükleme, indirme, kopyalama, taşıma, yeniden adlandırma, silme.
|
||
- UI: `/admin/files` (`views/admin/files/FileManager.tsx`) — breadcrumb, çoklu yükleme, önizleme.
|
||
- Avatar, aktivite görselleri, içe aktarma dosyaları ve veritabanı yedekleri ayrı konteynerlerde tutulur.
|
||
|
||
---
|
||
|
||
## 17. Gerçek Zamanlı Özellikler
|
||
|
||
- **Messenger**: SignalR hub'ı `/messengerhub`. Konuşma ve mesaj varlıkları veritabanında;
|
||
Redis etkinse backplane olarak kullanılır. Query string ile gelen `access_token`,
|
||
hub bağlantısı için `Authorization` başlığına çevrilir.
|
||
- **Video oda**: Oda oluşturma/başlatma/bitirme, katılımcı yönetimi, sohbet, doküman ve ekran
|
||
paylaşımı panelleri; TURN sunucusu `configs/deployment/configs/turnserver.conf` ile yapılandırılır.
|
||
- **Global arama**: `GlobalSearchAppService` üzerinden çapraz modül arama.
|
||
|
||
---
|
||
|
||
## 18. Frontend Mimarisi
|
||
|
||
### 18.1. Route ve bileşen çözümü
|
||
|
||
```
|
||
Route kayıtları (DB)
|
||
├─ componentPath ──► fiziksel view (React.lazy)
|
||
└─ CustomComponent ──► @babel/standalone ile runtime derleme ──► ComponentContext
|
||
│
|
||
DynamicRouter ──► ProtectedRoute ──► PermissionGuard ──► PageContainer
|
||
```
|
||
|
||
`ROUTES_ENUM` (`src/routes/route.constant.ts`) statik yol sözleşmelerini tutar; iş modülleri için
|
||
(`supplychain`, `maintenance`, `warehouse`, `projects`, `hr`, `crm`, `mrp`, `accounting`) ayrılmış
|
||
yol desenleri de buradadır. Bu alanların ekranları, fiziksel React sayfaları yerine ListForm
|
||
konfigürasyonu ile üretilir.
|
||
|
||
### 18.2. Durum yönetimi
|
||
|
||
- **easy-peasy** global store: `auth`, `theme`, `locale`, `abpConfig`, `admin`, `client`, `base`.
|
||
Oturum ve tercih verileri `localStorage` yerine store üzerinden yönetilir (`stateSync.ts`).
|
||
- **React Query**: sunucu verisi önbellekleme.
|
||
- **Context'ler**: `ComponentContext` (runtime bileşen kaydı), `DialogContext`, `ScrollContext`.
|
||
|
||
### 18.3. Tema ve lokalizasyon
|
||
|
||
- Tailwind tabanlı tasarım sistemi (`components/ui`) + DevExtreme temaları; açık/koyu mod ve
|
||
tema yapılandırıcı (`ThemeConfigurator`).
|
||
- **Varsayılan mod koyudur.** `proxy/theme/theme.config.ts`: `mode` ve `navMode` `dark`, DevExtreme
|
||
stili `dx.material.blue.dark.compact`. Kullanıcı tercihi store üzerinden saklanır; bu yalnızca
|
||
ilk açılış varsayılanıdır.
|
||
- Dil metinleri veritabanından gelir (`Sozsoft.Languages`); dil seçici header'dadır.
|
||
Tenant bazlı çeviri geçersiz kılma desteklenir.
|
||
- Layout seçenekleri: dikey menü, yatay menü, yığılmış yan menü, mobil navigasyon.
|
||
|
||
### 18.4. PWA ve sürüm yönetimi
|
||
|
||
- Kurulum iki kademelidir: **kabuk** (index.html + entry JS/CSS + eager vendor chunk'ları)
|
||
workbox precache manifest'inden gelir ve zorunludur; **bileşenler** (tüm lazy chunk'lar,
|
||
build'de üretilen `dist/warmup.json`) güncelleme penceresinde aynı ilerleme çubuğunda arka
|
||
planda indirilir. İkinci kademe best-effort'tur (inemeyen dosya kurulumu düşürmez, süre
|
||
bütçesi aşılırsa kalanlar runtime cache'e kalır); böylece deploy sonrası ilk gezinmede chunk
|
||
beklenmez ama yavaş bağlantıda kurulum timeout'a düşmez. DevExtreme temaları (~33 MB), font
|
||
ve görseller runtime cache'tedir.
|
||
- `registerType: 'prompt'` — yeni sürüm indirilir, indirme bitince otomatik devreye alınır
|
||
(`views/version/swRegistration.ts`, `sw.ts`, `AppUpdateDialog.tsx`).
|
||
- Isıtma yalnızca kuruluma bağlı değildir: uygulama açılışta `ENSURE_WARMUP` mesajı yollar,
|
||
service worker eksik kalan bileşenleri kaldığı yerden tamamlar.
|
||
- **Sürüm bilgisi backend'dedir.** `Sas_H_ChangeLog` tablosu tek kaynaktır; istemci sürüm
|
||
numarasını ve son sürümün notlarını `application-configuration` yanıtındaki
|
||
`extraProperties.changeLogs` alanından okur (`PlatformApplicationConfigurationContributor`),
|
||
tam listeyi ise `/api/app/change-log` endpoint'inden alır. Ayrı bir `version.json` isteği
|
||
yoktur. Changelog `/admin/changeLog` ekranında gösterilir; sürüm numarası son görülenden
|
||
farklıysa kullanıcı giriş sonrası oraya yönlendirilir (tetikleyici bundle değil, sürümdür —
|
||
yalnızca yeni bir git tag'i eklenmiş olsa da çalışır).
|
||
- **Sürüm notu akışı — DbMigrator gerektirmez:** `configs/change-logs/generate-change-logs.sh`
|
||
deploy sırasında (`deploy/app.sh`) git tag'lerinden `configs/change-logs/change-logs.json`
|
||
üretir, dosya API konteynerine `/etc/api/change-logs` altına salt okunur mount edilir ve
|
||
`ChangeLogStartupService` uygulama açılışında tabloyu bu dosyayla eşitler. Dosya imaja
|
||
**gömülmez**: api build context'i içindeyken her yeni tag Dockerfile'daki `COPY . .`
|
||
katmanını geçersiz kılıp imajı gereksiz yere yeniden derletiyordu; artık kod değişmediyse
|
||
imaj cache'ten gelir. Yeni sürüm için tag atıp deploy etmek yeterlidir. Notlar
|
||
**annotated** tag mesajından okunur (`git tag -a 1.2.0 -m "..."`), her satır bir madde.
|
||
- **Tablo git tag listesinin aynasıdır:** yeni tag eklenir, mesajı düzeltilen tag güncellenir,
|
||
git'ten silinen tag tablodan da (hard delete ile) kaldırılır. Bu yüzden `Sas_H_ChangeLog`
|
||
elle düzenlenmemelidir — ilk deploy'da geri alınır. Dosya okunamaz veya boşsa senkronizasyon
|
||
hiçbir şey yapmaz, tablo boşaltılmaz.
|
||
- Deploy algılaması service worker'ın kendi `registration.update()` kontrolüne dayanır:
|
||
herhangi bir chunk değiştiğinde entry hash'i, dolayısıyla index.html ve `sw.js` içindeki
|
||
precache manifest'i de değişir.
|
||
|
||
---
|
||
|
||
## 19. API ve Swagger
|
||
|
||
- Swagger UI, API kökünde yayınlanır; OAuth2 ile "Authorize" düğmesi üzerinden token alınabilir.
|
||
- Endpoint'ler ABP **conventional controller** mekanizmasıyla uygulama servislerinden üretilir:
|
||
|
||
| Namespace | Kök yol |
|
||
| --- | --- |
|
||
| `Sozsoft.Platform.ListForms.Administration` | `/api/admin/...` |
|
||
| Diğer `Sozsoft.Platform.*` servisleri | `/api/app/...` |
|
||
| Modül servisleri (Languages, Settings, MailQueue, Notifications, SqlQueryManager) | Modül kendi kök yolunu kullanır |
|
||
|
||
- DevExpress raporlama controller'ları (`CustomReportDesigner`, `CustomWebDocumentViewer`,
|
||
`QueryBuilder`) Swagger dokümanından hariç tutulur.
|
||
- Yanıtlar Brotli/Gzip ile sıkıştırılır; `X-Correlation-Id` başlığı istemciye açılır.
|
||
- Hata kodları: `PlatformConsts.AppErrorCodes` (`Error:0001` yetkisiz, `App.NoResults` kayıt yok,
|
||
`Error:0003` parametre geçersiz, `Error:0005` iç hata).
|
||
|
||
**Token örneği** (yer tutucularla):
|
||
|
||
```http
|
||
POST /connect/token HTTP/1.1
|
||
Content-Type: application/x-www-form-urlencoded
|
||
|
||
grant_type=password
|
||
&username=<KULLANICI>
|
||
&password=<PAROLA>
|
||
&client_id=Platform_PublicApi
|
||
&scope=offline_access%20Platform
|
||
```
|
||
|
||
---
|
||
|
||
## 20. Dağıtım (Deployment)
|
||
|
||
`configs/deployment` altında üç ortam için compose dosyaları ve numaralandırılmış scriptler bulunur.
|
||
|
||
| Dosya | Amaç |
|
||
| --- | --- |
|
||
| `docker-compose-data.yml` | Redis, SQL Server / PostgreSQL, yedek volume'ları |
|
||
| `docker-compose-app.yml` / `.dev.yml` / `.production.yml` | API, UI, migrator, nginx |
|
||
| `docker-compose-devops.yml` | Forgejo + runner (CI/CD) |
|
||
| `Dockerfile`, `api/*.Dockerfile`, `ui/Sozsoft.Platform.Ui.Dockerfile` | İmaj tanımları |
|
||
| `configs/nginx.conf`, `redis.conf`, `turnserver.conf`, `elasticsearch.yml` | Servis yapılandırmaları |
|
||
|
||
Script sırası (`configs/deployment/scripts`):
|
||
|
||
```
|
||
1-devops.sh → DevOps makinesi (Forgejo, runner)
|
||
2-data-postgres.sh /
|
||
3-data-sql.sh → Veri katmanı
|
||
4-production-build.sh → İmaj build
|
||
5-production-deploy.sh → Yayın
|
||
6-production-migrator-true.sh → Migration çalıştırma
|
||
7-setup_ssl.sh → Sertifika
|
||
8-dev-build.sh / 9-dev-deploy.sh / 10-dev-migrator-true.sh → Dev ortamı
|
||
```
|
||
|
||
Migrator servisi `SEED` ortam değişkeni ile çalışır ve compose dosyasında `SEED=${SEED:-true}`
|
||
olarak tanımlıdır: değişken verilmezse seed **çalışır**. Seed dosyaları imaja gömülmez; depodaki
|
||
`configs/seeds` klasöründen mount edilir (`App:SeedsPath`), böylece bir seed değiştiğinde imaj
|
||
build etmek gerekmez.
|
||
|
||
Ayrıntılı kurulum notları: [`configs/deployment/README.md`](configs/deployment/README.md),
|
||
[`Readme_Production.md`](configs/deployment/Readme_Production.md),
|
||
[`Readme_Devops.md`](configs/deployment/Readme_Devops.md).
|
||
|
||
> Bu dokümanlarda geçmişte örnek amaçlı bırakılmış kimlik bilgileri bulunabilir; üretimde
|
||
> tümü döndürülmeli ve secret yöneticisine taşınmalıdır.
|
||
|
||
---
|
||
|
||
## 21. Geliştirme Standartları ve Sık Kullanılan Komutlar
|
||
|
||
### 21.1. Çözüm kuralları
|
||
|
||
1. Her istek şu sırayla değerlendirilir: **(1)** ListForm konfigürasyonu → **(2)** SQL Query
|
||
Manager + Custom Endpoint → **(3)** Dynamic Service → **(4)** kod değişikliği (son çare,
|
||
gerekçe zorunlu).
|
||
2. Standart iş ihtiyaçları için yeni özel React sayfası/bileşeni geliştirilmez.
|
||
3. Her öneri tenant ve yetki tasarımını içerir.
|
||
4. Platform yetkilendirme desenleri atlanmaz.
|
||
5. Secret, tenant id veya bağlantı dizesi koda gömülmez.
|
||
|
||
### 21.2. Frontend
|
||
|
||
```powershell
|
||
cd ui
|
||
npm start # geliştirme sunucusu
|
||
npm run build # üretim derlemesi (metadata + version + vite build)
|
||
npm run lint # ESLint
|
||
npm run format # prettier --write + eslint --fix
|
||
```
|
||
|
||
### 21.3. Backend
|
||
|
||
```powershell
|
||
cd api
|
||
dotnet build
|
||
dotnet run --project src/Sozsoft.Platform.HttpApi.Host
|
||
dotnet format --include .\modules\Sozsoft.Notifications\ --folder
|
||
|
||
# Kod standardı kapısı (ölü kod / stil analizörleri)
|
||
dotnet build Sozsoft.Platform.sln --no-incremental `
|
||
-p:EnforceCodeStyleInBuild=true -p:GenerateDocumentationFile=true
|
||
dotnet format Sozsoft.Platform.sln --diagnostics IDE0005,IDE0161 --severity warn
|
||
|
||
# Migration (EntityFrameworkCore projesi içinde)
|
||
dotnet ef migrations add <Ad>
|
||
dotnet ef database update
|
||
dotnet ef migrations remove
|
||
```
|
||
|
||
.NET/ABP kod standardı (hedef sürümler, nullable politikası, ölü kod kuralları, modern C#
|
||
kullanımı, ABP katman sınırları) bağlayıcı olarak
|
||
[`.github/instructions/dotnet.instructions.md`](.github/instructions/dotnet.instructions.md)
|
||
dosyasındadır. Standart derlemede zorlanır: `api/Directory.Build.props` analizörleri açar,
|
||
`api/.editorconfig` kural şiddetlerini tanımlar; bu iki dosya standardın tek kaynağıdır.
|
||
|
||
Yeni ABP modülü eklemek için:
|
||
`abp new Sozsoft.<Modul> -t module --no-ui -m none --database-provider ef`
|
||
|
||
### 21.4. Seed dosyaları
|
||
|
||
İki ayrı seed yüzeyi vardır ve karıştırılmamalıdır.
|
||
|
||
**1. Depo içi (kod ile taşınan) seed'ler** — `api/src/Sozsoft.Platform.DbMigrator/Migrations/`.
|
||
Platformun kendi ekranları, menüleri, yetkileri ve dil metinleri buradadır; değişiklikleri
|
||
derlenip yayınlanır. Yeni bir modülün nasıl kurulacağını öğrenmek için başvurulacak dosyalar:
|
||
|
||
- `ListFormSeeder_Saas.cs`, `ListFormSeeder_Administration.cs` — ListForm + alan tanımları
|
||
- `MenusData.json` — `Routes`, `Modules`, `Menus`
|
||
- `PermissionsData.json` — yetki grupları ve tanımları
|
||
- `HostData.json` — ayar/entegrasyon değerleri
|
||
- `LanguagesData.json` — dil anahtarları (EN/TR)
|
||
- `WizardDataSeeder.cs`, `CustomComponentDataSeeder.cs`, `CrudDataSeeder.cs` — aşağıdaki
|
||
runtime seed dosyalarını okuyup uygulayan seeder'lar
|
||
|
||
**2. Runtime'da üretilen seed'ler** — `configs/seeds/`. Wizard, Component Manager ve CRUD Endpoint
|
||
Manager çalışma zamanında burayı yazar; veritabanı silinip yeniden oluşturulduğunda aynı dosyalar
|
||
geri yüklenir. Kapsam klasörü CDN düzeniyle aynıdır ve `SeedPathResolver` üzerinden çözülür:
|
||
|
||
```
|
||
configs/seeds/
|
||
├── host/ # host kapsamı
|
||
│ ├── wizard/ # {Ad}.json → WizardDataSeeder
|
||
│ ├── custom/ # {ComponentName}.json → CustomComponentDataSeeder
|
||
│ ├── crud/ # {EntityName}.json → CrudDataSeeder
|
||
│ ├── sql/{object,execute}/ # .sql (SQL Server)
|
||
│ └── postgres/{object,execute}/
|
||
├── tenants/{tenantId}/… # aynı düzen, tenant kapsamı
|
||
└── .imports/{importId}/ # wizard import staging + backup (seeder taramalarına girmez)
|
||
```
|
||
|
||
> Bu dosyalar elle de düzenlenebilir; ilgili ekrandan tekrar kaydedildiğinde yeniden üretilirler.
|
||
> Wizard dosyası `EditFileName` ile güncellenirse sunucu önce eski dosyayı ve ürettiği kayıtları
|
||
> siler, sonra yenisini üretir. Wizard'ın ürettiği ekran **ListForm detayından** düzenlendiğinde
|
||
> de aynı dosya güncellenir (`WizardSeedSynchronizer`): `ListForm`/`Fields` bölümleri ve
|
||
> `Wizard` bölümündeki karşılıkları veritabanındaki güncel haliyle değiştirilir.
|
||
|
||
---
|
||
|
||
## 22. Sorun Giderme
|
||
|
||
| Belirti | Olası neden ve çözüm |
|
||
| --- | --- |
|
||
| `/api/abp/application-configuration` 503 dönüyor | Veritabanına erişilemiyor. Bağlantı dizesini ve veri konteynerini kontrol edin; `/api/setup/application-status` ile durumu görün. |
|
||
| UI `/setup` ekranına düşüyor | Şema oluşmamış veya bekleyen migration var. Setup ekranından migration'ı tetikleyin ya da DbMigrator'ı çalıştırın. |
|
||
| Giriş "UserCannotSignIn..." hatası veriyor | [11.3](#113-giriş-engelleri) tablosuna bakın: IP, çalışma saati, doğrulama, şube/eş zamanlı kullanıcı limiti. |
|
||
| Yeni sürüm tarayıcıda görünmüyor | Service worker `prompt` modundadır; güncelleme bildirimini onaylayın veya sekmeyi tamamen kapatıp açın. |
|
||
| DevExtreme teması yüklenmiyor | `public/css` altındaki tema dosyaları runtime cache'tedir (StaleWhileRevalidate); hard refresh yeterlidir. |
|
||
| Hangfire başlangıçta hata veriyor | Bağlantı dizesi boşsa Hangfire kaydı atlanır ama ABP modülleri yüklenir. Bağlantı dizesini doğrulayın. |
|
||
| Dinamik servis yayınlanmıyor | Önce `TestCompile` çalıştırın; derleme hatası mesajı UI'da döner. `Publish` için ilgili yetki gerekir. |
|
||
| Raporlarda font/karakter bozukluğu (Linux) | `DevExpressFontConfiguration.InstallLinuxFonts` loglarını kontrol edin; konteynerde font paketi eksik olabilir. |
|
||
|
||
---
|
||
|
||
## 23. Bilinen Sınırlar ve Notlar
|
||
|
||
- `route.constant.ts` içindeki `supplychain`, `maintenance`, `warehouse`, `projects`, `crm`,
|
||
`mrp`, `accounting` ve `hr` yol sabitleri **yol sözleşmesidir**; bu alanların ekranları fiziksel
|
||
React sayfaları olarak değil, ListForm konfigürasyonu ile üretilir. `hr` altında yalnızca
|
||
organizasyon şeması (`OrgChart.tsx`) fiziksel bir view'dır.
|
||
- `Telegram` bildirim kanalı altyapıda tanımlıdır ancak UI'da kapalıdır.
|
||
- Depodaki `appsettings*.json` ve deployment dokümanları geliştirme değerleri/örnek kimlik
|
||
bilgileri içerir; üretim öncesi tümü değiştirilmelidir.
|
||
- SQL View Designer tek yönlüdür (model → T-SQL). Elle yazılmış ya da tasarımcının kanonik
|
||
şekline uymayan bir view tanımı geri okunamaz; dialog ham SQL moduna düşer.
|
||
- `api/test/Sozsoft.Platform.EntityFrameworkCore.Tests` şu an SQLite şema oluşturmada
|
||
(`nvarchar(max)` → `SQLite Error 1`) kırıktır; bu kırıklık kod standardından önce de vardı ve
|
||
ayrı bir iş olarak ele alınmalıdır.
|
||
- Rol–yetki eşleşmeleri veritabanında müşteri ortamına göre değişir; buradaki yetki kodları
|
||
tanımın kendisidir, atama değil.
|
||
|
||
---
|
||
|
||
## Lisans ve Sahiplik
|
||
|
||
Bu depo Sozsoft'a aittir. DevExpress/DevExtreme bileşenleri ticari lisans gerektirir
|
||
(`api/DevExpress_License.txt`).
|