From 3922c4653911fc36466fc36d574555bd46f7a14e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?=
<76204082+iamsedatozturk@users.noreply.github.com>
Date: Wed, 7 Oct 2026 21:08:10 +0300
Subject: [PATCH] =?UTF-8?q?Grid,=20Tree,=20FormDevexpress=20komponentlerin?=
=?UTF-8?q?=20yetenekleri=20e=C5=9Fitlendi?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/instructions/lowcode.instructions.md | 25 +-
README.md | 6 +-
claude.md | 5 +
.../5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json | 4 +-
ui/src/views/form/FormButtons.tsx | 2 +-
ui/src/views/form/FormDevExpress.tsx | 70 ++---
.../form/editors/GridBoxEditorComponent.tsx | 8 +-
.../editors/ImageUploadEditorComponent.tsx | 62 +++-
.../form/editors/TagBoxEditorComponent.tsx | 6 -
ui/src/views/form/shared/formItems.ts | 29 +-
ui/src/views/form/useLookupDataSource.ts | 8 +-
ui/src/views/list/CardView.tsx | 3 +-
ui/src/views/list/Grid.tsx | 96 +++---
ui/src/views/list/Tree.tsx | 95 +++---
.../list/editors/GridBoxEditorComponent.tsx | 30 --
.../editors/ImageUploadEditorComponent.tsx | 273 ------------------
.../editors/ImageViewerEditorComponent.tsx | 114 --------
.../list/editors/TagBoxEditorComponent.tsx | 42 ---
ui/src/views/list/editors/cellEditors.tsx | 172 +++++++++++
ui/src/views/list/shared/cascade.ts | 221 +++++++++-----
ui/src/views/list/shared/editPopup.ts | 2 +-
ui/src/views/list/shared/editingForm.ts | 88 ++++--
.../views/list/shared/editingFormScripts.ts | 183 ++++++++++--
ui/src/views/list/shared/imageValue.ts | 4 +-
ui/src/views/list/shared/workflowRows.tsx | 2 +-
ui/src/views/list/useListFormColumns.ts | 16 +-
ui/src/views/shared/MenuAddDialog.tsx | 2 +-
ui/src/views/shared/SharedGridBoxEditor.tsx | 16 +-
ui/src/views/shared/htmlEditorOptions.ts | 2 +-
ui/src/views/shared/lookupColor.tsx | 2 +-
30 files changed, 784 insertions(+), 804 deletions(-)
delete mode 100644 ui/src/views/list/editors/GridBoxEditorComponent.tsx
delete mode 100644 ui/src/views/list/editors/ImageUploadEditorComponent.tsx
delete mode 100644 ui/src/views/list/editors/ImageViewerEditorComponent.tsx
delete mode 100644 ui/src/views/list/editors/TagBoxEditorComponent.tsx
create mode 100644 ui/src/views/list/editors/cellEditors.tsx
diff --git a/.github/instructions/lowcode.instructions.md b/.github/instructions/lowcode.instructions.md
index 307cbea4..9f38d394 100644
--- a/.github/instructions/lowcode.instructions.md
+++ b/.github/instructions/lowcode.instructions.md
@@ -1490,9 +1490,28 @@ cascade eksik yetenek değildir ve analizde `Ready to Start`'ı engellemez. Tam
| `CascadeFilterOperator` | `StaticData` cascade filtresinin operatörü; varsayılan `=` |
| `CascadeEmptyFields` | **Ebeveyn alanda** doldurulur; bu alan değişince boşaltılacak çocuk alanlar, virgülle. Ara halka (İl) hem çocuk hem ebeveyn olduğu için iki tarafı birden taşır |
-Cascade liste popup'ında ve form sayfasında (`FormDevExpress`) aynı davranır. Form sayfasında çocuk
+Cascade liste popup'ında (Grid, Tree), satır içi düzenlemede ve form sayfasında (`FormDevExpress`)
+aynı kuralla çalışır; kural tek yerdedir (`list/shared/cascade.ts`, `getCascadeClearFields`): bir alan
+değişince ebeveyni o alan olan çocuklar **ve** alanın `CascadeEmptyFields` listesi boşaltılır. Kilit
+ve temizleme platform editörlerinde (TagBox, GridBox, ImageUpload) de uygulanır. Form sayfasında çocuk
yalnızca ebeveynin değeri **gerçekten değiştiğinde** temizlenir ve listesi yeni ebeveyn değeriyle
yeniden kurulur; formun aynı değeri tekrar bildirmesi (veri forma geri verilince) yok sayılır.
+
+**Liste popup'ı ↔ form sayfası editör eşliği.** İkisi aynı ListForm tanımından beslendiği için
+editör yetenekleri ortak koddan gelir; bir tarafa yeni yetenek ortak yardımcıya eklenerek verilir:
+
+| Yetenek | Ortak kaynak |
+| --- | --- |
+| `EditorOptions` varsayılanları (tarih maskesi/biçimi, HtmlEditor, telefon) | `withEditorTypeDefaults` (`list/shared/editingForm.ts`) |
+| Lookup varsayılanları (`valueExpr`, `displayExpr`, `searchEnabled`) | `getLookupEditorDefaults` |
+| Buton `onClick` (fonksiyon metni, `@SCAN_BARCODE`) ve bağlamı | `resolveEditorButtons` + `withButtonContext` |
+| Cascade temizleme/kilit | `list/shared/cascade.ts` |
+| Grid/Tree `onEditorPreparing` gövdesi | `prepareEditingEditor` (`list/shared/editingFormScripts.ts`) |
+| TagBox, GridBox, ImageUpload, ImageViewer | Tek uygulama `form/editors/*`; liste hücresi `list/editors/cellEditors.tsx` adaptörüyle bağlanır |
+
+DataGrid/TreeList platform editörlerini `editCellTemplate` ile çizer ve `onEditorPreparing` onlar için
+çalışmaz; salt-okunur/devre dışı kararı, cascade ve `EditorScript` bu editörlere
+`createCustomEditorCellAdapter` ile verilir.
Adres zincirinin hazır örneği Kiracılar ekranıdır: Ülke › İl › İlçe › Mahalle; mahalle lookup'ı
`PostalCode`'u `group` olarak döndürür ve `copy("Group", "PostalCode")` tarifi posta kodunu doldurur.
@@ -2842,7 +2861,7 @@ Preset mevcut JSON ile **birleşir**, diğer ayarları silmez; aynı anahtar var
| Çoklu görsel | `width`, `height`, `multiple`, `accept:image/*` |
| HTML tam araç çubuğu | `htmlEditorOptions.ts` varsayılanı: `toolbar.items` (tam liste), `toolbar.multiline`, `mediaResizing`, `imageUpload` (`tabs: file/url`, base64), `tableResizing`, `tableContextMenu` — boş `editorOptions` da aynı varsayılanı alır |
| Yükseklik 100 / 200 | `{"height":100}` · `{"height":200}` |
-| Barkod okutma butonu | `buttons[]` — kamera ikonlu buton; `onClick` = `"@SCAN_BARCODE"` token'ı. Yalnız `dxTextBox`. Token'ı `editingForm.ts` kamera diyaloğuna bağlar, okunan kod alana yazılır. HTTPS şart. |
+| Barkod okutma butonu | `buttons[]` — kamera ikonlu buton; `onClick` = `"@SCAN_BARCODE"` token'ı. Yalnız `dxTextBox`. Token'ı `resolveEditorButtons` (`editingForm.ts`) kamera diyaloğuna bağlar, okunan kod alana yazılır; liste popup'ı ve form sayfası aynı. HTTPS şart. Fonksiyon metni yazılan `onClick` olayla birlikte `formData`, `fieldName`, `mode` alır (popup'ta ek olarak `rowKey`, `rowIndex`). |
| Kamerayla foto çek | `{"accept":"image/*","capture":"environment"}` — yalnız `dxImageUpload`. Mobilde dosya seçici yerine **yalnızca** kamera açılır (`user` = ön kamera); masaüstünde yok sayılır. Ayarlanmazsa dokunmatik cihazda dosya seçicinin yanına ayrı bir kamera butonu gelir, yani ikisi birden kullanılabilir — bu kalıp kamerayı **zorunlu** kılmak içindir. |
#### 6.4.1 Telefon biçimleri (`format` token'ı)
@@ -2867,7 +2886,7 @@ varsayılanı ezer.
- Ülke alanı olan her ekranda yeni kayıt Türkiye ile açılır: `FormFieldsDefaultValueJson` →
`{ FieldName: "Country", FieldDbType: String, Value: "Türkiye", CustomValueType: Value }`.
- Ülke alanı değişince maske yenilenir: Card/Scheduler/Form sayfasında formun `fieldDataChanged` olayıyla,
- Grid/Tree'de `onEditorPreparing`'deki `attachFieldValueBroadcast` olayıyla (DataGrid formu `fieldDataChanged`
+ Grid/Tree'de `onEditorPreparing`'deki (`prepareEditingEditor`) `attachFieldValueBroadcast` olayıyla (DataGrid formu `fieldDataChanged`
yayınlamaz; `editorOptions.onValueChanged` da kullanılamaz — editör fabrikası onu kendi değer yazan
işleyicisinin üstüne birleştirir). Satır içi düzenlemede (form yok) maske satırın ülkesiyle açılır, değişikliği izlemez.
- `phoneCountry` ekranında sabit uzunluk `pattern`'ı (`^[0-9]{10}$`) yazılmaz; uzunluğu maske denetler,
diff --git a/README.md b/README.md
index d300db38..1116c845 100644
--- a/README.md
+++ b/README.md
@@ -446,9 +446,13 @@ ve atanan kullanıcı alanlarından kurulur.
`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.
- Cascade liste popup'ında ve form sayfasında (`/admin/form/...`, `FormDevExpress`) aynı çalışır.
+ Cascade liste popup'ında, satır içi düzenlemede ve form sayfasında (`/admin/form/...`, `FormDevExpress`)
+ aynı kuralla çalışır: alan değişince ebeveyni o alan olan çocuklar ve alanın `CascadeEmptyFields`
+ listesi boşaltılır.
Lookup'lı seçim kutusunda yazarak arama ikisinde de varsayılan açıktır; alanın `EditorOptions`'ında
`{"searchEnabled": false}` kapatır.
+- **Popup ↔ form sayfası eşliği:** `EditorOptions` varsayılanları, butonlar, `EditorScript`, cascade ve
+ platform editörleri (TagBox, GridBox, görsel) iki yerde ortak koddan gelir; tablo `lowcode.instructions.md` §4.3.4.
- **Doğrulama:** `ValidationRuleJson` ile required/range/pattern/custom kuralları. Kurallar liste popup'ında ve form sayfasında (`/admin/form/...`) aynı uygulanır; maske (`mask`) `EditorOptions` ile verilir.
- **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.
diff --git a/claude.md b/claude.md
index 33a8907d..f85a9554 100644
--- a/claude.md
+++ b/claude.md
@@ -231,6 +231,11 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
- **`phoneFormat.ts` ↔ `DynamicReportPhoneFormatter.cs`** — telefon token'larının (`phoneGlobal`, `phoneTR`,
`phoneIntl`, `phoneCountry`) görüntü kuralı iki yerde yazılır: liste/kart istemcide, dinamik rapor sunucuda.
Biri değişirse diğeri de değişir; yoksa liste ile rapor aynı numarayı farklı yazar.
+- **Liste popup'ı (Grid/Tree) ↔ form sayfası (`FormDevExpress`)** — editör yetenekleri ortak yardımcılardadır
+ (`list/shared/editingForm.ts`, `editingFormScripts.ts`, `cascade.ts`); TagBox/GridBox/ImageUpload/ImageViewer'ın
+ tek uygulaması `form/editors/*`, liste hücresi yalnızca `list/editors/cellEditors.tsx` adaptörüdür. Bir tarafa
+ yetenek eklenirken ortak yardımcıya eklenir; tek tarafa yazılan yetenek eşliği bozar. Tablo:
+ `lowcode.instructions.md` §4.3.4.
- **`htmlEditorOptions.ts` ↔ `EditorOptions.Html`** — HtmlEditor varsayılanı iki yerde yazılır ve
bloklar birebir aynıdır. İstemci iç içe blokları tek seviye birleştirdiği için seed edilen
`toolbar` varsayılanın yerine geçer; biri değişip diğeri değişmezse seed'li ekranlar eski araç
diff --git a/configs/seeds/data/App.DevRequests/5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json b/configs/seeds/data/App.DevRequests/5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json
index b8f65781..6d1b4980 100644
--- a/configs/seeds/data/App.DevRequests/5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json
+++ b/configs/seeds/data/App.DevRequests/5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json
@@ -18,9 +18,9 @@
"Priority": "5",
"Completed": false,
"SortOrder": 2,
- "Timesheets": "[{\"id\":\"6a817f32-69b6-6e06-3cc4-3a2428dfe74d\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Talep analiz edildi\",\"duration\":0.0167},{\"id\":\"9c434c1b-9451-efc8-02b1-3a2428e13282\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_ProductCategory tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"30fb4513-f16d-bb46-f408-3a2428e14ab8\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_Attribute tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"1dc7152e-2ff6-f6de-9205-3a2428e1655b\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_AttributeValue tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"dd3504f3-51d0-042b-a5b5-3a2428e19b77\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_Product tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"560153a2-526d-c786-f5b5-3a2428e2bfab\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_ProductAttributeLine tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"3414b481-2140-b3e6-dab3-3a2428e2d9b2\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_ProductVariant tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"a715a8e5-cb36-311c-2aa2-3a2428e2fa1a\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_ProductSupplier tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"8d745d78-25bf-b82a-c2f4-3a2428e31cbc\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_WorkCenter tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"c493b41a-a80e-e72d-2f9f-3a2428e333d3\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_WorkCenterCapacity tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"01397c97-65b8-c5e8-5766-3a2428e35783\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_Operation tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"a57fcb7d-12e9-9ca2-5a55-3a2428e36d82\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_OperationInstruction tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"4df60eac-980d-a497-93c4-3a2428e38bd9\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_Bom tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"6a68db4d-bb53-33b9-cf0b-3a2428e3a1bb\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_BomOperation tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"fb6aea44-6996-80d1-8d19-3a2428e3ba5a\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Inv_T_BomLine tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"ab475620-374d-e4a1-dc1b-3a2428e40761\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"App.DeveloperKit.CustomEndpoints ekran\\u0131na sat\\u0131r eklendi\",\"duration\":0.0167},{\"id\":\"52e08632-e712-8432-977e-3a2428e48174\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductCategory.json wizard\\u0027\\u0131 deploy edildi (2 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"4e8bdcfc-9621-2861-1954-3a2428e4e6a6\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"AttributeValue.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"c007dd02-6b11-d995-c720-3a2428e56195\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Attribute.json wizard\\u0027\\u0131 deploy edildi (3 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"4fee692c-bce3-3c65-80ad-3a2428e5c017\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"WorkCenterCapacity.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"da9fe300-0f4e-f900-b08d-3a2428e64100\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"WorkCenterGeneral.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"4bbfcb44-0ddb-a68e-5a7c-3a2428e7a2f3\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"WorkCenter.json wizard\\u0027\\u0131 deploy edildi (1 demo sat\\u0131r)\",\"duration\":0.0333},{\"id\":\"4f66f26a-ee05-4a6a-847f-3a2428e809f9\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"OperationInstruction.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"913a0473-6e15-797a-7160-3a2428e868cd\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"OperationSettings.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"85b8537e-a7ab-54ef-bb16-3a2428e8d1b9\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Operation.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"ca24a627-11b3-f8db-6f13-3a2428e934d0\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"BomOperation.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"6c0040f0-b981-9546-22ab-3a2428e9ac84\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"BomLine.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"037a0ab6-d2b5-5a38-a030-3a2428eaa433\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Bom.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"fa6d1319-7742-f551-e75e-3a2428eb27cc\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductVariant.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"62798abf-b710-74a7-006e-3a2428ecadd4\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductGeneral.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0333},{\"id\":\"93b9f36f-5e8c-8607-373e-3a2428ed1027\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductAttributeLine.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"c7fe1df4-3b68-222c-3a4b-3a2428ed62bd\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductPurchasing.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"d6c003ce-d518-45df-94a2-3a2428ee01c8\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductSupplier.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"d6b290e4-6dc9-7830-f0f9-3a2428ee7bc4\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductStock.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"bc64a3db-7a2f-5e01-effa-3a2428eedc11\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"ProductAccounting.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"d8959a4c-3c31-d2a3-8ca4-3a2428ef93c6\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"Product.json wizard\\u0027\\u0131 deploy edildi (6 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"e06847ef-a0b7-d8c5-7b14-3a2428f2c514\",\"date\":\"2026-10-07\",\"userName\":\"system@sozsoft.com\",\"description\":\"BomOverview.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.05}]",
+ "Timesheets": null,
"SubTasks": null,
- "Analysis": "
1. Amaç
\n
Envanter ve üretimin ana verisini kurmak: ürün kartı (satış/masraf/satınalma bayrakları, mal/hizmet, envanter takibi), nitelik–değer–varyant yapısı, tedarikçi fiyatları, iş merkezleri, operasyonlar, ürün ve varyant bazında reçeteler (BOM) ve iç içe açılan reçete genel bakışı (ağaç). Kullanıcılar stok, satınalma ve üretim planlama personelidir; sonraki satış/satınalma/üretim belgeleri bu ekranları lookup kaynağı olarak kullanır.
\n\n
2. Görsel analizi
\n
\n
[image-1] Ürünler listesi: Ürün Adı, İç Referans, Satış Fiyatı, Maliyet, Stokta, Öngörülen, Birim. Talep: liste ürün adı, resim, Satış, Masraflar, Satınalma kolonlarından oluşur; bu görseldeki kolonlar da listede olabilir. Stokta/Öngörülen stok hareketi gerektirdiği için alınmaz. Satırlar demo veri adayı.
\n
[image-2] Nitelik formu: Nitelik Adı, Görünüm Türü, Varyant Oluşturma; Nitelik Değerleri: Değer, Serbest metin, Varsayılan Ekstra Fiyat. Demo: renk → kırmızı, mavi.
\n
[image-3] Ürün – Genel Bilgi: Ürün Türü, Envanter Takibi (Seri No / Lot / Miktar), Satış Vergisi, Satınalma Vergisi, Kategori, Barkod, GTİP, İç Notlar. Talep: liste dışındaki bilgiler detayda sekme olarak (Kontaklar ekranı gibi).
[image-8] Reçete – Bileşenler: Komponent, Miktar, Birim, Operasyonda Tüketilen. Talep: BoM Türü eklenmez; reçete ürün ya da varyant bazında yazılır.
\n
[image-9] Reçete – Operasyonlar: Operasyon, İş Merkezi, Süre (dk). Demo: Apre – ram makinası – 60.
\n
[image-10] Reçete – Diğer: Üretim Hazırlığı, Esnek Tüketim, Operasyon Türü, Akış Zamanı, Hazırlama Günleri, Parti Büyüklüğü.
\n
[image-11] İş Merkezi. Talep: listede ad, etiketler, çalışma saatleri (İK ayarı haftalık çalışma limiti); detayda Genel Bilgi ve Ürün Kapasitesi sekmeleri.
\n
[image-12] Operasyon formu. Talep: listede Operasyon Adı, İş Merkezi, Varsayılan Süre; detayda Açıklamalar listesi.
\n
[image-13] Ürün Varyantları: 12 satır = renk × malzeme × boyut.
\n
[image-14] Reçete genel bakış. Talep: iç içe malzeme ve miktarlar, Tree Layout.
\n
\n\n
3. Çözüm yolu
\n
Wizard List ekranları + alt formlar. Kontaklar deseni: ana liste yalnız istenen kolonları taşır, diğer alanlar aynı tabloyu okuyan TabType: Form alt formlarda (ilişki Id → Id, yalnız düzenleme). Varyant üretimi Custom Endpoint Inventory.GenerateVariants (mevcut kayıt korunur); tetikleyici Ürün › Genel Bilgi sekmesinin açılış EditorScript'i (api()). İş merkezi çalışma saati için GET Custom Endpoint Inventory.WeeklyWorkingHours (ayar istemciye açık değil). Reçete genel bakışı Wizard List, Query kaynağı, Tree görünümü (RowId / ParentRowId); Query türetilmiş tabloya sarıldığından recursive CTE kullanılamaz, açılım CROSS APPLY ile sabit 4 seviye. Custom component gerekmez.
BomOverview Query: TableName \"Q\", KeyFieldName RowId (DbSourceType 16), ParentRowId ağaç ebeveyni; Inv_T_Bom'un TenantId ve IsDeleted'ı seçilir. Kök satır (Level 0, ParentRowId NULL) = reçete; bileşen ve operasyon satırları ebeveynlerinin altında; bileşenin aktif reçetesi (varyantı eşleşen, yoksa varyantsız, en yeni) varsa satırları o bileşenin altında açılır, 4 seviyeye kadar. Miktar = Π(üst satır miktarı ÷ alt reçete miktarı) × satır miktarı; bileşen maliyeti = miktar × (varyant maliyeti, yoksa ürün maliyeti); operasyon maliyeti = süre/60 × CostPerHour; kök ve üst bileşen ürünleri yeniden açılmaz. Kolonlar: RowId, ParentRowId, BomId, RootProduct, Level, RowType, ItemName, Quantity, Uom, UnitCost, TotalCost.
\n\n
6. Alt form ağacı
\n
\n
Taşıyıcı › Sekme
Hedef
TabType
Menü
İlişki
Ekle/Düzenle/Sil
\n
Nitelik › Nitelik Değerleri
App.Inventory.AttributeValue
List
Menüsüz
Id → AttributeId
✓/✓/✓
\n
Ürün › Genel Bilgi
App.Inventory.ProductGeneral
Form
Menüsüz
Id → Id
–/✓/–
\n
Ürün › Nitelik & Varyantlar
App.Inventory.ProductAttributeLine
List
Menüsüz
Id → ProductId
✓/✓/✓
\n
Ürün › Varyantlar
App.Inventory.ProductVariant
List
Menülü
Id → ProductId
–/✓/–
\n
Ürün › Satınalma
App.Inventory.ProductPurchasing
Form
Menüsüz
Id → Id
–/✓/–
\n
Ürün › Tedarikçiler
App.Inventory.ProductSupplier
List
Menüsüz
Id → ProductId
✓/✓/✓
\n
Ürün › Stok
App.Inventory.ProductStock
Form
Menüsüz
Id → Id
–/✓/–
\n
Ürün › Muhasebe
App.Inventory.ProductAccounting
Form
Menüsüz
Id → Id
–/✓/–
\n
Ürün › Ürün Reçeteleri
App.Inventory.Bom
List
Menülü
Id → ProductId
✓/✓/✓
\n
Varyant › Varyant Reçeteleri
App.Inventory.Bom
List
Menülü
Id → ProductVariantId, ProductId → ProductId
✓/✓/✓
\n
İş Merkezi › Genel Bilgi
App.Inventory.WorkCenterGeneral
Form
Menüsüz
Id → Id
–/✓/–
\n
İş Merkezi › Ürün Kapasitesi
App.Inventory.WorkCenterCapacity
List
Menüsüz
Id → WorkCenterId
✓/✓/✓
\n
Operasyon › Açıklamalar
App.Inventory.OperationInstruction
List
Menüsüz
Id → OperationId
✓/✓/✓
\n
Operasyon › Ayarlar
App.Inventory.OperationSettings
Form
Menüsüz
Id → Id
–/✓/–
\n
Reçete › Bileşenler
App.Inventory.BomLine
List
Menüsüz
Id → BomId
✓/✓/✓
\n
Reçete › Operasyonlar
App.Inventory.BomOperation
List
Menüsüz
Id → BomId
✓/✓/✓
\n
\n\n
7. Etkilenen kısımlar
\n
\n
14 yeni tablo; yeni menü kökü Envanter + Tanımlamalar; 8 menülü, 14 menüsüz ekran (6'sı aynı tabloyu okuyan Form sekmesi), her ekranda C/R/U/D/Export/Import/Note.
\n
Custom Endpoint Inventory.GenerateVariants (POST) — kayıt zaten var, değişmez. Yeni Custom Endpoint Inventory.WeeklyWorkingHours (GET /inventory/weekly-working-hours/): kiracı ayarı, yoksa global, yoksa tanım varsayılanı (45).
\n
Endpoint'leri kullanacak rollere App.DeveloperKit.CustomEndpoints.Post ve .Get yetkisi gerekir.
\n
İK ayarı App.HrSettings.Attendance.WeeklyLimitHours yalnız okunur. Dil anahtarları TR/EN; modül dokümanı App.Inventory.md.
\n
\n\n
8. Görünümler ve davranış
\n
\n
Ürünler listesi: Ürün Adı, Resim, Satış, Masraflar, Satınalma, İç Referans, Satış Fiyatı, Maliyet, Birim (ekleme formunda da bunlar; diğer alanlar varsayılanla açılır). Detayda sekmeler: Genel Bilgi (Favori, Ürün Türü, Envanter Takibi, Takip Şekli, Satış Vergisi, Satınalma Vergisi, Kategori, Barkod, GTİP, İç Notlar, Varyantlı, Aktif), Nitelik & Varyantlar, Varyantlar, Satınalma (Kontrol Kuralı, Açıklama), Tedarikçiler, Stok, Muhasebe, Ürün Reçeteleri.
\n
Genel Bilgi sekmesi açılınca Varyantlı alanının script'i varyant endpoint'ini çağırır; nitelik satırları değişince Genel Bilgi sekmesini yeniden açmak varyantları günceller.
\n
EditorScript (readOnly/set/clear): Envanter Takibi kapalı → Takip Şekli kilitli ve boş, açık → varsayılan Miktara Göre; Hizmet → Envanter Takibi kilitli ve kapalı; Reçete Parti Büyüklüğü kapalı → Parti Miktarı kilitli ve boş.
\n
Nitelik & Varyantlar: Nitelik seçilir, Değerler çoklu seçim (tagbox) niteliğe göre süzülür.
\n
İş Merkezleri listesi: İş Merkezi Adı, Etiketler, Çalışma Saatleri (haftalık saat). Yeni kayıtta Çalışma Saatleri boşsa script Inventory.WeeklyWorkingHours'tan doldurur (değiştirilebilir). Formda ayrıca Kod, Alternatif İş Merkezleri, Aktif. Detay: Genel Bilgi (verimlilik, OEE, kurulum/temizlik, saatlik maliyetler, gider hesabı, izin verilen çalışanlar, açıklama) ve Ürün Kapasitesi.
\n
Operasyonlar listesi: Operasyon Adı, İş Merkezi, Varsayılan Süre. Detay: Açıklamalar listesi ve Ayarlar (Varyantlara Uygula, Maliyete Dayalı, Süre Hesaplama, Aktif).
\n
Ürün Reçeteleri: BoM Türü yok. Ürün seçilir, Varyant boşsa ürün bazında, doluysa o varyant için; Varyantlar listesinin detayında Varyant Reçeteleri sekmesi. Satır butonu Genel Bakış (Url, BomId filtresi).
\n
Reçete Genel Bakış: açılış Tree (KeyExpr RowId, ParentIdExpr ParentRowId); salt okunur; Grid/Pivot da açık.
\n
Widget'lar: Toplam · Aktif · Pasif; Ürünler'de ek Satılabilir · Satınalınabilir · Varyantlı.
\n
\n\n
9. Kararlar
\n
\n
Detay sekmeleri Kontaklar desenindedir: aynı tabloyu okuyan Form alt formlar, ilişki Id → Id, ekleme/silme kapalı.
\n
Ürün listesine [image-1]'deki İç Referans, Satış Fiyatı, Maliyet, Birim eklendi; Stokta ve Öngörülen stok hareketi tabloları olmadığı için eklenmez (onay).
\n
Çalışma Saatleri = haftalık saat (WeeklyWorkingHours), varsayılan İK ayarı haftalık çalışma limitinden gelir; Vardiya bağlantısı kaldırıldı.
\n
Etiketler serbest metin (virgülle ayrılmış) (onay).
\n
Varyantlar ürünün Genel Bilgi sekmesi açılınca üretilir; ayrı buton yok (onay).
\n
Reçete Genel Bakış 4 seviyeye kadar açar; birim çevrimi yok (onay).
\n
Tek KDV oranı (%20), gelir/gider hesabı serbest kod (onay).
\n
Ekipman/Bakım sekmeleri, akıllı butonlar bu talepte yok (onay).
\n
Görünüm Türü kayıt bilgisi; Always ve Dynamic aynı, Never kombinasyona katılmaz (onay).
\n
Demo veri yalnız bağımsız satırlarda: Kategoriler (2), Nitelikler renk/malzeme/boyut, İş Merkezi ram makinası, Ürünler [image-1]'den 6 satır (birim Adet). Nitelik değerleri, Apre operasyonu ve reçete modül dokümanındaki akışla elle girilir.