From eb57bcd5caf0a653aa91c437abd866cb3c02a67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Fri, 9 Oct 2026 20:54:08 +0300 Subject: [PATCH] ApplicationSuite --- .../lowcode-reference.instructions.md | 5 +- README.md | 4 +- .../DynamicApi/ApplicationSuiteDto.cs | 10 ++ .../IListFormDynamicApiAppService.cs | 2 + .../ListForms/ListFormDynamicApiAppService.cs | 17 +++ .../Migrations/ListFormSeeder_Saas.cs | 143 ++++++++++++++++++ .../Migrations/WizardDataSeeder.cs | 2 +- .../Enums/TableNameEnum.cs | 3 +- .../PlatformConsts.cs | 1 + .../TableNameResolver.cs | 1 + .../Data/IWizardDataSeeder.cs | 16 ++ .../Data/PlatformDbMigrationService.cs | 19 ++- .../Data/SeedConsts.cs | 1 + .../Host/Definitions/ApplicationSuite.cs | 16 ++ .../EntityFrameworkCore/PlatformDbContext.cs | 13 ++ ....cs => 20261009171249_Initial.Designer.cs} | 61 +++++++- ...4_Initial.cs => 20261009171249_Initial.cs} | 31 ++++ .../PlatformDbContextModelSnapshot.cs | 59 ++++++++ .../seeds/data/Abp.Identity.Permissions.json | 70 ++++++++- .../App.Definitions.ApplicationSuite.json | 14 ++ .../53294e77-a4fb-45e4-a80e-acf07b5d75be.json | 6 +- .../fc6d0fbb-6b04-4d15-9d27-fec98e5c30fb.json | 2 +- .../data/App.Languages.LanguageText.json | 62 ++++++-- configs/seeds/data/App.Menus.Menu.json | 91 +++++++++-- .../seeds/docs/modules/App.Administration.md | 4 +- configs/seeds/docs/modules/App.Prc.md | 20 +-- configs/seeds/wizard/Adm_Approver.json | 4 +- configs/seeds/wizard/Prc_MaterialRequest.json | 11 +- .../Prc_MaterialRequestDeptApproval.json | 11 +- .../seeds/wizard/Prc_MaterialRequestLine.json | 11 +- .../wizard/Prc_MaterialRequestPlanning.json | 11 +- .../Prc_MaterialRequestPurchaseApproval.json | 11 +- .../seeds/wizard/Prc_MyMaterialRequest.json | 11 +- configs/seeds/wizard/Prc_RejectReason.json | 4 +- ui/src/services/tenant.service.ts | 12 ++ .../CreateTenantFromOrderDialog.tsx | 81 +++++++--- 36 files changed, 709 insertions(+), 131 deletions(-) create mode 100644 api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/ApplicationSuiteDto.cs create mode 100644 api/src/Sozsoft.Platform.Domain/Data/IWizardDataSeeder.cs create mode 100644 api/src/Sozsoft.Platform.Domain/Entities/Host/Definitions/ApplicationSuite.cs rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20261008061754_Initial.Designer.cs => 20261009171249_Initial.Designer.cs} (99%) rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20261008061754_Initial.cs => 20261009171249_Initial.cs} (99%) create mode 100644 configs/seeds/data/App.Definitions.ApplicationSuite.json diff --git a/.github/instructions/lowcode-reference.instructions.md b/.github/instructions/lowcode-reference.instructions.md index f5b7c32b..2683b2fc 100644 --- a/.github/instructions/lowcode-reference.instructions.md +++ b/.github/instructions/lowcode-reference.instructions.md @@ -1272,10 +1272,11 @@ soneklerini alır. | **Definitions › Global Search** | `App.Definitions.GlobalSearch` | `Sas_T_GlobalSearch` | tenant | Üretilen ekranın üst aramada çıkması için kayıt: `System`, `Group`, `Term`, `Weight`, `Url`. | | **Definitions › Contact Title** | `App.Definitions.ContactTitle` | `Sas_H_ContactTitle` | host | Ünvan/hitap lookup'ı (`Title`, `Abbreviation`). | | **Definitions › Termination Reasons** | `App.Definitions.TerminationReason` | `Sas_H_TerminationReason` | host | SGK işten çıkış kodları (`Code`, `Name`, `IsActive`); mevzuat kodu olduğu için bütün kiracılarda ortaktır. Seed `data/App.Definitions.TerminationReason.json` (06/07 mülga). Kullanıcının `TerminationReasonId` alanı `LookupQueryValues.TerminationReasonValues` ile buraya bağlanır. | +| **Definitions › Application Suites** | `App.Definitions.ApplicationSuite` | `Sas_H_ApplicationSuite` | host | Kiracıya açılan modül paketi (`Name` benzersiz, `Modules` `Sas_H_Module`'den çoklu `dxTagBox` — `\|` ile, `IsActive`). Sales Orders'ın kiracı oluşturma diyaloğu aktif paketleri `GET list-form-dynamic-api/application-suites` (`Tenants.Create`) ile okur ve seçilenin modüllerini forma yazar. Seed `data/App.Definitions.ApplicationSuite.json`. | | **Definitions › Currency** | `App.Definitions.Currency` | `Sas_H_Currency` | host | Para birimi + `Rate`. Tutar alanı olan ekranın kur lookup'ı ve `DbQuery` varsayılanı buradan beslenir. | | **Definitions › Country Group / Country / City / District** | `App.Definitions.CountryGroup` · `.Country` · `.City` · `.District` | `Sas_H_CountryGroup` · `Sas_H_Country` · `Sas_H_City` · `Sas_H_District` | host | Adres alanlarının hazır cascade zinciri (dört ayrı menü ve seed dosyası; `Order` sırası grup → ülke → il → ilçe). `Country` ayrıca `PhoneCode`, `PhoneNumberFormat`, `ZipRequired`, `StateRequired`, `TaxLabel` taşır — adres doğrulaması için kullan. | | **Public › Products / Payment Methods / Installment Options** | `App.Orders.Products` · `.PaymentMethods` · `.InstallmentOptions` | `Sas_H_Product` · `Sas_H_PaymentMethod` · `Sas_H_InstallmentOption` | host | Ürün, ödeme yöntemi (`Commission`), taksit — satış/abonelik ekranlarının ve public `/products` sayfasının kaynağı. | -| **Public › Sales Orders** | `App.Orders.SalesOrders` (alt form Sales Order Item) | `Sas_H_Order` + `Sas_H_OrderItem` | host | **Onay akışı + alt kalem + toplam + diyalog** birlikte kullanılan tam örnek (§12.7). | +| **Public › Sales Orders** | `App.Orders.SalesOrders` (alt form Sales Order Item) | `Sas_H_Order` + `Sas_H_OrderItem` | host | **Onay akışı + alt kalem + toplam + diyalog** birlikte kullanılan tam örnek (§12.7). Onaylanan siparişin `Tenant` komutu `CreateTenantFromOrderDialog`'u açar; diyalogda seçilen Application Suite modülleri doldurur (değiştirilebilir). | | **Public › Blog Category / Posts** | `App.BlogManagement.Category` · `.Posts` | `Sas_H_BlogCategory` · `Sas_H_BlogPost` | host | Çok dilli içerik (`ContentTr`/`ContentEn`), slug, yayın durumu, sayaç alanları; public `/blog` bu tablolardan okur, yayınlanmış yazılar sitemap'e girer. | | **Public › Demos** | `App.Demos` | `Sas_H_Demo` | host | Public `/demo` formundan gelen talepler — public form → tablo akışının örneği. | | **Tenants** | `AbpTenantManagement.Tenants` | `AbpTenants` | host | Kiracı kaydı, bağlantı dizesi diyaloğu (`TenantsConnectionString`), alt form olarak şubeler; yazma `list-form-dynamic-api/tenant-*`. Ekranların `IsTenant` davranışının kaynağı. | @@ -1284,7 +1285,7 @@ soneklerini alır. | **Languages › Language / Language Text** | `App.Languages.Language` · `.LanguageText` | `Sas_H_Language` · `Sas_H_LanguageKey` · `Sas_H_LanguageText` | host | Dil anahtarları. Üretilen her ekranın EN+TR metinleri buraya yazılır; ekran `data/App.Languages.{Language,LanguageText}.json` dosyalarına senkronlanır. Metin insert'i eksik `LanguageKey`'i de üretir, aynı kültür+kaynak+anahtar varsa eklemez. | | **Data Source** | `App.DataSource` | `Sas_H_DataSource` | host | `Code`, `DataSourceType`, `ConnectionString`. Tipli API (`/api/app/data-source`) bağlantı cümlesini hiçbir zaman döndürmez; okuma açıktır (açılır listeler), yazma `App.DataSource.Create/Update/Delete` ister. **İki tür kayıt bir arada:** elle tanımlanan host/harici bağlantılar ve `Code = tenant adı` olan otomatik tenant bağlantıları (Tenants ekranındaki bağlantı diyaloğu yönetir, elle dokunma). Varsayılan kaydı `HostDataSeeder` appsettings'teki bağlantı cümlesinden kurar. Çözüm kuralı `lowcode` §9.3.3. Bağlantı dizesi koda/JSON'a yazılmaz. | | **Background Workers › Recurring Jobs / Jobs** | `App.BackgroundWorkers.RecurringJobs` · `.Jobs` | `Sas_H_BackgroundWorker` · `Sas_H_BackgroundWorker_JobFlow` | host | Cron'lu işler ve çalıştırma geçmişi (`Tenant`, `ExecutionDate`, `Duration`, `Status`, `FailureReason`, `ExceptionDetails`). `WorkerType`/`Scope` değerleri §11'de; her kapsam ayrı bir Hangfire işidir, `Tenant` kolonu hangi kiracıda çalıştığını gösterir. Hazır işler (oturum temizliği, bildirim, yedek, şema sözlüğü) `data/App.BackgroundWorkers.RecurringJobs.json`'dan gelir. Ayrıntı: `lowcode` §9.10, `README.md` §14. | -| **Menus › Module / Routes / Menu / Manager** | `App.Menus.Module` · `.Routes` · `.Menu` · `.Manager` (`/admin/menuManager`) | `Sas_H_Module` · `Sas_H_Route` · `Sas_H_Menu` | host | Menü ve route veritabanından gelir; üretilen ekranın menü kaydı buradan açılır. `Menu` ekranı ağaç düzeninin referansıdır. Seed: `data/App.Menus.{Routes,Module,Menu}.json` — `Routes` dosyasına yalnızca var olan satırın `Seo*` alanları için dokunulur. | +| **Menus › Routes / Menu / Manager** · **Definitions › Module** | `App.Menus.Module` · `.Routes` · `.Menu` · `.Manager` (`/admin/menuManager`) | `Sas_H_Module` · `Sas_H_Route` · `Sas_H_Menu` | host | Menü ve route veritabanından gelir; üretilen ekranın menü kaydı buradan açılır. `Menu` ekranı ağaç düzeninin referansıdır. `Module` ekranının menü ve yetkisi Saas › Definitions altındadır (Applications ekranının hemen altı); ekran kodu `App.Menus.Module` olarak kalır. Seed: `data/App.Menus.{Routes,Module,Menu}.json` — `Routes` dosyasına yalnızca var olan satırın `Seo*` alanları için dokunulur. | | **Developer Kit › Dev Requests** | `App.DevRequests` | `Sas_H_DevRequest` | host | **Kanban/Todo düzeninin** referansı (`DefaultLayout: todo`): `Status`, `Priority`, `SortOrder`, `Tags`, `Assignees`, `SubTasks`, `Timesheets`; detayda `Description` yanında `Analysis` sekmesi (`AnalysisExpr`). MCP geliştirme döngüsünün kuyruğudur (`Backlog` → `Analysis` MCP analiz eder, `Ready to Start`'a kullanıcı alır; `Ready to Start` → `Testing`, `Staging`'e kullanıcı alır; araç çubuğunda DB Migrate butonu vardır — `UiEvalService.ApiDbMigrate()`, önce onay sorar, `App.Setup.Migrate`; yalnızca `start_dev_request` başlatır; açıklamadaki base64 görseller MCP'ye resim içeriği olarak gider, analiz `save_dev_request_analysis` ile yazılır, üretim notu `append_dev_request_note` ile `Analysis`'e eklenir — `Description` talebin yazıldığı hâliyle kalır; `lowcode.instructions.md` §0.11–§0.12). | | **Developer Kit › SQL Query Manager** | `App.SqlQueryManager` · `/admin/sqlQueryManager` | `Sas_H_CrudEndpoint` (üretilen CRUD uçları) | — | View/procedure/function/tablo tasarımı ve çalıştırma, tablodan CRUD endpoint üretimi (`.CrudEndpoints` yetkisi); karar sırasının 2. adımı buradan başlar. | | **Developer Kit › Files** | `App.Files` · `/admin/files` | Blob depolama | tenant | Dosya yöneticisi. Ekranın dosya alanı için ayrı depolama kurma; dosya/görsel editörleri ve Intranet Documents bu altyapıyı kullanır. | diff --git a/README.md b/README.md index e287c7c7..d3e77077 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ yazılır, PostgreSQL'de `PostgreSqlModelSyntax` ile çevrilir (`PlatformDbConte | `{sql\|postgres}/object` | Seed sırasında nesneyi oluşturur/günceller. SqlTableDesigner ve SqlQueryManager, deploy ettiği script'i bu klasöre yazar. | | `{sql\|postgres}/execute` | Nesneyi oluşturur; ayrıca tüm migration ve seed'ler bittikten sonra `FinalSeeder` dosya adından türettiği procedure'ü çalıştırır (dosya adı = procedure adı, `schema.Procedure.sql` de olur). | | `{sql\|postgres}/host/{object\|execute}` | Aynı iki kural, **yalnızca host veritabanında**. Tenant veritabanında karşılığı olmayan nesnelere dayanan script buraya konur — örneğin HangFire tabloları tenant migrate'inde de yalnızca host'a kurulduğu için `Sas_H_BackgroundWorker_JobFlow` view'ı buradadır. Sıra: `object` → `host/object` → `execute` → `host/execute`. SqlTableDesigner ve SqlQueryManager her zaman `object/`'e yazar; yalnızca host'ta çalışması gereken script File Manager'dan buraya taşınır. Wizard export/import bu klasörü de taşır. | -| `wizard` | ListForm Wizard'ın ürettiği `.json` konfigürasyonları; `WizardDataSeeder` okur. | +| `wizard` | ListForm Wizard'ın ürettiği `.json` konfigürasyonları; `WizardDataSeeder` okur. Contributor değildir (`IWizardDataSeeder`): her dosyayı kendi transaction'ında kurduğu için ABP contributor'ları commit edildikten sonra, `data/` dosyalarından önce çalışır — açık contributor transaction'ı içinde ayrı bağlantı, commit edilmemiş satırları bekleyip zaman aşımına düşer. | | `crud` | CrudEndpoint konfigürasyonları; `CrudDataSeeder` dosyaları `ICrudEndpointSeedApplier` üzerinden uygular. Politika **damga karşılaştırmalıdır**: eksik endpoint her zaman eklenir, mevcut bir kayıt yalnızca dosyanın `GeneratedAt` damgası kaydın `LastModificationTime`/`CreationTime` değerinden **yeniyse** güncellenir ya da silinir; aksi halde kayıt korunur ve log'a drift uyarısı düşer. Böylece CRUD Endpoint Manager'dan yapılan bir revizyon depodan gelen eski bir dosya yüzünden migrate sırasında geri alınmaz. Damgası olmayan (eski biçimde yazılmış) dosya hiçbir zaman yeni sayılmaz. | | `data` | Ekranlardan girilen listelerin veri aynası: tek dosya (`{ListFormCode}.json`) ya da satır başına dosya tutan klasör (`{ListFormCode}/{anahtar}.json`; klasör özyinelemeli taranır ve tamamı tek unit of work'te uygulanır). Biçimi yalnızca ekranın `SeedFilePath` tanımı belirler; hedefi okuyan/yazan her yol `ListFormSeedTarget` üzerinden gider ve tanımın dışında kalan dosya uygulanmaz. `ListForm.SeedFilePath` dolu olan ekranda `SeedSyncInsert/Update/Delete` bayraklarından işaretli olan işlemler dosyaya yansır (`ListFormSeedDataSynchronizer`); migrate/seed sırasında bütün contributor'lar bittikten sonra `ListFormSeedDataApplier` dosyayı geri uygular: anahtarı veritabanında **olmayan** satırları ekler, var olanlara dokunmaz. Aynı uygulayıcı wizard import'unun kapanışında da (`CompleteImport`) yalnızca o import'ta yazılan dosyalar için, `overwriteExisting` açık olarak çalışır — orada var olan satır dosyadaki değerlerle güncellenir. | @@ -2153,7 +2153,7 @@ configs/seeds/ │ # App.Menus.{Routes,Module,Menu}.json — route/modül/menü ağacı │ # Abp.Identity.Permission{Groups,s}.json — yetki tanımları │ # App.Definitions.{CountryGroup,Country,City,District}.json — adres zinciri -│ # App.Definitions.{Currency,ContactTitle,AiBot,TerminationReason}.json — para birimi, hitap, AI bot, SGK çıkış kodu +│ # App.Definitions.{Currency,ContactTitle,AiBot,TerminationReason,ApplicationSuite}.json — para birimi, hitap, AI bot, SGK çıkış kodu, uygulama paketi │ # App.Hr.{SkillType,SkillLevel,Skill}.json — İK yetkinlik tanımları │ # App.Hr.{Department,JobPosition}.json — İK departman → pozisyon (BranchId ile şubeye bağlı) │ # App.Hr.Intranet.*.json — İK › Intranet (duyuru, anket, sosyal akış, etkinlik) diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/ApplicationSuiteDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/ApplicationSuiteDto.cs new file mode 100644 index 00000000..c4936f32 --- /dev/null +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/ApplicationSuiteDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace Sozsoft.Platform.ListForms.DynamicApi; + +public class ApplicationSuiteDto +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string Modules { get; set; } +} diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/IListFormDynamicApiAppService.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/IListFormDynamicApiAppService.cs index c74694ea..68e9d72c 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/IListFormDynamicApiAppService.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/DynamicApi/IListFormDynamicApiAppService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace Sozsoft.Platform.ListForms.DynamicApi; @@ -12,6 +13,7 @@ public interface IListFormDynamicApiAppService Task PostTenantInsertAsync(DynamicApiBaseInput input); Task PostTenantUpdateAsync(DynamicApiBaseInput input); Task PostTenantDeleteAsync(DynamicApiBaseInput input); + Task> GetApplicationSuitesAsync(); Task PostCreateTenantFromOrderAsync(DynamicApiBaseInput input); Task PostNotificationInsertAsync(DynamicApiBaseInput input); } diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormDynamicApiAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormDynamicApiAppService.cs index b7f72ab3..9601577f 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormDynamicApiAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormDynamicApiAppService.cs @@ -37,6 +37,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic private readonly IConfiguration configuration; private readonly IOptions identityOptions; private readonly IRepository orderRepository; + private readonly IReadOnlyRepository applicationSuiteRepository; private readonly IListFormSeedDataSynchronizer seedDataSynchronizer; private readonly IRepository notificationTemplateRepository; private readonly IReadOnlyRepository notificationTypeRepository; @@ -51,6 +52,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic IConfiguration configuration, IOptions identityOptions, IRepository orderRepository, + IReadOnlyRepository applicationSuiteRepository, IListFormSeedDataSynchronizer seedDataSynchronizer, IRepository notificationTemplateRepository, IReadOnlyRepository notificationTypeRepository, @@ -64,6 +66,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic this.configuration = configuration; this.identityOptions = identityOptions; this.orderRepository = orderRepository; + this.applicationSuiteRepository = applicationSuiteRepository; this.seedDataSynchronizer = seedDataSynchronizer; this.notificationTemplateRepository = notificationTemplateRepository; this.notificationTypeRepository = notificationTypeRepository; @@ -273,6 +276,20 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic await seedDataSynchronizer.SyncRowAsync(input.ListFormCode, tenant.Id, SeedSyncOperation.Insert); } + /// + /// Siparişten kiracı oluşturma diyaloğunun paket seçenekleri. Diyaloğu açan kullanıcının paket + /// ekranını okuma yetkisi olmayabilir; bu yüzden uç, komutun kendi yetkisini (kiracı oluşturma) ister. + /// + [Authorize(TenantManagementPermissions.Tenants.Create)] + public async Task> GetApplicationSuitesAsync() + { + var suites = await applicationSuiteRepository.GetListAsync(x => x.IsActive); + + return [.. suites + .OrderBy(x => x.Name) + .Select(x => new ApplicationSuiteDto { Id = x.Id, Name = x.Name, Modules = x.Modules })]; + } + [Authorize(TenantManagementPermissions.Tenants.Create)] public async Task PostCreateTenantFromOrderAsync(DynamicApiBaseInput input) { diff --git a/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs b/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs index f649d97e..4aaa83f5 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs @@ -1755,6 +1755,149 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency } #endregion + #region ApplicationSuite + listFormName = AppCodes.Definitions.ApplicationSuite; + if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName)) + { + var listForm = await _listFormRepository.InsertAsync( + new ListForm() + { + ListFormType = ListFormTypeEnum.List, + PageSize = 10, + ExportJson = DefaultExportJson, + IsSubForm = false, + ShowNote = false, + LayoutJson = DefaultLayoutJson(), + CultureName = LanguageCodes.En, + ListFormCode = listFormName, + Name = listFormName, + Title = listFormName, + DataSourceCode = SeedConsts.DataSources.DefaultCode, + IsTenant = false, + IsBranch = false, + IsOrganizationUnit = false, + Description = $"{listFormName}.Description", + SelectCommandType = SelectCommandTypeEnum.Table, + SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.ApplicationSuite)), + KeyFieldName = "Id", + KeyFieldDbSourceType = DbType.Guid, + SeedFilePath = SeedPathResolver.GetDataFilePath(listFormName), + SeedSyncInsert = true, + SeedSyncUpdate = true, + SeedSyncDelete = true, + DefaultFilter = DefaultFilterJson, + SortMode = GridOptions.SortModeSingle, + FilterRowJson = DefaultFilterRowJson(), + HeaderFilterJson = DefaultHeaderFilterJson(), + SearchPanelJson = DefaultSearchPanelJson(), + GroupPanelJson = DefaultGroupPanelJson(), + SelectionJson = DefaultSelectionSingleJson, + ColumnOptionJson = DefaultColumnOptionJson(), + PermissionJson = DefaultPermissionJson(listFormName), + DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.ApplicationSuite)), + DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(), + PagerOptionJson = DefaultPagerOptionJson, + EditingOptionJson = DefaultEditingOptionJson(listFormName, 600, 350, true, true, true, true, false), + EditingFormJson = JsonSerializer.Serialize(new List + { + new() { + Order = 1, ColCount = 1, ColSpan = 1, ItemType = "group" }, + }), + InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(), + FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { + new() { FieldName = "IsActive", FieldDbType = DbType.Boolean, Value = "true", CustomValueType = FieldCustomValueTypeEnum.Value }, + }), + }); + + #region ApplicationSuite Fields + await _listFormFieldRepository.InsertManyAsync([ + new() { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Guid, + FieldName = "Id", + CaptionName = "App.Listform.ListformField.Id", + Width = 0, + ListOrderNo = 1, + Visible = false, + IsActive = true, + + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson + }, + new() { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Name", + EditGroupOrderNo = 1, + EditOrderNo = 1, + EditorType2 = EditorTypes.dxTextBox, + ColSpan = 1, + CaptionName = "App.Listform.ListformField.Name", + Width = 0, + ListOrderNo = 2, + Visible = true, + IsActive = true, + + AllowSearch = true, + SortIndex = 1, + SortDirection = GridColumnOptions.SortOrderAsc, + ValidationRuleJson = DefaultValidationRuleRequiredJson, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson + }, + new() { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Modules", + EditGroupOrderNo = 1, + EditOrderNo = 2, + EditorType2 = EditorTypes.dxTagBox, + ColSpan = 1, + CaptionName = "App.Listform.ListformField.Modules", + Width = 0, + ListOrderNo = 3, + Visible = true, + IsActive = true, + LookupJson = JsonSerializer.Serialize(new LookupDto { + DataSourceType = UiLookupDataSourceTypeEnum.Query, + DisplayExpr = "name", + ValueExpr = "key", + LookupQuery = LookupQueryValues.ModuleValues, + }), + ValidationRuleJson = DefaultValidationRuleRequiredJson, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson + }, + new() { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Boolean, + FieldName = "IsActive", + EditGroupOrderNo = 1, + EditOrderNo = 3, + EditorType2 = EditorTypes.dxCheckBox, + ColSpan = 1, + CaptionName = "App.Listform.ListformField.IsActive", + Width = 0, + ListOrderNo = 4, + Visible = true, + IsActive = true, + + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson + }, + ]); + #endregion + } + #endregion + #region Currency listFormName = AppCodes.Definitions.Currency; if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName)) diff --git a/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs b/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs index 744144a7..2eb7de2d 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Migrations/WizardDataSeeder.cs @@ -49,7 +49,7 @@ public class WizardDataSeeder( WizardInstallationChecker installationChecker, IUnitOfWorkManager unitOfWorkManager, IConfiguration configuration, - ILogger logger) : IDataSeedContributor, ITransientDependency + ILogger logger) : IWizardDataSeeder, ITransientDependency { private readonly string _appName = PlatformConsts.AppName; diff --git a/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs b/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs index ac5d114f..ded99813 100644 --- a/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs +++ b/api/src/Sozsoft.Platform.Domain.Shared/Enums/TableNameEnum.cs @@ -109,5 +109,6 @@ public enum TableNameEnum UserFamilyMember, UserEmergencyContact, UserBenefit, - TerminationReason + TerminationReason, + ApplicationSuite } diff --git a/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs b/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs index 660f85a4..51c65b8a 100644 --- a/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs +++ b/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs @@ -542,6 +542,7 @@ public static class PlatformConsts public const string City = Default + ".City"; public const string District = Default + ".District"; public const string TerminationReason = Default + ".TerminationReason"; + public const string ApplicationSuite = Default + ".ApplicationSuite"; public const string Sector = Default + ".Sector"; public const string UomCategory = Default + ".UomCategory"; diff --git a/api/src/Sozsoft.Platform.Domain.Shared/TableNameResolver.cs b/api/src/Sozsoft.Platform.Domain.Shared/TableNameResolver.cs index 8571c056..d5b216ae 100644 --- a/api/src/Sozsoft.Platform.Domain.Shared/TableNameResolver.cs +++ b/api/src/Sozsoft.Platform.Domain.Shared/TableNameResolver.cs @@ -24,6 +24,7 @@ public static class TableNameResolver { nameof(TableNameEnum.City), (TablePrefix.PlatformByName, MenuPrefix.Sas) }, { nameof(TableNameEnum.District), (TablePrefix.PlatformByName, MenuPrefix.Sas) }, { nameof(TableNameEnum.TerminationReason), (TablePrefix.PlatformByName, MenuPrefix.Sas) }, + { nameof(TableNameEnum.ApplicationSuite), (TablePrefix.PlatformByName, MenuPrefix.Sas) }, { nameof(TableNameEnum.Branch), (TablePrefix.TenantByName, MenuPrefix.Sas) }, { nameof(TableNameEnum.BranchUsers), (TablePrefix.TenantByName, MenuPrefix.Sas) }, { nameof(TableNameEnum.SettingDefinition), (TablePrefix.PlatformByName, MenuPrefix.Sas) }, diff --git a/api/src/Sozsoft.Platform.Domain/Data/IWizardDataSeeder.cs b/api/src/Sozsoft.Platform.Domain/Data/IWizardDataSeeder.cs new file mode 100644 index 00000000..7d661469 --- /dev/null +++ b/api/src/Sozsoft.Platform.Domain/Data/IWizardDataSeeder.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using Volo.Abp.Data; + +namespace Sozsoft.Platform.Data; + +/// +/// Wizard ekranlarini seed dosyalarindan kurar. Contributor degildir: her dosya kendi transaction'inda +/// kurulur ve ABP DataSeeder'in acik transaction'i icindeki ayri baglanti, diger contributor'larin +/// commit edilmemis satirlarini (ornegin varsayilan veri kaynagi) bekleyip zaman asimina duser. +/// Bu yuzden contributor'lar bittikten sonra, veri dosyalarindan once cagrilir. +/// Uygulamasi DbMigrator projesindedir; migrator disindaki host'larda kayitli olmayabilir. +/// +public interface IWizardDataSeeder +{ + Task SeedAsync(DataSeedContext context); +} diff --git a/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs b/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs index 669abdc6..b8e8d958 100644 --- a/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs +++ b/api/src/Sozsoft.Platform.Domain/Data/PlatformDbMigrationService.cs @@ -25,6 +25,7 @@ public class PlatformDbMigrationService : ITransientDependency private readonly ICurrentTenant _currentTenant; private readonly IConfiguration _configuration; private readonly IEnumerable _finalSeeders; + private readonly IEnumerable _wizardDataSeeders; private readonly IListFormSeedDataApplier _listFormSeedDataApplier; private readonly DistributedCacheCleaner _cacheCleaner; @@ -35,6 +36,7 @@ public class PlatformDbMigrationService : ITransientDependency ICurrentTenant currentTenant, IConfiguration configuration, IEnumerable finalSeeders, + IEnumerable wizardDataSeeders, IListFormSeedDataApplier listFormSeedDataApplier, DistributedCacheCleaner cacheCleaner) { @@ -44,6 +46,7 @@ public class PlatformDbMigrationService : ITransientDependency _currentTenant = currentTenant; _configuration = configuration; _finalSeeders = finalSeeders; + _wizardDataSeeders = wizardDataSeeders; _listFormSeedDataApplier = listFormSeedDataApplier; _cacheCleaner = cacheCleaner; @@ -242,16 +245,24 @@ public class PlatformDbMigrationService : ITransientDependency Logger.LogInformation("{TenantName} tenant shares the host database; seed files are already applied there.", tenant!.Name); } - await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) + var context = new DataSeedContext(tenant?.Id) .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, adminEmail) .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, adminPassword) .WithProperty(IdentityDataSeedContributor.AdminUserNamePropertyName, adminEmail) .WithProperty(SeedFileScope.PropertyName, applySeedFiles) - .WithProperty(SeedFileScope.CompletesPendingPropertyName, completesPending) - ); + .WithProperty(SeedFileScope.CompletesPendingPropertyName, completesPending); + + await _dataSeeder.SeedAsync(context); + + // Wizard ekranlari contributor'larin kayitlarina (veri kaynagi, ListForm) dayanir ve dosya basina + // kendi transaction'inda kurulur; contributor UoW'si commit edilmeden calisamaz (IWizardDataSeeder). + foreach (var wizardDataSeeder in _wizardDataSeeders) + { + await wizardDataSeeder.SeedAsync(context); + } // Veri seed dosyalari ListForm tanimlarina ve tablolara dayandigi icin butun - // contributor'lar bittikten sonra uygulanir; ABP contributor sirasi garanti degildir. + // contributor'lar ve wizard kurulumu bittikten sonra uygulanir; ABP contributor sirasi garanti degildir. if (applySeedFiles) { await _listFormSeedDataApplier.ApplyAsync(tenant?.Id); diff --git a/api/src/Sozsoft.Platform.Domain/Data/SeedConsts.cs b/api/src/Sozsoft.Platform.Domain/Data/SeedConsts.cs index bec74065..d3595686 100644 --- a/api/src/Sozsoft.Platform.Domain/Data/SeedConsts.cs +++ b/api/src/Sozsoft.Platform.Domain/Data/SeedConsts.cs @@ -366,6 +366,7 @@ public static class SeedConsts public const string City = Default + ".City"; public const string District = Default + ".District"; public const string TerminationReason = Default + ".TerminationReason"; + public const string ApplicationSuite = Default + ".ApplicationSuite"; public const string Sector = Default + ".Sector"; public const string UomCategory = Default + ".UomCategory"; diff --git a/api/src/Sozsoft.Platform.Domain/Entities/Host/Definitions/ApplicationSuite.cs b/api/src/Sozsoft.Platform.Domain/Entities/Host/Definitions/ApplicationSuite.cs new file mode 100644 index 00000000..84d92098 --- /dev/null +++ b/api/src/Sozsoft.Platform.Domain/Entities/Host/Definitions/ApplicationSuite.cs @@ -0,0 +1,16 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; + +namespace Sozsoft.Platform.Entities; + +/// +/// Kiracıya birlikte açılan modül paketi. Satış siparişinden kiracı oluşturulurken seçilir ve +/// Modules değeri kiracının modül listesine aktarılır; kiracı oluşmadan seçildiği için +/// tanım host tablosundadır. +/// +public class ApplicationSuite : FullAuditedEntity +{ + public string Name { get; set; } + public string Modules { get; set; } + public bool IsActive { get; set; } +} diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs index 3dbccc9f..1eca7331 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs @@ -74,6 +74,7 @@ public class PlatformDbContext : public DbSet IpRestrictions { get; set; } public DbSet ContactTitles { get; set; } public DbSet TerminationReasons { get; set; } + public DbSet ApplicationSuites { get; set; } public DbSet Currencies { get; set; } public DbSet CountryGroups { get; set; } public DbSet Countries { get; set; } @@ -985,6 +986,18 @@ public class PlatformDbContext : b.HasIndex(x => new { x.Code }).IsUnique().HasFilter("[IsDeleted] = 0"); }); + builder.Entity(b => + { + b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ApplicationSuite)), Prefix.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Name).IsRequired().HasMaxLength(128); + b.Property(x => x.Modules).IsRequired().HasMaxLength(1024); + b.Property(x => x.IsActive).HasDefaultValue(true); + + b.HasIndex(x => new { x.Name }).IsUnique().HasFilter("[IsDeleted] = 0"); + }); + builder.Entity(b => { b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.Currency)), Prefix.DbSchema); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261008061754_Initial.Designer.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261009171249_Initial.Designer.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261008061754_Initial.Designer.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261009171249_Initial.Designer.cs index 80524828..cae5867b 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261008061754_Initial.Designer.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261009171249_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Sozsoft.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20261008061754_Initial")] + [Migration("20261009171249_Initial")] partial class Initial { /// @@ -1049,6 +1049,65 @@ namespace Sozsoft.Platform.Migrations b.ToTable("Hr_T_AnnouncementLike", (string)null); }); + modelBuilder.Entity("Sozsoft.Platform.Entities.ApplicationSuite", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Modules") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Sas_H_ApplicationSuite", (string)null); + }); + modelBuilder.Entity("Sozsoft.Platform.Entities.BackgroundWorker", b => { b.Property("Id") diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261008061754_Initial.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261009171249_Initial.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261008061754_Initial.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261009171249_Initial.cs index 10c4f3c3..11a300be 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261008061754_Initial.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20261009171249_Initial.cs @@ -1341,6 +1341,27 @@ namespace Sozsoft.Platform.Migrations table.PrimaryKey("PK_Sas_H_AiBot", x => x.Id); }); + migrationBuilder.CreateTable( + name: "Sas_H_ApplicationSuite", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Modules = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: false), + IsActive = table.Column(type: "bit", nullable: false, defaultValue: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Sas_H_ApplicationSuite", x => x.Id); + }); + migrationBuilder.CreateTable( name: "Sas_H_BackgroundWorker", columns: table => new @@ -4642,6 +4663,13 @@ namespace Sozsoft.Platform.Migrations column: "Name", unique: true); + migrationBuilder.CreateIndex( + name: "IX_Sas_H_ApplicationSuite_Name", + table: "Sas_H_ApplicationSuite", + column: "Name", + unique: true, + filter: "[IsDeleted] = 0"); + migrationBuilder.CreateIndex( name: "IX_Sas_H_BackgroundWorker_Name", table: "Sas_H_BackgroundWorker", @@ -5139,6 +5167,9 @@ namespace Sozsoft.Platform.Migrations migrationBuilder.DropTable( name: "Sas_H_AiBot"); + migrationBuilder.DropTable( + name: "Sas_H_ApplicationSuite"); + migrationBuilder.DropTable( name: "Sas_H_BackgroundWorker"); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index 96b05347..30328bd4 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -1046,6 +1046,65 @@ namespace Sozsoft.Platform.Migrations b.ToTable("Hr_T_AnnouncementLike", (string)null); }); + modelBuilder.Entity("Sozsoft.Platform.Entities.ApplicationSuite", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Modules") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Sas_H_ApplicationSuite", (string)null); + }); + modelBuilder.Entity("Sozsoft.Platform.Entities.BackgroundWorker", b => { b.Property("Id") diff --git a/configs/seeds/data/Abp.Identity.Permissions.json b/configs/seeds/data/Abp.Identity.Permissions.json index 5421d3e2..77e41382 100644 --- a/configs/seeds/data/Abp.Identity.Permissions.json +++ b/configs/seeds/data/Abp.Identity.Permissions.json @@ -564,6 +564,66 @@ "MultiTenancySide": 2, "Modules": "Sas|Adm" }, + { + "GroupName": "App.Saas", + "Name": "App.Definitions.ApplicationSuite", + "ParentName": "App.Saas.Definitions", + "DisplayName": "App.Definitions.ApplicationSuite", + "Order": 10, + "IsEnabled": true, + "MultiTenancySide": 2, + "Modules": "Sas|Adm" + }, + { + "GroupName": "App.Saas", + "Name": "App.Definitions.ApplicationSuite.Create", + "ParentName": "App.Definitions.ApplicationSuite", + "DisplayName": "App.Platform.Create", + "Order": 1, + "IsEnabled": true, + "MultiTenancySide": 2, + "Modules": "Sas|Adm" + }, + { + "GroupName": "App.Saas", + "Name": "App.Definitions.ApplicationSuite.Update", + "ParentName": "App.Definitions.ApplicationSuite", + "DisplayName": "App.Platform.Update", + "Order": 2, + "IsEnabled": true, + "MultiTenancySide": 2, + "Modules": "Sas|Adm" + }, + { + "GroupName": "App.Saas", + "Name": "App.Definitions.ApplicationSuite.Delete", + "ParentName": "App.Definitions.ApplicationSuite", + "DisplayName": "App.Platform.Delete", + "Order": 3, + "IsEnabled": true, + "MultiTenancySide": 2, + "Modules": "Sas|Adm" + }, + { + "GroupName": "App.Saas", + "Name": "App.Definitions.ApplicationSuite.Export", + "ParentName": "App.Definitions.ApplicationSuite", + "DisplayName": "Export", + "Order": 4, + "IsEnabled": true, + "MultiTenancySide": 2, + "Modules": "Sas|Adm" + }, + { + "GroupName": "App.Saas", + "Name": "App.Definitions.ApplicationSuite.Import", + "ParentName": "App.Definitions.ApplicationSuite", + "DisplayName": "Import", + "Order": 5, + "IsEnabled": true, + "MultiTenancySide": 2, + "Modules": "Sas|Adm" + }, { "GroupName": "App.Saas", "Name": "App.Public", @@ -1697,9 +1757,9 @@ { "GroupName": "App.Saas", "Name": "App.Menus.Module", - "ParentName": "App.Menus", + "ParentName": "App.Saas.Definitions", "DisplayName": "App.Menus.Module", - "Order": 1, + "Order": 11, "IsEnabled": true, "MultiTenancySide": 2, "Modules": "Sas|Adm" @@ -1759,7 +1819,7 @@ "Name": "App.Menus.Routes", "ParentName": "App.Menus", "DisplayName": "App.Menus.Routes", - "Order": 2, + "Order": 1, "IsEnabled": true, "MultiTenancySide": 2, "Modules": "Sas|Adm" @@ -1819,7 +1879,7 @@ "Name": "App.Menus.Menu", "ParentName": "App.Menus", "DisplayName": "App.Menus.Menu", - "Order": 3, + "Order": 2, "IsEnabled": true, "MultiTenancySide": 2, "Modules": "Sas|Adm" @@ -1879,7 +1939,7 @@ "Name": "App.Menus.Manager", "ParentName": "App.Menus", "DisplayName": "App.Menus.Manager", - "Order": 4, + "Order": 3, "IsEnabled": true, "MultiTenancySide": 2, "Modules": "Sas|Adm" diff --git a/configs/seeds/data/App.Definitions.ApplicationSuite.json b/configs/seeds/data/App.Definitions.ApplicationSuite.json new file mode 100644 index 00000000..784d4e82 --- /dev/null +++ b/configs/seeds/data/App.Definitions.ApplicationSuite.json @@ -0,0 +1,14 @@ +{ + "ListFormCode": "App.Definitions.ApplicationSuite", + "KeyFieldName": "Id", + "GeneratedAt": "2026-10-09T00:00:00Z", + "Order": 0, + "Rows": [ + { + "Id": "0c1082fa-cb47-4793-bde2-f10dc822e2c0", + "Name": "Erp", + "Modules": "Adm|Hr|Inventory|Prc|Prj|Production|Pub|Sas", + "IsActive": true + } + ] +} diff --git a/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json b/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json index c1a2749a..cb0ea4fe 100644 --- a/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json +++ b/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json @@ -10,8 +10,8 @@ "UserName": "system@sozsoft.com", "RequestDate": null, "Status": "Testing", - "Title": "Satınalma -> Malzeme Talepleri", - "Description": "

Malzeme Talepleri : Satınalma yapılması için departmantların iç ve dış olmak üzere talep ettikleri ürünlerin kaydıdır. Talep eden, Talep Eden Departman, Mal Alımı olduğu zaman konulacak Depo ve Konum bilgisi ve Talep Tarihi bilgilerinden sonra Ürün ve talep edilen miktar bilgisi girilmeli. Ürün tanımında yer alan Birim bilgisi yine sistemle entegre şekilde gelmektedir. Termin Tarihi ürünün ne zaman ihtiyaç olduğu ve Talep Nedeni olarak ne amaçla istediği belirtilmelidir. Yine bu kaydın üst kısmında Taslak, Departman Onayı, Satınalma Onayı, Onaylandı, İşlemde, Tamamlandı gibi durumları da onay mekanizması Workflow gibi bir yöntemle yönetmeliyiz. Talepten sonra hemen talep edenin Departman Onaycısı onaylayacak bir liste üzerinden görmeli ve onaylamalı. Bu kişi Adm_T_Approver entity içerisindeki Onay Yeri : Satınalma ve Departman bazında gösterilecek) Sonrasında kayıt Satınalma departmanına düşmeli ondan sonra bu kayıt Satınalma Sorumlusu kabul etmeli ve Satınalma ile ilgili teklif toplama süreci başlamalı.



Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler listesinden oluşmalı.


Red Nedenleri : Bazı Satınalma talepleri hem departman onaycısı hemde satınalma tarafından reddedilebilir. Reddetme sebepleri aşağıadki gibidir. Bu liste Satınalma -> Tanımlamalar menüsüne yerleştirilmelidir.


", + "Title": "Satınalma -> Satınalma Talepleri", + "Description": "

Satınalma Talepleri : Satınalma yapılması için departmantların iç ve dış olmak üzere talep ettikleri ürünlerin kaydıdır. Talep eden, Talep Eden Departman, Mal Alımı olduğu zaman konulacak Depo ve Konum bilgisi ve Talep Tarihi bilgilerinden sonra Ürün ve talep edilen miktar bilgisi girilmeli. Ürün tanımında yer alan Birim bilgisi yine sistemle entegre şekilde gelmektedir. Termin Tarihi ürünün ne zaman ihtiyaç olduğu ve Talep Nedeni olarak ne amaçla istediği belirtilmelidir. Yine bu kaydın üst kısmında Taslak, Departman Onayı, Satınalma Onayı, Onaylandı, İşlemde, Tamamlandı gibi durumları da onay mekanizması Workflow gibi bir yöntemle yönetmeliyiz. Talepten sonra hemen talep edenin Departman Onaycısı onaylayacak bir liste üzerinden görmeli ve onaylamalı. Bu kişi Adm_T_Approver entity içerisindeki Onay Yeri : Satınalma ve Departman bazında gösterilecek) Sonrasında kayıt Satınalma departmanına düşmeli ondan sonra bu kayıt Satınalma Sorumlusu kabul etmeli ve Satınalma ile ilgili teklif toplama süreci başlamalı.



Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler listesinden oluşmalı.


Red Nedenleri : Bazı Satınalma talepleri hem departman onaycısı hemde satınalma tarafından reddedilebilir. Reddetme sebepleri aşağıadki gibidir. Bu liste Satınalma -> Tanımlamalar menüsüne yerleştirilmelidir.


", "DueDate": "2026-10-06T21:01:00", "Tags": "PO", "Assignees": "system@sozsoft.com", @@ -20,7 +20,7 @@ "SortOrder": 0, "Timesheets": "[{\"id\":\"746e8bc8-6246-5c53-2a75-3a24332eaef1\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_T_RejectReason tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"4d4ea437-e4fb-2542-a53a-3a24332ed605\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_T_MaterialRequest tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"c0e3a5b2-d85a-4813-343c-3a24332eec78\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_T_MaterialRequestLine tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"2922d002-6d30-3a07-7a51-3a2433302610\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"App.Definitions.Sequence ekran\\u0131na sat\\u0131r eklendi\",\"duration\":0.0167},{\"id\":\"980b02af-79bd-aaea-2e64-3a243330a1a5\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_P_MaterialRequestAfterSave SQL nesnesi kaydedildi\",\"duration\":0.0167},{\"id\":\"40f8aa4e-18ef-0e78-7f2d-3a2433310e09\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_P_MaterialRequestAfterSave SQL nesnesi kaydedildi\",\"duration\":0.0167},{\"id\":\"ffd1898f-6e00-6835-55cc-3a243331dc2c\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Adm_Approver.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"dc78ece5-0050-4749-7af1-3a2433326e07\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Adm_Approver.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"62e616c5-12b2-8803-4114-3a243332d2da\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_RejectReason.json wizard\\u0027\\u0131 deploy edildi (5 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"13a7f703-538b-a85d-9ee5-3a2433334bd2\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_T_MaterialRequestItem tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"b5e54d3a-6d12-009d-94a4-3a243333accc\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_P_MaterialRequestAfterSave SQL nesnesi kaydedildi\",\"duration\":0.0167},{\"id\":\"2c98a5ae-ccd7-8df9-3305-3a2433346916\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_MaterialRequestLine.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"2aa54ca5-5ca4-f039-a14e-3a243336492d\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_MyMaterialRequest.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0333},{\"id\":\"8aa70c93-93b9-0d5d-cf4f-3a2433372a47\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_MaterialRequestDeptApproval.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"ca3b6c15-8aa2-deb4-df27-3a2433380491\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_MaterialRequestPurchaseApproval.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"215c456f-2290-ecaf-be55-3a243338d23f\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_MaterialRequestPlanning.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"fd28ec5d-5402-9b18-d830-3a243339ec92\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Prc_MaterialRequest.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"e504030b-7f9d-3f4c-c6e8-3a24333a8db8\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"App.Prc mod\\u00FCl dok\\u00FCman\\u0131 kaydedildi\",\"duration\":0.0167},{\"id\":\"276aa28b-7210-616a-a412-3a24333aa710\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"14 tamamlanm\\u0131\\u015F alt g\\u00F6rev eklendi\",\"duration\":0.0167},{\"id\":\"24b186d3-397e-9eec-a86b-3a24333adcfa\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Analize \\u00FCretim notu eklendi\",\"duration\":0.0167}]", "SubTasks": "[{\"id\":\"834d9315-9266-2050-6954-3a24333aa6be\",\"title\":\"create_table: Prc_T_RejectReason\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"e5ffb0e9-9c69-4c53-b1d6-3a24333aa6be\",\"title\":\"create_table: Prc_T_MaterialRequest\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"f11f6c49-bfdb-a5fb-7d2c-3a24333aa6be\",\"title\":\"create_table: Prc_T_MaterialRequestItem\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"e4509378-28d6-80f6-7948-3a24333aa6be\",\"title\":\"save_sql_object: Prc_P_MaterialRequestAfterSave\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"a3053a8c-3eae-cf4d-11ad-3a24333aa6be\",\"title\":\"deploy_wizard: Adm_Approver.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"708f3732-6afd-913e-667d-3a24333aa6be\",\"title\":\"deploy_wizard: Prc_RejectReason.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"81e8f785-94a1-b919-12a9-3a24333aa6be\",\"title\":\"insert_row: App.Definitions.Sequence \\u2014 MaterialRequest\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"c637a664-1206-b91e-f0e5-3a24333aa6be\",\"title\":\"deploy_wizard: Prc_MaterialRequestLine.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"fad3ffa4-b62b-9d35-0796-3a24333aa6be\",\"title\":\"deploy_wizard: Prc_MyMaterialRequest.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"44b18a01-7267-e5e1-9ac4-3a24333aa6be\",\"title\":\"deploy_wizard: Prc_MaterialRequestDeptApproval.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"15c20659-f079-944a-90d0-3a24333aa6be\",\"title\":\"deploy_wizard: Prc_MaterialRequestPurchaseApproval.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"cdc5d85b-3cce-6973-7694-3a24333aa6be\",\"title\":\"deploy_wizard: Prc_MaterialRequestPlanning.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"15c9c83c-f96a-0386-b462-3a24333aa6be\",\"title\":\"deploy_wizard: Prc_MaterialRequest.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"54d0d2ad-15bf-8f0b-81c7-3a24333aa6be\",\"title\":\"save_module_doc: App.Prc.MaterialRequests\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true}]", - "Analysis": "

1. Amaç

\n

Departmanların iç/dış ihtiyaç duydukları malzemeleri satınalmaya iletmesi, talebin önce departman onaycısı sonra satınalma tarafından onaylanması ve onaylı talebin satınalma sorumlusuna (teklif toplama/planlama) düşmesi. Kullanıcılar: talep eden personel, departman onaycıları (Adm_T_Approver › Onay Yeri = Satınalma), satınalma ekibi.

\n\n

2. Görsel analizi

\n

[image-1] Talep formu (başlık + satır sekmesi). Üstte durum çubuğu: Taslak › Departman Onayı › Satınalma Onayı › Onaylandı › İşlemde › Kısmi Tamamlandı › Tamamlandı. Başlık: belge no (SRO/00001 → bizde MT-YYYY-00001), öncelik yıldızları (0–3), Talep Eden (kullanıcı), Departman, Genel Açıklama, Depo, Konum, Şirket (kiracı — alan açılmaz), Talep Tarihi. Sekme \"Talep Satırları\": Ürün, Miktar, Birim, Karşılama Şekli, Termin Tarihi, Talep Nedeni, Kendi Depomda, Tüm Depolar, Teslim, Planlanacak Miktar, Satınalma Sorumlusu, satır durumu rozeti. Görünen satır demo veri adayı değildir (müşteri ortamına ait ürün kodu).

\n

[image-2] Onay / Red Bilgileri sekmesi. İki grup: Departman Onayı (Departman Onaycıları — etiket listesi, Onaylayan, Onay Tarihi, Onay Notu) ve Satınalma Onayı (Onaylayan, Onay Tarihi, Onay Notu). Tümü salt okunur, akış doldurur.

\n

[image-3] Red Nedenleri listesi. Basit tanım listesi: Red Nedeni, Aktif, sürükle-sırala tutamacı. Satırlar demo veri: İhtiyaç yok, Miktar uygun değil, Yanlış ürün seçildi, Bütçe uygun değil, Diğer (hepsi aktif).

\n\n

3. Çözüm yolu

\n

Wizard List (ComponentKind 0) + menüsüz alt form (satırlar) + Grid Workflow (§10.7 \"onaylı talep formu\" iskeleti). Aynı tablo üzerinde durum filtresiyle ayrılmış beş liste ekranı. Onaycı kullanıcı listeleri kayıt sonrası SQL prosedürüyle (save_sql_object) Adm_T_Approver'dan doldurulur ve akış düğümü @Kolon onaycısıyla okur (İzin Talepleri'ndeki @ManagerUserNames deseni). Serbest yerleşim gerekmediği için custom component yok.

\n\n

4. Menü yeri

\n

Satınalma › Malzeme Talepleri › {5 liste} ; Satınalma › Tanımlamalar › Red Nedenleri

\n\n\n\n\n\n\n\n\n\n\n
SeviyeKodAd (TR / EN)İkonDurum
KökApp.PrcSatınalma / Purchasing—Var
AraApp.Prc.DefinitionsTanımlamalar / Definitions—Var
EkranApp.Prc.RejectReasonRed Nedenleri / Rejection ReasonsFcCancelYeni
AraApp.Prc.MaterialRequestsMalzeme Talepleri / Material RequestsFcListYeni
EkranApp.Prc.MyMaterialRequestTaleplerim / My RequestsFcPortraitModeYeni
EkranApp.Prc.MaterialRequestDeptApprovalDepartman Onayı Bekleyenler / Awaiting Department ApprovalFcApprovalYeni
EkranApp.Prc.MaterialRequestPurchaseApprovalSatınalma Onayı Bekleyenler / Awaiting Purchasing ApprovalFcApprovalYeni
EkranApp.Prc.MaterialRequestPlanningPlanlama Bekleyenler / Awaiting PlanningFcPlannerYeni
EkranApp.Prc.MaterialRequestTüm Talepler / All RequestsFcDocumentYeni
\n

ModuleId Prc, izin grubu App.Prc, route /admin/list/{ListFormCode}. Taleplerim talepte menü listesi olarak açıkça istendiği için persona kuralına rağmen menüde durur (girdi).

\n

Yetki: App.Prc › App.Prc.Definitions (Var) › App.Prc.RejectReason ; App.Prc › App.Prc.MaterialRequests (Yeni) › her liste ; alt form: App.Prc › App.Prc.MaterialRequests › {Liste} › App.Prc.MaterialRequestLine.

\n\n

5. Veri modeli

\n

Prc_T_RejectReason (yeni) — Tanım tablosu: Evet (talep \"Tanımlamalar menüsüne\" diyor, görselde Aktif kolonu). Kiracı + tam audit.

\n\n\n\n
KolonTipZorunluNot
Namenvarchar(128)✓Red nedeni
SortOrderint✓varsayılan 0; görseldeki sıralama tutamacı
IsActivebit✓DEFAULT 1
\n\n

Prc_T_MaterialRequest (yeni) — Tanım tablosu: Hayır (hareket belgesi). Kiracı + tam audit.

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
KolonTipZorunluNot
RequestNonvarchar(32)Numaratör (Adm_T_Sequence \"MaterialRequest\", MT-YYYY-00001, yıllık sıfırlama)
Priorityint✓0–3 yıldız, DEFAULT 0
RequesterUserIduniqueidentifier✓AbpUsers; varsayılan @USERID
DepartmentIduniqueidentifier✓Hr_T_Department; talep edenin AbpUsers.DepartmentId'sinden dolar, değiştirilebilir
WarehouseIduniqueidentifier✓Inv_T_Warehouse
LocationIduniqueidentifier✓Inv_T_Location, depoya göre süzülür
RequestDatedatetime✓DEFAULT GETDATE()
Descriptionnvarchar(MAX)Genel Açıklama (dxTextArea)
Statusnvarchar(32)✓Draft / DeptApproval / PurchaseApproval / Approved / InProgress / PartiallyDone / Done / Rejected; DEFAULT 'Draft'
ApprovalStatus, ApproverId, ApprovalDate, ApprovalNotenvarchar(32) / uniqueidentifier / datetime / nvarchar(MAX)WorkflowDto alanları
DeptApproverUserNamesnvarchar(MAX)\"|\" ayrılmış, prosedür doldurur; formda \"Departman Onaycıları\" (salt okunur)
PurchaseApproverUserNamesnvarchar(MAX)\"|\" ayrılmış, prosedür doldurur (gizli)
DeptApprovedBy, DeptApprovalDate, DeptApprovalNoteuniqueidentifier / datetime / nvarchar(MAX)Görsel 2 sol grup
PurchaseApprovedBy, PurchaseApprovalDate, PurchaseApprovalNoteuniqueidentifier / datetime / nvarchar(MAX)Görsel 2 sağ grup
RejectReasonIduniqueidentifierPrc_T_RejectReason (aktifler)
\n\n

Prc_T_MaterialRequestLine (yeni) — Tanım tablosu: Hayır. Kiracı + tam audit; FK MaterialRequestId → Prc_T_MaterialRequest (Cascade).

\n\n\n\n\n\n\n\n\n\n\n\n
KolonTipZorunluNot
MaterialRequestIduniqueidentifier✓üst kayıt
ProductIduniqueidentifier✓Inv_T_Product, yalnız IsActive=1 ve CanBePurchased=1; görüntü \"[InternalReference] Name\"
Quantitydecimal(18,4)✓> 0
UomIduniqueidentifier✓Adm_T_Uom; üründen COALESCE(PurchaseUomId, UomId) ile dolar, salt okunur
FulfillmentMethodnvarchar(16)✓Purchase (Satınalma) / Transfer (Depodan Transfer); DEFAULT 'Purchase'
DueDatedate✓Termin; talep tarihinden önce olamaz
RequestReasonnvarchar(256)✓Talep Nedeni
DeliveredQuantitydecimal(18,4)✓Teslim, DEFAULT 0, salt okunur
PlannedQuantitydecimal(18,4)Planlanacak Miktar; satır eklenince Quantity ile dolar, satınalma düzenler
PurchaseResponsibleUserIduniqueidentifierAbpUsers; Satınalma Sorumlusu (planlamada atanır)
LineStatusnvarchar(16)✓Waiting / Planned / Done / Cancelled; DEFAULT 'Waiting'
\n

Var olan tablo değişikliği: Adm_T_Approver.ApprovalArea statik listesine PurchaseDesk (Satınalma Masası / Purchasing Desk) seçeneği eklenir (Onaycılar wizard güncellemesi, kolon değişmez).

\n\n

6. Alt form ağacı

\n\n
SekmeHedef ListFormCodeTabTypeMenüİlişkiEkle / Düzenle / SilYetki yolu
Talep SatırlarıApp.Prc.MaterialRequestLineListMenüsüzId → MaterialRequestId✓ / ✓ / ✓App.Prc › App.Prc.MaterialRequests › {Liste} › App.Prc.MaterialRequestLine
\n

Onay / Red Bilgileri ayrı tablo değildir; ana formun ikinci düzenleme grubu (salt okunur alanlar) olarak çizilir. Alt form beş listenin hepsinde aynı ekrandır; ekleme/silme yalnız Status = Draft iken açıktır (alt formun Insert/Delete BeforeCommand'ında üst kayıt durumu kontrolü).

\n\n

7. Etkilenen kısımlar

\n

Yeni: 3 tablo, 1 prosedür (Prc_P_MaterialRequestResolveApprovers), 1 tanım ekranı, 1 alt form, 5 liste ekranı, ara menü App.Prc.MaterialRequests ve aynı kodlu ara yetki, her ekranın C/R/U/D/E/I/N yetkileri, dil anahtarları (alanlar, durum ve karşılama şekli statik seçenekleri), Adm_T_Sequence'e \"MaterialRequest\" satırı. Değişen: Onaycılar (App.Definitions.Approver) ApprovalArea seçeneği. İş akışı: iki onay düğümü + talep sahibine Inform (e-posta). Ürün, depo, konum, departman ekranlarına dokunulmaz.

\n\n

8. Görünümler ve davranış

\n

Liste filtreleri (aynı tablo, DefaultFilter): Taleplerim = RequesterUserId = @USERID (tüm durumlar; ekle açık); Departman Onayı Bekleyenler = Status = 'DeptApproval' + ApprovalIsFilterUserName; Satınalma Onayı Bekleyenler = Status = 'PurchaseApproval' + ApprovalIsFilterUserName; Planlama Bekleyenler = Status IN ('Approved','InProgress','PartiallyDone'); Tüm Talepler = filtresiz. Onay listelerinde ekleme kapalı.

\n

Görünümler: her listede Grid + Card + Pivot + Chart (açılış grid); Tüm Talepler'de ek olarak Todo (kanban) Status kolonuyla, durum sırası görseldeki çubukla aynı. Alt formda widget yok.

\n

Widget'lar: Tüm Talepler: Toplam · Departman Onayında · Satınalma Onayında · Onaylandı · Reddedildi. Taleplerim: Taleplerim · Onay Bekleyen · Onaylanan · Reddedilen. Red Nedenleri: Toplam · Aktif · Pasif.

\n

İş akışı (WorkflowDto, Taleplerim + iki onay listesi + Tüm Talepler'de aynı grafik): Start → Approval \"Departman Onayı\" (Approver = @DeptApproverUserNames) → onayda Approval \"Satınalma Onayı\" (Approver = @PurchaseApproverUserNames) → onayda Inform (talep sahibi) → End \"Onaylandı\"; her iki ret dalı → Inform → End \"Reddedildi\". ApprovalIsResetWorkflow = true (Taslak'a dönen kayıt düzenlenince akış baştan).

\n

Durum geçişleri: Kayıt Draft açılır; satır girildikten sonra toolbar butonu \"Onaya Gönder\" (CommandColumnDto, yalnız Draft ve en az bir satır varken) Status = DeptApproval yapar ve akışı başlatır. Prosedür (UpdateAfterCommand) akış düğümüne göre Status'u DeptApproval → PurchaseApproval → Approved / Rejected olarak senkronlar ve Dept*/Purchase* onay alanlarını ApproverId/ApprovalDate/ApprovalNote'tan kopyalar. Approved sonrası İşlemde / Kısmi Tamamlandı / Tamamlandı, Planlama Bekleyenler'deki satır butonlarıyla elle verilir; satırların tamamı LineStatus = Done olunca Status = Done, bir kısmı Done ise PartiallyDone (aynı prosedür).

\n

Onaycı çözümü (prosedür): DeptApproverUserNames = Adm_T_Approver'da DepartmentId = talebin departmanı, ApprovalArea = 'Purchase', IsActive = 1 kullanıcıların UserName'leri; PurchaseApproverUserNames = ApprovalArea = 'PurchaseDesk', IsActive = 1 kullanıcılar. Liste boşsa \"Onaya Gönder\" hata mesajıyla durur (boş onaycı akışı kilitler).

\n

Red: Ret notu zorunlu; RejectReasonId onay listelerinde onaycı tarafından düzenlenebilir alan, Rejected durumunda zorunlu (doğrulama prosedürde).

\n

EditorScript: RequestDate açılışta bugün; RequesterUserId açılışta @USERID ve DepartmentId kullanıcının departmanı; WarehouseId değişince LocationId temizlenir ve konum lookup'ı depoya süzülür (cascade); ProductId değişince UomId üründen dolar; Quantity değişince PlannedQuantity boşsa Quantity'ye eşitlenir; DueDate < RequestDate ise uyarı ve engel. Status ≠ Draft iken başlık alanları salt okunur.

\n\n

9. Kararlar

\n
    \n
  • Belge no biçimi MT-YYYY-00001 (Odoo'daki SRO/ yerine platform numaratörü; İK ekranlarıyla tutarlı).
  • \n
  • \"Şirket\" alanı açılmaz; kiracı kapsamı karşılar.
  • \n
  • (onay) Satınalma onayçısı Adm_T_Approver'a eklenen yeni Onay Yeri PurchaseDesk (Satınalma Masası) satırlarından okunur; departmandan bağımsız, herhangi birinin onayı yeterli.
  • \n
  • (onay) Taslak aşaması için \"Onaya Gönder\" toolbar butonu; buton olmadan akış kayıtta hemen başlar ve Taslak durumu kullanılamaz.
  • \n
  • (onay) Görseldeki \"Kendi Depomda\" ve \"Tüm Depolar\" stok miktarı kolonları üretilmez: uygulamada stok miktarı/hareket tablosu yok (Inv_T_Product yalnız kart bilgisi taşır). Stok modülü gelince sorgu kolonu olarak eklenecek ayrı talep.
  • \n
  • (onay) Karşılama Şekli seçenekleri: Satınalma / Depodan Transfer.
  • \n
  • Satır durumu (rozet) LineStatus ile; başlık durumu satırlardan türetilir.
  • \n
  • Görseldeki \"Transferler\" akıllı butonu ve teklif toplama süreci bu talebin dışında (teklif/sipariş modülü yok); Planlama Bekleyenler listesi o sürecin giriş noktasıdır.
  • \n
  • Red Nedenleri demo verisi görseldeki 5 satır (SortOrder 1–5, aktif).
  • \n
\n\n

10. Üretim planı

\n
    \n
  1. create_table: Prc_T_RejectReason
  2. \n
  3. create_table: Prc_T_MaterialRequest
  4. \n
  5. create_table: Prc_T_MaterialRequestLine
  6. \n
  7. save_sql_object: Prc_P_MaterialRequestResolveApprovers
  8. \n
  9. deploy_wizard: Adm_Approver.json (PurchaseDesk seçeneği, güncelleme)
  10. \n
  11. deploy_wizard: Prc_RejectReason.json (seed 5 satır)
  12. \n
  13. insert_row: App.Definitions.Sequence — MaterialRequest
  14. \n
  15. deploy_wizard: Prc_MaterialRequestLine.json
  16. \n
  17. deploy_wizard: Prc_MyMaterialRequest.json
  18. \n
  19. deploy_wizard: Prc_MaterialRequestDeptApproval.json
  20. \n
  21. deploy_wizard: Prc_MaterialRequestPurchaseApproval.json
  22. \n
  23. deploy_wizard: Prc_MaterialRequestPlanning.json
  24. \n
  25. deploy_wizard: Prc_MaterialRequest.json
  26. \n
\n\n

11. Üretime hazır

\n

Şartlı — (onay) etiketli 4 karar: Satınalma onaycısı için PurchaseDesk onay yeri, \"Onaya Gönder\" butonuyla Taslak aşaması, stok miktarı kolonlarının (Kendi Depomda / Tüm Depolar) stok modülüne ertelenmesi, Karşılama Şekli seçenekleri.

MCP

\n

Üretilenler: tablolar Prc_T_RejectReason, Prc_T_MaterialRequest, Prc_T_MaterialRequestItem; prosedür Prc_P_MaterialRequestAfterSave (SQL Server + PostgreSQL); numaratör MaterialRequest (MT-{yyyy}-00001, yıllık); ekranlar App.Prc.RejectReason (5 demo satır), menüsüz alt form App.Prc.MaterialRequestLine, App.Prc.MyMaterialRequest, App.Prc.MaterialRequestDeptApproval, App.Prc.MaterialRequestPurchaseApproval, App.Prc.MaterialRequestPlanning, App.Prc.MaterialRequest; Onaycılar'a PurchaseDesk (Satınalma Masası) onay yeri; menü Satınalma › Malzeme Talepleri (yeni ara menü/yetki) ve Satınalma › Tanımlamalar › Red Nedenleri; modül dokümanı App.Prc › Malzeme Talepleri.

\n

Analizden sapmalar / varsayımlar:

\n
    \n
  • Satır tablosu Prc_T_MaterialRequestItem adıyla açıldı: Adm_T_Uom.Id nvarchar olduğu için UomId nvarchar(64) olmalıydı; önce açılan Prc_T_MaterialRequestLine scripti (UomId uniqueidentifier) kullanılmıyor. Migrate'ten önce Wizard Manager / SQL Query Manager'dan bu scripti silmeniz önerilir (onayınız olmadan tablo düşürülmedi).
  • \n
  • Platform akışı onaylayanı kullanıcı adı (metin) olarak yazıyor; ApproverId uniqueidentifier olduğu için akışa bağlanmadı. Departman/Satınalma onaylayanı, tarihi ve notu prosedürde kaydı son güncelleyen kullanıcıdan ve akışın ApprovalDate/ApprovalNote alanlarından kopyalanır.
  • \n
  • Prosedür adı planda Prc_P_MaterialRequestResolveApprovers idi; onaycı çözümü + durum senkronu tek prosedürde: Prc_P_MaterialRequestAfterSave.
  • \n
  • \"Onaya Gönder\" ayrı buton olarak yazılmadı; akışın Start düğümü (platformun Onaya Gönder işlemi) kullanılır. İşlemde / Kısmi Tamamlandı / Tamamlandı satır durumlarından türetilir (ayrı satır butonu yok). Todo (kanban) görünümü eklenmedi.
  • \n
  • Onay listeleri ApprovalStatus (akış düğüm başlığı) ile süzülür; Status kayıt/satır kaydı sonrası prosedürle güncellenir. Akış onayı kayıt güncelleme komutunu tetiklemezse Status ve onaylayan bilgileri bir sonraki kayıtta güncellenir.
  • \n
  • Red nedeni zorunluluğu sunucuda zorlanmadı; alan onay listelerinde düzenlenebilir.
  • \n
\n

DB Migrate bekleyen wizard'lar: Adm_Approver.json, Prc_RejectReason.json, Prc_MaterialRequestLine.json, Prc_MyMaterialRequest.json, Prc_MaterialRequestDeptApproval.json, Prc_MaterialRequestPurchaseApproval.json, Prc_MaterialRequestPlanning.json, Prc_MaterialRequest.json.

" + "Analysis": "

1. Amaç

\n

Departmanların iç/dış ihtiyaç duydukları malzemeleri satınalmaya iletmesi, talebin önce departman onaycısı sonra satınalma tarafından onaylanması ve onaylı talebin satınalma sorumlusuna (teklif toplama/planlama) düşmesi. Kullanıcılar: talep eden personel, departman onaycıları (Adm_T_Approver › Onay Yeri = Satınalma), satınalma ekibi.

\n\n

2. Görsel analizi

\n

[image-1] Talep formu (başlık + satır sekmesi). Üstte durum çubuğu: Taslak › Departman Onayı › Satınalma Onayı › Onaylandı › İşlemde › Kısmi Tamamlandı › Tamamlandı. Başlık: belge no (SRO/00001 → bizde MT-YYYY-00001), öncelik yıldızları (0–3), Talep Eden (kullanıcı), Departman, Genel Açıklama, Depo, Konum, Şirket (kiracı — alan açılmaz), Talep Tarihi. Sekme \"Talep Satırları\": Ürün, Miktar, Birim, Karşılama Şekli, Termin Tarihi, Talep Nedeni, Kendi Depomda, Tüm Depolar, Teslim, Planlanacak Miktar, Satınalma Sorumlusu, satır durumu rozeti. Görünen satır demo veri adayı değildir (müşteri ortamına ait ürün kodu).

\n

[image-2] Onay / Red Bilgileri sekmesi. İki grup: Departman Onayı (Departman Onaycıları — etiket listesi, Onaylayan, Onay Tarihi, Onay Notu) ve Satınalma Onayı (Onaylayan, Onay Tarihi, Onay Notu). Tümü salt okunur, akış doldurur.

\n

[image-3] Red Nedenleri listesi. Basit tanım listesi: Red Nedeni, Aktif, sürükle-sırala tutamacı. Satırlar demo veri: İhtiyaç yok, Miktar uygun değil, Yanlış ürün seçildi, Bütçe uygun değil, Diğer (hepsi aktif).

\n\n

3. Çözüm yolu

\n

Wizard List (ComponentKind 0) + menüsüz alt form (satırlar) + Grid Workflow (§10.7 \"onaylı talep formu\" iskeleti). Aynı tablo üzerinde durum filtresiyle ayrılmış beş liste ekranı. Onaycı kullanıcı listeleri kayıt sonrası SQL prosedürüyle (save_sql_object) Adm_T_Approver'dan doldurulur ve akış düğümü @Kolon onaycısıyla okur (İzin Talepleri'ndeki @ManagerUserNames deseni). Serbest yerleşim gerekmediği için custom component yok.

\n\n

4. Menü yeri

\n

Satınalma › Satınalma Talepleri › {5 liste} ; Satınalma › Tanımlamalar › Red Nedenleri

\n\n\n\n\n\n\n\n\n\n\n
SeviyeKodAd (TR / EN)İkonDurum
KökApp.PrcSatınalma / Purchasing—Var
AraApp.Prc.DefinitionsTanımlamalar / Definitions—Var
EkranApp.Prc.RejectReasonRed Nedenleri / Rejection ReasonsFcCancelYeni
AraApp.Prc.MaterialRequestsSatınalma Talepleri / Material RequestsFcListYeni
EkranApp.Prc.MyMaterialRequestTaleplerim / My RequestsFcPortraitModeYeni
EkranApp.Prc.MaterialRequestDeptApprovalDepartman Onayı Bekleyenler / Awaiting Department ApprovalFcApprovalYeni
EkranApp.Prc.MaterialRequestPurchaseApprovalSatınalma Onayı Bekleyenler / Awaiting Purchasing ApprovalFcApprovalYeni
EkranApp.Prc.MaterialRequestPlanningPlanlama Bekleyenler / Awaiting PlanningFcPlannerYeni
EkranApp.Prc.MaterialRequestTüm Talepler / All RequestsFcDocumentYeni
\n

ModuleId Prc, izin grubu App.Prc, route /admin/list/{ListFormCode}. Taleplerim talepte menü listesi olarak açıkça istendiği için persona kuralına rağmen menüde durur (girdi).

\n

Yetki: App.Prc › App.Prc.Definitions (Var) › App.Prc.RejectReason ; App.Prc › App.Prc.MaterialRequests (Yeni) › her liste ; alt form: App.Prc › App.Prc.MaterialRequests › {Liste} › App.Prc.MaterialRequestLine.

\n\n

5. Veri modeli

\n

Prc_T_RejectReason (yeni) — Tanım tablosu: Evet (talep \"Tanımlamalar menüsüne\" diyor, görselde Aktif kolonu). Kiracı + tam audit.

\n\n\n\n
KolonTipZorunluNot
Namenvarchar(128)✓Red nedeni
SortOrderint✓varsayılan 0; görseldeki sıralama tutamacı
IsActivebit✓DEFAULT 1
\n\n

Prc_T_MaterialRequest (yeni) — Tanım tablosu: Hayır (hareket belgesi). Kiracı + tam audit.

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
KolonTipZorunluNot
RequestNonvarchar(32)Numaratör (Adm_T_Sequence \"MaterialRequest\", MT-YYYY-00001, yıllık sıfırlama)
Priorityint✓0–3 yıldız, DEFAULT 0
RequesterUserIduniqueidentifier✓AbpUsers; varsayılan @USERID
DepartmentIduniqueidentifier✓Hr_T_Department; talep edenin AbpUsers.DepartmentId'sinden dolar, değiştirilebilir
WarehouseIduniqueidentifier✓Inv_T_Warehouse
LocationIduniqueidentifier✓Inv_T_Location, depoya göre süzülür
RequestDatedatetime✓DEFAULT GETDATE()
Descriptionnvarchar(MAX)Genel Açıklama (dxTextArea)
Statusnvarchar(32)✓Draft / DeptApproval / PurchaseApproval / Approved / InProgress / PartiallyDone / Done / Rejected; DEFAULT 'Draft'
ApprovalStatus, ApproverId, ApprovalDate, ApprovalNotenvarchar(32) / uniqueidentifier / datetime / nvarchar(MAX)WorkflowDto alanları
DeptApproverUserNamesnvarchar(MAX)\"|\" ayrılmış, prosedür doldurur; formda \"Departman Onaycıları\" (salt okunur)
PurchaseApproverUserNamesnvarchar(MAX)\"|\" ayrılmış, prosedür doldurur (gizli)
DeptApprovedBy, DeptApprovalDate, DeptApprovalNoteuniqueidentifier / datetime / nvarchar(MAX)Görsel 2 sol grup
PurchaseApprovedBy, PurchaseApprovalDate, PurchaseApprovalNoteuniqueidentifier / datetime / nvarchar(MAX)Görsel 2 sağ grup
RejectReasonIduniqueidentifierPrc_T_RejectReason (aktifler)
\n\n

Prc_T_MaterialRequestLine (yeni) — Tanım tablosu: Hayır. Kiracı + tam audit; FK MaterialRequestId → Prc_T_MaterialRequest (Cascade).

\n\n\n\n\n\n\n\n\n\n\n\n
KolonTipZorunluNot
MaterialRequestIduniqueidentifier✓üst kayıt
ProductIduniqueidentifier✓Inv_T_Product, yalnız IsActive=1 ve CanBePurchased=1; görüntü \"[InternalReference] Name\"
Quantitydecimal(18,4)✓> 0
UomIduniqueidentifier✓Adm_T_Uom; üründen COALESCE(PurchaseUomId, UomId) ile dolar, salt okunur
FulfillmentMethodnvarchar(16)✓Purchase (Satınalma) / Transfer (Depodan Transfer); DEFAULT 'Purchase'
DueDatedate✓Termin; talep tarihinden önce olamaz
RequestReasonnvarchar(256)✓Talep Nedeni
DeliveredQuantitydecimal(18,4)✓Teslim, DEFAULT 0, salt okunur
PlannedQuantitydecimal(18,4)Planlanacak Miktar; satır eklenince Quantity ile dolar, satınalma düzenler
PurchaseResponsibleUserIduniqueidentifierAbpUsers; Satınalma Sorumlusu (planlamada atanır)
LineStatusnvarchar(16)✓Waiting / Planned / Done / Cancelled; DEFAULT 'Waiting'
\n

Var olan tablo değişikliği: Adm_T_Approver.ApprovalArea statik listesine PurchaseDesk (Satınalma Masası / Purchasing Desk) seçeneği eklenir (Onaycılar wizard güncellemesi, kolon değişmez).

\n\n

6. Alt form ağacı

\n\n
SekmeHedef ListFormCodeTabTypeMenüİlişkiEkle / Düzenle / SilYetki yolu
Talep SatırlarıApp.Prc.MaterialRequestLineListMenüsüzId → MaterialRequestId✓ / ✓ / ✓App.Prc › App.Prc.MaterialRequests › {Liste} › App.Prc.MaterialRequestLine
\n

Onay / Red Bilgileri ayrı tablo değildir; ana formun ikinci düzenleme grubu (salt okunur alanlar) olarak çizilir. Alt form beş listenin hepsinde aynı ekrandır; ekleme/silme yalnız Status = Draft iken açıktır (alt formun Insert/Delete BeforeCommand'ında üst kayıt durumu kontrolü).

\n\n

7. Etkilenen kısımlar

\n

Yeni: 3 tablo, 1 prosedür (Prc_P_MaterialRequestResolveApprovers), 1 tanım ekranı, 1 alt form, 5 liste ekranı, ara menü App.Prc.MaterialRequests ve aynı kodlu ara yetki, her ekranın C/R/U/D/E/I/N yetkileri, dil anahtarları (alanlar, durum ve karşılama şekli statik seçenekleri), Adm_T_Sequence'e \"MaterialRequest\" satırı. Değişen: Onaycılar (App.Definitions.Approver) ApprovalArea seçeneği. İş akışı: iki onay düğümü + talep sahibine Inform (e-posta). Ürün, depo, konum, departman ekranlarına dokunulmaz.

\n\n

8. Görünümler ve davranış

\n

Liste filtreleri (aynı tablo, DefaultFilter): Taleplerim = RequesterUserId = @USERID (tüm durumlar; ekle açık); Departman Onayı Bekleyenler = Status = 'DeptApproval' + ApprovalIsFilterUserName; Satınalma Onayı Bekleyenler = Status = 'PurchaseApproval' + ApprovalIsFilterUserName; Planlama Bekleyenler = Status IN ('Approved','InProgress','PartiallyDone'); Tüm Talepler = filtresiz. Onay listelerinde ekleme kapalı.

\n

Görünümler: her listede Grid + Card + Pivot + Chart (açılış grid); Tüm Talepler'de ek olarak Todo (kanban) Status kolonuyla, durum sırası görseldeki çubukla aynı. Alt formda widget yok.

\n

Widget'lar: Tüm Talepler: Toplam · Departman Onayında · Satınalma Onayında · Onaylandı · Reddedildi. Taleplerim: Taleplerim · Onay Bekleyen · Onaylanan · Reddedilen. Red Nedenleri: Toplam · Aktif · Pasif.

\n

İş akışı (WorkflowDto, Taleplerim + iki onay listesi + Tüm Talepler'de aynı grafik): Start → Approval \"Departman Onayı\" (Approver = @DeptApproverUserNames) → onayda Approval \"Satınalma Onayı\" (Approver = @PurchaseApproverUserNames) → onayda Inform (talep sahibi) → End \"Onaylandı\"; her iki ret dalı → Inform → End \"Reddedildi\". ApprovalIsResetWorkflow = true (Taslak'a dönen kayıt düzenlenince akış baştan).

\n

Durum geçişleri: Kayıt Draft açılır; satır girildikten sonra toolbar butonu \"Onaya Gönder\" (CommandColumnDto, yalnız Draft ve en az bir satır varken) Status = DeptApproval yapar ve akışı başlatır. Prosedür (UpdateAfterCommand) akış düğümüne göre Status'u DeptApproval → PurchaseApproval → Approved / Rejected olarak senkronlar ve Dept*/Purchase* onay alanlarını ApproverId/ApprovalDate/ApprovalNote'tan kopyalar. Approved sonrası İşlemde / Kısmi Tamamlandı / Tamamlandı, Planlama Bekleyenler'deki satır butonlarıyla elle verilir; satırların tamamı LineStatus = Done olunca Status = Done, bir kısmı Done ise PartiallyDone (aynı prosedür).

\n

Onaycı çözümü (prosedür): DeptApproverUserNames = Adm_T_Approver'da DepartmentId = talebin departmanı, ApprovalArea = 'Purchase', IsActive = 1 kullanıcıların UserName'leri; PurchaseApproverUserNames = ApprovalArea = 'PurchaseDesk', IsActive = 1 kullanıcılar. Liste boşsa \"Onaya Gönder\" hata mesajıyla durur (boş onaycı akışı kilitler).

\n

Red: Ret notu zorunlu; RejectReasonId onay listelerinde onaycı tarafından düzenlenebilir alan, Rejected durumunda zorunlu (doğrulama prosedürde).

\n

EditorScript: RequestDate açılışta bugün; RequesterUserId açılışta @USERID ve DepartmentId kullanıcının departmanı; WarehouseId değişince LocationId temizlenir ve konum lookup'ı depoya süzülür (cascade); ProductId değişince UomId üründen dolar; Quantity değişince PlannedQuantity boşsa Quantity'ye eşitlenir; DueDate < RequestDate ise uyarı ve engel. Status ≠ Draft iken başlık alanları salt okunur.

\n\n

9. Kararlar

\n
    \n
  • Belge no biçimi MT-YYYY-00001 (Odoo'daki SRO/ yerine platform numaratörü; İK ekranlarıyla tutarlı).
  • \n
  • \"Şirket\" alanı açılmaz; kiracı kapsamı karşılar.
  • \n
  • (onay) Satınalma onayçısı Adm_T_Approver'a eklenen yeni Onay Yeri PurchaseDesk (Satınalma Masası) satırlarından okunur; departmandan bağımsız, herhangi birinin onayı yeterli.
  • \n
  • (onay) Taslak aşaması için \"Onaya Gönder\" toolbar butonu; buton olmadan akış kayıtta hemen başlar ve Taslak durumu kullanılamaz.
  • \n
  • (onay) Görseldeki \"Kendi Depomda\" ve \"Tüm Depolar\" stok miktarı kolonları üretilmez: uygulamada stok miktarı/hareket tablosu yok (Inv_T_Product yalnız kart bilgisi taşır). Stok modülü gelince sorgu kolonu olarak eklenecek ayrı talep.
  • \n
  • (onay) Karşılama Şekli seçenekleri: Satınalma / Depodan Transfer.
  • \n
  • Satır durumu (rozet) LineStatus ile; başlık durumu satırlardan türetilir.
  • \n
  • Görseldeki \"Transferler\" akıllı butonu ve teklif toplama süreci bu talebin dışında (teklif/sipariş modülü yok); Planlama Bekleyenler listesi o sürecin giriş noktasıdır.
  • \n
  • Red Nedenleri demo verisi görseldeki 5 satır (SortOrder 1–5, aktif).
  • \n
\n\n

10. Üretim planı

\n
    \n
  1. create_table: Prc_T_RejectReason
  2. \n
  3. create_table: Prc_T_MaterialRequest
  4. \n
  5. create_table: Prc_T_MaterialRequestLine
  6. \n
  7. save_sql_object: Prc_P_MaterialRequestResolveApprovers
  8. \n
  9. deploy_wizard: Adm_Approver.json (PurchaseDesk seçeneği, güncelleme)
  10. \n
  11. deploy_wizard: Prc_RejectReason.json (seed 5 satır)
  12. \n
  13. insert_row: App.Definitions.Sequence — MaterialRequest
  14. \n
  15. deploy_wizard: Prc_MaterialRequestLine.json
  16. \n
  17. deploy_wizard: Prc_MyMaterialRequest.json
  18. \n
  19. deploy_wizard: Prc_MaterialRequestDeptApproval.json
  20. \n
  21. deploy_wizard: Prc_MaterialRequestPurchaseApproval.json
  22. \n
  23. deploy_wizard: Prc_MaterialRequestPlanning.json
  24. \n
  25. deploy_wizard: Prc_MaterialRequest.json
  26. \n
\n\n

11. Üretime hazır

\n

Şartlı — (onay) etiketli 4 karar: Satınalma onaycısı için PurchaseDesk onay yeri, \"Onaya Gönder\" butonuyla Taslak aşaması, stok miktarı kolonlarının (Kendi Depomda / Tüm Depolar) stok modülüne ertelenmesi, Karşılama Şekli seçenekleri.

MCP

\n

Üretilenler: tablolar Prc_T_RejectReason, Prc_T_MaterialRequest, Prc_T_MaterialRequestItem; prosedür Prc_P_MaterialRequestAfterSave (SQL Server + PostgreSQL); numaratör MaterialRequest (MT-{yyyy}-00001, yıllık); ekranlar App.Prc.RejectReason (5 demo satır), menüsüz alt form App.Prc.MaterialRequestLine, App.Prc.MyMaterialRequest, App.Prc.MaterialRequestDeptApproval, App.Prc.MaterialRequestPurchaseApproval, App.Prc.MaterialRequestPlanning, App.Prc.MaterialRequest; Onaycılar'a PurchaseDesk (Satınalma Masası) onay yeri; menü Satınalma › Satınalma Talepleri (yeni ara menü/yetki) ve Satınalma › Tanımlamalar › Red Nedenleri; modül dokümanı App.Prc › Satınalma Talepleri.

\n

Analizden sapmalar / varsayımlar:

\n
    \n
  • Satır tablosu Prc_T_MaterialRequestItem adıyla açıldı: Adm_T_Uom.Id nvarchar olduğu için UomId nvarchar(64) olmalıydı; önce açılan Prc_T_MaterialRequestLine scripti (UomId uniqueidentifier) kullanılmıyor. Migrate'ten önce Wizard Manager / SQL Query Manager'dan bu scripti silmeniz önerilir (onayınız olmadan tablo düşürülmedi).
  • \n
  • Platform akışı onaylayanı kullanıcı adı (metin) olarak yazıyor; ApproverId uniqueidentifier olduğu için akışa bağlanmadı. Departman/Satınalma onaylayanı, tarihi ve notu prosedürde kaydı son güncelleyen kullanıcıdan ve akışın ApprovalDate/ApprovalNote alanlarından kopyalanır.
  • \n
  • Prosedür adı planda Prc_P_MaterialRequestResolveApprovers idi; onaycı çözümü + durum senkronu tek prosedürde: Prc_P_MaterialRequestAfterSave.
  • \n
  • \"Onaya Gönder\" ayrı buton olarak yazılmadı; akışın Start düğümü (platformun Onaya Gönder işlemi) kullanılır. İşlemde / Kısmi Tamamlandı / Tamamlandı satır durumlarından türetilir (ayrı satır butonu yok). Todo (kanban) görünümü eklenmedi.
  • \n
  • Onay listeleri ApprovalStatus (akış düğüm başlığı) ile süzülür; Status kayıt/satır kaydı sonrası prosedürle güncellenir. Akış onayı kayıt güncelleme komutunu tetiklemezse Status ve onaylayan bilgileri bir sonraki kayıtta güncellenir.
  • \n
  • Red nedeni zorunluluğu sunucuda zorlanmadı; alan onay listelerinde düzenlenebilir.
  • \n
\n

DB Migrate bekleyen wizard'lar: Adm_Approver.json, Prc_RejectReason.json, Prc_MaterialRequestLine.json, Prc_MyMaterialRequest.json, Prc_MaterialRequestDeptApproval.json, Prc_MaterialRequestPurchaseApproval.json, Prc_MaterialRequestPlanning.json, Prc_MaterialRequest.json.

" } ] } diff --git a/configs/seeds/data/App.DevRequests/fc6d0fbb-6b04-4d15-9d27-fec98e5c30fb.json b/configs/seeds/data/App.DevRequests/fc6d0fbb-6b04-4d15-9d27-fec98e5c30fb.json index 3900ae21..04f2e14e 100644 --- a/configs/seeds/data/App.DevRequests/fc6d0fbb-6b04-4d15-9d27-fec98e5c30fb.json +++ b/configs/seeds/data/App.DevRequests/fc6d0fbb-6b04-4d15-9d27-fec98e5c30fb.json @@ -20,7 +20,7 @@ "SortOrder": 10, "Timesheets": "[{\"id\":\"5eeb942f-071a-75e0-1ad6-3a243219320c\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Talep analiz edildi\",\"duration\":0.0167},{\"id\":\"d0e49c7b-da82-481c-85d2-3a24321c8660\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Adm_T_Approver tablosu olu\\u015Fturuldu\",\"duration\":0.0167},{\"id\":\"7ff88954-171a-2ee9-ec8f-3a24321d0f63\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Approver.json wizard\\u0027\\u0131 deploy edildi (0 demo sat\\u0131r)\",\"duration\":0.0167},{\"id\":\"48a59c85-5eda-5991-4e53-3a24321db3f3\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"App.Administration mod\\u00FCl dok\\u00FCman\\u0131 kaydedildi\",\"duration\":0.0167},{\"id\":\"bab3c506-9ad8-d234-5572-3a24321dbcf4\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"2 tamamlanm\\u0131\\u015F alt g\\u00F6rev eklendi\",\"duration\":0.0167},{\"id\":\"09e17f9b-4670-e7b3-d5d1-3a24321dcee3\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"Analize \\u00FCretim notu eklendi\",\"duration\":0.0167},{\"id\":\"3279c17a-42fe-0dfd-e46a-3a24321dd838\",\"date\":\"2026-10-09\",\"userName\":\"system@sozsoft.com\",\"description\":\"App.DevRequests ekran\\u0131nda sat\\u0131r g\\u00FCncellendi (Status)\",\"duration\":0.0167}]", "SubTasks": "[{\"id\":\"ef29af4c-7249-7197-d021-3a24321dbcea\",\"title\":\"create_table: Adm_T_Approver\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true},{\"id\":\"b3f03b7c-60cb-97a7-f2f6-3a24321dbcea\",\"title\":\"deploy_wizard: Approver.json\",\"assignee\":\"system@sozsoft.com\",\"dueDate\":\"2026-10-09\",\"completed\":true}]", - "Analysis": "

Amaç

\n

Uygulamadaki tüm onay adımlarının onaycılarını tek listede toplamak: hangi departmanın hangi onay yerinde (Satınalma, Depo …) kimin onaylayacağı. İlk kullanıcısı Satınalma modülüdür (Malzeme Talepleri departman onayı); yöneticiler ve sistem sorumluları tanımlar.

\n\n

Çözüm yolu

\n

Tek Wizard List ekranı (tablo kaynaklı, popup düzenleme). Akışlar onaycıyı bu tablodan kayıt sonrası prosedürle okur ve @Kolon onaycısı olarak kullanır (§4.7); bu ekranın kendisinde iş akışı yoktur. Bu yapı, platform tablosu Hr_T_Department'a kolon eklemeyi gereksiz kılar.

\n\n

Menü yeri

\n

Yönetim › Tanımlamalar › Onaycılar

\n\n\n\n\n\n
SeviyeKodAd (TR / EN)İkonDurum
KökApp.AdministrationYönetim / Administration—Var
AraApp.Administration.DefinitionsTanımlamalar / Definitions—Var
EkranApp.Definitions.ApproverOnaycılar / ApproversFcApprovalYeni
\n

ModuleId: Adm · İzin grubu: App.Administration · Route: /admin/list/App.Definitions.Approver

\n

Yetki: App.Administration › App.Administration.Definitions (Var) › App.Definitions.Approver (Yeni)

\n\n

Veri modeli

\n

Adm_T_Approver — yeni, tenant + audit + soft delete. Tanım tablosu: Evet (onay akışlarının onaycı kaynağı).

\n\n\n\n\n\n\n
KolonTipZorunluNot
DepartmentIduniqueidentifier✓→ Hr_T_Department; listede \"Şube / Departman\" adı
ApprovalAreanvarchar(32)✓Purchase / Warehouse / HumanResources / Finance (Satınalma / Depo / İnsan Kaynakları / Finans); DEFAULT 'Purchase'
ApproverUserIduniqueidentifier✓→ AbpUsers (aktif)
IsActivebit✓DEFAULT 1
\n

Tekil kısıt: TenantId + DepartmentId + ApprovalArea + ApproverUserId. Aynı departman ve onay yerine birden çok onaycı girilebilir; akış bunları | ile birleştirip herhangi birinin onayını kabul eder.

\n\n

Etkilenen kısımlar

\n
    \n
  • 1 yeni tablo, 1 yeni ekran, Yönetim › Tanımlamalar menüsünde 1 satır; yetkiler C/R/U/D/E/I/N.
  • \n
  • Dil: ekran adları, alan başlıkları (Departman, Onay Yeri, Onaylayacak Kişi), StaticLookup Purchase/Warehouse/HumanResources/Finance.
  • \n
  • Var olan ekranlara dokunulmaz. \"Satınalma -> Malzeme Talepleri\" talebinin departman onaycısı bu tablodan (ApprovalArea = 'Purchase') okunacaktır; o talebin analizi bu ekrana göre güncellenmelidir (Hr_T_Department kolon ihtiyacı kalkar).
  • \n
\n\n

Görünümler ve davranış

\n
    \n
  • Grid/Card/Pivot/Chart açık, varsayılan grid; liste Onay Yeri ve Departman'a göre gruplanabilir.
  • \n
  • Widget: Toplam / Aktif / Pasif.
  • \n
  • Departman lookup'ı aktif şubelerin departmanlarını \"Şube - Departman\" biçiminde gösterir; Onaylayacak Kişi aktif kullanıcıları ad soyad ile gösterir.
  • \n
  • Pasif satır akışlarda onaycı olarak kullanılmaz.
  • \n
\n\n

Kararlar

\n
    \n
  • Ekran adı \"Onaycılar\", kod App.Definitions.Approver, tablo Adm_T_Approver — Yönetim tanımlarının kod/önek ailesi. Talep başlığı \"Satınalma Onaycıları\" olsa da açıklama tüm onayların burada toplanacağını söylüyor.
  • \n
  • Onay Yeri seçenekleri (onay): Satınalma, Depo, İnsan Kaynakları, Finans. Yeni yer eklemek seçenek listesine satır eklemektir.
  • \n
  • Şube kolonu tutulmaz; şube departmandan gelir.
  • \n
  • Demo veri yazılmaz (departman ve kullanıcı Id'leri kiracıya özgü).
  • \n
\n\n

Üretim planı

\n
    \n
  1. create_table: Adm_T_Approver
  2. \n
  3. deploy_wizard: Approver.json
  4. \n
\n\n

Üretime hazır

\n

Evet

MCP

\n
    \n
  • Tablo: Adm_T_Approver (DepartmentId FK → Hr_T_Department, ApprovalArea DEFAULT 'Purchase', ApproverUserId, IsActive DEFAULT 1); tekil TenantId+DepartmentId+ApprovalArea+ApproverUserId. Kiracı + tam audit.
  • \n
  • Ekran: App.Definitions.Approver (grid, IsTenant), Toplam/Aktif/Pasif widget'ı.
  • \n
  • Menü/yetki: Yönetim › Tanımlamalar (sıra 6); App.Administration › App.Administration.Definitions › App.Definitions.Approver + C/U/D/E/I/N.
  • \n
  • Dil: App.StaticLookup.Purchase/Warehouse/HumanResources/Finance (EN+TR).
  • \n
  • Demo veri: yok.
  • \n
  • Analize eklenen varsayılanlar: yok.
  • \n
  • DB Migrate bekleyen wizard: Approver.json.
  • \n
" + "Analysis": "

Amaç

\n

Uygulamadaki tüm onay adımlarının onaycılarını tek listede toplamak: hangi departmanın hangi onay yerinde (Satınalma, Depo …) kimin onaylayacağı. İlk kullanıcısı Satınalma modülüdür (Satınalma Talepleri departman onayı); yöneticiler ve sistem sorumluları tanımlar.

\n\n

Çözüm yolu

\n

Tek Wizard List ekranı (tablo kaynaklı, popup düzenleme). Akışlar onaycıyı bu tablodan kayıt sonrası prosedürle okur ve @Kolon onaycısı olarak kullanır (§4.7); bu ekranın kendisinde iş akışı yoktur. Bu yapı, platform tablosu Hr_T_Department'a kolon eklemeyi gereksiz kılar.

\n\n

Menü yeri

\n

Yönetim › Tanımlamalar › Onaycılar

\n\n\n\n\n\n
SeviyeKodAd (TR / EN)İkonDurum
KökApp.AdministrationYönetim / Administration—Var
AraApp.Administration.DefinitionsTanımlamalar / Definitions—Var
EkranApp.Definitions.ApproverOnaycılar / ApproversFcApprovalYeni
\n

ModuleId: Adm · İzin grubu: App.Administration · Route: /admin/list/App.Definitions.Approver

\n

Yetki: App.Administration › App.Administration.Definitions (Var) › App.Definitions.Approver (Yeni)

\n\n

Veri modeli

\n

Adm_T_Approver — yeni, tenant + audit + soft delete. Tanım tablosu: Evet (onay akışlarının onaycı kaynağı).

\n\n\n\n\n\n\n
KolonTipZorunluNot
DepartmentIduniqueidentifier✓→ Hr_T_Department; listede \"Şube / Departman\" adı
ApprovalAreanvarchar(32)✓Purchase / Warehouse / HumanResources / Finance (Satınalma / Depo / İnsan Kaynakları / Finans); DEFAULT 'Purchase'
ApproverUserIduniqueidentifier✓→ AbpUsers (aktif)
IsActivebit✓DEFAULT 1
\n

Tekil kısıt: TenantId + DepartmentId + ApprovalArea + ApproverUserId. Aynı departman ve onay yerine birden çok onaycı girilebilir; akış bunları | ile birleştirip herhangi birinin onayını kabul eder.

\n\n

Etkilenen kısımlar

\n
    \n
  • 1 yeni tablo, 1 yeni ekran, Yönetim › Tanımlamalar menüsünde 1 satır; yetkiler C/R/U/D/E/I/N.
  • \n
  • Dil: ekran adları, alan başlıkları (Departman, Onay Yeri, Onaylayacak Kişi), StaticLookup Purchase/Warehouse/HumanResources/Finance.
  • \n
  • Var olan ekranlara dokunulmaz. \"Satınalma -> Satınalma Talepleri\" talebinin departman onaycısı bu tablodan (ApprovalArea = 'Purchase') okunacaktır; o talebin analizi bu ekrana göre güncellenmelidir (Hr_T_Department kolon ihtiyacı kalkar).
  • \n
\n\n

Görünümler ve davranış

\n
    \n
  • Grid/Card/Pivot/Chart açık, varsayılan grid; liste Onay Yeri ve Departman'a göre gruplanabilir.
  • \n
  • Widget: Toplam / Aktif / Pasif.
  • \n
  • Departman lookup'ı aktif şubelerin departmanlarını \"Şube - Departman\" biçiminde gösterir; Onaylayacak Kişi aktif kullanıcıları ad soyad ile gösterir.
  • \n
  • Pasif satır akışlarda onaycı olarak kullanılmaz.
  • \n
\n\n

Kararlar

\n
    \n
  • Ekran adı \"Onaycılar\", kod App.Definitions.Approver, tablo Adm_T_Approver — Yönetim tanımlarının kod/önek ailesi. Talep başlığı \"Satınalma Onaycıları\" olsa da açıklama tüm onayların burada toplanacağını söylüyor.
  • \n
  • Onay Yeri seçenekleri (onay): Satınalma, Depo, İnsan Kaynakları, Finans. Yeni yer eklemek seçenek listesine satır eklemektir.
  • \n
  • Şube kolonu tutulmaz; şube departmandan gelir.
  • \n
  • Demo veri yazılmaz (departman ve kullanıcı Id'leri kiracıya özgü).
  • \n
\n\n

Üretim planı

\n
    \n
  1. create_table: Adm_T_Approver
  2. \n
  3. deploy_wizard: Approver.json
  4. \n
\n\n

Üretime hazır

\n

Evet

MCP

\n
    \n
  • Tablo: Adm_T_Approver (DepartmentId FK → Hr_T_Department, ApprovalArea DEFAULT 'Purchase', ApproverUserId, IsActive DEFAULT 1); tekil TenantId+DepartmentId+ApprovalArea+ApproverUserId. Kiracı + tam audit.
  • \n
  • Ekran: App.Definitions.Approver (grid, IsTenant), Toplam/Aktif/Pasif widget'ı.
  • \n
  • Menü/yetki: Yönetim › Tanımlamalar (sıra 6); App.Administration › App.Administration.Definitions › App.Definitions.Approver + C/U/D/E/I/N.
  • \n
  • Dil: App.StaticLookup.Purchase/Warehouse/HumanResources/Finance (EN+TR).
  • \n
  • Demo veri: yok.
  • \n
  • Analize eklenen varsayılanlar: yok.
  • \n
  • DB Migrate bekleyen wizard: Approver.json.
  • \n
" } ] } diff --git a/configs/seeds/data/App.Languages.LanguageText.json b/configs/seeds/data/App.Languages.LanguageText.json index 25748040..4f8cefed 100644 --- a/configs/seeds/data/App.Languages.LanguageText.json +++ b/configs/seeds/data/App.Languages.LanguageText.json @@ -3782,7 +3782,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Menus.Menu", - "Value": "Menü Listesi" + "Value": "Menüler" }, { "Id": "3dbc4dc8-6662-59b0-a03b-a83320599d9b", @@ -92976,7 +92976,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Definitions.Approver.Desc", - "Value": "Onaycılar — uygulamadaki tüm onay adımlarında her departman için kimin onaylayacağını tutan tek liste.\nNerede: Yönetim › Tanımlamalar › Onaycılar.\nAlanlar: departman (Şube - Departman olarak gösterilir), onay yeri (Satınalma / Satınalma Masası / Depo / İnsan Kaynakları / Finans), onaylayacak kişi, aktif.\nKullanıldığı yer: onay akışları kaydın departmanı ve onay yerine göre onaycıları buradan okur. Satınalma › Malzeme Talepleri: departman onayı talep edenin departmanındaki Satınalma satırlarını, satınalma onayı ise Satınalma Masası satırlarını (departmandan bağımsız) kullanır. Aynı departman ve onay yerine birden çok onaycı girilebilir; herhangi birinin onayı yeterlidir. Pasif satırlar akışlarda kullanılmaz." + "Value": "Onaycılar — uygulamadaki tüm onay adımlarında her departman için kimin onaylayacağını tutan tek liste.\nNerede: Yönetim › Tanımlamalar › Onaycılar.\nAlanlar: departman (Şube - Departman olarak gösterilir), onay yeri (Satınalma / Satınalma Masası / Depo / İnsan Kaynakları / Finans), onaylayacak kişi, aktif.\nKullanıldığı yer: onay akışları kaydın departmanı ve onay yerine göre onaycıları buradan okur. Satınalma › Satınalma Talepleri: departman onayı talep edenin departmanındaki Satınalma satırlarını, satınalma onayı ise Satınalma Masası satırlarını (departmandan bağımsız) kullanır. Aynı departman ve onay yerine birden çok onaycı girilebilir; herhangi birinin onayı yeterlidir. Pasif satırlar akışlarda kullanılmaz." }, { "Id": "cd7ff644-eefa-516e-8c8c-8b4fa0ec76f8", @@ -93116,7 +93116,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.RejectReason.Desc", - "Value": "Red Nedenleri — satınalma taleplerinin reddedilme sebepleri (ihtiyaç yok, miktar uygun değil, yanlış ürün, bütçe uygun değil, diğer).\nNerede: Satınalma › Tanımlamalar › Red Nedenleri.\nAlanlar: red nedeni, sıra (seçim listesindeki sırası), aktif.\nKullanıldığı yer: Satınalma › Malzeme Talepleri — departman onaycısı ya da satınalma talebi reddederken neden seçer. Yalnız aktif nedenler listelenir; kullanılmış neden silinmez, pasife alınır." + "Value": "Red Nedenleri — satınalma taleplerinin reddedilme sebepleri (ihtiyaç yok, miktar uygun değil, yanlış ürün, bütçe uygun değil, diğer).\nNerede: Satınalma › Tanımlamalar › Red Nedenleri.\nAlanlar: red nedeni, sıra (seçim listesindeki sırası), aktif.\nKullanıldığı yer: Satınalma › Satınalma Talepleri — departman onaycısı ya da satınalma talebi reddederken neden seçer. Yalnız aktif nedenler listelenir; kullanılmış neden silinmez, pasife alınır." }, { "Id": "31115331-7e79-54e9-ae55-a2e682571c43", @@ -93172,7 +93172,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.MaterialRequestLine.Desc", - "Value": "Talep Satırları — malzeme talebinde istenen ürünler.\nNerede: Satınalma › Malzeme Talepleri › herhangi bir liste › Talep Satırları sekmesi (kendi menüsü yoktur).\nAlanlar: ürün (aktif ve satın alınabilir ürünler), miktar, birim (ürünün satınalma biriminden gelir, salt okunur), karşılama şekli (Satınalma / Depodan Transfer), termin tarihi, talep nedeni, teslim edilen miktar (salt okunur), planlanacak miktar (boşsa miktar), satınalma sorumlusu, satır durumu (Bekliyor / Planlandı / Tamamlandı / İptal).\nKurallar: satır yalnız talep onaya gönderilmeden eklenip silinebilir. Satır durumları değişince talebin durumu yeniden hesaplanır (İşlemde / Kısmi Tamamlandı / Tamamlandı)." + "Value": "Talep Satırları — malzeme talebinde istenen ürünler.\nNerede: Satınalma › Satınalma Talepleri › herhangi bir liste › Talep Satırları sekmesi (kendi menüsü yoktur).\nAlanlar: ürün (aktif ve satın alınabilir ürünler), miktar, birim (ürünün satınalma biriminden gelir, salt okunur), karşılama şekli (Satınalma / Depodan Transfer), termin tarihi, talep nedeni, teslim edilen miktar (salt okunur), planlanacak miktar (boşsa miktar), satınalma sorumlusu, satır durumu (Bekliyor / Planlandı / Tamamlandı / İptal).\nKurallar: satır yalnız talep onaya gönderilmeden eklenip silinebilir. Satır durumları değişince talebin durumu yeniden hesaplanır (İşlemde / Kısmi Tamamlandı / Tamamlandı)." }, { "Id": "d6911bd6-3f4a-582d-8328-e01403808802", @@ -93368,7 +93368,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.MyMaterialRequest.Desc", - "Value": "Taleplerim — açtığınız malzeme talepleri, tüm durumlarıyla.\nNerede: Satınalma › Malzeme Talepleri › Taleplerim.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden (siz), departman (varsayılan olarak sizin departmanınız), malın konulacağı depo ve konum, talep tarihi, durum, genel açıklama; Talep Satırları sekmesi: ürün, miktar, birim, karşılama şekli, termin tarihi, talep nedeni.\nAkış: satırları girip onaya gönderin — önce departman onaycısı (Onaycılar › departmanınız için Satınalma onay yeri), ardından satınalma (Satınalma Masası onay yeri) onaylar ya da reddeder. Satırlar yalnız onaya göndermeden önce eklenip silinebilir. Onay / red bilgileri onay grubunda görünür.\nİlişkili: Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler." + "Value": "Taleplerim — açtığınız malzeme talepleri, tüm durumlarıyla.\nNerede: Satınalma › Satınalma Talepleri › Taleplerim.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden (siz), departman (varsayılan olarak sizin departmanınız), malın konulacağı depo ve konum, talep tarihi, durum, genel açıklama; Talep Satırları sekmesi: ürün, miktar, birim, karşılama şekli, termin tarihi, talep nedeni.\nAkış: satırları girip onaya gönderin — önce departman onaycısı (Onaycılar › departmanınız için Satınalma onay yeri), ardından satınalma (Satınalma Masası onay yeri) onaylar ya da reddeder. Satırlar yalnız onaya göndermeden önce eklenip silinebilir. Onay / red bilgileri onay grubunda görünür.\nİlişkili: Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler." }, { "Id": "ce3d734c-f508-5647-8f8d-2bf6b056c79a", @@ -93578,7 +93578,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.MaterialRequests", - "Value": "Malzeme Talepleri" + "Value": "Satınalma Talepleri" }, { "Id": "cf76b42b-82ed-5838-9fb2-30b0c8caf3e5", @@ -93816,7 +93816,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.MaterialRequestDeptApproval.Desc", - "Value": "Departman Onayı Bekleyenler — departman onaycısının kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Malzeme Talepleri › Departman Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da talep edenin departmanı için Satınalma onay yerinde tanımlı onaycılar; her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi açıp Talep Satırları sekmesini inceleyin, ardından Onayla (talep satınalma onayına geçer) ya da not ve red nedeniyle (Satınalma › Tanımlamalar › Red Nedenleri) Reddet. Burada satır eklenip silinemez.\nİlişkili: Taleplerim, Satınalma Onayı Bekleyenler, Tüm Talepler." + "Value": "Departman Onayı Bekleyenler — departman onaycısının kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Satınalma Talepleri › Departman Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da talep edenin departmanı için Satınalma onay yerinde tanımlı onaycılar; her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi açıp Talep Satırları sekmesini inceleyin, ardından Onayla (talep satınalma onayına geçer) ya da not ve red nedeniyle (Satınalma › Tanımlamalar › Red Nedenleri) Reddet. Burada satır eklenip silinemez.\nİlişkili: Taleplerim, Satınalma Onayı Bekleyenler, Tüm Talepler." }, { "Id": "1c9a636f-fdfa-50bf-b3a4-874deed5dad1", @@ -93858,7 +93858,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.MaterialRequestPurchaseApproval.Desc", - "Value": "Satınalma Onayı Bekleyenler — departmanca onaylanmış ve satınalmanın kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Malzeme Talepleri › Satınalma Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da Satınalma Masası onay yerinde tanımlı onaycılar (departmandan bağımsız); her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi ve satırlarını inceleyip Onayla (talep Onaylandı olur, Planlama Bekleyenler'e düşer, talep edene bilgi gider) ya da not ve red nedeniyle Reddet.\nİlişkili: Departman Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler." + "Value": "Satınalma Onayı Bekleyenler — departmanca onaylanmış ve satınalmanın kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Satınalma Talepleri › Satınalma Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da Satınalma Masası onay yerinde tanımlı onaycılar (departmandan bağımsız); her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi ve satırlarını inceleyip Onayla (talep Onaylandı olur, Planlama Bekleyenler'e düşer, talep edene bilgi gider) ya da not ve red nedeniyle Reddet.\nİlişkili: Departman Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler." }, { "Id": "9e5e455f-ecc8-5066-8fb4-63884166647d", @@ -93900,7 +93900,7 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.MaterialRequestPlanning.Desc", - "Value": "Planlama Bekleyenler — onaylanmış ve satırları henüz tamamlanmamış malzeme talepleri; satınalma ekibinin iş listesi.\nNerede: Satınalma › Malzeme Talepleri › Planlama Bekleyenler.\nNe yapılır: talebi açıp Talep Satırları sekmesinde satınalma sorumlusunu, planlanacak miktarı ve satır durumunu (Bekliyor / Planlandı / Tamamlandı / İptal) girin. Talebin durumu satırları izler: bir satır Planlandı → İşlemde, satırların bir kısmı Tamamlandı → Kısmi Tamamlandı, tüm satırlar Tamamlandı ya da İptal → Tamamlandı (talep bu listeden çıkar). Teklif toplama sürecinin giriş noktasıdır.\nİlişkili: Satınalma Onayı Bekleyenler, Tüm Talepler." + "Value": "Planlama Bekleyenler — onaylanmış ve satırları henüz tamamlanmamış malzeme talepleri; satınalma ekibinin iş listesi.\nNerede: Satınalma › Satınalma Talepleri › Planlama Bekleyenler.\nNe yapılır: talebi açıp Talep Satırları sekmesinde satınalma sorumlusunu, planlanacak miktarı ve satır durumunu (Bekliyor / Planlandı / Tamamlandı / İptal) girin. Talebin durumu satırları izler: bir satır Planlandı → İşlemde, satırların bir kısmı Tamamlandı → Kısmi Tamamlandı, tüm satırlar Tamamlandı ya da İptal → Tamamlandı (talep bu listeden çıkar). Teklif toplama sürecinin giriş noktasıdır.\nİlişkili: Satınalma Onayı Bekleyenler, Tüm Talepler." }, { "Id": "04e8c193-a841-520d-b338-0d4a73ca066b", @@ -93942,7 +93942,49 @@ "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Prc.MaterialRequest.Desc", - "Value": "Tüm Talepler — kurumun bütün malzeme talepleri, tüm durumlarıyla; satınalma yönetiminin listesi.\nNerede: Satınalma › Malzeme Talepleri › Tüm Talepler.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden, departman, depo ve konum, talep tarihi, durum (Taslak › Departman Onayı › Satınalma Onayı › Onaylandı › İşlemde › Kısmi Tamamlandı › Tamamlandı ya da Reddedildi), onay durumu, red nedeni, genel açıklama; onay grubu: departman onaycıları, departman / satınalma onaylayanı, tarihi ve notu; Talep Satırları sekmesi.\nAkış: Grid Workflow — departman onaycısı (Onaycılar › talebin departmanı için Satınalma onay yeri) → satınalma (Satınalma Masası onay yeri) → Onaylandı / Reddedildi; talep edene bilgi gider. Onay sonrası durum satır durumlarını izler.\nİlişkili: Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Satınalma › Tanımlamalar › Red Nedenleri." + "Value": "Tüm Talepler — kurumun bütün malzeme talepleri, tüm durumlarıyla; satınalma yönetiminin listesi.\nNerede: Satınalma › Satınalma Talepleri › Tüm Talepler.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden, departman, depo ve konum, talep tarihi, durum (Taslak › Departman Onayı › Satınalma Onayı › Onaylandı › İşlemde › Kısmi Tamamlandı › Tamamlandı ya da Reddedildi), onay durumu, red nedeni, genel açıklama; onay grubu: departman onaycıları, departman / satınalma onaylayanı, tarihi ve notu; Talep Satırları sekmesi.\nAkış: Grid Workflow — departman onaycısı (Onaycılar › talebin departmanı için Satınalma onay yeri) → satınalma (Satınalma Masası onay yeri) → Onaylandı / Reddedildi; talep edene bilgi gider. Onay sonrası durum satır durumlarını izler.\nİlişkili: Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Satınalma › Tanımlamalar › Red Nedenleri." + }, + { + "Id": "3d2aa673-6148-5445-9fb8-c260913a910f", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.Definitions.ApplicationSuite", + "Value": "Applications" + }, + { + "Id": "7fd9d184-04c4-58cb-b602-78149c395bf2", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.Definitions.ApplicationSuite", + "Value": "Uygulamalar" + }, + { + "Id": "56d2d143-77ab-535e-a3f0-e0782ad519a4", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.Definitions.ApplicationSuite.Description", + "Value": "Module packages offered to tenants. Saas › Definitions › Applications.\nEach suite has a unique name and a module list selected from the platform modules (multi-select).\nWhen a tenant is created from Public › Sales Orders (Tenant command), the selected suite fills the modules automatically; the modules can still be changed in the dialog.\nOnly active suites are offered in the dialog." + }, + { + "Id": "bb2a8a13-ee34-5952-8011-e819c6084275", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.Definitions.ApplicationSuite.Description", + "Value": "Kiracılara sunulan modül paketleri. Saas › Tanımlamalar › Uygulamalar.\nHer paketin benzersiz bir adı ve platform modüllerinden çoklu seçilen modül listesi vardır.\nPublic › Satış Siparişleri ekranındaki Kiracı komutuyla kiracı oluşturulurken seçilen paket modülleri otomatik doldurur; modüller diyalogda yine değiştirilebilir.\nDiyalogda yalnızca aktif paketler listelenir." + }, + { + "Id": "9838a893-5f2d-52e8-b327-a87981975711", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.Tenant.Name", + "Value": "Tenant Name" + }, + { + "Id": "a3150b09-e4c7-5387-8cb0-b43929ae3f30", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.Tenant.Name", + "Value": "Kiracı Adı" } ] } diff --git a/configs/seeds/data/App.Menus.Menu.json b/configs/seeds/data/App.Menus.Menu.json index 2af00d24..19f8d5d4 100644 --- a/configs/seeds/data/App.Menus.Menu.json +++ b/configs/seeds/data/App.Menus.Menu.json @@ -259,6 +259,21 @@ "ElementId": null, "ModuleId": "Sas" }, + { + "Id": "6bbbe0ea-fb60-56ed-baef-7b9af0b6e784", + "Code": "App.Definitions.ApplicationSuite", + "DisplayName": "App.Definitions.ApplicationSuite", + "Order": 10, + "Url": "/admin/list/App.Definitions.ApplicationSuite", + "Icon": "FcPackage", + "ParentCode": "App.Saas.Definitions", + "RequiredPermissionName": "App.Definitions.ApplicationSuite", + "CssClass": null, + "Target": null, + "IsDisabled": false, + "ElementId": null, + "ModuleId": "Sas" + }, { "Id": "f1effbfd-7fec-5056-845c-6223010eb2d6", "Code": "App.Definitions.TerminationReason", @@ -578,10 +593,10 @@ "Id": "49faddb1-274f-40a7-bfa1-403d97c7925e", "Code": "App.Menus.Module", "DisplayName": "App.Menus.Module", - "Order": 1, + "Order": 9, "Url": "/admin/list/App.Menus.Module", "Icon": "FcGrid", - "ParentCode": "App.Menus", + "ParentCode": "App.Saas.Definitions", "RequiredPermissionName": "App.Menus.Module", "CssClass": null, "Target": null, @@ -593,7 +608,7 @@ "Id": "8b3fd17d-beba-4bec-ba6a-a3df93f3f5f7", "Code": "App.Menus.Routes", "DisplayName": "App.Menus.Routes", - "Order": 2, + "Order": 1, "Url": "/admin/list/App.Menus.Routes", "Icon": "FcMultipleInputs", "ParentCode": "App.Menus", @@ -608,7 +623,7 @@ "Id": "00d732b9-032b-4525-bab2-1663edfd56b2", "Code": "App.Menus.Menu", "DisplayName": "App.Menus.Menu", - "Order": 3, + "Order": 2, "Url": "/admin/list/App.Menus.Menu", "Icon": "FcMenu", "ParentCode": "App.Menus", @@ -623,7 +638,7 @@ "Id": "07488e92-3067-459a-ae58-37a959912784", "Code": "App.Menus.Manager", "DisplayName": "App.Menus.Manager", - "Order": 4, + "Order": 3, "Url": "/admin/menuManager", "Icon": "FaRegListAlt", "ParentCode": "App.Menus", @@ -2765,124 +2780,168 @@ "ModuleId": "Prj" }, { - "ParentCode": "App.Inventory.Definitions", + "Id": "5bc3d7e4-ad9a-49be-945d-0f92a4035acc", "Code": "App.Inventory.Warehouse", "DisplayName": "App.Inventory.Warehouse", "Order": 7, "Url": "/admin/list/App.Inventory.Warehouse", "Icon": "FcHome", + "ParentCode": "App.Inventory.Definitions", "RequiredPermissionName": "App.Inventory.Warehouse", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Inventory" }, { - "ParentCode": "App.Inventory.Definitions", + "Id": "e0e71cb4-720a-4365-8680-bf3a0b95440f", "Code": "App.Inventory.Location", "DisplayName": "App.Inventory.Location", "Order": 8, "Url": "/admin/list/App.Inventory.Location", "Icon": "FcTreeStructure", + "ParentCode": "App.Inventory.Definitions", "RequiredPermissionName": "App.Inventory.Location", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Inventory" }, { - "ParentCode": "App.Inventory.Definitions", + "Id": "25a6a7b3-eea6-42fc-bbaa-e56920f26cb4", "Code": "App.Inventory.OperationType", "DisplayName": "App.Inventory.OperationType", "Order": 9, "Url": "/admin/list/App.Inventory.OperationType", "Icon": "FcProcess", + "ParentCode": "App.Inventory.Definitions", "RequiredPermissionName": "App.Inventory.OperationType", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Inventory" }, { - "ParentCode": "App.Administration.Definitions", + "Id": "db640151-75a3-435d-a806-784c7cfcfe2d", "Code": "App.Definitions.Approver", "DisplayName": "App.Definitions.Approver", "Order": 6, "Url": "/admin/list/App.Definitions.Approver", "Icon": "FcApproval", + "ParentCode": "App.Administration.Definitions", "RequiredPermissionName": "App.Definitions.Approver", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Adm" }, { - "ParentCode": "App.Prc.Definitions", + "Id": "4386ea81-1cec-4002-8a8b-d95b1690de90", "Code": "App.Prc.RejectReason", "DisplayName": "App.Prc.RejectReason", "Order": 5, "Url": "/admin/list/App.Prc.RejectReason", "Icon": "FcCancel", + "ParentCode": "App.Prc.Definitions", "RequiredPermissionName": "App.Prc.RejectReason", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Prc" }, { - "ParentCode": "App.Prc", + "Id": "b9c609a2-b30d-4b63-835c-58e9d4cdda5f", "Code": "App.Prc.MaterialRequests", "DisplayName": "App.Prc.MaterialRequests", "Order": 2, "Url": null, "Icon": "FcList", + "ParentCode": "App.Prc", "RequiredPermissionName": null, + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Prc" }, { - "ParentCode": "App.Prc.MaterialRequests", + "Id": "14e5c127-6c82-40ff-8fd0-841f1a15bfa5", "Code": "App.Prc.MyMaterialRequest", "DisplayName": "App.Prc.MyMaterialRequest", "Order": 1, "Url": "/admin/list/App.Prc.MyMaterialRequest", "Icon": "FcPortraitMode", + "ParentCode": "App.Prc.MaterialRequests", "RequiredPermissionName": "App.Prc.MyMaterialRequest", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Prc" }, { - "ParentCode": "App.Prc.MaterialRequests", + "Id": "3e06da59-736e-4c8c-b68a-f554ca278670", "Code": "App.Prc.MaterialRequestDeptApproval", "DisplayName": "App.Prc.MaterialRequestDeptApproval", "Order": 2, "Url": "/admin/list/App.Prc.MaterialRequestDeptApproval", "Icon": "FcApproval", + "ParentCode": "App.Prc.MaterialRequests", "RequiredPermissionName": "App.Prc.MaterialRequestDeptApproval", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Prc" }, { - "ParentCode": "App.Prc.MaterialRequests", + "Id": "4a672706-d675-4a2a-904f-da7dab8b3843", "Code": "App.Prc.MaterialRequestPurchaseApproval", "DisplayName": "App.Prc.MaterialRequestPurchaseApproval", "Order": 3, "Url": "/admin/list/App.Prc.MaterialRequestPurchaseApproval", "Icon": "FcApproval", + "ParentCode": "App.Prc.MaterialRequests", "RequiredPermissionName": "App.Prc.MaterialRequestPurchaseApproval", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Prc" }, { - "ParentCode": "App.Prc.MaterialRequests", + "Id": "893db5a1-88bb-4116-be3c-54ffb800b61c", "Code": "App.Prc.MaterialRequestPlanning", "DisplayName": "App.Prc.MaterialRequestPlanning", "Order": 4, "Url": "/admin/list/App.Prc.MaterialRequestPlanning", "Icon": "FcPlanner", + "ParentCode": "App.Prc.MaterialRequests", "RequiredPermissionName": "App.Prc.MaterialRequestPlanning", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Prc" }, { - "ParentCode": "App.Prc.MaterialRequests", + "Id": "99ab4ed0-b594-4492-817e-a091fb7c3080", "Code": "App.Prc.MaterialRequest", "DisplayName": "App.Prc.MaterialRequest", "Order": 5, "Url": "/admin/list/App.Prc.MaterialRequest", "Icon": "FcDocument", + "ParentCode": "App.Prc.MaterialRequests", "RequiredPermissionName": "App.Prc.MaterialRequest", + "CssClass": null, + "Target": null, "IsDisabled": false, + "ElementId": null, "ModuleId": "Prc" } ] diff --git a/configs/seeds/docs/modules/App.Administration.md b/configs/seeds/docs/modules/App.Administration.md index 4809046c..ff33176f 100644 --- a/configs/seeds/docs/modules/App.Administration.md +++ b/configs/seeds/docs/modules/App.Administration.md @@ -72,7 +72,7 @@ Yetki ağacı: `App.Administration` grubu › `App.Administration.Definitions` ### 7. Entegrasyonlar -Dış entegrasyon yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar, Departmanlar, Şubeler ve Satınalma tanımları yalnızca okunur. Onaycılar'ı Satınalma › Malzeme Talepleri departman onayı (`ApprovalArea = 'Purchase'`) okuyacaktır; diğer onay yerleri ilgili modüllerin akışları için hazırdır. +Dış entegrasyon yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar, Departmanlar, Şubeler ve Satınalma tanımları yalnızca okunur. Onaycılar'ı Satınalma › Satınalma Talepleri departman onayı (`ApprovalArea = 'Purchase'`) okuyacaktır; diğer onay yerleri ilgili modüllerin akışları için hazırdır. ### 8. Akış örneği @@ -178,7 +178,7 @@ Dış entegrasyon yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıc | Menü | `App.Administration.Definitions` › `App.Definitions.Approver` (sıra 6) | | Yetki | `App.Definitions.Approver` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Onaycılar — uygulamadaki tüm onay adımlarında her departman için kimin onaylayacağını tutan tek liste. | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Adm_T_Approver` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | diff --git a/configs/seeds/docs/modules/App.Prc.md b/configs/seeds/docs/modules/App.Prc.md index 55bafc7f..a213272b 100644 --- a/configs/seeds/docs/modules/App.Prc.md +++ b/configs/seeds/docs/modules/App.Prc.md @@ -67,7 +67,7 @@ Yok. Tanımlar Yönetim › Tanımlamalar › Kontaklar'ın Satış ve Satınalm - Geri alma: Kontak sekmeleri bu tanımlara bağlı olduğu için önce kontak tarafındaki seçimler temizlenir; ekranlar `delete_wizard` ile silinir, tablolar yalnızca açık onayla `dropTables: true` ile düşürülür. -## Malzeme Talepleri (`App.Prc.MaterialRequests`) +## Satınalma Talepleri (`App.Prc.MaterialRequests`) ### 1. Amaç ve kapsam @@ -87,7 +87,7 @@ Departmanların iç ve dış ihtiyaç duydukları malzemeleri satınalmaya iletm ### 3. Menü ve ekranlar -Satınalma (`App.Prc`) › Malzeme Talepleri (`App.Prc.MaterialRequests`): +Satınalma (`App.Prc`) › Satınalma Talepleri (`App.Prc.MaterialRequests`): | Ekran | Kod | Filtre / not | | --- | --- | --- | @@ -255,7 +255,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | Menü | `App.Prc.Definitions` › `App.Prc.RejectReason` (sıra 5) | | Yetki | `App.Prc.RejectReason` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Red Nedenleri — satınalma taleplerinin reddedilme sebepleri (ihtiyaç yok, miktar uygun değil, yanlış ürün, bütçe uygun değil, diğer). | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Prc_T_RejectReason` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | @@ -270,7 +270,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | `SortOrder` | Sıra | dxNumberBox | ✓ | ✓ | | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | -### Malzeme Talepleri (`App.Prc.MaterialRequests`) +### Satınalma Talepleri (`App.Prc.MaterialRequests`) #### Taleplerim — `App.Prc.MyMaterialRequest` @@ -281,7 +281,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | Menü | `App.Prc.MaterialRequests` › `App.Prc.MyMaterialRequest` (sıra 1) | | Yetki | `App.Prc.MyMaterialRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Taleplerim — açtığınız malzeme talepleri, tüm durumlarıyla. | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Prc_T_MaterialRequest` · filtre `"IsDeleted" = 'false' AND "RequesterUserId" = '@USERID'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | @@ -326,7 +326,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | Menü | `App.Prc.MaterialRequests` › `App.Prc.MaterialRequestDeptApproval` (sıra 2) | | Yetki | `App.Prc.MaterialRequestDeptApproval` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Departman Onayı Bekleyenler — departman onaycısının kararını bekleyen malzeme talepleri. | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Prc_T_MaterialRequest` · filtre `"IsDeleted" = 'false' AND "ApprovalStatus" = N'Departman Onayı'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | @@ -364,7 +364,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | Menü | `App.Prc.MaterialRequests` › `App.Prc.MaterialRequestPurchaseApproval` (sıra 3) | | Yetki | `App.Prc.MaterialRequestPurchaseApproval` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Satınalma Onayı Bekleyenler — departmanca onaylanmış ve satınalmanın kararını bekleyen malzeme talepleri. | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Prc_T_MaterialRequest` · filtre `"IsDeleted" = 'false' AND "ApprovalStatus" = N'Satınalma Onayı'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | @@ -405,7 +405,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | Menü | `App.Prc.MaterialRequests` › `App.Prc.MaterialRequestPlanning` (sıra 4) | | Yetki | `App.Prc.MaterialRequestPlanning` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Planlama Bekleyenler — onaylanmış ve satırları henüz tamamlanmamış malzeme talepleri; satınalma ekibinin iş listesi. | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Prc_T_MaterialRequest` · filtre `"IsDeleted" = 'false' AND "ApprovalStatus" = N'Onaylandı' AND "Status" <> 'Done'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | @@ -442,7 +442,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | Menü | `App.Prc.MaterialRequests` › `App.Prc.MaterialRequest` (sıra 5) | | Yetki | `App.Prc.MaterialRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Tüm Talepler — kurumun bütün malzeme talepleri, tüm durumlarıyla; satınalma yönetiminin listesi. | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Prc_T_MaterialRequest` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | @@ -487,7 +487,7 @@ Yönetim › Tanımlamalar › Onaycılar (onay yerleri Satınalma ve Satınalma | Menü | Menüsüz (alt form) | | Yetki | `App.Prc.MaterialRequestLine` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Açıklama | Talep Satırları — malzeme talebinde istenen ürünler. | -| Geliştirme talebi | Satınalma -> Malzeme Talepleri | +| Geliştirme talebi | Satınalma -> Satınalma Talepleri | | Kaynak | `Prc_T_MaterialRequestItem` · filtre `"IsDeleted" = 'false'` | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | diff --git a/configs/seeds/wizard/Adm_Approver.json b/configs/seeds/wizard/Adm_Approver.json index ca82b2b9..ec5399ce 100644 --- a/configs/seeds/wizard/Adm_Approver.json +++ b/configs/seeds/wizard/Adm_Approver.json @@ -33,7 +33,7 @@ "TitleEn": "Approvers", "TitleTr": "Onaycılar", "DescEn": "Approvers — the single list of who approves what for each department across the application.\nWhere: Administration › Definitions › Approvers.\nFields: department (shown as Branch - Department), approval area (Purchasing / Purchasing Desk / Warehouse / Human Resources / Finance), approver user, active.\nUsed by: approval workflows read the approvers of the record's department and area. Purchasing › Material Requests: the department approval uses area Purchasing for the requester's department; the purchasing approval uses area Purchasing Desk (any department). Several approvers may be defined for the same department and area; any one of them can approve. Passive rows are ignored by workflows.", - "DescTr": "Onaycılar — uygulamadaki tüm onay adımlarında her departman için kimin onaylayacağını tutan tek liste.\nNerede: Yönetim › Tanımlamalar › Onaycılar.\nAlanlar: departman (Şube - Departman olarak gösterilir), onay yeri (Satınalma / Satınalma Masası / Depo / İnsan Kaynakları / Finans), onaylayacak kişi, aktif.\nKullanıldığı yer: onay akışları kaydın departmanı ve onay yerine göre onaycıları buradan okur. Satınalma › Malzeme Talepleri: departman onayı talep edenin departmanındaki Satınalma satırlarını, satınalma onayı ise Satınalma Masası satırlarını (departmandan bağımsız) kullanır. Aynı departman ve onay yerine birden çok onaycı girilebilir; herhangi birinin onayı yeterlidir. Pasif satırlar akışlarda kullanılmaz.", + "DescTr": "Onaycılar — uygulamadaki tüm onay adımlarında her departman için kimin onaylayacağını tutan tek liste.\nNerede: Yönetim › Tanımlamalar › Onaycılar.\nAlanlar: departman (Şube - Departman olarak gösterilir), onay yeri (Satınalma / Satınalma Masası / Depo / İnsan Kaynakları / Finans), onaylayacak kişi, aktif.\nKullanıldığı yer: onay akışları kaydın departmanı ve onay yerine göre onaycıları buradan okur. Satınalma › Satınalma Talepleri: departman onayı talep edenin departmanındaki Satınalma satırlarını, satınalma onayı ise Satınalma Masası satırlarını (departmandan bağımsız) kullanır. Aynı departman ve onay yerine birden çok onaycı girilebilir; herhangi birinin onayı yeterlidir. Pasif satırlar akışlarda kullanılmaz.", "Texts": [ { "Key": "App.StaticLookup.Purchase", @@ -1428,6 +1428,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/configs/seeds/wizard/Prc_MaterialRequest.json b/configs/seeds/wizard/Prc_MaterialRequest.json index 7a6f1351..ccfcfbf1 100644 --- a/configs/seeds/wizard/Prc_MaterialRequest.json +++ b/configs/seeds/wizard/Prc_MaterialRequest.json @@ -1,9 +1,4 @@ { - "Pending": { - "Since": "2026-10-09T00:00:00", - "Replaced": {}, - "ListFormCodes": [] - }, "Wizard": { "ComponentKind": 0, "WizardName": "Prc_MaterialRequest", @@ -30,7 +25,7 @@ }, "Language": { "MenuParentEn": "Material Requests", - "MenuParentTr": "Malzeme Talepleri", + "MenuParentTr": "Satınalma Talepleri", "PermissionGroupEn": "Purchasing", "PermissionGroupTr": "Satınalma", "MenuEn": "All Requests", @@ -38,7 +33,7 @@ "TitleEn": "All Material Requests", "TitleTr": "Tüm Talepler", "DescEn": "All Requests — every material request of the company in every status; used by purchasing management.\nWhere: Purchasing › Material Requests › All Requests.\nFields: request no (MT-YYYY-00001, automatic), priority, requester, department, warehouse and location, request date, status (Draft › Department Approval › Purchasing Approval › Approved › In Progress › Partially Done › Done, or Rejected), approval status, rejection reason, general description; approval group: department approvers, department / purchasing approver, date and note; Request Lines tab.\nFlow: Grid Workflow — department approver (Approvers › area Purchasing of the request's department) → purchasing (area Purchasing Desk) → Approved / Rejected; the requester is notified. Status after approval follows the line statuses.\nRelated: My Requests, Awaiting Department Approval, Awaiting Purchasing Approval, Awaiting Planning, Purchasing › Definitions › Rejection Reasons.", - "DescTr": "Tüm Talepler — kurumun bütün malzeme talepleri, tüm durumlarıyla; satınalma yönetiminin listesi.\nNerede: Satınalma › Malzeme Talepleri › Tüm Talepler.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden, departman, depo ve konum, talep tarihi, durum (Taslak › Departman Onayı › Satınalma Onayı › Onaylandı › İşlemde › Kısmi Tamamlandı › Tamamlandı ya da Reddedildi), onay durumu, red nedeni, genel açıklama; onay grubu: departman onaycıları, departman / satınalma onaylayanı, tarihi ve notu; Talep Satırları sekmesi.\nAkış: Grid Workflow — departman onaycısı (Onaycılar › talebin departmanı için Satınalma onay yeri) → satınalma (Satınalma Masası onay yeri) → Onaylandı / Reddedildi; talep edene bilgi gider. Onay sonrası durum satır durumlarını izler.\nİlişkili: Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Satınalma › Tanımlamalar › Red Nedenleri.", + "DescTr": "Tüm Talepler — kurumun bütün malzeme talepleri, tüm durumlarıyla; satınalma yönetiminin listesi.\nNerede: Satınalma › Satınalma Talepleri › Tüm Talepler.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden, departman, depo ve konum, talep tarihi, durum (Taslak › Departman Onayı › Satınalma Onayı › Onaylandı › İşlemde › Kısmi Tamamlandı › Tamamlandı ya da Reddedildi), onay durumu, red nedeni, genel açıklama; onay grubu: departman onaycıları, departman / satınalma onaylayanı, tarihi ve notu; Talep Satırları sekmesi.\nAkış: Grid Workflow — departman onaycısı (Onaycılar › talebin departmanı için Satınalma onay yeri) → satınalma (Satınalma Masası onay yeri) → Onaylandı / Reddedildi; talep edene bilgi gider. Onay sonrası durum satır durumlarını izler.\nİlişkili: Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Satınalma › Tanımlamalar › Red Nedenleri.", "Texts": [ { "Key": "App.Prc.MaterialRequest.Group.Request", @@ -4022,6 +4017,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/configs/seeds/wizard/Prc_MaterialRequestDeptApproval.json b/configs/seeds/wizard/Prc_MaterialRequestDeptApproval.json index dc1fcbf8..428812b1 100644 --- a/configs/seeds/wizard/Prc_MaterialRequestDeptApproval.json +++ b/configs/seeds/wizard/Prc_MaterialRequestDeptApproval.json @@ -1,9 +1,4 @@ { - "Pending": { - "Since": "2026-10-09T00:00:00", - "Replaced": {}, - "ListFormCodes": [] - }, "Wizard": { "ComponentKind": 0, "WizardName": "Prc_MaterialRequestDeptApproval", @@ -30,7 +25,7 @@ }, "Language": { "MenuParentEn": "Material Requests", - "MenuParentTr": "Malzeme Talepleri", + "MenuParentTr": "Satınalma Talepleri", "PermissionGroupEn": "Purchasing", "PermissionGroupTr": "Satınalma", "MenuEn": "Awaiting Department Approval", @@ -38,7 +33,7 @@ "TitleEn": "Awaiting Department Approval", "TitleTr": "Departman Onayı Bekleyenler", "DescEn": "Awaiting Department Approval — material requests waiting for the department approver's decision.\nWhere: Purchasing › Material Requests › Awaiting Department Approval.\nWho: approvers defined in Administration › Definitions › Approvers with area Purchasing for the requester's department; each approver sees only the requests assigned to them.\nWhat to do: open the request, review the Request Lines tab, then Approve (the request moves to purchasing approval) or Reject with a note and a rejection reason (Purchasing › Definitions › Rejection Reasons). Lines cannot be added or removed here.\nRelated: My Requests, Awaiting Purchasing Approval, All Requests.", - "DescTr": "Departman Onayı Bekleyenler — departman onaycısının kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Malzeme Talepleri › Departman Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da talep edenin departmanı için Satınalma onay yerinde tanımlı onaycılar; her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi açıp Talep Satırları sekmesini inceleyin, ardından Onayla (talep satınalma onayına geçer) ya da not ve red nedeniyle (Satınalma › Tanımlamalar › Red Nedenleri) Reddet. Burada satır eklenip silinemez.\nİlişkili: Taleplerim, Satınalma Onayı Bekleyenler, Tüm Talepler.", + "DescTr": "Departman Onayı Bekleyenler — departman onaycısının kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Satınalma Talepleri › Departman Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da talep edenin departmanı için Satınalma onay yerinde tanımlı onaycılar; her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi açıp Talep Satırları sekmesini inceleyin, ardından Onayla (talep satınalma onayına geçer) ya da not ve red nedeniyle (Satınalma › Tanımlamalar › Red Nedenleri) Reddet. Burada satır eklenip silinemez.\nİlişkili: Taleplerim, Satınalma Onayı Bekleyenler, Tüm Talepler.", "Texts": [ { "Key": "App.Prc.MaterialRequest.Group.Request", @@ -3059,6 +3054,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/configs/seeds/wizard/Prc_MaterialRequestLine.json b/configs/seeds/wizard/Prc_MaterialRequestLine.json index 2d882e38..4b395b29 100644 --- a/configs/seeds/wizard/Prc_MaterialRequestLine.json +++ b/configs/seeds/wizard/Prc_MaterialRequestLine.json @@ -1,9 +1,4 @@ { - "Pending": { - "Since": "2026-10-09T00:00:00", - "Replaced": {}, - "ListFormCodes": [] - }, "Wizard": { "ComponentKind": 0, "WizardName": "Prc_MaterialRequestLine", @@ -31,7 +26,7 @@ }, "Language": { "MenuParentEn": "Material Requests", - "MenuParentTr": "Malzeme Talepleri", + "MenuParentTr": "Satınalma Talepleri", "PermissionGroupEn": "Purchasing", "PermissionGroupTr": "Satınalma", "MenuEn": "Request Lines", @@ -39,7 +34,7 @@ "TitleEn": "Request Lines", "TitleTr": "Talep Satırları", "DescEn": "Request Lines — the products requested in a material request.\nWhere: Purchasing › Material Requests › any list › Request Lines tab (no menu of its own).\nFields: product (active, purchasable products), quantity, unit (copied from the product's purchase unit, read-only), fulfilment (Purchasing / Warehouse Transfer), due date, request reason, delivered quantity (read-only), planned quantity (defaults to quantity), purchasing responsible, line status (Waiting / Planned / Done / Cancelled).\nRules: lines can be added or deleted only while the request has not been sent for approval. Changing line statuses recalculates the request status (In Progress / Partially Done / Done).", - "DescTr": "Talep Satırları — malzeme talebinde istenen ürünler.\nNerede: Satınalma › Malzeme Talepleri › herhangi bir liste › Talep Satırları sekmesi (kendi menüsü yoktur).\nAlanlar: ürün (aktif ve satın alınabilir ürünler), miktar, birim (ürünün satınalma biriminden gelir, salt okunur), karşılama şekli (Satınalma / Depodan Transfer), termin tarihi, talep nedeni, teslim edilen miktar (salt okunur), planlanacak miktar (boşsa miktar), satınalma sorumlusu, satır durumu (Bekliyor / Planlandı / Tamamlandı / İptal).\nKurallar: satır yalnız talep onaya gönderilmeden eklenip silinebilir. Satır durumları değişince talebin durumu yeniden hesaplanır (İşlemde / Kısmi Tamamlandı / Tamamlandı).", + "DescTr": "Talep Satırları — malzeme talebinde istenen ürünler.\nNerede: Satınalma › Satınalma Talepleri › herhangi bir liste › Talep Satırları sekmesi (kendi menüsü yoktur).\nAlanlar: ürün (aktif ve satın alınabilir ürünler), miktar, birim (ürünün satınalma biriminden gelir, salt okunur), karşılama şekli (Satınalma / Depodan Transfer), termin tarihi, talep nedeni, teslim edilen miktar (salt okunur), planlanacak miktar (boşsa miktar), satınalma sorumlusu, satır durumu (Bekliyor / Planlandı / Tamamlandı / İptal).\nKurallar: satır yalnız talep onaya gönderilmeden eklenip silinebilir. Satır durumları değişince talebin durumu yeniden hesaplanır (İşlemde / Kısmi Tamamlandı / Tamamlandı).", "Texts": [ { "Key": "App.StaticLookup.Purchase", @@ -2408,6 +2403,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/configs/seeds/wizard/Prc_MaterialRequestPlanning.json b/configs/seeds/wizard/Prc_MaterialRequestPlanning.json index 8a43e4d1..f37e2346 100644 --- a/configs/seeds/wizard/Prc_MaterialRequestPlanning.json +++ b/configs/seeds/wizard/Prc_MaterialRequestPlanning.json @@ -1,9 +1,4 @@ { - "Pending": { - "Since": "2026-10-09T00:00:00", - "Replaced": {}, - "ListFormCodes": [] - }, "Wizard": { "ComponentKind": 0, "WizardName": "Prc_MaterialRequestPlanning", @@ -30,7 +25,7 @@ }, "Language": { "MenuParentEn": "Material Requests", - "MenuParentTr": "Malzeme Talepleri", + "MenuParentTr": "Satınalma Talepleri", "PermissionGroupEn": "Purchasing", "PermissionGroupTr": "Satınalma", "MenuEn": "Awaiting Planning", @@ -38,7 +33,7 @@ "TitleEn": "Awaiting Planning", "TitleTr": "Planlama Bekleyenler", "DescEn": "Awaiting Planning — approved material requests whose lines are not all completed yet; the purchasing team's work list.\nWhere: Purchasing › Material Requests › Awaiting Planning.\nWhat to do: open the request and, on the Request Lines tab, set the purchasing responsible, the quantity to plan and the line status (Waiting / Planned / Done / Cancelled). The request status follows the lines: any line Planned → In Progress, some lines Done → Partially Done, all lines Done or Cancelled → Done (the request then leaves this list). This list is the starting point of the quotation process.\nRelated: Awaiting Purchasing Approval, All Requests.", - "DescTr": "Planlama Bekleyenler — onaylanmış ve satırları henüz tamamlanmamış malzeme talepleri; satınalma ekibinin iş listesi.\nNerede: Satınalma › Malzeme Talepleri › Planlama Bekleyenler.\nNe yapılır: talebi açıp Talep Satırları sekmesinde satınalma sorumlusunu, planlanacak miktarı ve satır durumunu (Bekliyor / Planlandı / Tamamlandı / İptal) girin. Talebin durumu satırları izler: bir satır Planlandı → İşlemde, satırların bir kısmı Tamamlandı → Kısmi Tamamlandı, tüm satırlar Tamamlandı ya da İptal → Tamamlandı (talep bu listeden çıkar). Teklif toplama sürecinin giriş noktasıdır.\nİlişkili: Satınalma Onayı Bekleyenler, Tüm Talepler.", + "DescTr": "Planlama Bekleyenler — onaylanmış ve satırları henüz tamamlanmamış malzeme talepleri; satınalma ekibinin iş listesi.\nNerede: Satınalma › Satınalma Talepleri › Planlama Bekleyenler.\nNe yapılır: talebi açıp Talep Satırları sekmesinde satınalma sorumlusunu, planlanacak miktarı ve satır durumunu (Bekliyor / Planlandı / Tamamlandı / İptal) girin. Talebin durumu satırları izler: bir satır Planlandı → İşlemde, satırların bir kısmı Tamamlandı → Kısmi Tamamlandı, tüm satırlar Tamamlandı ya da İptal → Tamamlandı (talep bu listeden çıkar). Teklif toplama sürecinin giriş noktasıdır.\nİlişkili: Satınalma Onayı Bekleyenler, Tüm Talepler.", "Texts": [ { "Key": "App.Prc.MaterialRequest.Group.Request", @@ -2979,6 +2974,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/configs/seeds/wizard/Prc_MaterialRequestPurchaseApproval.json b/configs/seeds/wizard/Prc_MaterialRequestPurchaseApproval.json index 0090cbc8..36afa8dc 100644 --- a/configs/seeds/wizard/Prc_MaterialRequestPurchaseApproval.json +++ b/configs/seeds/wizard/Prc_MaterialRequestPurchaseApproval.json @@ -1,9 +1,4 @@ { - "Pending": { - "Since": "2026-10-09T00:00:00", - "Replaced": {}, - "ListFormCodes": [] - }, "Wizard": { "ComponentKind": 0, "WizardName": "Prc_MaterialRequestPurchaseApproval", @@ -30,7 +25,7 @@ }, "Language": { "MenuParentEn": "Material Requests", - "MenuParentTr": "Malzeme Talepleri", + "MenuParentTr": "Satınalma Talepleri", "PermissionGroupEn": "Purchasing", "PermissionGroupTr": "Satınalma", "MenuEn": "Awaiting Purchasing Approval", @@ -38,7 +33,7 @@ "TitleEn": "Awaiting Purchasing Approval", "TitleTr": "Satınalma Onayı Bekleyenler", "DescEn": "Awaiting Purchasing Approval — material requests approved by the department and waiting for purchasing.\nWhere: Purchasing › Material Requests › Awaiting Purchasing Approval.\nWho: approvers defined in Administration › Definitions › Approvers with area Purchasing Desk (any department); each approver sees only the requests assigned to them.\nWhat to do: review the request and its lines, then Approve (the request becomes Approved and appears in Awaiting Planning, the requester is notified) or Reject with a note and a rejection reason.\nRelated: Awaiting Department Approval, Awaiting Planning, All Requests.", - "DescTr": "Satınalma Onayı Bekleyenler — departmanca onaylanmış ve satınalmanın kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Malzeme Talepleri › Satınalma Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da Satınalma Masası onay yerinde tanımlı onaycılar (departmandan bağımsız); her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi ve satırlarını inceleyip Onayla (talep Onaylandı olur, Planlama Bekleyenler'e düşer, talep edene bilgi gider) ya da not ve red nedeniyle Reddet.\nİlişkili: Departman Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler.", + "DescTr": "Satınalma Onayı Bekleyenler — departmanca onaylanmış ve satınalmanın kararını bekleyen malzeme talepleri.\nNerede: Satınalma › Satınalma Talepleri › Satınalma Onayı Bekleyenler.\nKim: Yönetim › Tanımlamalar › Onaycılar'da Satınalma Masası onay yerinde tanımlı onaycılar (departmandan bağımsız); her onaycı yalnız kendisine düşen talepleri görür.\nNe yapılır: talebi ve satırlarını inceleyip Onayla (talep Onaylandı olur, Planlama Bekleyenler'e düşer, talep edene bilgi gider) ya da not ve red nedeniyle Reddet.\nİlişkili: Departman Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler.", "Texts": [ { "Key": "App.Prc.MaterialRequest.Group.Request", @@ -3466,6 +3461,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/configs/seeds/wizard/Prc_MyMaterialRequest.json b/configs/seeds/wizard/Prc_MyMaterialRequest.json index 3d72ae60..bfebec84 100644 --- a/configs/seeds/wizard/Prc_MyMaterialRequest.json +++ b/configs/seeds/wizard/Prc_MyMaterialRequest.json @@ -1,9 +1,4 @@ { - "Pending": { - "Since": "2026-10-09T00:00:00", - "Replaced": {}, - "ListFormCodes": [] - }, "Wizard": { "ComponentKind": 0, "WizardName": "Prc_MyMaterialRequest", @@ -30,7 +25,7 @@ }, "Language": { "MenuParentEn": "Material Requests", - "MenuParentTr": "Malzeme Talepleri", + "MenuParentTr": "Satınalma Talepleri", "PermissionGroupEn": "Purchasing", "PermissionGroupTr": "Satınalma", "MenuEn": "My Requests", @@ -38,7 +33,7 @@ "TitleEn": "My Material Requests", "TitleTr": "Taleplerim", "DescEn": "My Requests — the material requests you opened, in every status.\nWhere: Purchasing › Material Requests › My Requests.\nFields: request no (MT-YYYY-00001, automatic), priority, requester (you), department (your department by default), warehouse and location where the goods will be put, request date, status, general description; Request Lines tab: product, quantity, unit, fulfilment, due date, request reason.\nFlow: add lines, then send for approval — the department approver (Approvers › area Purchasing for your department) and then purchasing (area Purchasing Desk) approve or reject. Lines can only be added or removed before sending. Approval / rejection details are shown in the approval group.\nRelated: Awaiting Department Approval, Awaiting Purchasing Approval, Awaiting Planning, All Requests.", - "DescTr": "Taleplerim — açtığınız malzeme talepleri, tüm durumlarıyla.\nNerede: Satınalma › Malzeme Talepleri › Taleplerim.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden (siz), departman (varsayılan olarak sizin departmanınız), malın konulacağı depo ve konum, talep tarihi, durum, genel açıklama; Talep Satırları sekmesi: ürün, miktar, birim, karşılama şekli, termin tarihi, talep nedeni.\nAkış: satırları girip onaya gönderin — önce departman onaycısı (Onaycılar › departmanınız için Satınalma onay yeri), ardından satınalma (Satınalma Masası onay yeri) onaylar ya da reddeder. Satırlar yalnız onaya göndermeden önce eklenip silinebilir. Onay / red bilgileri onay grubunda görünür.\nİlişkili: Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler.", + "DescTr": "Taleplerim — açtığınız malzeme talepleri, tüm durumlarıyla.\nNerede: Satınalma › Satınalma Talepleri › Taleplerim.\nAlanlar: talep no (MT-YYYY-00001, otomatik), öncelik, talep eden (siz), departman (varsayılan olarak sizin departmanınız), malın konulacağı depo ve konum, talep tarihi, durum, genel açıklama; Talep Satırları sekmesi: ürün, miktar, birim, karşılama şekli, termin tarihi, talep nedeni.\nAkış: satırları girip onaya gönderin — önce departman onaycısı (Onaycılar › departmanınız için Satınalma onay yeri), ardından satınalma (Satınalma Masası onay yeri) onaylar ya da reddeder. Satırlar yalnız onaya göndermeden önce eklenip silinebilir. Onay / red bilgileri onay grubunda görünür.\nİlişkili: Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler.", "Texts": [ { "Key": "App.Prc.MaterialRequest.Group.Request", @@ -4073,6 +4068,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/configs/seeds/wizard/Prc_RejectReason.json b/configs/seeds/wizard/Prc_RejectReason.json index c98104af..fa8f4e56 100644 --- a/configs/seeds/wizard/Prc_RejectReason.json +++ b/configs/seeds/wizard/Prc_RejectReason.json @@ -33,7 +33,7 @@ "TitleEn": "Rejection Reasons", "TitleTr": "Red Nedenleri", "DescEn": "Rejection Reasons — reasons a purchasing request can be rejected for (no need, quantity not suitable, wrong product, budget not suitable, other).\nWhere: Purchasing › Definitions › Rejection Reasons.\nFields: reason, sort order (order in the selection list), active.\nUsed by: Purchasing › Material Requests — the department approver or purchasing selects a reason when rejecting a request. Only active reasons are offered; deactivate a used reason instead of deleting it.", - "DescTr": "Red Nedenleri — satınalma taleplerinin reddedilme sebepleri (ihtiyaç yok, miktar uygun değil, yanlış ürün, bütçe uygun değil, diğer).\nNerede: Satınalma › Tanımlamalar › Red Nedenleri.\nAlanlar: red nedeni, sıra (seçim listesindeki sırası), aktif.\nKullanıldığı yer: Satınalma › Malzeme Talepleri — departman onaycısı ya da satınalma talebi reddederken neden seçer. Yalnız aktif nedenler listelenir; kullanılmış neden silinmez, pasife alınır." + "DescTr": "Red Nedenleri — satınalma taleplerinin reddedilme sebepleri (ihtiyaç yok, miktar uygun değil, yanlış ürün, bütçe uygun değil, diğer).\nNerede: Satınalma › Tanımlamalar › Red Nedenleri.\nAlanlar: red nedeni, sıra (seçim listesindeki sırası), aktif.\nKullanıldığı yer: Satınalma › Satınalma Talepleri — departman onaycısı ya da satınalma talebi reddederken neden seçer. Yalnız aktif nedenler listelenir; kullanılmış neden silinmez, pasife alınır." }, "Groups": [ { @@ -1251,6 +1251,6 @@ }, "DevRequest": { "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", - "Title": "Satınalma -> Malzeme Talepleri" + "Title": "Satınalma -> Satınalma Talepleri" } } \ No newline at end of file diff --git a/ui/src/services/tenant.service.ts b/ui/src/services/tenant.service.ts index 225bb20b..8f597050 100644 --- a/ui/src/services/tenant.service.ts +++ b/ui/src/services/tenant.service.ts @@ -8,6 +8,18 @@ export type CreateTenantFromOrderInput = { modules: string } +export type ApplicationSuiteDto = { + id: string + name: string + modules: string +} + +export const getApplicationSuites = () => + apiService.fetchData({ + method: 'GET', + url: '/api/app/list-form-dynamic-api/application-suites', + }) + export const getTenants = (skipCount = 0, maxResultCount = 10) => apiService.fetchData>({ method: 'GET', diff --git a/ui/src/views/admin/tenant-management/CreateTenantFromOrderDialog.tsx b/ui/src/views/admin/tenant-management/CreateTenantFromOrderDialog.tsx index 077c442e..ab3ca597 100644 --- a/ui/src/views/admin/tenant-management/CreateTenantFromOrderDialog.tsx +++ b/ui/src/views/admin/tenant-management/CreateTenantFromOrderDialog.tsx @@ -10,7 +10,11 @@ import { } from '@/components/ui' import { MULTIVALUE_DELIMITER } from '@/constants/app.constant' import { getModules } from '@/services/menu.service' -import { createTenantFromOrder } from '@/services/tenant.service' +import { + ApplicationSuiteDto, + createTenantFromOrder, + getApplicationSuites, +} from '@/services/tenant.service' import { SelectBoxOption } from '@/types/shared' import { useLocalization } from '@/utils/hooks/useLocalization' import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik' @@ -18,6 +22,7 @@ import { useEffect, useState } from 'react' import * as Yup from 'yup' type CreateTenantFromOrderValues = { + applicationSuiteId: string | null name: string modules: string[] } @@ -40,36 +45,42 @@ const CreateTenantFromOrderDialog = ({ }: CreateTenantFromOrderDialogProps) => { const { translate } = useLocalization() const [moduleOptions, setModuleOptions] = useState([]) - const [isModulesLoading, setIsModulesLoading] = useState(false) + const [suites, setSuites] = useState([]) + const [isLoading, setIsLoading] = useState(false) useEffect(() => { if (!open) { return } - const fetchModules = async () => { - setIsModulesLoading(true) + const fetchOptions = async () => { + setIsLoading(true) - try { - const response = await getModules() - const items = response?.data ?? [] + const [modulesResult, suitesResult] = await Promise.allSettled([ + getModules(), + getApplicationSuites(), + ]) - setModuleOptions( - items.map((item: any) => ({ - value: String(item.key ?? item.Key ?? ''), - label: String(item.name ?? item.Name ?? ''), - })), - ) - } catch { - setModuleOptions([]) - } finally { - setIsModulesLoading(false) - } + setModuleOptions( + modulesResult.status === 'fulfilled' + ? (modulesResult.value?.data ?? []).map((item: any) => ({ + value: String(item.key ?? item.Key ?? ''), + label: String(item.name ?? item.Name ?? ''), + })) + : [], + ) + setSuites(suitesResult.status === 'fulfilled' ? (suitesResult.value?.data ?? []) : []) + setIsLoading(false) } - fetchModules() + fetchOptions() }, [open]) + const suiteOptions: SelectBoxOption[] = suites.map((suite) => ({ + value: suite.id, + label: suite.name, + })) + const handleSubmit = async ( values: CreateTenantFromOrderValues, { setSubmitting }: FormikHelpers, @@ -115,6 +126,7 @@ const CreateTenantFromOrderDialog = ({ initialValues={{ + applicationSuiteId: null, name: '', modules: [], }} @@ -124,6 +136,33 @@ const CreateTenantFromOrderDialog = ({ {({ errors, touched, isSubmitting }) => (
+ + + {({ field, form }: FieldProps) => ( +