# Envanter (`App.Inventory`) > Menünün altındaki her dal bu dosyada bir bölümdür (`module-doc:section`); dosya ve bölümler ilk deploy'da otomatik açılır. `module-doc:todo` işaretli alt bölümleri modülü üreten kişi ya da AI doldurur (`lowcode.instructions.md` §0.13); MCP ile üretimde talep bu bölümler doldurulmadan Testing'e alınamaz. "Ek — Ekran envanteri" bölümü wizard dosyalarından üretilir, elle düzenlenmez. ## Tanımlamalar (`App.Inventory.Definitions`) ### 1. Amaç ve kapsam Envanterin ana verisi: ürün kartı (satış/masraf/satınalma bayrakları, mal/hizmet, envanter takibi ve yöntemi, nitelik–varyant, tedarikçi fiyatları, stok ve muhasebe bilgileri), ölçü birimine bağlı reçeteler (bileşen + operasyon; ürün ya da varyant bazında), çok seviyeli reçete patlatma raporu ve fiziksel stok yapısı: şubeye bağlı depolar, depolarda iç içe konumlar, şube/depo bazında operasyon türleri. İş merkezleri ve operasyonlar Üretim modülündedir ([App.Production.md](App.Production.md)). Kullanıcılar: stok, satınalma ve üretim planlama ekipleri. Stok hareketi, sipariş ve üretim emri bu dalın kapsamı dışındadır. ### 2. Analiz ve kararlar Onaylanan analiz (talep "Inventory -> Tanımlamalar"): - Menü `Envanter › Tanımlamalar`; ara menü kodu `App.Inventory.Definitions` (Satınalmadaki `App.Prc.Definitions` kalıbı). - Görsellerdeki Kategori ve Etiket alanları için Ürün Kategorileri ve İş Merkezi Etiketleri tanım ekranları eklendi. - İş Merkezi Etiketleri, İş Merkezleri ve Operasyonlar (alt formlarıyla) sonradan `Üretim › Tanımlamalar` altına taşındı: kod `App.Production.*`, tablo `Prd_T_*` (`App.Production.md` §2). - Ürün Türü yalnız Mal / Hizmet; Kombo yok. BoM Türü alanı yok (talep). - Vergiler oran (varsayılan %20), muhasebe hesapları serbest metin kod olarak tutulur (onaylı). - Varyantlar kalıcı tabloda tutulmaz: `VariantKey` = seçili nitelik değeri Id'lerinin, nitelik adı sırasıyla `|` birleşimi; aynı kombinasyon hep aynı anahtarı üretir. "Varyant Oluşturma = Asla" olan nitelik kartezyene girmez, Hemen/Dinamik aynı davranır (onaylı). - Haftalık çalışma saati ayardan (`%WeeklyWorkingTimeLimit%`) okunur, yoksa 40 (onaylı). - Reçete patlatmada alt reçete: önce bileşenin varyantına özel, yoksa genel; birden fazlaysa en eski oluşturulan. Onaylanan analiz (talep "Envanter -> Tanımlamalar"): - Depolar, Konumlar, Operasyon Türleri üç ayrı liste ekranı; tablolar `Inv_T_Warehouse`, `Inv_T_Location`, `Inv_T_OperationType`. - Şube platform şube filtresiyle değil kolonla tutulur (`IsBranch = false`, `BranchId` → `Sas_T_Branch`): talep Şube Adı'nı listede görünen, seçilen alan olarak istedi. Görsellerdeki "Firma" sütunu Şube'ye karşılık gelir. - Konum ve Operasyon Türü'nde şube ayrıca tutulur ("şube ve depo bazında"); depo listesini süzer. - Konumlar'da Malzeme Türü ve Depolama Kategorisi alınmadı (talepte yok, kaynak tablo yok). Operasyon Türü'nde yalnız Genel sekmesinin çekirdek alanları alındı; Donanım, Barkod Uygulaması, lot/seri, paket, iade türü, kart rengi kapsam dışı. - Depolar demo verisi: görseldeki 4 depo (WH, GRP, IKT, KZL), ilk aktif şubeye (Branch1) bağlı (onaylı). Üretimde verilen ek kararlar: - Query kaynağı türetilmiş tabloya (`FROM (…) AS "Q"`) sarıldığı için özyinelemeli CTE kullanılamaz. Varyant kartezyeni ürün başına en fazla **5 nitelik**, reçete patlatma en fazla **4 bileşen seviyesi** ile sabit derinlikli birleşimlerle kuruldu; derinlik sınırı döngü korumasıdır. - Genel Bakış'ta kök reçete satırının maliyeti boştur; maliyetler bileşen ve operasyon satırlarındadır. - Depo kodu tekilliği `UQ_Inv_T_Warehouse_TenantId_Code` kısıtıyla sağlanır (ayrı InsertBefore kontrolü yazılmadı; aynı kod kaydedilirken veritabanı hatası döner). - `Inv_T_Location`'da `WarehouseId`/`ParentId`/`DepartmentId` için FK yazılmadı: migrate scriptleri dosya adı sırasıyla çalışır ve `Inv_T_Location` `Inv_T_Warehouse`'tan önce sıralanır. Bütünlük lookup'larla korunur; `Inv_T_OperationType` → `Inv_T_Location` FK'leri vardır. ### 3. Menü ve ekranlar `Envanter (App.Inventory) › Tanımlamalar (App.Inventory.Definitions)` altında sırasıyla: Ürün Kategorileri, Nitelikler, Ürünler, Ürün Varyantları, Reçeteler, Reçeteye Genel Bakış, Depolar, Konumlar, Operasyon Türleri. Sekmeler (menüsüz alt formlar): - Nitelikler › Nitelik Değerleri - Reçeteler › Bileşenler, Operasyonlar, Diğer (aynı satır), Genel Bakış (menülü, Tree) - Ürünler › Genel Bilgi, Stok, Muhasebe (aynı satır), Nitelik & Varyantlar, Varyantlar (menülü, salt okunur), Satınalma, Reçeteler (menülü) Konumlar ağaç görünümüyle açılır (`ParentId`); Grid'e geçilebilir. ### 4. Veri modeli Tüm tablolar kiracı + tam audit + soft delete, anahtar `Id uniqueidentifier`. Birim kolonları `nvarchar(64)` → `Adm_T_Uom.Id`; tedarikçi → `Adm_T_Contact`; para birimi → `Sas_H_Currency`; menşe → `Sas_H_Country`; sorumlu → `AbpUsers`; şube → `Sas_T_Branch`. | Tablo | İçerik | | --- | --- | | `Inv_T_ProductCategory` | Ad, üst kategori, aktif | | `Inv_T_Attribute` / `Inv_T_AttributeValue` | Nitelik (görünüm türü, varyant oluşturma) ve değerleri (serbest metin, ekstra fiyat, renk, sıra) | | `Inv_T_Product` | Ürün kartı ve Genel Bilgi/Stok/Muhasebe sekmelerinin alanları | | `Inv_T_ProductAttributeLine` | Ürün × nitelik, `ValueIds` (`|` ayrımlı değer Id) | | `Inv_T_ProductSupplier` | Tedarikçi, min. miktar, birim, fiyat, kur, teslim süresi, varyant | | `Inv_T_Bom` / `Inv_T_BomComponent` / `Inv_T_BomOperation` | Reçete başlığı (ürün, varyant, miktar, birim, planlama), bileşenler (operasyona bağlanabilir), operasyonlar (iş merkezi `Prd_T_WorkCenter`, operasyon `Prd_T_Operation`, süre) | | `Inv_T_Warehouse` | Şube, kod (kiracı içinde tekil, 16), ad, aktif | | `Inv_T_Location` | Şube, depo, üst konum, kod (32), ad, konum türü (`Internal`/`External`), departman (`Hr_T_Department`), depo sorumlusu, aktif | | `Inv_T_OperationType` | Şube, depo, ad, tür (`Receipt`/`Delivery`/`InternalTransfer`/`Manufacturing`/`Repair`), sıra öneki, barkod, kaynak ve hedef konum, aktif | ### 5. İş kuralları ve hesaplar - **Varyant satış fiyatı** = ürün satış fiyatı + seçili değerlerin ekstra fiyatları toplamı. - **Genel Bakış miktarı:** seviye k bileşen miktarı = üst miktar × bileşen miktarı ÷ alt reçete miktarı. - **Genel Bakış maliyeti:** bileşen maliyeti = miktar × ürün maliyeti. Operasyon süresi aynı oranla ölçeklenir; maliyet = süre ÷ 60 × iş merkezi saatlik maliyeti. Operasyonlar her seviyede "Operasyonlar" düğümünde toplanır. - **Ürün formu:** Hizmet seçilince envanter takibi kapanır ve kilitlenir. Takip yöntemi yalnız takip açıkken girilir; takip açılınca "Miktara göre" gelir. Satınalma birimi boşsa birimi izler. - **Reçete bileşeni:** ürün seçilince birim üründen dolar. - **Reçete operasyonu:** operasyon seçilince iş merkezi ve varsayılan süre dolar. - **Çoklu değer alanları** (`dxTagBox`) `|` ile ayrılmış metin kolonunda saklanır. - **Şube › depo › konum zinciri:** Konum ve Operasyon Türü formunda depo seçili şubenin aktif depolarına, üst/kaynak/hedef konum seçili deponun konumlarına, departman seçili şubenin departmanlarına süzülür. Şube değişince depo, konum ve departman; depo değişince konum alanları temizlenir. - **Varsayılanlar:** yeni konumda tür İç, yeni operasyon türünde tür Alım, tüm yeni tanımlarda Aktif işaretli. ### 6. Yetki ve görünürlük İzin grubu `App.Inventory`. Her ekranın okuma yetkisi `App.Inventory.Definitions` altında; alt formların yetkisi bağlı oldukları listenin altındadır. Her listede `.Create/.Update/.Delete/.Export/.Import/.Note`. Yetkiler hiçbir role otomatik verilmez. Yeni sekmelerin yetkisi role verilmeden sekmeler boş görünür. Tüm ekranlar kiracı filtrelidir. Depolar, Konumlar ve Operasyon Türleri platform şube filtresi kullanmaz; kullanıcı yetkisi olan her ekranda kiracının tüm şubelerinin kayıtlarını görür. ### 7. Entegrasyonlar Dış entegrasyon yok. Reçete operasyonları iş merkezi ve operasyonu Üretim modülünden okur; Üretim de ürün ve nitelik değerlerini buradan okur. Ölçü Birimleri, Kontaklar, Para Birimleri, Ülkeler, Şubeler, Departmanlar ve Kullanıcılar yalnız lookup kaynağıdır. Satış ve satınalma sipariş ekranları ürünü `CanBeSold` / `CanBePurchased` ile süzecek; stok hareket belgeleri operasyon türünü ve konumları bu daldan seçecek; bu dalda sipariş ve hareket ekranı yoktur. ### 8. Akış örneği 1. Nitelikler'de renk (kırmızı, mavi), malzeme (çelik, tahta), boyut (40x40, 80x100, 10x30) değerlerini gir. 2. Üretim › İş Merkezleri'nde "ram makinası"nın saatlik maliyetini gir. 3. Üretim › Operasyonlar'da "Apre"yi ram makinası, 60 dk olarak tanımla. 4. Ürünler'de "(40X40mm) Mamül Sepeti Üst Geçme Kepi" › Nitelik & Varyantlar sekmesine üç niteliği ekle. Varyantlar sekmesinde 12 kombinasyon görünür. 5. Reçeteler'de kep için 1 Adet reçete aç. Bileşenler'e 20 Adet AUTONİCS PR12-4DN Sensör, Operasyonlar'a Apre ekle. 6. Genel Bakış sekmesi ağacı ve maliyetleri gösterir. 7. Depolar'da "Grup Şirketler" (GRP) deposunu şubeye bağla. 8. Konumlar'da GRP için "Stock" kök konumunu, altına "ALDORA MOBİLYA G/Ç" (kod GRP ALD, departman, sorumlu), onun altına "ANA DEPO AB07" konumunu İç türüyle gir; ağaç üç seviye gösterir. 9. Operasyon Türleri'nde GRP için "Alımlar" (tür Alım, sıra öneki GRP/IN/, hedef konum Stock) tanımla. ### 9. Sık sorulanlar - **Varyant neden kayboldu?** Nitelik satırından değer ya da nitelik silinirse kombinasyon ve anahtarı değişir. O varyantı kullanan reçete ve tedarikçi satırlarının varyantı yeniden seçilmelidir. - **Genel Bakış'ta alt seviye görünmüyor?** Bileşenin aktif ve miktarı > 0 bir reçetesi olmalıdır. 4 seviyeden derin yapılar gösterilmez. - **Kaç nitelik desteklenir?** Ürün başına 5. Fazlası varyant listesine katılmaz. - **Form açılınca Aktif kutusu boş geliyor?** Eski ürün ekranlarında form varsayılanları wizard deploy'unda yazılamadı (bkz. 10). Kayıtta kutu işaretlenmelidir. Depolar, Konumlar ve Operasyon Türleri'nde varsayılan tablodan okunur. - **Depo seçimi boş geliyor?** Önce şube seçilmelidir; depo listesi şubeye göre süzülür ve yalnız aktif depolar gelir. - **Aynı depo kodu kaydedilemiyor?** Depo kodu kiracı içinde tekildir; silinen (soft delete) bir deponun kodu da tekrar kullanılamaz. - **Depo ya da konum silinebilir mi?** Konumu veya operasyon türü olan depoyu, alt konumu olan konumu silmeyin; pasife alın. ### 10. Dosyalar ve geri alma - **Tablolar:** `sql/object/Inv_T_*.sql` (12 tablo; bu talepte `Inv_T_Warehouse`, `Inv_T_Location`, `Inv_T_OperationType`). - **Wizard'lar:** ProductCategory, Attribute, AttributeValue, ProductVariant, BomOverview, Bom, BomComponent, BomOperation, BomOther, Product, ProductGeneral, ProductAttributeLine, ProductSupplier, ProductStock, ProductAccounting, Warehouse, Location, OperationType (`.json`). - **Demo veri aynaları:** `data/App.Inventory.{ProductCategory,Attribute,Product,Warehouse}.json`. - **Geri alma:** Wizard Manager'da ana ekranlar (Product, Bom, Attribute) önce, alt formları sonra silinir. Depolar/Konumlar/Operasyon Türleri bağımsızdır; tablo düşürülecekse sıra OperationType → Location → Warehouse (FK). Tablolar ancak açık onayla `dropTables` ile düşürülür. - **Sorgu bağımlılığı:** Sorgular SQL Server'a özgüdür (`STRING_SPLIT`, `CONCAT_WS`, `STRING_AGG`, `CROSS APPLY`). - **Açık nokta:** Eski ürün ekranlarının form varsayılanları (Aktif = true, Birim = Adet, Miktar = 1, Süre = 60, Kur = TRY) düz wizard biçimiyle dosyaya yazılmadı. ListForm düzenleyicisinden ya da `ListForm` bölümlü yeniden deploy ile eklenmelidir. ## Ek — Ekran envanteri (otomatik) > Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. ### Tanımlamalar (`App.Inventory.Definitions`) #### Ürün Kategorileri — `App.Inventory.ProductCategory` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_ProductCategory.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.ProductCategory` (sıra 1) | | Yetki | `App.Inventory.ProductCategory` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürün Kategorileri — ürünleri raporlama, filtreleme ve varsayılan muhasebe için gruplar (ör. Elektrik ve Elektronik Malzemeler, Mamuller). | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_ProductCategory` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart, Tree (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | | Veri aynası | `data/App.Inventory.ProductCategory.json` | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `Name` | Ad | dxTextBox | ✓ | ✓ | | | `ParentId` | Üst Kategori | dxSelectBox | | ✓ | sorgu: Inv_T_ProductCategory | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | #### Nitelikler — `App.Inventory.Attribute` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_Attribute.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.Attribute` (sıra 2) | | Yetki | `App.Inventory.Attribute` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Nitelikler — varyant oluşturan ürün özellikleri (renk, malzeme, boyut). | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_Attribute` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Alt formlar | `App.Inventory.AttributeValue` (Id → AttributeId) | | Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | | Form varsayılanları | IsActive=true | | Veri aynası | `data/App.Inventory.Attribute.json` | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `Name` | Nitelik Adı | dxTextBox | ✓ | ✓ | | | `DisplayType` | Görünüm Türü | dxRadioGroup | ✓ | ✓ | liste: Radio, Pills, Select, Color, Multi, Image | | `VariantCreation` | Varyant Oluşturma | dxRadioGroup | ✓ | ✓ | liste: Always, Dynamic, Never | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | #### Ürünler — `App.Inventory.Product` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_Product.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.Product` (sıra 3) | | Yetki | `App.Inventory.Product` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürünler — satış, satınalma, stok ve üretimin ortak kullandığı ürün kartı. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_Product` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Alt formlar | `App.Inventory.ProductGeneral` (Id → Id), `App.Inventory.ProductAttributeLine` (Id → ProductId), `App.Inventory.ProductSupplier` (Id → ProductId), `App.Inventory.ProductStock` (Id → Id), `App.Inventory.ProductAccounting` (Id → Id), `App.Inventory.Bom` (Id → ProductId) | | Widget'lar | `App.Widget.Total`, `App.Widget.Saleable`, `App.Widget.Purchasable`, `App.Widget.Service` | | Form varsayılanları | IsActive=true, IsFavorite=false, CanBeSold=true, CanBeExpensed=false, CanBePurchased=false, IsFavorite=false, UomId=Adet, PurchaseUomId=Adet, SalesPrice=0, Cost=0, TrackInventory=true, TrackingMethod=Quantity, ProductType=Wares | | Veri aynası | `data/App.Inventory.Product.json` | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `Name` | Ürün Adı | dxTextBox | ✓ | ✓ | | | `IsFavorite` | Favori | dxCheckBox | | ✓ | | | `CanBeSold` | Satış | dxCheckBox | | ✓ | | | `CanBeExpensed` | Masraflar | dxCheckBox | | ✓ | | | `CanBePurchased` | Satınalma | dxCheckBox | | ✓ | | | `ProductType` | Ürün Türü | dxSelectBox | ✓ | ✓ | liste: Wares, Service · script | | `CategoryId` | Kategori | dxSelectBox | | ✓ | sorgu: Inv_T_ProductCategory | | `TrackInventory` | Envanter Takibi | dxCheckBox | | ✓ | script | | `TrackingMethod` | Takip Yöntemi | dxSelectBox | | ✓ | liste: Serial, Lot, Quantity | | `SalesPrice` | Satış Fiyatı | dxNumberBox | | ✓ | | | `Cost` | Maliyet | dxNumberBox | | ✓ | | | `InternalReference` | İç Referans | dxTextBox | | ✓ | | | `UomId` | Birim | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Uom · script | | `PurchaseUomId` | Satınalma Birimi | dxSelectBox | | ✓ | sorgu: Adm_T_Uom | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | | `Image` | Resim | dxImageUpload | | ✓ | | #### Ürün Varyantları — `App.Inventory.ProductVariant` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_ProductVariant.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.ProductVariant` (sıra 4) | | Yetki | `App.Inventory.ProductVariant` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürün Varyantları — üründe seçilen nitelik değerlerinin her kombinasyonu (ör. kırmızı · çelik · 40x40), salt okunur. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `SELECT CAST(p.Id AS nvarchar(36)) + ':' + CONCAT_WS('\|', l1.VId, l2.VId, l3.VId, l4.VId, l5.VId) AS [Key], p.Id AS ProductId, p.Name AS ProductName, CONCAT_WS('\|', l1.VId, l2.VId, l3.VId, l4.VId, l5.VId) AS VariantKey, CONCAT_WS(', ', l1.VName, l2.VName, l3.VName, l4.VName, l5.VName) AS VariantName, p.InternalReference, CAST(p.SalesPrice + ISNULL(l1.XP, 0) + ISNULL(l2.XP, 0) + ISNULL(l3.XP, 0) + ISNULL(l4.XP, 0) + ISNULL(l5.XP, 0) AS decimal(18,4)) AS SalesPrice, p.Cost, p.UomId, p.CategoryId, p.IsActive, p.TenantId, p.IsDeleted FROM Inv_T_Product p LEFT JOIN (SELECT x.ProductId, x.Rk, CAST(s.value AS nvarchar(36)) AS VId, av.Name AS VName, av.ExtraPrice AS XP FROM (SELECT pl.ProductId, pl.ValueIds, DENSE_RANK() OVER (PARTITION BY pl.ProductId ORDER BY a.Name, a.Id) AS Rk FROM Inv_T_ProductAttributeLine pl INNER JOIN Inv_T_Attribute a ON a.Id = pl.AttributeId AND a.IsDeleted = 'false' AND a.VariantCreation <> 'Never' WHERE pl.IsDeleted = 'false') x CROSS APPLY STRING_SPLIT(x.ValueIds, '\|') s INNER JOIN Inv_T_AttributeValue av ON CAST(av.Id AS nvarchar(36)) = s.value AND av.IsDeleted = 'false') l1 ON l1.ProductId = p.Id AND l1.Rk = 1 LEFT JOIN (SELECT x.ProductId, x.Rk, CAST(s.value AS nvarchar(36)) AS VId, av.Name AS VName, av.ExtraPrice AS XP FROM (SELECT pl.ProductId, pl.ValueIds, DENSE_RANK() OVER (PARTITION BY pl.ProductId ORDER BY a.Name, a.Id) AS Rk FROM Inv_T_ProductAttributeLine pl INNER JOIN Inv_T_Attribute a ON a.Id = pl.AttributeId AND a.IsDeleted = 'false' AND a.VariantCreation <> 'Never' WHERE pl.IsDeleted = 'false') x CROSS APPLY STRING_SPLIT(x.ValueIds, '\|') s INNER JOIN Inv_T_AttributeValue av ON CAST(av.Id AS nvarchar(36)) = s.value AND av.IsDeleted = 'false') l2 ON l2.ProductId = p.Id AND l2.Rk = 2 LEFT JOIN (SELECT x.ProductId, x.Rk, CAST(s.value AS nvarchar(36)) AS VId, av.Name AS VName, av.ExtraPrice AS XP FROM (SELECT pl.ProductId, pl.ValueIds, DENSE_RANK() OVER (PARTITION BY pl.ProductId ORDER BY a.Name, a.Id) AS Rk FROM Inv_T_ProductAttributeLine pl INNER JOIN Inv_T_Attribute a ON a.Id = pl.AttributeId AND a.IsDeleted = 'false' AND a.VariantCreation <> 'Never' WHERE pl.IsDeleted = 'false') x CROSS APPLY STRING_SPLIT(x.ValueIds, '\|') s INNER JOIN Inv_T_AttributeValue av ON CAST(av.Id AS nvarchar(36)) = s.value AND av.IsDeleted = 'false') l3 ON l3.ProductId = p.Id AND l3.Rk = 3 LEFT JOIN (SELECT x.ProductId, x.Rk, CAST(s.value AS nvarchar(36)) AS VId, av.Name AS VName, av.ExtraPrice AS XP FROM (SELECT pl.ProductId, pl.ValueIds, DENSE_RANK() OVER (PARTITION BY pl.ProductId ORDER BY a.Name, a.Id) AS Rk FROM Inv_T_ProductAttributeLine pl INNER JOIN Inv_T_Attribute a ON a.Id = pl.AttributeId AND a.IsDeleted = 'false' AND a.VariantCreation <> 'Never' WHERE pl.IsDeleted = 'false') x CROSS APPLY STRING_SPLIT(x.ValueIds, '\|') s INNER JOIN Inv_T_AttributeValue av ON CAST(av.Id AS nvarchar(36)) = s.value AND av.IsDeleted = 'false') l4 ON l4.ProductId = p.Id AND l4.Rk = 4 LEFT JOIN (SELECT x.ProductId, x.Rk, CAST(s.value AS nvarchar(36)) AS VId, av.Name AS VName, av.ExtraPrice AS XP FROM (SELECT pl.ProductId, pl.ValueIds, DENSE_RANK() OVER (PARTITION BY pl.ProductId ORDER BY a.Name, a.Id) AS Rk FROM Inv_T_ProductAttributeLine pl INNER JOIN Inv_T_Attribute a ON a.Id = pl.AttributeId AND a.IsDeleted = 'false' AND a.VariantCreation <> 'Never' WHERE pl.IsDeleted = 'false') x CROSS APPLY STRING_SPLIT(x.ValueIds, '\|') s INNER JOIN Inv_T_AttributeValue av ON CAST(av.Id AS nvarchar(36)) = s.value AND av.IsDeleted = 'false') l5 ON l5.ProductId = p.Id AND l5.Rk = 5` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | | Kapsam | Kiracı | | Form varsayılanları | IsActive=true | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `ProductId` | Ürün | dxSelectBox | | ✓ | sorgu: Inv_T_Product | | `InternalReference` | İç Referans | dxTextBox | | ✓ | | | `ProductName` | Adı | dxTextBox | | ✓ | | | `VariantName` | Varyant Değerleri | dxTextBox | | ✓ | | | `SalesPrice` | Satış Fiyatı | dxNumberBox | | ✓ | | | `Cost` | Maliyet | dxNumberBox | | ✓ | | | `UomId` | Birim | dxSelectBox | | ✓ | sorgu: Adm_T_Uom | | `CategoryId` | Kategori | dxSelectBox | | ✓ | sorgu: Inv_T_ProductCategory | | `IsActive` | Aktif | dxCheckBox | | ✓ | | #### Reçeteler — `App.Inventory.Bom` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_Bom.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.Bom` (sıra 5) | | Yetki | `App.Inventory.Bom` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Reçeteler — bir ürünü üretmek için gereken hammadde, yarı mamul ve operasyonlar. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_Bom` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Alt formlar | `App.Inventory.BomComponent` (Id → BomId), `App.Inventory.BomOperation` (Id → BomId), `App.Inventory.BomOther` (Id → Id), `App.Inventory.BomOverview` (Id → BomId) | | Widget'lar | `App.Widget.Total`, `App.Widget.VariantBased`, `App.Widget.Active` | | Form varsayılanları | UomId=Adet, IsActive=true, Quantity=0 | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `ProductId` | Ürün | dxSelectBox | ✓ | ✓ | sorgu: Inv_T_Product | | `Reference` | Referans | dxTextBox | | ✓ | | | `VariantKey` | Ürün Varyantı | dxSelectBox | | ✓ | sorgu: Inv_T_Product (← ProductId) | | `Quantity` | Miktar | dxNumberBox | ✓ | ✓ | | | `UomId` | Birim | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Uom | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | #### Reçeteye Genel Bakış — `App.Inventory.BomOverview` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_BomOverview.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.BomOverview` (sıra 6) | | Yetki | `App.Inventory.BomOverview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Reçeteye Genel Bakış — her aktif reçetenin çok seviyeli patlatılmış hali, ağaç olarak (salt okunur). | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) AS nvarchar(400)) AS NodeKey, CAST(NULL AS nvarchar(400)) AS ParentKey, b0.Id AS BomId, 0 AS NodeLevel, CAST('Product' AS nvarchar(20)) AS NodeType, CAST(p0.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(b0.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') AS nvarchar(400)) AS Name, CAST(b0.Quantity AS decimal(18,4)) AS Quantity, CAST(u0.Name AS nvarchar(64)) AS UomName, CAST(NULL AS decimal(18,4)) AS Cost, b0.TenantId, b0.IsDeleted, CAST(NULL AS nvarchar(400)) AS ParentName FROM Inv_T_Bom b0 INNER JOIN Inv_T_Product p0 ON p0.Id = b0.ProductId LEFT JOIN Adm_T_Uom u0 ON u0.Id = b0.UomId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 1, 'Component', CAST(p1.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(c1.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') AS nvarchar(400)), CAST(c1.Quantity AS decimal(18,4)), u1.Name, CAST(c1.Quantity * p1.Cost AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(bp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_Bom bp INNER JOIN Inv_T_Product pp ON pp.Id = bp.ProductId WHERE bp.Id = b0.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' INNER JOIN Inv_T_Product p1 ON p1.Id = c1.ProductId LEFT JOIN Adm_T_Uom u1 ON u1.Id = c1.UomId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 2, 'Component', CAST(p2.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(c2.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') AS nvarchar(400)), CAST(c1.Quantity * c2.Quantity / b1.Quantity AS decimal(18,4)), u2.Name, CAST(c1.Quantity * c2.Quantity / b1.Quantity * p2.Cost AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(cp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_BomComponent cp INNER JOIN Inv_T_Product pp ON pp.Id = cp.ProductId WHERE cp.Id = c1.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomComponent c2 ON c2.BomId = b1.Id AND c2.IsDeleted = 'false' INNER JOIN Inv_T_Product p2 ON p2.Id = c2.ProductId LEFT JOIN Adm_T_Uom u2 ON u2.Id = c2.UomId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/C' + CAST(c3.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 3, 'Component', CAST(p3.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(c3.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') AS nvarchar(400)), CAST(c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity AS decimal(18,4)), u3.Name, CAST(c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity * p3.Cost AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(cp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_BomComponent cp INNER JOIN Inv_T_Product pp ON pp.Id = cp.ProductId WHERE cp.Id = c2.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomComponent c2 ON c2.BomId = b1.Id AND c2.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c2.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c2.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c2.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b2 INNER JOIN Inv_T_BomComponent c3 ON c3.BomId = b2.Id AND c3.IsDeleted = 'false' INNER JOIN Inv_T_Product p3 ON p3.Id = c3.ProductId LEFT JOIN Adm_T_Uom u3 ON u3.Id = c3.UomId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/C' + CAST(c3.Id AS nvarchar(36)) + '/C' + CAST(c4.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/C' + CAST(c3.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 4, 'Component', CAST(p4.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(c4.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') AS nvarchar(400)), CAST(c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity * c4.Quantity / b3.Quantity AS decimal(18,4)), u4.Name, CAST(c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity * c4.Quantity / b3.Quantity * p4.Cost AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(cp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_BomComponent cp INNER JOIN Inv_T_Product pp ON pp.Id = cp.ProductId WHERE cp.Id = c3.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomComponent c2 ON c2.BomId = b1.Id AND c2.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c2.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c2.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c2.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b2 INNER JOIN Inv_T_BomComponent c3 ON c3.BomId = b2.Id AND c3.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c3.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c3.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c3.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b3 INNER JOIN Inv_T_BomComponent c4 ON c4.BomId = b3.Id AND c4.IsDeleted = 'false' INNER JOIN Inv_T_Product p4 ON p4.Id = c4.ProductId LEFT JOIN Adm_T_Uom u4 ON u4.Id = c4.UomId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 1, 'OperationGroup', 'Operasyonlar', CAST(SUM(o.DurationMin) AS decimal(18,4)), 'Dakika', CAST(SUM(o.DurationMin / 60 * w.CostPerHour) AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(bp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_Bom bp INNER JOIN Inv_T_Product pp ON pp.Id = bp.ProductId WHERE bp.Id = b0.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomOperation o ON o.BomId = b0.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 GROUP BY b0.Id, b0.TenantId, b0.IsDeleted UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/OPS/O' + CAST(o.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), b0.Id, 2, 'Operation', op.Name + ' - ' + w.Name, CAST(o.DurationMin AS decimal(18,4)), 'Dakika', CAST(o.DurationMin / 60 * w.CostPerHour AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST('Operasyonlar' AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomOperation o ON o.BomId = b0.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_Operation op ON op.Id = o.OperationId INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 2, 'OperationGroup', 'Operasyonlar', CAST(SUM(o.DurationMin * c1.Quantity / b1.Quantity) AS decimal(18,4)), 'Dakika', CAST(SUM(o.DurationMin * c1.Quantity / b1.Quantity / 60 * w.CostPerHour) AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(cp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_BomComponent cp INNER JOIN Inv_T_Product pp ON pp.Id = cp.ProductId WHERE cp.Id = c1.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomOperation o ON o.BomId = b1.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 GROUP BY b0.Id, b0.TenantId, b0.IsDeleted, c1.Id UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/OPS/O' + CAST(o.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), b0.Id, 3, 'Operation', op.Name + ' - ' + w.Name, CAST(o.DurationMin * c1.Quantity / b1.Quantity AS decimal(18,4)), 'Dakika', CAST(o.DurationMin * c1.Quantity / b1.Quantity / 60 * w.CostPerHour AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST('Operasyonlar' AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomOperation o ON o.BomId = b1.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_Operation op ON op.Id = o.OperationId INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 3, 'OperationGroup', 'Operasyonlar', CAST(SUM(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity / b2.Quantity) AS decimal(18,4)), 'Dakika', CAST(SUM(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity / b2.Quantity / 60 * w.CostPerHour) AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(cp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_BomComponent cp INNER JOIN Inv_T_Product pp ON pp.Id = cp.ProductId WHERE cp.Id = c2.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomComponent c2 ON c2.BomId = b1.Id AND c2.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c2.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c2.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c2.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b2 INNER JOIN Inv_T_BomOperation o ON o.BomId = b2.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 GROUP BY b0.Id, b0.TenantId, b0.IsDeleted, c1.Id, c2.Id UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/OPS/O' + CAST(o.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), b0.Id, 4, 'Operation', op.Name + ' - ' + w.Name, CAST(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity / b2.Quantity AS decimal(18,4)), 'Dakika', CAST(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity / b2.Quantity / 60 * w.CostPerHour AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST('Operasyonlar' AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomComponent c2 ON c2.BomId = b1.Id AND c2.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c2.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c2.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c2.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b2 INNER JOIN Inv_T_BomOperation o ON o.BomId = b2.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_Operation op ON op.Id = o.OperationId INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/C' + CAST(c3.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/C' + CAST(c3.Id AS nvarchar(36)) AS nvarchar(400)), b0.Id, 4, 'OperationGroup', 'Operasyonlar', CAST(SUM(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity / b3.Quantity) AS decimal(18,4)), 'Dakika', CAST(SUM(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity / b3.Quantity / 60 * w.CostPerHour) AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST((SELECT pp.Name + ISNULL(' (' + (SELECT STRING_AGG(avn.Name, ', ') FROM STRING_SPLIT(cp.VariantKey, '\|') sn INNER JOIN Inv_T_AttributeValue avn ON CAST(avn.Id AS nvarchar(36)) = sn.value) + ')', '') FROM Inv_T_BomComponent cp INNER JOIN Inv_T_Product pp ON pp.Id = cp.ProductId WHERE cp.Id = c3.Id) AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomComponent c2 ON c2.BomId = b1.Id AND c2.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c2.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c2.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c2.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b2 INNER JOIN Inv_T_BomComponent c3 ON c3.BomId = b2.Id AND c3.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c3.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c3.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c3.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b3 INNER JOIN Inv_T_BomOperation o ON o.BomId = b3.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1 GROUP BY b0.Id, b0.TenantId, b0.IsDeleted, c1.Id, c2.Id, c3.Id UNION ALL SELECT CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/C' + CAST(c3.Id AS nvarchar(36)) + '/OPS/O' + CAST(o.Id AS nvarchar(36)) AS nvarchar(400)), CAST('B' + CAST(b0.Id AS nvarchar(36)) + '/C' + CAST(c1.Id AS nvarchar(36)) + '/C' + CAST(c2.Id AS nvarchar(36)) + '/C' + CAST(c3.Id AS nvarchar(36)) + '/OPS' AS nvarchar(400)), b0.Id, 5, 'Operation', op.Name + ' - ' + w.Name, CAST(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity / b3.Quantity AS decimal(18,4)), 'Dakika', CAST(o.DurationMin * c1.Quantity * c2.Quantity / b1.Quantity * c3.Quantity / b2.Quantity / b3.Quantity / 60 * w.CostPerHour AS decimal(18,4)), b0.TenantId, b0.IsDeleted, CAST('Operasyonlar' AS nvarchar(400)) FROM Inv_T_Bom b0 INNER JOIN Inv_T_BomComponent c1 ON c1.BomId = b0.Id AND c1.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c1.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c1.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c1.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b1 INNER JOIN Inv_T_BomComponent c2 ON c2.BomId = b1.Id AND c2.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c2.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c2.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c2.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b2 INNER JOIN Inv_T_BomComponent c3 ON c3.BomId = b2.Id AND c3.IsDeleted = 'false' CROSS APPLY (SELECT TOP 1 bb.Id, bb.Quantity FROM Inv_T_Bom bb WHERE bb.ProductId = c3.ProductId AND bb.IsDeleted = 'false' AND bb.IsActive = 1 AND bb.Quantity > 0 AND (bb.VariantKey IS NULL OR bb.VariantKey = '' OR bb.VariantKey = c3.VariantKey) ORDER BY CASE WHEN bb.VariantKey = c3.VariantKey THEN 0 ELSE 1 END, bb.CreationTime) b3 INNER JOIN Inv_T_BomOperation o ON o.BomId = b3.Id AND o.IsDeleted = 'false' INNER JOIN Prd_T_Operation op ON op.Id = o.OperationId INNER JOIN Prd_T_WorkCenter w ON w.Id = o.WorkCenterId WHERE b0.IsDeleted = 'false' AND b0.IsActive = 1` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart, Tree (açılış tree) | | Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `Name` | Ürün | dxTextBox | | ✓ | | | `ParentKey` | Üst Düğüm | dxTextBox | | | | | `ParentName` | Üst Düğüm | dxTextBox | | | | | `Quantity` | Miktar | dxNumberBox | | ✓ | | | `UomName` | Birim | dxTextBox | | ✓ | | | `Cost` | Maliyet | dxNumberBox | | ✓ | | | `NodeType` | Satır Türü | dxSelectBox | | ✓ | liste: Product, Component, OperationGroup, Operation | | `NodeLevel` | Seviye | dxNumberBox | | ✓ | | | `BomId` | Reçete | dxTextBox | | | | | `IsDeleted` | Silindi | dxCheckBox | | | | #### Depolar — `App.Inventory.Warehouse` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_Warehouse.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.Warehouse` (sıra 7) | | Yetki | `App.Inventory.Warehouse` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Depolar — stoğun fiziksel olarak tutulduğu yerler; her depo bir şubeye bağlıdır. | | Geliştirme talebi | Envanter -> Tanımlamalar | | Kaynak | `Inv_T_Warehouse` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | | Form varsayılanları | IsActive=true | | Veri aynası | `data/App.Inventory.Warehouse.json` | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | | `Code` | Depo Kodu | dxTextBox | ✓ | ✓ | | | `Name` | Depo Adı | dxTextBox | ✓ | ✓ | | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | #### Konumlar — `App.Inventory.Location` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_Location.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.Location` (sıra 8) | | Yetki | `App.Inventory.Location` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Konumlar — şube ve depo bazında iç içe tanımlanan stok konumları (ör. GRP › Stock › Ana Depo AB07). | | Geliştirme talebi | Envanter -> Tanımlamalar | | Kaynak | `Inv_T_Location` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart, Tree (açılış tree) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | | Form varsayılanları | LocationType=Internal, IsActive=true | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | | `WarehouseId` | Depo | dxSelectBox | ✓ | ✓ | sorgu: Inv_T_Warehouse (← BranchId) | | `Code` | Konum Kodu | dxTextBox | | ✓ | | | `Name` | Konum | dxTextBox | ✓ | ✓ | | | `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department (← BranchId) | | `ResponsibleUserId` | Depo Sorumlusu | dxSelectBox | | ✓ | sorgu: AbpUsers | | `LocationType` | Konum Türü | dxSelectBox | ✓ | ✓ | liste: Internal, External | | `ParentId` | Üst Lokasyon | dxSelectBox | | ✓ | sorgu: Inv_T_Location (← WarehouseId) | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | #### Operasyon Türleri — `App.Inventory.OperationType` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_OperationType.json` | | Yol | Liste (Wizard) | | Menü | `App.Inventory.Definitions` › `App.Inventory.OperationType` (sıra 9) | | Yetki | `App.Inventory.OperationType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Operasyon Türleri — şube ve depo bazında tanımlanan stok operasyon türleri (ör. Alımlar, Teslimatlar, İç Transferler). | | Geliştirme talebi | Envanter -> Tanımlamalar | | Kaynak | `Inv_T_OperationType` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | | Form varsayılanları | OperationKind=Receipt, IsActive=true | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | | `WarehouseId` | Depo | dxSelectBox | ✓ | ✓ | sorgu: Inv_T_Warehouse (← BranchId) | | `Name` | Operasyon Türü | dxTextBox | ✓ | ✓ | | | `OperationKind` | Tür | dxSelectBox | ✓ | ✓ | liste: Receipt, Delivery, InternalTransfer, Manufacturing, Repair | | `SequencePrefix` | Sıra Öneki | dxTextBox | | ✓ | | | `Barcode` | Barkod | dxTextBox | | ✓ | | | `SourceLocationId` | Kaynak Konum | dxSelectBox | | ✓ | sorgu: Inv_T_Location (← WarehouseId) | | `DestinationLocationId` | Hedef Konum | dxSelectBox | | ✓ | sorgu: Inv_T_Location (← WarehouseId) | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | #### Nitelik Değerleri — `App.Inventory.AttributeValue` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_AttributeValue.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.AttributeValue` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Nitelik Değerleri — bir niteliğin alabileceği değerler (ör. renk: kırmızı, mavi; boyut: 40x40). | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_AttributeValue` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Form varsayılanları | IsCustom=false, IsActive=true | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `AttributeId` | Nitelik | dxSelectBox | | | sorgu: Inv_T_Attribute | | `Name` | Değer | dxTextBox | ✓ | ✓ | | | `IsCustom` | Serbest Metin | dxCheckBox | | ✓ | | | `ExtraPrice` | Varsayılan Ekstra Fiyat | dxNumberBox | | ✓ | | | `ColorCode` | Renk Kodu | dxColorBox | | ✓ | | | `SortOrder` | Sıra | dxNumberBox | | ✓ | | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | #### Bileşenler — `App.Inventory.BomComponent` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_BomComponent.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.BomComponent` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Reçete Bileşenleri — reçetenin tükettiği hammadde ve yarı mamuller. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_BomComponent` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `BomId` | Reçete | dxTextBox | | | | | `ProductId` | Komponent | dxSelectBox | ✓ | ✓ | sorgu: Inv_T_Product · script | | `VariantKey` | Bileşen Varyantı | dxSelectBox | | ✓ | sorgu: Inv_T_Product (← ProductId) | | `Quantity` | Miktar | dxNumberBox | ✓ | ✓ | | | `UomId` | Birim | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Uom | | `BomOperationId` | Operasyonda Tüketilenler | dxSelectBox | | ✓ | sorgu: Inv_T_BomOperation (← BomId) | | `SortOrder` | Sıra | dxNumberBox | | ✓ | | #### Operasyonlar — `App.Inventory.BomOperation` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_BomOperation.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.BomOperation` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Reçete Operasyonları — reçetenin üretim adımları ve süreleri. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_BomOperation` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `BomId` | Reçete | dxTextBox | | | | | `OperationId` | Operasyon | dxSelectBox | ✓ | ✓ | sorgu: Prd_T_Operation · script | | `WorkCenterId` | İş Merkezi | dxSelectBox | ✓ | ✓ | sorgu: Prd_T_WorkCenter | | `DurationMin` | Süre (dakika) | dxNumberBox | ✓ | ✓ | | | `SortOrder` | Sıra | dxNumberBox | | ✓ | | #### Diğer — `App.Inventory.BomOther` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_BomOther.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.BomOther` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Reçete Diğer Ayarlar — reçetenin üretim hazırlığı ve planlama parametreleri. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_Bom` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `ReadyToProduce` | Üretim Hazırlığı | dxRadioGroup | ✓ | ✓ | liste: AllAvailable, FirstOperation | | `ProductionLeadDays` | Üretim Akış Zamanı (gün) | dxNumberBox | | ✓ | | | `FlexibleConsumption` | Esnek Tüketim | dxRadioGroup | ✓ | ✓ | liste: Allowed, Warning, Blocked | | `PreparationDays` | Üretim Siparişi Hazırlama Günleri | dxNumberBox | | ✓ | | | `BatchSize` | Parti Büyüklüğü | dxNumberBox | | ✓ | | #### Genel Bilgi — `App.Inventory.ProductGeneral` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_ProductGeneral.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.ProductGeneral` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürün Genel Bilgi — ürünün vergi, barkod, satınalma kontrol ve iç not bilgileri. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_Product` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `SalesTaxRate` | Satış Vergisi (%) | dxNumberBox | ✓ | ✓ | | | `PurchaseTaxRate` | Satınalma Vergisi (%) | dxNumberBox | ✓ | ✓ | | | `Barcode` | Barkod | dxTextBox | | ✓ | | | `PurchaseControlPolicy` | Kontrol Kuralı | dxRadioGroup | ✓ | ✓ | liste: Ordered, Received | | `PurchaseDescription` | Satınalma Açıklaması | dxTextBox | | ✓ | | | `InternalNotes` | İç Notlar | dxTextBox | | ✓ | | #### Nitelik & Varyantlar — `App.Inventory.ProductAttributeLine` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_ProductAttributeLine.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.ProductAttributeLine` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürün Nitelik & Varyantlar — ürünün nitelikleri ve bu ürün için kullanılan değerler. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_ProductAttributeLine` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `ProductId` | Ürün | dxTextBox | | | | | `AttributeId` | Nitelik | dxSelectBox | ✓ | ✓ | sorgu: Inv_T_Attribute | | `ValueIds` | Değerler | dxTagBox | ✓ | ✓ | sorgu: Inv_T_AttributeValue (← AttributeId) | #### Satınalma — `App.Inventory.ProductSupplier` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_ProductSupplier.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.ProductSupplier` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürün Tedarikçi Fiyatları — ürünün hangi tedarikçiden hangi bedele alındığı. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_ProductSupplier` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Kapsam | Kiracı | | Form varsayılanları | MinQuantity=0, CurrencyId=TRY, UomId=Adet, Price=0 | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `ProductId` | Ürün | dxTextBox | | | | | `ContactId` | Tedarikçi | dxSelectBox | ✓ | ✓ | sorgu: Adm_T_Contact | | `VariantKey` | Ürün Varyantı | dxSelectBox | | ✓ | sorgu: Inv_T_Product (← ProductId) | | `MinQuantity` | Miktar | dxNumberBox | ✓ | ✓ | | | `UomId` | Birim | dxSelectBox | | ✓ | sorgu: Adm_T_Uom | | `Price` | Birim Fiyat | dxNumberBox | ✓ | ✓ | | | `CurrencyId` | Kur | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | | `LeadTimeDays` | Teslim Süresi (gün) | dxNumberBox | | ✓ | | #### Stok — `App.Inventory.ProductStock` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_ProductStock.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.ProductStock` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürün Stok — ürünün lojistik ve izlenebilirlik bilgileri. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_Product` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `ResponsibleUserId` | Sorumlu | dxSelectBox | | ✓ | sorgu: AbpUsers | | `LotValuation` | Lot/Seri Bazında Değerleme | dxCheckBox | | ✓ | | | `Weight` | Ağırlık (kg) | dxNumberBox | | ✓ | | | `CustomLotSerial` | Özel Lot/Seri | dxTextBox | | ✓ | | | `Volume` | Hacim (m³) | dxNumberBox | | ✓ | | | `GtipCode` | GTİP Kodu | dxTextBox | | ✓ | | | `OriginCountryId` | Malların Menşei | dxSelectBox | | ✓ | sorgu: Sas_H_Country | | `ReceiptNote` | Alım İçin Açıklama | dxTextBox | | ✓ | | | `DeliveryNote` | Teslimatlar İçin Açıklama | dxTextArea | | ✓ | | | `InternalTransferNote` | İç Transferler İçin Açıklama | dxTextArea | | ✓ | | #### Muhasebe — `App.Inventory.ProductAccounting` | Özellik | Değer | | --- | --- | | Wizard | `wizard/Inventory_ProductAccounting.json` | | Yol | Liste (Wizard) | | Menü | Menüsüz (alt form) | | Yetki | `App.Inventory.ProductAccounting` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Ürün Muhasebe — ürünün maliyet ve gelir hesapları. | | Geliştirme talebi | Inventory -> Tanımlamalar | | Kaynak | `Inv_T_Product` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | | Kapsam | Kiracı | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | --- | --- | --- | --- | --- | --- | | `IncomeAccount` | Gelir Hesabı | dxTextBox | | ✓ | | | `ExpenseAccount` | Gider Hesabı | dxTextBox | | ✓ | |