# Low-Code Genişletilmiş Referans (JSON Kolon ve Modül Sözleşmeleri) `lowcode.instructions.md` **nasıl üretileceğini** anlatır; bu dosya **neyin ayarlanabildiğini** tek tek listeler. Orada "bunun bir JSON kolonu var" denen her şeyin alan alan karşılığı burada durur: ListForm/ListFormField'ın tüm JSON kolonları, grafik sözleşmesi, Visual Designer envanteri ve zamanlanmış e-posta modülü. Son bölüm (§12) Saas ve Administration menülerindeki **hazır gelen bütün ekranları** ve bunların yeni bir komponentte nasıl kullanılacağını listeler. **Kullanım sırası:** `ai.instructions.md` → `lowcode.instructions.md` → **bu dosya** → `README.md`. Bir istek geldiğinde önce ana dosyadaki karar sırasını işlet; "hangi anahtarı yazacağım?" sorusunda buraya bak. **Kaynak:** Buradaki her tablo `api/src/Sozsoft.Platform.Application.Contracts/ListForms/**` ve `api/src/Sozsoft.Platform.Domain/Entities/Tenant/ListForm/ListForm.cs` dosyalarından çıkarılmıştır. Çelişki hâlinde **kod esastır**; bu dosya güncellenir. **Ortak kurallar** - Bütün `*Json` kolonları veritabanında **tek satır JSON string** olarak durur; wizard seed dosyasına yazarken kaçışlanır. - Varsayılan değeri olan bir alanı tekrar yazmak zorunda değilsin; yalnızca farklı olanı yaz. - `Accepted Values` yazan yerlerde değer birebir eşleşmelidir (büyük/küçük harf dahil). - **Bilinmeyen anahtar sessizce düşer — tarayıcıya hiç ulaşmaz.** `GridOptionsDto` bu 47 kolonun ham metnini `[JsonIgnore]` ile gizler ve istemciye yalnızca tipli DTO'ya (`SchedulerOptionJson` → `SchedulerOptionDto`) çözülmüş hâlini yollar. Dolayısıyla: - DTO'da olmayan bir DevExtreme seçeneğini `*Json`'a yazmak **işe yaramaz**; kalıcı olarak gerekiyorsa önce ilgili DTO'ya alan eklenir (ve bu dosya güncellenir). - Yanlış **tipte** yazılan değer (`"3"` yerine `3`, dizi yerine metin) `JsonSerializer` tarafında `JsonException` fırlatır ve ekranın metadata isteği tamamen düşer — sessiz değil, gürültülü bir hatadır. Tipleri tablodaki gibi yaz. - Bu kural yalnızca alan seviyesindeki `ListFormField.EditorOptions` için geçmez: orası ham metin olarak taşınır, tanımadığı anahtarı doğrudan editöre geçirir (§9.8). --- ## 0. Üretim yetenek envanteri — bir komponent üretirken tara Bir ekran/komponent üretirken **her katmanı sırayla geç**. Cevabı "gerekmiyor" olan katmanı atla, ama hiçbirini görmeden bırakma; kullanıcı "şunu da yapabilir miydik?" dediğinde cevap "kod yazmamız gerekir" olmasın. | # | Katman | Sorulacak soru | Nerede | | --- | --- | --- | --- | | 0 | **Hazır yetenek** | Bu talebin karşılığı Saas/Administration menüsünde zaten var mı? | §12.5 | | 1 | **Veri** | Tablo/view var mı, join gerekiyor mu, anahtar ve tipi ne? | `lowcode` §8 · §9.6 | | 2 | **Ekran türü** | Liste mi, tek kayıt formu mu, serbest yerleşim mi? Kaç görünüm açılacak? | `lowcode` §0.6.1 · §9.8 · §5.4 | | 3 | **Sütunlar** | Editör tipi, biçim, hizalama, genişlik, band, gizli/aktif | `lowcode` §4.3 · §9.7 | | 4 | **Lookup** | Sabit liste mi, sorgu mu, servis mi? Cascade var mı? | `lowcode` §4.3.4 | | 5 | **Varsayılanlar** | Kullanıcı/tarih/tenant/sequence/sorgu ile otomatik dolacak alanlar | `lowcode` §4.3.5 · §9.9 | | 6 | **Alan davranışı** | Hesap, kopyalama, temizleme, koşullu kilit, uyarı, servis çağrısı | `lowcode` §5 | | 7 | **Editör görünümü** | Maske, ondalık, tarih biçimi, arama, çoklu seçim, görsel yükleme | `lowcode` §6 | | 8 | **Doğrulama** | Zorunluluk, aralık, desen, karşılaştırma + sunucu tarafı kontrol | `lowcode` §4.3.6 · §4 | | 9 | **Filtre/arama** | Filtre satırı, başlık filtresi, arama paneli, ek filtre çubuğu, grup paneli | §2.6 · `lowcode` §4.3.8 | | 10 | **Özet** | Toplam/adet satırı, grup özetleri, pivot | §9.5 · §6 | | 11 | **Biçimlendirme** | Koşullu satır/hücre rengi, CSS sınıfı | `lowcode` §4.3.7 | | 12 | **Düzenleme deneyimi** | Popup/satır/hücre/batch, form grupları, kopyalama, toplu silme | §3 | | 13 | **Aksiyonlar** | Toolbar ve satır butonları: adres, diyalog, script, yetki, koşullu görünürlük | `lowcode` §4.9 | | 14 | **Yazma mantığı** | Özel SQL, before/after kancaları, farklı servis adresi | §4 | | 15 | **Ana-detay** | Alt form sekmeleri ve ilişki alanları | §5.2 | | 16 | **Gösterge** | Üstte KPI kartları, grafik | §5.3 · §8 | | 17 | **Süreç** | Onay akışı, bilgilendirme, durum alanları | `lowcode` §4.7 | | 18 | **Otomasyon** | Zamanlanmış iş, zamanlanmış e-posta, bildirim kuralı | `lowcode` §9.10–§9.11 · §11 | | 19 | **Çıktı** | Hazır grid raporu ya da rapor şablonu | `lowcode` §9.12 | | 20 | **Yetki** | Ekran, alan, komut ve buton yetkileri; menü görünürlüğü | §5.1 · `lowcode` §4.2 | | 21 | **Tenant/şube** | `IsTenant`, `IsBranch`, `IsOrganizationUnit`, sorgularda kırılım | `lowcode` §4.2 | | 22 | **Dil** | Menü, başlık, alan, buton, mesaj metinleri EN + TR | `lowcode` §4.2 | | 23 | **Kullanıcı tercihi** | Grid durumunun saklanması, kullanıcı/rol/dil varyantı | §2.5 · §5.7 | | 24 | **Seed** | Üretilen her artefaktın dosyası + yalnızca DB'de yaşayan kayıtların geri getirici script'i | `lowcode` §0.2 · §9.14 | Serbest yerleşimli bir komponent (Visual Designer) üretiyorsan 0–2 ve 13–24 aynen geçerlidir; 3–12 yerine tasarımcı envanteri (§10.1), `Form` sözleşmesi (§10.2), veri kaynağı/filtre sözleşmesi (§10.4), bileşen prop sözleşmeleri (§10.5–§10.9), olay yükleri (§10.10) ve event script'leri (`lowcode` §7.8) kullanılır. 20. katman (yetki) orada iki yerdedir: düğüm başına `designerPermission` ve `Form`'un dört komut yetkisi. Katmanların çoğunda cevap yeni bir artefakt değil, platformun **hazır bir ekranıdır**: numaratör, bildirim, zamanlanmış iş, rapor, ayar, dil, yetki, şube, kısıt, dosya. Hepsinin envanteri §12'de — "kod yazmamız gerekir" demeden önce §12.5'e bak. --- ## 1. ListForm JSON kolon haritası Bir List ekranının bütün davranışı bu kolonlardadır. "Şunu yapabilir miyiz?" sorusunun cevabı önce bu tabloda aranır. Aşağıdaki tablo `*Json` bloklarını listeler. Bunların **öncesinde** ekranın düz kolonları gelir ve çoğu isteğin cevabı aslında oradadır: | Kolon | Varsayılan | Ne yapar | | --- | --- | --- | | `ListFormCode` | — | Ekranın kimliği; route, metadata ve varyantlar bu koda bağlanır | | `DataSourceCode` | `"Default"` | Hangi bağlantıdan okunacağı (`Sas_H_DataSource`) | | `SelectCommandType` | `1` Table | `1` Table · `2` View · `3` TableValuedFunction · `4` Query · `5` StoredProcedure | | `SelectCommand` | — | Tablo/view adı, fonksiyon çağrısı ya da sorgu metni | | `TableName` | `SelectCommand` | Üretilen `SELECT`'te kolonların ve join'lerin önüne yazılan **alias**. Boşsa `SelectCommand` kullanılır; `SelectCommand` bir sorgu metni ya da fonksiyon çağrısıysa buraya kısa bir ad yaz | | `KeyFieldName` · `KeyFieldDbSourceType` | — · `16` String | Anahtar kolon ve `System.Data.DbType` karşılığı | | `SelectFieldsDefaultValueJson` | — | **Okuma** sorgusuna parametre olarak katılan değerler (`FieldsDefaultValueDto[]`) — `@USERID`, `@TENANTID` gibi | | `DefaultFilter` | — | Her sorgunun sonuna `AND` ile eklenen sabit `WHERE` koşulu. `DefaultValueHelper` üzerinden geçer, yani `@USERID`/`@TENANTID`/`@NOW` gibi token'lar çözülür. Soft delete'li tabloda (`IsDeletedField: true`) wizard buraya `"IsDeleted" = 'false'` yazar | | `SortMode` | — | `UiGridSortModeEnum`: `1` Single · `2` Multiple · `3` None | | `PageSize` | — | Sayfa başına kayıt; `0` = tümü | | `Name` · `Title` · `Description` | — | Ekran adı, başlığı, açıklaması — **dil anahtarı** yazılır | | `IsTenant` · `IsBranch` · `IsOrganizationUnit` | `IsMultiTenant` · `false` · `false` | Otomatik kırılım filtresi | | Kolon | Ne yapılandırır | Bölüm | | --- | --- | --- | | `ColumnOptionJson` | Grid genel görünümü (kenarlık, satır rengi, kolon seçici, sabitleme) | §2.1 | | `CommandColumnJson` | Toolbar ve satır butonları | `lowcode` §4.9 | | `RowJson` | Satır yüksekliği ve metin kaydırma | §2.2 | | `PagerOptionJson` | Sayfalama şeridi | §2.3 | | `SelectionJson` | Seçim modu ve checkbox davranışı | §2.4 | | `StateStoringJson` | Kullanıcının grid tercihlerinin saklanması | §2.5 | | `FilterRowJson` · `HeaderFilterJson` · `FilterPanelJson` · `SearchPanelJson` · `GroupPanelJson` | Filtre/arama/gruplama panelleri | §2.6 | | `ExtraFilterJson` | Ekran üstü ek filtre çubuğu | `lowcode` §4.3.8 | | `EditingOptionJson` | Düzenleme modu, izinler, popup ayarları | §3.1 | | `EditingFormJson` | Düzenleme formunun grup/sekme yerleşimi | §3.2 | | `InsertCommand` · `UpdateCommand` · `DeleteCommand` (+ `*Before`/`*After`) | Özel SQL komutları ve kancalar | §4 | | `*FieldsDefaultValueJson` | Otomatik doldurulan alanlar | `lowcode` §4.3.5 | | `*ServiceAddress` | Yazma işlemini karşılayan uç | §4.3 | | `PermissionJson` | Ekran yetkileri | §5.1 | | `SubFormsJson` | Alt form sekmeleri | §5.2 | | `WidgetsJson` | KPI kartları | §5.3 | | `WorkflowJson` | Onay akışı | `lowcode` §4.7 | | `LayoutJson` | Açık görünümler ve varsayılan | §5.4 | | `PivotOptionJson` | Pivot görünümü | §6 | | `TreeOptionJson` · `GanttOptionJson` · `SchedulerOptionJson` · `TodoOptionJson` | Ağaç/Gantt/Takvim/Kanban eşlemeleri | §7 | | `SeriesJson` ve diğer 21 grafik kolonu | Chart görünümü | §8 | | `CustomJsSourcesJson` · `CustomStyleSourcesJson` | Sayfaya enjekte edilen JS/CSS | §5.5 | | `AdaptiveLayoutJson` | Dar ekranda öğe gizleme (grafik) | §8.4 | | `CommonJson` · `DataSourceJson` | Grafik geneli ve grafik sorgusu | §8.2 · §8.3 | | `Width` · `Height` · `FullHeight` | Ekran boyutu | — | | `ListFormType` · `IsSubForm` · `SubFormsListFormType` · `ShowNote` | Ekranın türü ve alt form davranışı | §5.6 | | `CultureName` · `UserId` · `RoleId` | Aynı ekranın dil/kullanıcı/rol varyantı | §5.7 | --- ## 2. Grid görünümü ### 2.1 `ColumnOptionJson` (`GridColumnOptionDto`) | Anahtar | Varsayılan | Anlam | | --- | --- | --- | | `ShowBorders` | `true` | Dış kenarlık | | `ShowRowLines` | `true` | Satır çizgileri | | `ShowColumnLines` | `false` | Kolon çizgileri | | `RowAlternationEnabled` | `true` | Tek/çift satır renklendirme | | `AllowColumnReordering` | `true` | Kullanıcı kolon sırasını değiştirebilir | | `AllowColumnResizing` | `true` | Kolon genişliği değiştirilebilir | | `ColumnResizingMode` | `"widget"` | `nextColumn` \| `widget` | | `ColumnAutoWidth` | `false` | İçeriğe göre genişlik | | `ColumnFixingEnabled` | `false` | Kolon sabitleme menüsü | | `ColumnChooserEnabled` | `false` | Kolon seçici düğmesi | | `ColumnChooserMode` | `"dragAndDrop"` | `dragAndDrop` \| `select` | | `ColumnHidingEnabled` | `true` | Dar ekranda kolon gizleme | | `HoverStateEnabled` | `false` | Satır üzerine gelince vurgulama | | `FocusedRowEnabled` | `true` | Odaklı satır | | `ShowColumnHeaders` | `true` | Başlık satırı | | `RtlEnabled` | `false` | Sağdan sola | ### 2.2 `RowJson` (`GridRowDto`) | Anahtar | Varsayılan | Anlam | | --- | --- | --- | | `RowHeight` | `"auto"` | Satır yüksekliği (CSS) | | `WhiteSpace` | `"normal"` | Uzun metnin kaydırılması | | `OverflowWrap` | `"break-word"` | Kelime kırma | ### 2.3 `PagerOptionJson` (`GridPagerOptionDto`) Adı yalnızca sayfalamayı çağrıştırsa da bu blok **kaydırma ve yükleniyor panelini** de taşır. | Anahtar | Varsayılan | Anlam | | --- | --- | --- | | `Visible` | `true` | Sayfalama şeridi | | `ShowPageSizeSelector` | `false` | Sayfa boyu seçici | | `ShowInfo` | `false` | "Page 1 of 4 (37 items)" bilgisi | | `ShowNavigationButtons` | `true` | İleri/geri düğmeleri | | `AllowedPageSizes` | `"10,20,50,100"` | **Virgüllü metin**, dizi değil | | `InfoText` | `"Page {0} of {1} ({2} items)"` | `{0}` sayfa · `{1}` toplam sayfa · `{2}` kayıt | | `DisplayMode` | `"adaptive"` | `adaptive` \| `compact` \| `full` | | `ScrollingMode` | `"standard"` | `standard` \| `virtual` \| `infinite` — uzun listelerde `virtual` | | `LoadPanelEnabled` | `"auto"` | **Metin** alanıdır: `"auto"` \| `"true"` \| `"false"` | | `LoadPanelText` | `"Loading..."` | Yükleniyor metni | Sayfa başına kayıt sayısı ekranın `PageSize` alanındadır; `0` = tümü. `ScrollingMode` ile `PageSize` birlikte düşünülür: `virtual`/`infinite` seçilip `PageSize: 0` yazılırsa sayfalama devre dışı kalır ve tüm küme tek istekte çekilir. ### 2.4 `SelectionJson` (`SelectionDto`) | Anahtar | Varsayılan | Değerler | | --- | --- | --- | | `Mode` | `"none"` | `single` \| `multiple` \| `none` | | `AllowSelectAll` | `false` | | | `SelectAllMode` | `"allPages"` | `allPages` \| `page` | | `ShowCheckBoxesMode` | `"always"` | `always` \| `none` \| `onClick` \| `onLongTap` | Toolbar butonları seçili satırlarla çalışır (`lowcode` §4.9); onay akışı varsa wizard `single` yazar. ### 2.5 `StateStoringJson` (`StateStoringDto`) | Anahtar | Varsayılan | Anlam | | --- | --- | --- | | `Enabled` | `true` | Kullanıcının kolon/filtre/sıralama tercihleri saklansın mı | | `Type` | `"custom"` | `custom` (sunucuda kullanıcı bazlı) \| `localStorage` \| `sessionStorage` | | `StorageKey` | — | Anahtar; boşsa ekran kodundan türer | | `SavingTimeout` | `5000` | Değişiklikten kaç ms sonra yazılacağı — **`[Range(1500, 5000)]`**, dışına çıkan değer doğrulamada reddedilir | `Type: "custom"` tercih edilir: tercih sunucuda `ListFormCustomization` kaydı olarak (`ListFormCustomizationTypeEnum.GridState = 2`) kullanıcı bazlı saklanır, bu yüzden başka tarayıcıdan girildiğinde de korunur. `localStorage`/`sessionStorage` yalnızca o tarayıcıdadır. ### 2.6 Filtre, arama ve gruplama panelleri **`FilterRowJson`** (`GridFilterRowDto`): `Visible` (`false`), `ApplyFilter` (`auto` \| `onClick`), `AllowUserUiFilterSave` (varsayılan `true` — kullanıcı kendi filtresini kaydedebilir; kayıt `ListFormCustomizationTypeEnum.UserUiFilter = 1` olarak tutulur). **`HeaderFilterJson`** (`GridHeaderFilterDto`): `Visible` (`false`), `AllowSearch` (`false`), `Height` (`325`), `Width` (`252`), `SearchTimeout` (`500`). **`FilterPanelJson`** (`FilterPanelDto`): `Visible` (`false`), `FilterEnabled` (`false`), `Texts.ClearFilter` (`"Clear"`) / `Texts.CreateFilter` (`"Create Filter"`) / `Texts.FilterEnabledHint` (`"Enable the filter"`), `CustomizeText` (serbest JSON; filtre metnini biçimlendirmek için — sözlükte tipi yoktur, olduğu gibi bileşene geçer). **`SearchPanelJson`** (`SearchPanelDto`): `Visible` (`false`), `Width` (`160`). **`GroupPanelJson`** (`GroupPanelDto`): `Visible` (`false`), `AutoExpandAll` (`false`). `AutoExpandAll: true` **fazladan bir sorgu daha** çalıştırır. --- ## 3. Düzenleme ### 3.1 `EditingOptionJson` (`GridEditingDto`) | Anahtar | Varsayılan | Anlam | | --- | --- | --- | | `Mode` | `"popup"` | `batch` \| `cell` \| `row` \| `form` \| `popup` | | `RefreshMode` | `"full"` | `full` \| `reshape` \| `repaint` | | `AllowAdding` / `AllowUpdating` / `AllowDeleting` | `false` | Aksiyon izinleri (yetki ayrıca `PermissionJson`) | | `AllowAllDeleting` | `false` | Toplu silme düğmesi | | `AllowDuplicate` | `false` | Kaydı kopyalayarak yeni kayıt | | `AllowDetail` | `false` | Satırda Detay düğmesi | | `ConfirmDelete` | `true` | Silme onayı | | `UseIcons` | `false` | Aksiyonlar ikon olarak | | `NewRowPosition` | `"viewportTop"` | `first` \| `last` \| `pageTop` \| `pageBottom` \| `viewportTop` \| `viewportBottom` | | `StartEditAction` | `"click"` | `click` \| `dblClick` | | `SelectTextOnEditStart` | `false` | Düzenlemeye girince metni seç | | `EditColumnName` | — | Aksiyon sütununun başlığı | | `SendOnlyChangedFormValuesUpdate` | `false` | Update'te yalnızca değişen alanları gönder | | `AddPageUrl` | — | Yeni kayıt popup yerine bu adreste açılır | | `Popup` | — | Aşağıdaki alt nesne | `Popup` (`GridEditingPopupDto`): `Title`, `ShowTitle` (`true`), `Width` (`700`), `Height` (`500`), `FullScreen` (`false`), `HideOnOutsideClick` (`true`), `ResizeEnabled` (`true`), `DragEnabled` (`true`), `RestorePosition` (`true`), `Position` (`center` \| `top` \| `bottom` \| `left` \| `right`). ### 3.2 `EditingFormJson` (`EditingFormDto[]`) Düzenleme formundaki grupların listesi. Alanların hangi gruba düştüğü `ListFormField` üzerindeki `EditGroupOrderNo` / `EditOrderNo` ile belirlenir. | Anahtar | Varsayılan | Anlam | | --- | --- | --- | | `Order` | `1` | Grubun sırası (`EditGroupOrderNo` ile eşleşir) | | `ItemType` | `"group"` | `group` (kullanılan) \| `tabbed` \| `simple` \| `empty` \| `button` | | `Caption` | — | Grup başlığı (dil anahtarı) | | `ColCount` | `2` | Grup içi kolon sayısı | | `ColSpan` | `2` | Grubun formda kapladığı kolon | Wizard bu listeyi `Groups` bloğundan üretir; anahtar alan ve `IncludeInEditingForm: false` olanlar dışarıda kalır. --- ## 4. Yazma komutları ve kancalar ### 4.1 Komutlar | Kolon | Ne zaman | | --- | --- | | `InsertCommand` / `UpdateCommand` / `DeleteCommand` | Boşsa platform komutu kendi üretir; doluysa **bu SQL** çalışır | | `InsertBeforeCommand` / `InsertAfterCommand` | Insert'ten önce/sonra | | `UpdateBeforeCommand` / `UpdateAfterCommand` | Update'ten önce/sonra | | `DeleteBeforeCommand` / `DeleteAfterCommand` | Delete'ten önce/sonra | **Kancalar, kod yazmadan iş mantığı çalıştırmanın yeridir**: stok düşme, hareket kaydı, durum güncelleme, log, bildirim kuyruğuna satır ekleme. Karmaşıklaşınca gövdeyi bir stored procedure'e taşı ve kancadan onu çağır (`EXEC Wms_S_AfterOrderInsert @Id, @USERID`). ### 4.2 Komut içinde kullanılabilen anahtarlar | Token | Değer | | --- | --- | | `@ID` | Kaydın anahtarı (Delete'te seçili anahtar kümesi) | | `@USERID` · `@USERNAME` · `@ROLES` | Oturumdaki kullanıcı | | `@FieldName` | Ekrandan gelen o alanın değeri — tablodaki her kolon için geçerlidir (`@OrderNo`, `@Amount`) | `*FieldsDefaultValueJson` ile üretilen değerler (`@NOW`, `@NEWID`, `@TENANTID`, Sequence…) komuta parametre olarak katılır (`lowcode` §4.3.5). **String birleştirme ile sorgu kurma.** ### 4.3 `*ServiceAddress` `InsertServiceAddress` / `UpdateServiceAddress` / `DeleteServiceAddress` varsayılan olarak `list-form-data/insert|update|delete` uçlarıdır. Yazma işini bir Custom Endpoint ya da Dynamic Service'e devretmek istiyorsan bu alanı o ucun adresiyle değiştirirsin — ekranın geri kalanı (form, doğrulama, yetki) aynı kalır. --- ## 5. Ekran seviyesindeki diğer bloklar ### 5.1 `PermissionJson` (`PermissionCrudDto`) Tek harfli anahtarlar: `R` (read), `C` (create), `U` (update), `D` (delete), `E` (export), `I` (import), `N` (note). Değerler **yetki adıdır**, boolean değil: ```json { "R": "App.Mrp.Orders", "C": "App.Mrp.Orders.Create", "U": "App.Mrp.Orders.Update", "D": "App.Mrp.Orders.Delete", "E": "App.Mrp.Orders.Export", "I": "App.Mrp.Orders.Import", "N": "App.Mrp.Orders.Note" } ``` Alan seviyesindeki karşılığı `ListFormField.PermissionJson`'dır ve **şeması farklıdır** (`ListFormFieldPermissionDto`) — ekran seviyesindeki yedi harfli sözleşmeyi buraya kopyalama: | Anahtar | Tip | Anlam | | --- | --- | --- | | `Deny` | bool | `true` ise alan **hiç dönmez**; diğer anahtarlara bakılmaz | | `C` · `R` · `U` | string | Yaratma / okuma / güncelleme yetkisinin **adı**. Boşsa ekranın kendi Create/Read/Update yetkisi kullanılır | | `E` | bool | Alan dışa aktarımda yer alsın mı | | `I` | bool | Alan içe aktarımda kabul edilsin mi | ```json { "C": "App.Mrp.Orders.Create", "R": "App.Mrp.Orders", "U": "App.Mrp.Orders.Update", "E": true, "I": true, "Deny": false } ``` `ListFormField` üzerindeki `CanRead` / `CanCreate` / `CanUpdate` / `CanExport` kolonları **veritabanında yoktur** (`[NotMapped]`); `ListFormFieldManager.SetPermissionsAsync` bu JSON'u oturumdaki yetkilerle karşılaştırarak istek başına hesaplar. Üçü de `false` çıkan alan metadata'dan tamamen düşer — yani okuma yetkisi olmayan bir kolon sorguya bile girmez. Wizard varsayılan olarak `DefaultFieldPermissionJson(permissionName)` üretir. ### 5.2 `SubFormsJson` (`SubFormDto[]`) | Anahtar | Anlam | | --- | --- | | `TabType` | Sekmenin görünümü — `ListFormTabTypeEnum`: `List` \| `Card` \| `Tree` \| `Gantt` \| `Scheduler` \| `Todo` \| `Form` \| `Chart` \| `Pivot` | | `TabTitle` | Dil anahtarı | | `Code` | Hedef `ListFormCode` | | `IsRefresh` | Ana kayıt değişince yenilensin | | `Relation[]` | `ParentFieldName` → `ChildFieldName` + `DbType` (`System.Data.DbType`, **sayı**; bileşik anahtarda birden çok satır) | Alt formun kendisi de bir ListForm'dur: `IsSubForm = true` olmalı ve genellikle `CreateMenu: false` ile menüsüz üretilir (`lowcode` §4.2). `TabType`, hedef ekranın `LayoutJson`'ında açık olan bir görünüm olmalıdır; kapalı bir görünüm sekmede boş çizilir. ### 5.3 `WidgetsJson` (`WidgetEditDto[]`) Ekranın üstündeki KPI şeridi. **Sözleşmesi sezgisel değildir, dikkatle oku:** | Anahtar | Ne yazılır | | --- | --- | | `SqlQuery` | Kartları besleyen sorgu. **Zorunludur** — boş olan widget hiç çizilmez | | `Title` · `SubTitle` · `Value` · `Color` · `Icon` · `OnClick` | **Sorgu sonucundaki kolon adları** — sabit metin değil. Sunucu her satırda bu adlı kolonu okur; kolon yoksa boş string döner | | `ColSpan` · `ColGap` · `ClassName` | Şeritteki yerleşim (widget başına, karta değil) | | `ValueClassName` | Değerin CSS sınıfı, varsayılan `text-3xl` | | `IsActive` | `false` ise sorgu hiç çalıştırılmaz | **Bir widget, sorgunun döndürdüğü her satır için bir kart çizer.** Yani tek bir widget kaydıyla "Bekleyen / Onaylı / Reddedilen" üçlüsü tek sorgudan üretilebilir: ```sql SELECT 'Bekleyen' AS Baslik, COUNT(*) AS Deger, 'amber' AS Renk, 'FaClock' AS Ikon FROM Mrp_T_Order WHERE Status = 1 UNION ALL SELECT 'Onaylı', COUNT(*), 'green', 'FaCheck' FROM Mrp_T_Order WHERE Status = 2 ``` ```json { "Title": "Baslik", "Value": "Deger", "Color": "Renk", "Icon": "Ikon", "ColSpan": 4, "IsActive": true } ``` Sorgu ekranın `DataSourceCode` bağlantısında, **olduğu gibi** çalıştırılır: - Ekranın otomatik tenant/şube/OU filtresi **uygulanmaz**. - `@USERID` / `@TENANTID` gibi token'lar **çözülmez** — bunlar `*FieldsDefaultValueJson` ve `DefaultFilter` yolunun sözleşmesidir. Widget sorgusuna yazılırsa bağlanmamış parametre hatası verir. Kiracı kırılımı gerekiyorsa ya kiracıya özel bir `DataSource` kullan, ya da kırılımı sorgunun okuduğu view'ın içine göm. ### 5.4 `LayoutJson` (`LayoutDto`) | Anahtar | Varsayılan | | --- | --- | | `Grid` · `Card` · `Pivot` · `Chart` · `Tree` · `Gantt` · `Scheduler` | `true` | | `Todo` | `false` | | `DefaultLayout` | `"grid"` | Wizard'daki görünüm bayraklarının karşılığıdır. **DTO varsayılanları yanıltıcıdır:** blok yazılmazsa yedi görünüm birden açık gelir; ekranın üstünde çalışmayan görünüm düğmeleri çıkmasın diye wizard bu bloğu her zaman açıkça yazar. `DefaultLayout`, `true` olan bir görünümü göstermelidir (§7'deki zorunlu `*Expr` alanları boşsa o görünümün JSON'u hiç yazılmaz). ### 5.5 `CustomJsSourcesJson` / `CustomStyleSourcesJson` Her ikisi de **string dizisidir**. Bir eleman `http` ya da `/` ile başlıyorsa dosya olarak sayfaya eklenir (`