From 2cacec19c7813d915deb5fcca61fbebfdb25f765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Tue, 7 Oct 2025 01:16:21 +0300 Subject: [PATCH] =?UTF-8?q?Tenant=20seeder=20=C3=A7al=C4=B1=C5=9Fmalar?= =?UTF-8?q?=C4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Orders/PaymentMethodDto.cs | 3 +- .../Public/PublicAppService.cs | 4 +- .../Seeds/ListFormsSeeder.cs | 792 +++++++++++++++++- .../Seeds/PlatformDataSeeder.cs | 343 ++++---- .../Seeds/SeederData.json | 700 +++++++++------- .../Seeds/SeederDto.cs | 22 +- .../PlatformConsts.cs | 1 + .../Entities/Administration/ClassType.cs | 17 +- .../Entities/Administration/EventCategory.cs | 11 - .../Entities/Administration/EventType.cs | 11 - .../Administration/RegistrationType.cs | 7 - .../Entities/Administration/SkillType.cs | 9 - .../Entities/Administration/UomCategory.cs | 7 - .../Entities/Coordinator/Classroom.cs | 43 +- .../Entities/Platform/AiBot.cs | 6 - .../Entities/Saas/Forum/ForumCategory.cs | 19 +- .../Entities/Saas/Public/About.cs | 14 - .../Entities/Saas/Public/BlogCategory.cs | 23 - .../Entities/Saas/Public/BlogPost.cs | 37 - .../Entities/Saas/Public/Contact.cs | 24 - .../Entities/Saas/Public/PaymentMethod.cs | 15 +- .../Entities/Saas/Public/Product.cs | 26 - .../Entities/Saas/Public/Service.cs | 12 - .../Entities/Saas/Report/ReportCategory.cs | 16 - .../EntityFrameworkCore/PlatformDbContext.cs | 3 - ....cs => 20251006221403_Initial.Designer.cs} | 46 +- ...3_Initial.cs => 20251006221403_Initial.cs} | 24 +- .../PlatformDbContextModelSnapshot.cs | 44 +- ui/src/proxy/admin/list-form/options.ts | 1 + ui/src/services/form.service.ts | 3 + ui/src/views/form/FormDevExpress.tsx | 1 - ui/src/views/form/useGridData.tsx | 4 +- ui/src/views/form/useLookupDataSource.ts | 12 +- 33 files changed, 1473 insertions(+), 827 deletions(-) rename api/src/Kurs.Platform.EntityFrameworkCore/Migrations/{20251006121303_Initial.Designer.cs => 20251006221403_Initial.Designer.cs} (99%) rename api/src/Kurs.Platform.EntityFrameworkCore/Migrations/{20251006121303_Initial.cs => 20251006221403_Initial.cs} (99%) diff --git a/api/src/Kurs.Platform.Application.Contracts/Orders/PaymentMethodDto.cs b/api/src/Kurs.Platform.Application.Contracts/Orders/PaymentMethodDto.cs index 07775b6e..3fcb7d1e 100644 --- a/api/src/Kurs.Platform.Application.Contracts/Orders/PaymentMethodDto.cs +++ b/api/src/Kurs.Platform.Application.Contracts/Orders/PaymentMethodDto.cs @@ -1,8 +1,9 @@ +using System; using Volo.Abp.Application.Dtos; namespace Kurs.Platform.Orders; -public class PaymentMethodDto : EntityDto +public class PaymentMethodDto : EntityDto { public string Name { get; set; } public decimal Commission { get; set; } diff --git a/api/src/Kurs.Platform.Application/Public/PublicAppService.cs b/api/src/Kurs.Platform.Application/Public/PublicAppService.cs index 897e4629..0f1602e7 100644 --- a/api/src/Kurs.Platform.Application/Public/PublicAppService.cs +++ b/api/src/Kurs.Platform.Application/Public/PublicAppService.cs @@ -29,7 +29,7 @@ public class PublicAppService : PlatformAppService private readonly IRepository _postRepository; private readonly IRepository _categoryRepository; private readonly IRepository _productRepository; - private readonly IRepository _paymentMethodRepository; + private readonly IRepository _paymentMethodRepository; private readonly IRepository _installmentOptionRepository; private readonly IRepository _orderRepository; private readonly IRepository _aboutRepository; @@ -43,7 +43,7 @@ public class PublicAppService : PlatformAppService IRepository postRepository, IRepository categoryRepository, IRepository productRepository, - IRepository paymentMethodRepository, + IRepository paymentMethodRepository, IRepository installmentOptionRepository, IRepository orderRepository, IRepository aboutRepository, diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs index 17f074f4..53759801 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs @@ -1116,6 +1116,752 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency } #endregion + #region Tenant + if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == ListFormCodes.Forms.FormTenant)) + { + var formTenant = await _listFormRepository.InsertAsync( + new ListForm() + { + ListFormType = ListFormTypeEnum.Form, + IsSubForm = false, + LayoutJson = JsonSerializer.Serialize(new LayoutDto() + { + Grid = true, + Card = true, + Pivot = true, + Chart = true, + DefaultLayout = "grid", + CardLayoutColumn = 4 + }), + SubFormsJson = JsonSerializer.Serialize(new List() { + new { + TabTitle = "Branches", + TabType = ListFormTabTypeEnum.List, + Code = ListFormCodes.Lists.Branch, + Relation = new List() { + new { + ParentFieldName = "Id", + ChildFieldName = "TenantId" + } + } + } + }), + CultureName = LanguageCodes.En, + ListFormCode = ListFormCodes.Forms.FormTenant, + Name = TenantManagementPermissions.Tenants.Default, + Title = TenantManagementPermissions.Tenants.Default, + DataSourceCode = SeedConsts.DataSources.DefaultCode, + IsTenant = false, + IsBranch = false, + IsOrganizationUnit = false, + Description = TenantManagementPermissions.Tenants.Default, + SelectCommandType = SelectCommandTypeEnum.Table, + SelectCommand = "AbpTenants", + KeyFieldName = "Id", + KeyFieldDbSourceType = DbType.Guid, + SortMode = GridOptions.SortModeSingle, + FilterRowJson = JsonSerializer.Serialize(new GridFilterRowDto + { + Visible = true + }), + HeaderFilterJson = JsonSerializer.Serialize(new + { + Visible = true + }), + SearchPanelJson = JsonSerializer.Serialize(new + { + Visible = true + }), + GroupPanelJson = JsonSerializer.Serialize(new + { + Visible = true + }), + SelectionJson = JsonSerializer.Serialize(new SelectionDto + { + Mode = GridOptions.SelectionModeSingle, + AllowSelectAll = false + }), + ColumnOptionJson = JsonSerializer.Serialize(new + { + ColumnFixingEnabled = true, + ColumnChooserEnabled = true + }), + PermissionJson = JsonSerializer.Serialize(new PermissionCrudDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + D = TenantManagementPermissions.Tenants.Delete, + E = TenantManagementPermissions.Tenants.Default + ".Export", + I = TenantManagementPermissions.Tenants.Default + ".Import" + }), + PagerOptionJson = JsonSerializer.Serialize(new GridPagerOptionDto + { + Visible = true, + AllowedPageSizes = "10,20,50,100", + ShowPageSizeSelector = true, + ShowNavigationButtons = true, + ShowInfo = false, + InfoText = "Page {0} of {1} ({2} items)", + DisplayMode = GridColumnOptions.PagerDisplayModeAdaptive, + ScrollingMode = GridColumnOptions.ScrollingModeStandard, + LoadPanelEnabled = "auto", + LoadPanelText = "Loading..." + }), + EditingOptionJson = JsonSerializer.Serialize(new GridEditingDto + { + Popup = new GridEditingPopupDto() + { + Title = "Tenant Form", + Width = 900, + Height = 450 + }, + AllowDeleting = true, + AllowAdding = true, + AllowUpdating = true, + SendOnlyChangedFormValuesUpdate = false, + }), + EditingFormJson = JsonSerializer.Serialize(new List() + { + new() { Order=1, ColCount=2, ColSpan=1, ItemType="group", Items = + [ + new EditingFormItemDto { Order=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=2, DataField="OrganizationName", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=3, DataField="Founder", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=4, DataField="VknTckn", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, + new EditingFormItemDto { Order=5, DataField="TaxOffice", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=6, DataField="Mobile", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, + new EditingFormItemDto { Order=7, DataField="Phone", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxNumberBox }, + new EditingFormItemDto { Order=8, DataField="Fax", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=9, DataField="IsActive", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox }, + ] + }, + new() { Order=2, ColCount=1, ColSpan=1, ItemType="group", Items = + [ + new EditingFormItemDto { Order=1, DataField="Country", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=2, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=3, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=4, DataField="Street", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=5, DataField="PostalCode", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=6, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=7, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=8, DataField="Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=9, DataField="Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + ] + } + }), + CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] { + new() { + Hint = "Manage", + Text = "Manage", + AuthName = TenantManagementPermissions.Tenants.ManageConnectionStrings, + DialogName = "TenantsConnectionString", + DialogParameters = JsonSerializer.Serialize(new { + name = "@Name", + id = "@Id" + }) + }, + }), + InsertServiceAddress = "list-form-dynamic-api/tenant-insert", + UpdateServiceAddress = "list-form-dynamic-api/tenant-update", + DeleteCommand = "DELETE FROM \"AbpTenants\" WHERE \"Id\"=@Id", + DeleteFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { + new() { + FieldName = "Id", + FieldDbType = DbType.Guid, + Value = "@ID", + CustomValueType = FieldCustomValueTypeEnum.CustomKey } + }), + FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { + new() { + FieldName = "IsActive", + FieldDbType = DbType.Boolean, + Value = "true", + CustomValueType = FieldCustomValueTypeEnum.Value } + }) + + } + ); + + #region Tenants Fields + await _listFormFieldRepository.InsertManyAsync( + [ + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Guid, + FieldName = "Id", + Width = 500, + ListOrderNo = 1, + Visible = false, + IsActive = true, + IsDeleted = false, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Name", + Width = 100, + ListOrderNo = 2, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "OrganizationName", + Width = 200, + ListOrderNo = 3, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Founder", + Width = 200, + ListOrderNo = 4, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "VknTckn", + Width = 100, + ListOrderNo = 5, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "TaxOffice", + Width = 150, + ListOrderNo = 6, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Country", + Width = 100, + ListOrderNo = 7, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + LookupJson = JsonSerializer.Serialize(new LookupDto + { + DataSourceType = UiLookupDataSourceTypeEnum.Query, + DisplayExpr = "Name", + ValueExpr = "Key", + LookupQuery = lookupQueryCountryValues, + CascadeEmptyFields = "City,District,Street" + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "City", + Width = 100, + ListOrderNo = 8, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + LookupJson = JsonSerializer.Serialize(new LookupDto + { + DataSourceType = UiLookupDataSourceTypeEnum.Query, + DisplayExpr = "Name", + ValueExpr = "Key", + LookupQuery = lookupQueryCityValues, + CascadeRelationField = "Country", + CascadeFilterOperator="=", + CascadeParentFields = "Country", + CascadeEmptyFields = "District,Street" + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "District", + Width = 100, + ListOrderNo = 9, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + LookupJson = JsonSerializer.Serialize(new LookupDto + { + DataSourceType = UiLookupDataSourceTypeEnum.Query, + DisplayExpr = "Name", + ValueExpr = "Key", + LookupQuery = lookupQueryDistrictValues, + CascadeRelationField = "City", + CascadeFilterOperator="=", + CascadeParentFields = "Country,City", + CascadeEmptyFields = "Street", + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Street", + Width = 100, + ListOrderNo = 10, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + LookupJson = JsonSerializer.Serialize(new LookupDto + { + DataSourceType = UiLookupDataSourceTypeEnum.Query, + DisplayExpr = "Name", + ValueExpr = "Key", + LookupQuery = lookupQueryStreetValues, + CascadeRelationField = "District", + CascadeFilterOperator="=", + CascadeParentFields = "Country,City,District" + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Address", + Width = 150, + ListOrderNo = 11, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Address2", + Width = 150, + ListOrderNo = 12, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "PostalCode", + Width = 100, + ListOrderNo = 13, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Email", + Width = 170, + ListOrderNo = 14, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Website", + Width = 170, + ListOrderNo = 15, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Mobile", + Width = 100, + ListOrderNo = 16, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Phone", + Width = 100, + ListOrderNo = 17, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Fax", + Width = 100, + ListOrderNo = 18, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new ListFormField + { + ListFormCode = formTenant.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Boolean, + FieldName = "IsActive", + Width = 100, + ListOrderNo = 19, + Visible = true, + IsActive = true, + IsDeleted = false, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = TenantManagementPermissions.Tenants.Create, + R = TenantManagementPermissions.Tenants.Default, + U = TenantManagementPermissions.Tenants.Update, + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + ]); + #endregion + + } + #endregion + #endregion #region List @@ -1214,30 +1960,30 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency }), EditingFormJson = JsonSerializer.Serialize(new List() { - new() { Order=1, ColCount=1, ColSpan=1, ItemType="group", Items = + new() { Order=1, ColCount=2, ColSpan=1, ItemType="group", Items = [ - new EditingFormItemDto { Order=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=2, DataField="OrganizationName", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=3, DataField="Founder", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=4, DataField="VknTckn", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, - new EditingFormItemDto { Order=5, DataField="TaxOffice", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=6, DataField="Mobile", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, - new EditingFormItemDto { Order=7, DataField="Phone", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxNumberBox }, - new EditingFormItemDto { Order=8, DataField="Fax", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=9, DataField="IsActive", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox }, + new EditingFormItemDto { Order=1, DataField="Name", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=2, DataField="OrganizationName", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=3, DataField="Founder", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=4, DataField="VknTckn", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, + new EditingFormItemDto { Order=5, DataField="TaxOffice", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=6, DataField="Mobile", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, + new EditingFormItemDto { Order=7, DataField="Phone", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxNumberBox }, + new EditingFormItemDto { Order=8, DataField="Fax", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=9, DataField="IsActive", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxCheckBox }, ] }, - new() { Order=2, ColCount=1, ColSpan=1, ItemType="group", Items = + new() { Order=2, ColCount=2, ColSpan=1, ItemType="group", Items = [ - new EditingFormItemDto { Order=1, DataField="Country", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, - new EditingFormItemDto { Order=2, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, - new EditingFormItemDto { Order=3, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, - new EditingFormItemDto { Order=4, DataField="Street", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, - new EditingFormItemDto { Order=5, DataField="PostalCode", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions=showClearButton }, - new EditingFormItemDto { Order=6, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=7, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=8, DataField="Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=9, DataField="Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=1, DataField="Country", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=2, DataField="City", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=3, DataField="District", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=4, DataField="Street", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxSelectBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=5, DataField="PostalCode", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions=showClearButton }, + new EditingFormItemDto { Order=6, DataField="Address", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=7, DataField="Address2", ColSpan=1, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=8, DataField="Email", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=9, DataField="Website", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, ] } }), @@ -1259,6 +2005,12 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency AuthName = AppCodes.Branches, Url = "/admin/list/list-branch", }, + new() { + Hint = "Branches", + Text = "Branches", + AuthName = AppCodes.Branches, + Url = "/admin/form/form-tenant/@Id", + }, }), InsertServiceAddress = "list-form-dynamic-api/tenant-insert", UpdateServiceAddress = "list-form-dynamic-api/tenant-update", diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs index 09298ff3..7d79e72d 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs @@ -58,7 +58,7 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency private readonly IRepository _routeRepository; private readonly IRepository _customEndpointRepository; private readonly IRepository _productRepository; - private readonly IRepository _paymentMethodRepository; + private readonly IRepository _paymentMethodRepository; private readonly IRepository _installmentOptionRepository; private readonly IRepository _customComponentRepository; private readonly IRepository _reportCategoriesRepository; @@ -126,7 +126,7 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency IRepository aboutRepository, IRepository servicesRepository, IRepository productRepository, - IRepository paymentMethodRepository, + IRepository paymentMethodRepository, IRepository installmentOptionRepository, IRepository blogCategoryRepository, IRepository blogPostsRepository, @@ -704,7 +704,7 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _uomCategoryRepository.InsertAsync(new UomCategory(item.Id, item.Name)); + await _uomCategoryRepository.InsertAsync(new UomCategory { Name = item.Name }); } } @@ -714,15 +714,20 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _uomRepository.InsertAsync(new Uom + var category = await _uomCategoryRepository.FirstOrDefaultAsync(x => x.Name == item.UomCategoryName); + if (category != null) { - Name = item.Name, - Type = item.Type, - Ratio = item.Ratio, - IsActive = item.IsActive, - Rounding = item.Rounding, - UomCategoryId = item.UomCategoryId - }); + + await _uomRepository.InsertAsync(new Uom + { + Name = item.Name, + Type = item.Type, + Ratio = item.Ratio, + IsActive = item.IsActive, + Rounding = item.Rounding, + UomCategoryId = category.Id + }); + } } } @@ -750,38 +755,49 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency { await _skillTypeRepository.InsertAsync ( - new SkillType(item.Id, item.Name) - ); + new SkillType + { + Name = item.Name + } + , autoSave: true); } } foreach (var item in items.Skills) { - var exists = await _skillRepository.AnyAsync(x => x.Name == item.Name && x.SkillTypeId == item.SkillTypeId); + var exists = await _skillRepository.AnyAsync(x => x.Name == item.Name); if (!exists) { - await _skillRepository.InsertAsync(new Skill + var skillType = await _skillTypeRepository.FirstOrDefaultAsync(x => x.Name == item.SkillTypeName); + if (skillType != null) { - Name = item.Name, - SkillTypeId = item.SkillTypeId - }); + await _skillRepository.InsertAsync(new Skill + { + Name = item.Name, + SkillTypeId = skillType.Id + }, autoSave: true); + } } } foreach (var item in items.SkillLevels) { - var exists = await _skillLevelRepository.AnyAsync(x => x.Name == item.Name && x.SkillTypeId == item.SkillTypeId); + var exists = await _skillLevelRepository.AnyAsync(x => x.Name == item.Name); if (!exists) { - await _skillLevelRepository.InsertAsync(new SkillLevel + var skillType = await _skillTypeRepository.FirstOrDefaultAsync(x => x.Name == item.SkillTypeName); + if (skillType != null) { - Name = item.Name, - Progress = item.Progress, - IsDefault = item.IsDefault, - SkillTypeId = item.SkillTypeId, - }); + await _skillLevelRepository.InsertAsync(new SkillLevel + { + Name = item.Name, + Progress = item.Progress, + IsDefault = item.IsDefault, + SkillTypeId = skillType.Id, + }, autoSave: true); + } } } @@ -819,13 +835,11 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - var newCategory = new BlogCategory( - item.Id, - item.Name, - item.Slug, - item.Description - ) + var newCategory = new BlogCategory { + Name = item.Name, + Slug = item.Slug, + Description = item.Description, DisplayOrder = item.DisplayOrder, PostCount = item.PostCount }; @@ -840,20 +854,24 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _blogPostsRepository.InsertAsync(new BlogPost( - Guid.NewGuid(), - item.Title, - item.Slug, - item.ContentTr, - item.ContentEn, - item.Summary, - item.ReadTime, - item.CoverImage, - item.CategoryId, - item.AuthorId, - true, - DateTime.UtcNow - )); + var category = await _blogCategoryRepository.FirstOrDefaultAsync(x => x.Name == item.CategoryName); + if (category != null) + { + await _blogPostsRepository.InsertAsync(new BlogPost + { + Title = item.Title, + Slug = item.Slug, + ContentTr = item.ContentTr, + ContentEn = item.ContentEn, + Summary = item.Summary, + CoverImage = item.CoverImage, + ReadTime = item.ReadTime, + CategoryId = category.Id, + AuthorId = item.AuthorId, + IsPublished = true, + PublishedAt = DateTime.UtcNow + }); + } } } @@ -863,14 +881,14 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - var newCategory = new ForumCategory( - Guid.NewGuid(), - item.Name, - item.Slug, - item.Description, - item.Icon, - item.DisplayOrder - ); + var newCategory = new ForumCategory + { + Name = item.Name, + Slug = item.Slug, + Description = item.Description, + Icon = item.Icon, + DisplayOrder = item.DisplayOrder + }; await _forumCategoryRepository.InsertAsync(newCategory); } @@ -882,10 +900,10 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _aiBotRepository.InsertAsync(new AiBot( - Guid.NewGuid(), - item.BotName - )); + await _aiBotRepository.InsertAsync(new AiBot + { + BotName = item.BotName, + }); } } @@ -930,17 +948,17 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _productRepository.InsertAsync(new Product( - Guid.NewGuid(), - item.Name, - item.Description, - item.Category, - item.Order, - item.MonthlyPrice, - item.YearlyPrice, - item.IsQuantityBased, - item.ImageUrl - )); + await _productRepository.InsertAsync(new Product + { + Name = item.Name, + Description = item.Description, + Category = item.Category, + Order = item.Order, + MonthlyPrice = item.MonthlyPrice, + YearlyPrice = item.YearlyPrice, + IsQuantityBased = item.IsQuantityBased, + ImageUrl = item.ImageUrl + }); } } @@ -950,12 +968,12 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _paymentMethodRepository.InsertAsync(new PaymentMethod( - item.Id, - item.Name, - item.Commission, - item.Logo - )); + await _paymentMethodRepository.InsertAsync(new PaymentMethod + { + Name = item.Name, + Commission = item.Commission, + Logo = item.Logo + }); } } @@ -994,11 +1012,12 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _reportCategoriesRepository.InsertAsync(new ReportCategory( - Guid.NewGuid(), - item.Name, - item.Description, - item.Icon)); + await _reportCategoriesRepository.InsertAsync(new ReportCategory + { + Name = item.Name, + Description = item.Description, + Icon = item.Icon + }); } } @@ -1008,14 +1027,14 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _servicesRepository.InsertAsync(new Service( - Guid.NewGuid(), - item.Icon, - item.Title, - item.Description, - item.Type, - item.Features - )); + await _servicesRepository.InsertAsync(new Service + { + Icon = item.Icon, + Title = item.Title, + Description = item.Description, + Type = item.Type, + Features = item.Features + }); } } @@ -1024,12 +1043,12 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency var exists = await _aboutRepository.FirstOrDefaultAsync(); if (exists == null) { - await _aboutRepository.InsertAsync(new About( - Guid.NewGuid(), - JsonSerializer.Serialize(item.Stats), - JsonSerializer.Serialize(item.Descriptions), - JsonSerializer.Serialize(item.Sections) - )); + await _aboutRepository.InsertAsync(new About + { + StatsJson = JsonSerializer.Serialize(item.Stats), + DescriptionsJson = JsonSerializer.Serialize(item.Descriptions), + SectionsJson = JsonSerializer.Serialize(item.Sections) + }); } } @@ -1038,17 +1057,17 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency var exists = await _contactRepository.FirstOrDefaultAsync(); if (exists == null) { - await _contactRepository.InsertAsync(new Contact( - Guid.NewGuid(), - item.Address, - item.Phone, - item.Email, - item.Location, - item.TaxNumber, - JsonSerializer.Serialize(item.Bank), - JsonSerializer.Serialize(item.WorkHour), - JsonSerializer.Serialize(item.Map) - )); + await _contactRepository.InsertAsync(new Contact + { + Address = item.Address, + Phone = item.Phone, + Email = item.Email, + Location = item.Location, + TaxNumber = item.TaxNumber, + BankJson = JsonSerializer.Serialize(item.Bank), + WorkHoursJson = JsonSerializer.Serialize(item.WorkHour), + MapJson = JsonSerializer.Serialize(item.Map) + }); } } @@ -1058,19 +1077,19 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _classroomRepository.InsertAsync(new Classroom( - Guid.NewGuid(), - item.Name, - item.Description, - item.Subject, - item.TeacherId, - item.TeacherName, - item.ScheduledStartTime, - item.ScheduledEndTime, - item.Duration, - item.MaxParticipants, - item.SettingsJson - )); + await _classroomRepository.InsertAsync(new Classroom + { + Name = item.Name, + Description = item.Description, + Subject = item.Subject, + TeacherId = item.TeacherId, + TeacherName = item.TeacherName, + ScheduledStartTime = item.ScheduledStartTime, + ScheduledEndTime = item.ScheduledEndTime, + Duration = item.Duration, + MaxParticipants = item.MaxParticipants, + SettingsJson = item.SettingsJson + }); } } @@ -1292,7 +1311,10 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _eventTypeRepository.InsertAsync(new EventType(item.Id, item.Name)); + await _eventTypeRepository.InsertAsync(new EventType + { + Name = item.Name + }); } } @@ -1302,7 +1324,10 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _eventCategoryRepository.InsertAsync(new EventCategory(item.Id, item.Name)); + await _eventCategoryRepository.InsertAsync(new EventCategory + { + Name = item.Name + }); } } @@ -1354,11 +1379,11 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _registrationTypeRepository.InsertAsync(new RegistrationType( - item.Id, - item.Name, - item.Status - )); + await _registrationTypeRepository.InsertAsync(new RegistrationType + { + Name = item.Name, + Status = item.Status + }); } } @@ -1368,12 +1393,16 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _registrationMethodRepository.InsertAsync(new RegistrationMethod + var registrationType = await _registrationTypeRepository.FirstOrDefaultAsync(x => x.Name == item.RegistrationTypeName); + if (registrationType != null) { - RegistrationTypeId = item.RegistrationTypeId, - Name = item.Name, - Status = item.Status - }); + await _registrationMethodRepository.InsertAsync(new RegistrationMethod + { + RegistrationTypeId = registrationType.Id, + Name = item.Name, + Status = item.Status + }); + } } } @@ -1383,14 +1412,18 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _classTypeRepository.InsertAsync(new ClassType( - item.Id, - item.RegistrationTypeId, - item.Name, - item.MinStudentCount, - item.MaxStudentCount, - item.Status - )); + var registrationType = await _registrationTypeRepository.FirstOrDefaultAsync(x => x.Name == item.RegistrationTypeName); + if (registrationType != null) + { + await _classTypeRepository.InsertAsync(new ClassType + { + RegistrationTypeId = registrationType.Id, + Name = item.Name, + MinStudentCount = item.MinStudentCount, + MaxStudentCount = item.MaxStudentCount, + Status = item.Status + }); + } } } @@ -1400,12 +1433,16 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _classRepository.InsertAsync(new() + var classType = await _classTypeRepository.FirstOrDefaultAsync(x => x.Name == item.ClassTypeName); + if (classType != null) { - ClassTypeId = item.ClassTypeId, - Name = item.Name, - Status = item.Status, - }); + await _classRepository.InsertAsync(new() + { + ClassTypeId = classType.Id, + Name = item.Name, + Status = item.Status, + }); + } } } @@ -1415,16 +1452,20 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency if (!exists) { - await _levelRepository.InsertAsync(new Level + var classType = await _classTypeRepository.FirstOrDefaultAsync(x => x.Name == item.ClassTypeName); + if (classType != null) { - ClassTypeId = item.ClassTypeId, - Name = item.Name, - LevelType = item.LevelType, - LessonCount = item.LessonCount, - Status = item.Status, - LessonDuration = item.LessonDuration, - MonthlyPaymentRate = item.MonthlyPaymentRate - }); + await _levelRepository.InsertAsync(new Level + { + ClassTypeId = classType.Id, + Name = item.Name, + LevelType = item.LevelType, + LessonCount = item.LessonCount, + Status = item.Status, + LessonDuration = item.LessonDuration, + MonthlyPaymentRate = item.MonthlyPaymentRate + }); + } } } } diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json index 2a413e7f..37215c40 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json @@ -3662,7 +3662,6 @@ "IsEnabled": true, "MultiTenancySide": 3 }, - { "GroupName": "App.Administration", "Name": "App.Definitions.Schedule", @@ -3711,7 +3710,6 @@ "IsEnabled": true, "MultiTenancySide": 3 }, - { "GroupName": "App.Administration", "Name": "App.Definitions.ScheduleLesson", @@ -4192,7 +4190,6 @@ "IsEnabled": true, "MultiTenancySide": 3 }, - { "GroupName": "App.Administration", "Name": "App.Definitions.Level", @@ -4241,7 +4238,6 @@ "IsEnabled": true, "MultiTenancySide": 3 }, - { "GroupName": "App.Coordinator", "Name": "App.Classroom", @@ -9213,14 +9209,18 @@ "path": "/admin/menuManager", "componentPath": "@/views/menu/MenuManager", "routeType": "protected", - "authority": ["App.Menus.Manager"] + "authority": [ + "App.Menus.Manager" + ] }, { "key": "admin.listFormManagement.wizard", "path": "/admin/listform/wizard", "componentPath": "@/views/admin/listForm/Wizard", "routeType": "protected", - "authority": ["App.Listforms.Wizard"] + "authority": [ + "App.Listforms.Wizard" + ] }, { "key": "admin.listFormManagement.edit", @@ -9234,14 +9234,18 @@ "path": "/admin/forumManagement", "componentPath": "@/views/forum/Management", "routeType": "protected", - "authority": ["App.ForumManagement"] + "authority": [ + "App.ForumManagement" + ] }, { "key": "admin.ai", "path": "/admin/ai", "componentPath": "@/views/ai/Assistant", "routeType": "protected", - "authority": ["Abp.Identity.Ai"] + "authority": [ + "Abp.Identity.Ai" + ] }, { "key": "admin.profile.general", @@ -9283,28 +9287,36 @@ "path": "/admin/settings", "componentPath": "@/views/settings/Settings", "routeType": "protected", - "authority": ["App.Setting"] + "authority": [ + "App.Setting" + ] }, { "key": "admin.identity.user.detail", "path": "/admin/users/detail/:userId", "componentPath": "@/views/admin/user-management/Details", "routeType": "protected", - "authority": ["AbpIdentity.Users.Update"] + "authority": [ + "AbpIdentity.Users.Update" + ] }, { "key": "admin.identity.ous", "path": "/admin/ous", "componentPath": "@/views/admin/organization-unit/OrganizationUnits", "routeType": "protected", - "authority": ["Abp.Identity.OrganizationUnits"] + "authority": [ + "Abp.Identity.OrganizationUnits" + ] }, { "key": "admin.forum", "path": "/admin/forum", "componentPath": "@/views/forum/Forum", "routeType": "protected", - "authority": ["App.ForumManagement.Publish"] + "authority": [ + "App.ForumManagement.Publish" + ] }, { "key": "admin.list", @@ -9353,112 +9365,144 @@ "path": "/admin/developerkit", "componentPath": "@/views/developerKit/DashboardPage", "routeType": "protected", - "authority": ["App.DeveloperKit"] + "authority": [ + "App.DeveloperKit" + ] }, { "key": "admin.developerkit.entities", "path": "/admin/developerkit/entities", "componentPath": "@/views/developerKit/EntityPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Entity"] + "authority": [ + "App.DeveloperKit.Entity" + ] }, { "key": "admin.developerkit.entities.new", "path": "/admin/developerkit/entities/new", "componentPath": "@/views/developerKit/EntityDetailPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Entity"] + "authority": [ + "App.DeveloperKit.Entity" + ] }, { "key": "admin.developerkit.entities.edit", "path": "/admin/developerkit/entities/edit/:id", "componentPath": "@/views/developerKit/EntityDetailPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Entity"] + "authority": [ + "App.DeveloperKit.Entity" + ] }, { "key": "admin.developerkit.migrations", "path": "/admin/developerkit/migrations", "componentPath": "@/views/developerKit/MigrationPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Migrations"] + "authority": [ + "App.DeveloperKit.Migrations" + ] }, { "key": "admin.developerkit.endpoints", "path": "/admin/developerkit/endpoints", "componentPath": "@/views/developerKit/EndpointPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Endpoints"] + "authority": [ + "App.DeveloperKit.Endpoints" + ] }, { "key": "admin.developerkit.components", "path": "/admin/developerkit/components", "componentPath": "@/views/developerKit/ComponentPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Components"] + "authority": [ + "App.DeveloperKit.Components" + ] }, { "key": "admin.developerkit.components.new", "path": "/admin/developerkit/components/new", "componentPath": "@/views/developerKit/ComponentDetailPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Components"] + "authority": [ + "App.DeveloperKit.Components" + ] }, { "key": "admin.developerkit.components.view", "path": "/admin/developerkit/components/view/:id", "componentPath": "@/views/developerKit/ComponentDetailPage", "routeType": "protected", - "authority": ["App.DeveloperKit.Components"] + "authority": [ + "App.DeveloperKit.Components" + ] }, { "key": "admin.developerkit.components.edit", "path": "/admin/developerkit/components/edit/:id", "componentPath": "@/views/developerKit/CodePage", "routeType": "protected", - "authority": ["App.DeveloperKit.Components"] + "authority": [ + "App.DeveloperKit.Components" + ] }, { "key": "admin.reportManagement", "path": "/admin/reports/management", "componentPath": "@/views/report/DashboardPage", "routeType": "protected", - "authority": ["App.Reports.Management"] + "authority": [ + "App.Reports.Management" + ] }, { "key": "admin.reports.view", "path": "/admin/reports/:id", "componentPath": "@/views/report/ReportViewerPage", "routeType": "protected", - "authority": ["App.Reports.Categories"] + "authority": [ + "App.Reports.Categories" + ] }, { "key": "admin.classroom.dashboard", "path": "/admin/classroom/dashboard", "componentPath": "@/views/classroom/Dashboard", "routeType": "protected", - "authority": ["App.Classroom.Dashboard"] + "authority": [ + "App.Classroom.Dashboard" + ] }, { "key": "admin.classroom.classes", "path": "/admin/classroom/classes", "componentPath": "@/views/classroom/ClassList", "routeType": "protected", - "authority": ["App.Classroom.List"] + "authority": [ + "App.Classroom.List" + ] }, { "key": "admin.classroom.classroom", "path": "/admin/classroom/room/:id", "componentPath": "@/views/classroom/RoomDetail", "routeType": "protected", - "authority": ["App.Classroom.RoomDetail"] + "authority": [ + "App.Classroom.RoomDetail" + ] }, { "key": "admin.classroom.planning", "path": "/admin/classroom/planning/:id", "componentPath": "@/views/classroom/PlanningPage", "routeType": "protected", - "authority": ["App.Classroom.Planning"] + "authority": [ + "App.Classroom.Planning" + ] }, { "key": "admin.supplychain.materialTypes", @@ -16661,8 +16705,8 @@ { "resourceName": "Platform", "key": "App.Definitions.UomCategory", - "tr": "Ölçü Birimi Kategorileri", - "en": "Units of Measure Categories" + "tr": "Ölçü Kategorileri", + "en": "Unit Categories" }, { "resourceName": "Platform", @@ -21352,7 +21396,10 @@ "descriptionKey": "Abp.Localization.DefaultLanguage.Description", "defaultValue": "en", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -21386,7 +21433,10 @@ "descriptionKey": "Abp.Localization.Timezone.Description", "defaultValue": "UTC", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -21542,7 +21592,11 @@ "descriptionKey": "App.SiteManagement.Theme.Style.Description", "defaultValue": "dx.light.compact", "isVisibleToClients": true, - "providers": ["U", "G", "D"], + "providers": [ + "U", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -21590,7 +21644,10 @@ "descriptionKey": "App.SiteManagement.General.NewMemberNotificationEmails.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -21606,7 +21663,10 @@ "descriptionKey": "App.SiteManagement.General.TimedLoginEmails.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -21622,7 +21682,11 @@ "descriptionKey": "App.Sender.Sms.PostaGuvercini.Url.Description", "defaultValue": "https://www.postaguvercini.com/api_http", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21638,7 +21702,11 @@ "descriptionKey": "App.Sender.Sms.PostaGuvercini.Username.Description", "defaultValue": "2AIlj4QlCrvlbDDBS/712A==", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": true, "mainGroupKey": "App.Sender", @@ -21654,7 +21722,11 @@ "descriptionKey": "App.Sender.Sms.PostaGuvercini.Password.Description", "defaultValue": "oTuwyZM9sxfJI+jDH5wJAw==", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": true, "mainGroupKey": "App.Sender", @@ -21670,7 +21742,11 @@ "descriptionKey": "App.Sender.WhatsApp.Url.Description", "defaultValue": "https://graph.facebook.com/v21.0", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21686,7 +21762,11 @@ "descriptionKey": "App.Sender.WhatsApp.PhoneNumberId.Description", "defaultValue": "442035112335974", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21702,7 +21782,11 @@ "descriptionKey": "App.Sender.WhatsApp.Token.Description", "defaultValue": "EAANoftqZAJ64BO5oPwXPqniUtNGF70u8TKvQVzGZBaYQh5UY8fYrgQkcXP9UbQUqT9PWRah1L7TzcBIiWQMacT8AkmZB33AP1begLoywIZCsQSdBSUz21GQaCowfVosYgBoXSyqH8irSBPQDLIjxxVxrC2n76SD9X6zPXeHgOqIPY92DqJXplstWrlhtZCAZDZD", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21718,7 +21802,11 @@ "descriptionKey": "App.Sender.WhatsApp.TemplateName.Description", "defaultValue": "kurs_platform_notification", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21734,7 +21822,10 @@ "descriptionKey": "App.Sender.Rocket.Url.Description", "defaultValue": "https://chat.sozsoft.com/api/v1", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21750,7 +21841,10 @@ "descriptionKey": "App.Sender.Rocket.UserId.Description", "defaultValue": "LfpzPjzag4QJXm84N", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21766,7 +21860,10 @@ "descriptionKey": "App.Sender.Rocket.Token.Description", "defaultValue": "jvqALawvXn0Q7c6FfHJV3h58DCHDfQLgFF5y7oIc7oc", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -21782,7 +21879,11 @@ "descriptionKey": "Abp.Mailing.DefaultFromDisplayName.Description", "defaultValue": "Kurs", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21798,7 +21899,11 @@ "descriptionKey": "Abp.Mailing.DefaultFromAddress.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21814,7 +21919,11 @@ "descriptionKey": "Abp.Mailing.Smtp.UserName.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21830,7 +21939,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Password.Description", "defaultValue": "QT9L7BCl1CT/1Hq19HoSlQ==", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": true, "mainGroupKey": "Abp.Mailing", @@ -21846,7 +21959,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Host.Description", "defaultValue": "127.0.0.1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21862,7 +21979,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Port.Description", "defaultValue": "25", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21878,7 +21999,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Domain.Description", "defaultValue": "sozsoft.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21894,7 +22019,11 @@ "descriptionKey": "Abp.Mailing.Smtp.EnableSsl.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21910,7 +22039,11 @@ "descriptionKey": "Abp.Mailing.AWS.Profile.Description", "defaultValue": "mail-sdk-user", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21926,7 +22059,11 @@ "descriptionKey": "Abp.Mailing.AWS.Region.Description", "defaultValue": "eu-central-1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21942,7 +22079,11 @@ "descriptionKey": "Abp.Mailing.AWS.AccessKey.Description", "defaultValue": "aXW8L21rP6dPO6Txj76Be2FCpWRBa25EMrSAVL76", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21958,7 +22099,11 @@ "descriptionKey": "Abp.Mailing.AWS.AccessKeyId.Description", "defaultValue": "AKIATULUYBLX4IY3S2P1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -21974,7 +22119,10 @@ "descriptionKey": "Abp.Account.IsSelfRegistrationEnabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -21990,7 +22138,10 @@ "descriptionKey": "Abp.Account.EnableLocalLogin.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -22006,7 +22157,11 @@ "descriptionKey": "Abp.Account.TwoFactor.Enabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -22022,7 +22177,10 @@ "descriptionKey": "Abp.Account.Captcha.MaxFailedAccessAttempts.Description", "defaultValue": "3", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -22038,7 +22196,10 @@ "descriptionKey": "Abp.Account.Captcha.EndPoint.Description", "defaultValue": "https://challenges.cloudflare.com/turnstile/v0/siteverify", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -22054,7 +22215,10 @@ "descriptionKey": "Abp.Account.Captcha.SiteKey.Description", "defaultValue": "0x4AAAAAAAGadwQME-GSYuJU", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -22070,7 +22234,10 @@ "descriptionKey": "Abp.Account.Captcha.SecretKey.Description", "defaultValue": "0x4AAAAAAAGad_f_WP47IcNBs9FTu5DhNX8", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -22086,7 +22253,11 @@ "descriptionKey": "Abp.Identity.Profile.General.RequireVerifiedAccount.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22102,7 +22273,11 @@ "descriptionKey": "Abp.Identity.Profile.General.BlacklistedEmailProviders.Description", "defaultValue": "gmail.com\r\nyahoo.com\r\nhotmail.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22118,7 +22293,11 @@ "descriptionKey": "Abp.Identity.Password.ForceUsersToPeriodicallyChangePassword.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22134,7 +22313,11 @@ "descriptionKey": "Abp.Identity.Password.PasswordChangePeriodDays.Description", "defaultValue": "0", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22150,7 +22333,11 @@ "descriptionKey": "Abp.Identity.Password.RequiredLength.Description", "defaultValue": "6", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22166,7 +22353,11 @@ "descriptionKey": "Abp.Identity.Password.RequiredUniqueChars.Description", "defaultValue": "1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22182,7 +22373,11 @@ "descriptionKey": "Abp.Identity.Password.RequireNonAlphanumeric.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22198,7 +22393,11 @@ "descriptionKey": "Abp.Identity.Password.RequireLowercase.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22214,7 +22413,11 @@ "descriptionKey": "Abp.Identity.Password.RequireUppercase.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22230,7 +22433,11 @@ "descriptionKey": "Abp.Identity.Password.RequireDigit.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22246,7 +22453,11 @@ "descriptionKey": "Abp.Identity.Lockout.AllowedForNewUsers.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22262,7 +22473,11 @@ "descriptionKey": "Abp.Identity.Lockout.LockoutDuration.Description", "defaultValue": "300", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22278,7 +22493,11 @@ "descriptionKey": "Abp.Identity.Lockout.MaxFailedAccessAttempts.Description", "defaultValue": "5", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22294,7 +22513,10 @@ "descriptionKey": "Abp.Identity.SignIn.RequireConfirmedEmail.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22310,7 +22532,10 @@ "descriptionKey": "Abp.Identity.SignIn.RequireConfirmedPhoneNumber.Description", "defaultValue": "False", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22326,7 +22551,10 @@ "descriptionKey": "Abp.Identity.User.IsUserNameUpdateEnabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22342,7 +22570,10 @@ "descriptionKey": "Abp.Identity.User.IsEmailUpdateEnabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -22518,27 +22749,21 @@ ], "UomCategories": [ { - "Id": "1a79a36e-e062-4335-9ddf-0557c60f3ea9", "Name": "Adet" }, { - "Id": "1e97bf2c-dec8-50bb-af20-70e71d752871", "Name": "Ağırlık" }, { - "Id": "1e97bf2c-dec8-50bb-af20-70e71d752872", "Name": "Çalışma Süresi" }, { - "Id": "1e97bf2c-dec8-50bb-af20-70e71d752873", "Name": "Uzunluk / Mesafe" }, { - "Id": "1e97bf2c-dec8-50bb-af20-70e71d752874", "Name": "Yüzey" }, { - "Id": "1e97bf2c-dec8-50bb-af20-70e71d752875", "Name": "Hacim" } ], @@ -22549,7 +22774,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1a79a36e-e062-4335-9ddf-0557c60f3ea9" + "UomCategoryName": "Adet" }, { "Name": "ADET", @@ -22557,7 +22782,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1a79a36e-e062-4335-9ddf-0557c60f3ea9" + "UomCategoryName": "Adet" }, { "Name": "TAKIM", @@ -22565,7 +22790,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1a79a36e-e062-4335-9ddf-0557c60f3ea9" + "UomCategoryName": "Adet" }, { "Name": "Düzine", @@ -22573,7 +22798,7 @@ "Ratio": 12.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1a79a36e-e062-4335-9ddf-0557c60f3ea9" + "UomCategoryName": "Adet" }, { "Name": "g", @@ -22581,7 +22806,7 @@ "Ratio": 1000.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752871" + "UomCategoryName": "Ağırlık" }, { "Name": "ons", @@ -22589,7 +22814,7 @@ "Ratio": 35.274, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752871" + "UomCategoryName": "Ağırlık" }, { "Name": "pound", @@ -22597,7 +22822,7 @@ "Ratio": 2.20462, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752871" + "UomCategoryName": "Ağırlık" }, { "Name": "kg", @@ -22605,7 +22830,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752871" + "UomCategoryName": "Ağırlık" }, { "Name": "t", @@ -22613,7 +22838,7 @@ "Ratio": 1000.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752871" + "UomCategoryName": "Ağırlık" }, { "Name": "Saat", @@ -22621,7 +22846,7 @@ "Ratio": 8.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752872" + "UomCategoryName": "Çalışma Süresi" }, { "Name": "Gün", @@ -22629,7 +22854,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752872" + "UomCategoryName": "Çalışma Süresi" }, { "Name": "mm", @@ -22637,7 +22862,7 @@ "Ratio": 1000.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "cm", @@ -22645,7 +22870,7 @@ "Ratio": 100.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "inç", @@ -22653,7 +22878,7 @@ "Ratio": 39.3701, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "ayak", @@ -22661,7 +22886,7 @@ "Ratio": 3.28084, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "yd", @@ -22669,7 +22894,7 @@ "Ratio": 1.09361, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "m", @@ -22677,7 +22902,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "MT", @@ -22685,7 +22910,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "km", @@ -22693,7 +22918,7 @@ "Ratio": 1000.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "mil", @@ -22701,7 +22926,7 @@ "Ratio": 1609.34, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752873" + "UomCategoryName": "Uzunluk / Mesafe" }, { "Name": "ft²", @@ -22709,7 +22934,7 @@ "Ratio": 10.76391, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752874" + "UomCategoryName": "Yüzey" }, { "Name": "m²", @@ -22717,7 +22942,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752874" + "UomCategoryName": "Yüzey" }, { "Name": "inç³", @@ -22725,7 +22950,7 @@ "Ratio": 61.0237, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752875" + "UomCategoryName": "Hacim" }, { "Name": "sıvı ons (Amerikan)", @@ -22733,7 +22958,7 @@ "Ratio": 33.814, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752875" + "UomCategoryName": "Hacim" }, { "Name": "çeyrek(Amerikan)", @@ -22741,7 +22966,7 @@ "Ratio": 1.05669, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752875" + "UomCategoryName": "Hacim" }, { "Name": "L", @@ -22749,7 +22974,7 @@ "Ratio": 1.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752875" + "UomCategoryName": "Hacim" }, { "Name": "galon (Amerikan)", @@ -22757,7 +22982,7 @@ "Ratio": 3.78541, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752875" + "UomCategoryName": "Hacim" }, { "Name": "ayak³", @@ -22765,7 +22990,7 @@ "Ratio": 28.3168, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752875" + "UomCategoryName": "Hacim" }, { "Name": "m³", @@ -22773,7 +22998,7 @@ "Ratio": 1000.0, "IsActive": true, "Rounding": 0.01, - "UomCategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752875" + "UomCategoryName": "Hacim" } ], "Currencies": [ @@ -24167,7 +24392,6 @@ ], "BlogCategories": [ { - "Id": "1e97bf2c-dec8-50bb-af20-70e71d752871", "Name": "blog.categories.technology", "Slug": "ai-ve-gelecegi", "Description": "blog.posts.ai.excerpt", @@ -24175,7 +24399,6 @@ "PostCount": 1 }, { - "Id": "6d0ae65d-8b91-5bbf-879d-87ee25410458", "Name": "blog.categories.webdev", "Slug": "web-gelistirmede-son-trendler", "Description": "blog.posts.web.excerpt", @@ -24183,7 +24406,6 @@ "PostCount": 1 }, { - "Id": "e938e6e6-f355-5807-a7f7-f0d4fe368fc5", "Name": "blog.categories.security", "Slug": "siber-guvenlik-tehditleri-ve-korunma-yollari", "Description": "blog.posts.security.excerpt", @@ -24191,7 +24413,6 @@ "PostCount": 1 }, { - "Id": "ebd1b9aa-14ce-5c0b-9514-a4cbd5a7cf94", "Name": "blog.categories.mobile", "Slug": "mobil-uygulama-gelistirmede-cross-platform-cozumler", "Description": "blog.posts.mobile.excerpt", @@ -24199,7 +24420,6 @@ "PostCount": 1 }, { - "Id": "741ef542-0591-5472-9bf2-593047eb4122", "Name": "blog.categories.database", "Slug": "veritabani-yonetim-sistemleri-karsilastirmasi", "Description": "blog.posts.database.excerpt", @@ -24207,7 +24427,6 @@ "PostCount": 1 }, { - "Id": "dbc8578c-1a99-594a-8997-bddd0eac8571", "Name": "blog.categories.digital", "Slug": "dijital-pazarlamada-veri-analizi", "Description": "blog.posts.digital.excerpt", @@ -24217,7 +24436,6 @@ ], "BlogPosts": [ { - "TenantId": null, "Title": "blog.posts.ai.title", "Slug": "ai-ve-gelecegi", "ContentTr": "

Yapay zeka (YZ), yalnızca teknoloji dünyasının değil; üretimden finansa, sağlıktan eğitime, perakendeden hukuk sektörüne kadar birçok alanın dönüşümünü tetikleyen en güçlü araçlardan biri haline geldi. Son yıllarda yapay zekanın iş dünyasındaki etkisi, yalnızca verimliliği artırmakla kalmıyor; karar alma mekanizmalarını değiştiriyor, yeni iş modellerini mümkün kılıyor ve organizasyonel yapıların yeniden tasarlanmasını sağlıyor.

2020’li yıllarla birlikte, 'Yapay Zeka' kavramı yalnızca araştırma laboratuvarlarının değil, CEO'ların, yöneticilerin, girişimcilerin ve KOBİ’lerin gündemine girdi. Ancak bu hızlı gelişim, bazı etik ve sosyal sorumluluk konularını da beraberinde getiriyor. Bu yazıda, yapay zekanın iş dünyasındaki kullanım alanlarını, sunduğu fırsatları, karşılaşılan zorlukları ve çözülmesi gereken etik meseleleri detaylı şekilde ele alacağız.

🚀 İş Dünyasında Yapay Zeka: Neden Bu Kadar Önemli?

Yapay zeka sistemleri; büyük veri setlerini analiz ederek, kalıpları tanıyarak ve tahminlerde bulunarak işletmelere hızlı ve doğru karar alma fırsatı sunar. Bu durum, insan hatasını azaltırken, operasyonel süreçlerde zaman ve maliyet tasarrufu sağlar.

📈 YZ'nin Kurumsal Faydaları:

  • Operasyonel Verimlilik: Otomasyon ve süreç optimizasyonu ile daha az kaynakla daha fazla üretim.
  • Müşteri Deneyimi: Chatbot'lar, öneri sistemleri ve kişiselleştirilmiş hizmetler.
  • Tahminleme Yeteneği: Satış tahmini, stok yönetimi, müşteri davranışı analizi.
  • Hızlı Karar Alma: Gerçek zamanlı veriye dayalı içgörülerle karar süreçleri.

🧠 YZ'nin İşlevsel Kullanım Alanları

🏭 1. Üretim ve Lojistik

  • Arıza tahmini (predictive maintenance)
  • Akıllı robotlar ile otomatikleştirilmiş üretim hatları
  • Rota optimizasyonu, tedarik zinciri modelleme

💰 2. Finans ve Bankacılık

  • Otomatik risk analizi
  • Dolandırıcılık tespiti (fraud detection)
  • Robo-danışmanlar ile yatırım önerileri

🛒 3. Perakende ve E-Ticaret

  • Ürün öneri motorları
  • Dinamik fiyatlandırma
  • Görsel arama ile alışveriş

👩‍⚕️ 4. Sağlık

  • Görüntüleme sistemleriyle hastalık teşhisi (örneğin radyoloji)
  • Hastane kaynak planlaması
  • Sanal hasta asistanları

🧾 5. İnsan Kaynakları ve İK Analitiği

  • CV tarama ve aday sıralama
  • Çalışan bağlılığı analizi
  • Performans tahminleme

🌐 YZ’nin Getirdiği Yeni İş Modelleri

  • As-a-Service Modeller: AI-as-a-Service (AIaaS) ile küçük işletmeler bile ileri seviye AI çözümlerine erişebiliyor.
  • Otonom Karar Mekanizmaları: İnsan müdahalesine gerek kalmadan iş süreçlerinin belirli adımları AI tarafından yürütülüyor.
  • Veri Tabanlı Kültür: Veri odaklı karar verme kültürü yaygınlaşıyor, 'sezgisel yöneticilik' yerine 'algoritmik yöneticilik' ortaya çıkıyor.

⚖️ YZ ve Etik: Geleceği Belirleyen Soru İşaretleri

Her teknolojik ilerleme, yeni sorumlulukları da beraberinde getirir. Yapay zekanın iş dünyasında yaygınlaşması ile birlikte birçok etik tartışma gündeme gelmiştir.

🔍 Başlıca Etik Sorunlar:

  • Veri Gizliliği: YZ sistemlerinin çalışabilmesi için büyük miktarda veri gerekir. Bu verilerin toplanması, saklanması ve kullanımı ne kadar etik?
  • Karar Şeffaflığı: YZ'nin aldığı kararlar neden ve nasıl alınıyor? Algoritmalar 'açıklanabilir' mi?
  • Önyargı (Bias) Riski: Eğitim verisindeki önyargılar (cinsiyet, ırk vb.) algoritmaya da yansıyabilir.
  • İş Gücü Etkisi: Otomasyon bazı meslekleri ortadan kaldırabilir. Toplum nasıl adapte olacak?

🌱 Kurumlar Ne Yapmalı?

  • Etik kurullar kurmalı
  • Yapay zekada şeffaflık ilkesi benimsenmeli
  • Algoritmik denetim ve insan gözetimi sağlanmalı
  • Yeniden beceri kazandırma (reskilling) programları başlatılmalı

👥 İnsan ve Yapay Zeka: Rekabet mi? İşbirliği mi?

YZ’nin insanlar yerine geçtiği değil, insanla birlikte çalıştığı senaryolar her geçen gün daha değerli hale geliyor. Bu bağlamda 'human-in-the-loop' ve 'augmented intelligence' (tamamlayıcı zekâ) yaklaşımları öne çıkıyor.

💡 İnsanlar strateji, empati ve yaratıcılıkta güçlüdür. Yapay zeka ise hız, hesaplama ve analizde. İkisini birlikte kullanmak rekabet avantajı yaratır.

📌 YZ’ye Hazır Olmak İçin Kurumların Atması Gereken Adımlar

  1. YZ Stratejisi Oluşturun: Hangi süreçlerde yapay zekadan fayda sağlanabileceğini belirleyin.
  2. Veri Kalitesine Yatırım Yapın: AI, kaliteli veri ile beslenir.
  3. İçeriden Yetkinlik Geliştirin: Veri bilimciler, ML mühendisleri ve etik uzmanları yetiştirin.
  4. Pilot Projeler Başlatın: Düşük riskli alanlarda başlayarak öğrenme sürecini başlatın.
  5. Etik ve Hukuki Uyum Süreçlerini Tanımlayın.

Sonuç: Yapay Zeka, Geleceğin Değil; Bugünün Gerçeği

Yapay zekâ artık sadece büyük teknoloji şirketlerinin değil, her ölçekteki işletmenin gündeminde yer almalıdır. Karar süreçlerini hızlandırmak, müşteriyi daha iyi tanımak, rekabette öne geçmek için YZ bir lüks değil, stratejik zorunluluk haline gelmiştir. Ancak bu gücün etik, şeffaf ve sorumlu şekilde kullanılması, geleceğimizi şekillendirmede belirleyici olacaktır.

Unutmayın: Yapay zeka, yalnızca bir teknoloji değil; yeni bir iş yapma biçimidir.

", @@ -24225,11 +24443,10 @@ "ReadTime": "5 dk", "Summary": "blog.posts.ai.excerpt", "CoverImage": "https://images.pexels.com/photos/8386434/pexels-photo-8386434.jpeg?auto=compress&cs=tinysrgb&w=1920", - "CategoryId": "1e97bf2c-dec8-50bb-af20-70e71d752871", + "CategoryName": "blog.categories.technology", "AuthorId": "1668adf0-fd2a-5216-9834-6b6874ec2a05" }, { - "TenantId": null, "Title": "blog.posts.web.title", "Slug": "web-gelistirmede-son-trendler", "ContentTr": "

Web teknolojileri, dijital dünyanın kalbinde yer almaya devam ediyor. 1990'ların basit HTML sayfalarından günümüzün dinamik, gerçek zamanlı ve yapay zekâ destekli web uygulamalarına kadar uzanan bu yolculuk, her yıl yeni paradigmalar, araçlar ve yaklaşımlar ortaya koyuyor. 2024 itibarıyla web geliştirme alanında yaşanan dönüşüm, yalnızca geliştiriciler için değil, ürün sahipleri, tasarımcılar ve iş dünyası için de oyunun kurallarını yeniden yazıyor.

Bu yazıda; Serverless mimari, WebAssembly, mikro ön yüzler, edge computing, yapay zekâ destekli geliştirme, Progressive Web Apps (PWA), modern frontend framework gelişmeleri ve daha fazlasını içeren kapsamlı bir trend analizine yer vereceğiz.

☁️ 1. Serverless Mimarilerin Yükselişi

Serverless (sunucusuz mimari), geliştiricilerin altyapı yönetimiyle uğraşmadan, sadece işlev (function) bazlı geliştirme yapmasına olanak tanır. Sunucular elbette vardır, ancak bu sunucuların kurulumu, ölçeklenmesi ve yönetimi bulut sağlayıcılar tarafından yapılır.

🚀 Öne Çıkan Faydalar:

  • Maliyet avantajı: Kullanım bazlı faturalama (pay-as-you-go)
  • Yüksek ölçeklenebilirlik: Trafiğe göre otomatik ayarlama
  • Hızlı prototipleme ve üretim süreci

🔧 Popüler Serverless Platformlar:

  • AWS Lambda
  • Azure Functions
  • Google Cloud Functions
  • Vercel / Netlify (Functions + Deployment)

⚙️ 2. WebAssembly (Wasm): Tarayıcıda Performans Devrimi

WebAssembly, C/C++, Rust, Go gibi dillerde yazılan kodların tarayıcıda neredeyse yerel hızda çalıştırılmasını sağlar. JavaScript’in sınırlarını zorlayan uygulamalar (video düzenleme, oyun, CAD, 3D modelleme) artık web üzerinde kullanılabilir hale geliyor.

🎯 Kullanım Senaryoları:

  • Gerçek zamanlı görüntü işleme
  • Bilimsel hesaplamalar
  • Oyun motorları (Unity, Godot Web)
  • Machine Learning inference işlemleri

🔥 Neden Önemli?

Wasm sayesinde web yalnızca formlar ve içerik sunan bir platform değil; yüksek performanslı uygulamalar için gerçek bir çalışma ortamı haline geliyor.

🧩 3. Mikro Ön Uç Mimarileri

Micro Frontends, monolitik frontend yapılarının yönetimini kolaylaştırmak için ortaya çıkmış modern bir yaklaşımdır. Her ekip kendi bileşenini bağımsız geliştirip dağıtabilir.

📦 Faydaları:

  • Ekiplerin paralel çalışması
  • Teknoloji bağımsızlığı (bir modül React, diğeri Vue olabilir)
  • Hata izolasyonu

📚 Uygulama Teknikleri:

  • Module Federation (Webpack 5)
  • Web Components (Shadow DOM)
  • iframe tabanlı segmentasyon (eski yöntem)

🛰️ 4. Edge Computing ile Daha Hızlı Web Deneyimi

Web içerikleri, CDN’lerin ötesine geçerek doğrudan uç noktalarda (edge) işlenmeye başladı. Bu yaklaşım, sunucuya ulaşma süresini minimuma indirerek milisaniyelik farklarla daha hızlı uygulamalar ortaya çıkarır.

⚙️ Edge Bileşenleri:

  • Cloudflare Workers
  • Vercel Edge Functions
  • Netlify Edge Middleware

🤖 5. AI Destekli Web Geliştirme

Yapay zekâ, artık sadece kullanıcıya sunduğunuz deneyimi değil, doğrudan geliştirme sürecini de dönüştürüyor.

💡 Kullanım Alanları:

  • Kod önerileri (GitHub Copilot, Amazon CodeWhisperer)
  • Otomatik test senaryosu üretimi
  • Tasarımdan HTML'e otomatik geçiş (Figma to Code)
  • Kullanıcı etkileşimlerine göre otomatik UI güncellemeleri

📲 6. Progressive Web Apps (PWA): Uygulama Gibi Web

PWA’lar, tarayıcıdan erişilen ama mobil uygulama gibi çalışan web uygulamalarıdır.

Özellikleri:

  • Offline çalışabilir
  • Ana ekrana eklenebilir
  • Push bildirimleri alabilir

Kullanım Alanı:

  • Haber siteleri
  • E-ticaret uygulamaları
  • Eğitim platformları

🧪 7. Modern JavaScript Framework Gelişmeleri

🔹 React (Server Components + RSC)

React, sunucu taraflı bileşenlerle (RSC) artık daha az JS yükleyerek SEO ve performans sorunlarını çözmeye yöneliyor.

🔹 Vue 3 + Vite

Composition API, reactive sistem ve Vite entegrasyonu ile Vue 3, performans ve geliştirici deneyimi açısından büyük atılım yaptı.

🔹 Svelte ve SvelteKit

Compile-time çalışan Svelte, JS bundle boyutlarını azaltarak son kullanıcıya neredeyse anında sayfa yükleme deneyimi sunar.

🔹 Astro

'Island Architecture' yaklaşımıyla yalnızca etkileşimli alanlara JS yükler, geri kalanı statik tutar.

🧱 8. Yeni Nesil CSS: Utility-First, CSS-in-JS ve Tailwind Ekosistemi

  • Tailwind CSS, atomic/utility-first yaklaşımıyla devrim yaratmaya devam ediyor.
  • CSS-in-JS (styled-components, Emotion) ile bileşen bazlı stillendirme yaygınlaştı.
  • Container Queries, native responsive mimaride yeni bir çağ açıyor.
  • CSS Variables + Dark Mode desteği yaygınlaştı.

🔐 9. Web Güvenliği Trendleri

  • Content Security Policy (CSP) uygulamaları artıyor.
  • Subresource Integrity (SRI) ile CDN'den gelen dosyaların bütünlüğü kontrol ediliyor.
  • SameSite Cookie kullanımı yaygınlaştı.
  • OAuth2, OpenID Connect ve WebAuthn gibi kimlik doğrulama standartları ön plana çıkıyor.

🧠 10. Geliştirici Deneyimini Arttıran Araçlar

  • Vite, Webpack’e göre daha hızlı dev ve build süreciyle öne çıkıyor.
  • ESLint + Prettier kombinasyonuyla kod kalitesi kontrol altında.
  • Turborepo, monorepo yönetimini kolaylaştırıyor.
  • Storybook, bileşen odaklı UI geliştirmede standart haline geliyor.

🔚 Sonuç: Geleceğe Hazır Web Geliştirici Olmak

2024’ün öne çıkan web geliştirme trendleri, yalnızca araçlarla ilgili değil; aynı zamanda yaklaşım ve mimari farkındalıkla da ilgilidir. Web geliştirici olarak yalnızca bir framework’ü öğrenmek değil, neden o teknolojiyi seçtiğinizi bilmek, yazılım kalitenizi ve uzun vadeli sürdürülebilirliği belirler.

Geleceğin web dünyasında yer almak için:

  • Modüler ve ölçeklenebilir düşünün,
  • Performans odaklı geliştirin,
  • Güvenliği en baştan tasarlayın,
  • Öğrenmeye ve değişime açık kalın.


", @@ -24237,11 +24454,10 @@ "ReadTime": "7 dk", "Summary": "blog.posts.web.excerpt", "CoverImage": "https://images.pexels.com/photos/11035471/pexels-photo-11035471.jpeg?auto=compress&cs=tinysrgb&w=1920", - "CategoryId": "6d0ae65d-8b91-5bbf-879d-87ee25410458", + "CategoryName": "blog.categories.webdev", "AuthorId": "7df16a77-92ed-50e6-8749-ae34345c01b9" }, { - "TenantId": null, "Title": "blog.posts.security.title", "Slug": "siber-guvenlik-tehditleri-ve-korunma-yollari", "ContentTr": "

Dijitalleşmenin yaşamın her alanına nüfuz ettiği günümüzde, siber güvenlik artık yalnızca bir IT meselesi olmaktan çıkmış, bireylerin, küçük işletmelerin ve devasa kurumların ortak sorumluluğu haline gelmiştir. İnternete bağlı her cihaz, her hesap ve her uygulama, potansiyel bir saldırı yüzeyi olarak değerlendirilebilir. Siber saldırıların sayısı her geçen yıl artarken, saldırıların karmaşıklığı ve hedef kitlesi de genişlemektedir.

Günümüz siber tehdit ortamı; kişisel veri hırsızlığı, fidye yazılımları, kimlik avı saldırıları, sıfır gün açıkları, DDoS saldırıları ve daha pek çok sofistike yöntemle şekilleniyor. Bu yazıda, siber tehditleri daha yakından tanıyacak, bireysel ve kurumsal düzeyde alınabilecek etkili güvenlik önlemlerini ele alacak ve dijital dünyada güvenlik kültürünü nasıl geliştirebileceğinizi detaylarıyla paylaşacağız.

🚨 Siber Tehdit Türleri ve Nasıl Çalışırlar?

🔐 1. Kimlik Avı (Phishing)

Saldırganların sahte e-posta, SMS veya web siteleri aracılığıyla kullanıcıları kandırarak şifre, kredi kartı bilgisi gibi hassas verilerini ele geçirmeye çalıştığı saldırı türüdür. Genellikle aciliyet duygusu yaratılarak kullanıcı aksiyona zorlanır.

Korunma Yolu: E-posta adresinin doğruluğunu kontrol etmek, bilinmeyen bağlantılara tıklamamak, görsel olarak profesyonel görünen ancak dilbilgisi hataları barındıran iletilere karşı dikkatli olmak.

💣 2. Fidye Yazılımı (Ransomware)

Bilgisayarınıza bulaştıktan sonra dosyalarınızı şifreleyen ve şifreyi açmak için fidye talep eden yazılımlardır. En bilinen örneklerinden biri WannaCry saldırısıdır.

Korunma Yolu: Güncel antivirüs kullanmak, sistem ve uygulama yamalarını zamanında yapmak, düzenli olarak offline yedek almak, bilinmeyen dosyaları açmamak.

🌐 3. DDoS (Dağıtılmış Hizmet Engelleme) Saldırıları

Çok sayıda sistemden hedef sunucuya aşırı istek gönderilerek sistemin hizmet veremez hale getirilmesidir. Özellikle online hizmet sunan firmalar için büyük risk taşır.

Korunma Yolu: Yük dengeleyiciler, firewall’lar ve DDoS önleme servisleri (Cloudflare, AWS Shield vb.) kullanmak.

🐞 4. Sıfır Gün Açıkları (Zero-Day Exploits)

Henüz keşfedilmemiş veya yayınlanmamış yazılım açıklarının kötü niyetli kişilerce kullanılmasıdır. Bu tür açıklar genellikle çok hızlı etkiler yaratır.

Korunma Yolu: Yazılım sağlayıcılarının güvenlik duyurularını takip etmek, sistemleri sürekli güncel tutmak, davranışsal tehdit algılama sistemleri kullanmak.

🧑‍💻 5. İç Tehditler (Insider Threats)

Kurum içinde çalışan kişilerin (kasıtlı veya kazara) bilgi sızdırması ya da zarara yol açmasıdır. En tehlikeli ve gözden kaçan tehditlerden biridir.

Korunma Yolu: Rol tabanlı erişim kontrolü, kullanıcı aktivitelerinin loglanması, veri kaybı önleme (DLP) çözümleri.

🛡️ Bireyler İçin Uygulanabilir Siber Güvenlik İpuçları

🔑 Güçlü Şifreler Kullanın

  • Şifreniz en az 12 karakter olmalı.
  • Büyük/küçük harf, sayı ve özel karakter içermeli.
  • Her hesap için farklı şifre kullanın.

💡 Yardımcı: Bitwarden, 1Password gibi şifre yöneticileri kullanın.

📲 İki Faktörlü Kimlik Doğrulama (2FA) Kullanın

Şifreniz çalınsa bile, ikinci doğrulama faktörü (SMS, e-posta, Authenticator uygulaması) sizi korur.

💻 Yazılımları Güncel Tutun

Güvenlik açıklarının büyük kısmı, zamanında yapılmayan yazılım güncellemeleri nedeniyle istismar edilir.

✉️ E-Posta ve Linklerde Dikkatli Olun

  • “.exe”, “.zip”, “.scr” gibi uzantılara sahip eklentilerden kaçının.
  • “Resmi gibi görünen” ama garip domainlerden gelen e-postaları ciddiye almayın.

🌐 Halka Açık Wi-Fi Kullanırken Dikkat

  • Hassas işlemleri (banka, ödeme vs.) yapmaktan kaçının.
  • VPN kullanarak bağlantınızı şifreleyin.

🔍 Sosyal Medyada Paylaşımlara Dikkat

  • Doğum tarihiniz, ev adresiniz, kimlik bilgileriniz gibi kişisel bilgileri açık etmeyin.
  • “Bu testi çöz ve hangi kahramansın öğren!” türü uygulamalardan kaçının.

🏢 Kurumlar İçin Siber Güvenlik Stratejileri

  1. Güvenlik Farkındalık Eğitimi: Personelin sosyal mühendislik saldırılarına karşı eğitilmesi şarttır.
  2. Yedekleme Politikası: Kritik veriler yedeklenmeli ve test edilmelidir.
  3. Erişim Yetkileri: Her kullanıcı sadece ihtiyacı olan verilere erişebilmeli.
  4. Güvenlik Duvarı ve IDS/IPS Kullanımı: Ağa gelen trafiğin kontrol edilmesi şarttır.
  5. Sızma Testleri ve Güvenlik Denetimleri: Periyodik olarak yapılmalı, zayıf noktalar proaktif olarak kapatılmalı.

🧠 Siber Güvenlik Kültürü: En Güçlü Savunma

En gelişmiş yazılımlar, en pahalı donanımlar dahi, bilinçsiz kullanıcılar tarafından etkisiz hale getirilebilir. Bu nedenle:

  • Her düzeyde güvenlik farkındalığı şarttır.
  • Güvenlik, sadece IT'nin değil tüm organizasyonun sorumluluğudur.
  • Proaktif önlemler, reaktif çözümlerden her zaman daha ekonomiktir.

Sonuç: Bilgi Güvenliği, Dijital Hayatın Sigortasıdır

Siber güvenlik, artık lüks değil; bir zorunluluktur. Bireyler olarak dijital ayak izimize sahip çıkmalı, kurumlar olarak siber dayanıklılığımızı artırmalıyız. Teknolojinin faydalarını güven içinde kullanabilmek için bilinçli kullanıcı olmak, güvenlik politikalarını uygulamak ve sürekli gelişen tehditlere karşı tetikte olmak şarttır.

Unutmayın: Siber güvenlik sadece bir teknoloji değil, bir yaşam tarzıdır.

", @@ -24249,10 +24465,10 @@ "ReadTime": "6 dk", "Summary": "blog.posts.security.excerpt", "CoverImage": "https://images.pexels.com/photos/5380642/pexels-photo-5380642.jpeg?auto=compress&cs=tinysrgb&w=1920", - "CategoryId": "e938e6e6-f355-5807-a7f7-f0d4fe368fc5" + "CategoryName": "blog.categories.security", + "AuthorId": "c107a187-5e41-51e1-a5b3-5bf85c16b39e" }, { - "TenantId": null, "Title": "blog.posts.mobile.title", "Slug": "mobil-uygulama-gelistirmede-cross-platform-cozumler", "ContentTr": "

Mobil teknolojiler, modern yaşamın ayrılmaz bir parçası haline gelmiş durumda. Günümüzde milyarlarca insanın elinde taşıdığı akıllı cihazlar, işletmeler için yeni fırsatlar ve aynı zamanda rekabet baskısı yaratıyor. Kullanıcılar, markalarla etkileşim kurmak, hizmet almak veya ürün satın almak için mobil uygulamaları tercih ediyor. Bu da mobil uygulama geliştirmeyi, yazılım dünyasının en stratejik ve talep gören alanlarından biri haline getiriyor.

📱 Mobil Uygulama Geliştirmeye Genel Bakış

Mobil uygulamalar iki ana kategoriye ayrılır:

  1. Native Uygulamalar: iOS için Swift/Objective-C ve Android için Kotlin/Java kullanılarak geliştirilir. Her platform için ayrı kod yazılır.
  2. Cross-Platform (Çapraz Platform) Uygulamalar: Tek bir kod tabanı ile birden fazla platformda (iOS, Android) çalışabilir uygulamalar geliştirilebilir.

Native uygulamalar yüksek performans ve platforma özel deneyim sunsa da, geliştirme maliyetleri ve zaman açısından zorluklar barındırır. Her platform için ayrı geliştirici, ayrı test ve ayrı sürüm yönetimi gerekir. Bu noktada, cross-platform geliştirme paradigması devreye girer.

🌐 Cross-Platform Geliştirmenin Temel Avantajları

1. Tek Kod Tabanı, Daha Az Geliştirme Süresi

Geliştiriciler yalnızca bir kez kod yazar ve bu kod hem iOS hem de Android için kullanılır. Bu, geliştirme süresini önemli ölçüde azaltır.

2. Maliyet Tasarrufu

Ayrı ayrı mobil geliştirici ekipleri kurmaya gerek kalmaz. Daha küçük bir ekiple daha kısa sürede üretim yapılabilir.

3. Kolay Bakım ve Güncelleme

Tek bir kod üzerinde yapılacak güncelleme, tüm platformlarda etkili olur. Bu da bakım maliyetlerini düşürür ve hata yönetimini kolaylaştırır.

4. Hızlı MVP Geliştirme

Minimum Viable Product (MVP) geliştirmek isteyen startup’lar için idealdir. Hızla piyasaya çıkıp kullanıcı geri bildirimi toplanabilir.

5. Platformlar Arası Tutarlılık

Aynı kod tabanı, UI/UX açısından platformlar arası tutarlılığı sağlar.

🧪 Cross-Platform Geliştirmenin Zorlukları

1. Performans Kısıtları

Native'e göre bir miktar performans kaybı olabilir. Özellikle grafik yoğun uygulamalarda bu fark hissedilir.

2. Donanım Özelliklerine Kısıtlı Erişim

Kamera, Bluetooth, sensörler gibi donanıma erişim native kadar doğrudan olmayabilir. Ek köprü çözümler (bridges/plugins) gerekir.

3. Platforma Özel UX Detayları

Her platformun kendi kullanıcı alışkanlıkları vardır. Tek tip tasarım, platforma özel deneyimi yansıtamayabilir.

4. Framework Güncellemelerine Bağımlılık

Kullandığınız framework’ün gelişim hızına ve topluluğuna bağlı olarak bazı güncellemeler beklemek gerekebilir.

🚀 Popüler Cross-Platform Frameworkler

🔹 React Native (Facebook)

  • Dil: JavaScript / TypeScript
  • Avantajlar: Geniş topluluk, zengin bileşen kütüphaneleri, Native modül desteği.
  • Dezavantajlar: Performans kritik uygulamalarda sınırlı olabilir.
  • Kullanım Alanı: Sosyal medya, e-ticaret, içerik yönetimi uygulamaları.

🔹 Flutter (Google)

  • Dil: Dart
  • Avantajlar: Yüksek performans, zengin UI, native benzeri his.
  • Dezavantajlar: Dart dili geliştiricilere yabancı olabilir, büyük boyutlu uygulama paketleri.
  • Kullanım Alanı: Görsel yoğun uygulamalar, animasyonlu içerikler.

🔹 Xamarin (Microsoft)

  • Dil: C# / .NET
  • Avantajlar: .NET tabanlı projelerle uyum, native API erişimi.
  • Dezavantajlar: Zayıf topluluk etkileşimi, UI özelleştirme karmaşıklığı.
  • Kullanım Alanı: Kurumsal uygulamalar, Microsoft ekosistemine entegre sistemler.

🔹 Capacitor / Ionic (WebView Tabanlı)

  • Dil: HTML, CSS, JavaScript
  • Avantajlar: Web teknolojileriyle mobil uygulama geliştirme, hızlı prototipleme.
  • Dezavantajlar: Performans zayıf, donanıma erişim kısıtlı.
  • Kullanım Alanı: Form tabanlı uygulamalar, bilgi servisleri.

🧩 Hangi Framework Hangi Proje İçin Daha Uygun?

Proje TipiÖnerilen FrameworkNeden?MVP geliştirmeFlutter, React NativeHızlı geliştirme ve UI avantajıKurumsal uygulamalarXamarin.NET altyapısıyla uyumGörsel yoğun mobil uygulamalarFlutterYüksek performanslı UIMevcut web projesini mobil yapmakIonic, React NativeWeb bilgi birikiminin kullanımıYüksek performanslı oyun/AR/VRNativeMaksimum donanım kontrolü


🛠️ Performans, Test ve Bakım Açısından Değerlendirme

  • Performans: Flutter, performans açısından React Native'e göre genellikle bir adım öndedir. Dart ile doğrudan native bytecode’a dönüşüm yapılır.
  • Test: Flutter, widget testleri için yerleşik destek sunarken, React Native topluluk tabanlı çözümlere dayanır.
  • Sürüm Yönetimi: Tek kod tabanı, versiyon güncellemelerini merkezi hale getirir. Ancak App Store ve Play Store süreçleri yine ayrı yürütülür.

🎯 Sonuç: Doğru Framework = Başarılı Mobil Strateji

Cross-platform mobil geliştirme, özellikle kaynakları sınırlı ama zaman baskısı yüksek olan projelerde mükemmel bir çözüm sunar. Ancak her çözüm gibi, bu yaklaşım da kendi içinde dikkatli bir değerlendirme ister. Uygulamanızın doğası, kullanıcı kitleniz, performans gereksinimleriniz ve teknik kadronuzun yetkinlikleri bu kararda belirleyici olmalıdır.

Karmaşık donanım etkileşimleri gerektiren oyunlar, yüksek hassasiyetli medya uygulamaları gibi özel durumlar dışında, cross-platform çözümler modern uygulama geliştirme süreçlerinin merkezinde yer almaya devam edecektir.

", @@ -24260,11 +24476,10 @@ "Summary": "blog.posts.mobile.excerpt", "ReadTime": "4 dk", "CoverImage": "https://images.pexels.com/photos/13017583/pexels-photo-13017583.jpeg?auto=compress&cs=tinysrgb&w=1920", - "CategoryId": "ebd1b9aa-14ce-5c0b-9514-a4cbd5a7cf94", + "CategoryName": "blog.categories.mobile", "AuthorId": "c107a187-5e41-51e1-a5b3-5bf85c16b39e" }, { - "TenantId": null, "Title": "blog.posts.database.title", "Slug": "veritabani-yonetim-sistemleri-karsilastirmasi", "ContentTr": "

Veritabanları, günümüzün dijital dünyasında veri temelli karar alma süreçlerinin, web ve mobil uygulamaların, iş zekası çözümlerinin ve büyük veri altyapılarının temel yapı taşlarından biridir. Özellikle veri hacminin, veri çeşitliliğinin ve veri erişim gereksinimlerinin sürekli arttığı günümüzde, uygun bir veritabanı yönetim sistemi (VTYS) seçimi yapmak, teknik olduğu kadar stratejik de bir karardır. Geliştiriciler, yazılım mimarları ve karar vericiler için bu yazı, ilişkisel (RDBMS) ve NoSQL veritabanlarının temel yapılarını, avantajlarını, zorluklarını ve hangi senaryolarda hangisinin tercih edilmesi gerektiğini detaylı bir biçimde ortaya koyacaktır.

📌 Veritabanlarının Rolü ve Önemi

Bir yazılım projesinde veritabanı, genellikle en az görünür ama en kritik bileşenlerden biridir. Kullanıcı verilerinin saklanması, ürün bilgilerinin yönetimi, işlem geçmişlerinin kaydı, raporlama sistemlerinin desteklenmesi ve daha fazlası veritabanı altyapısına dayanır.

Kötü yapılandırılmış veya yanlış seçilmiş bir veritabanı:

  • Performans darboğazlarına,
  • Veri tutarsızlıklarına,
  • Güvenlik açıklarına,
  • Ölçekleme zorluklarına ve
  • Geliştirme süreçlerinde verimsizliklere yol açabilir.

Bu nedenle, VTYS seçimi sadece teknik özellikler değil, aynı zamanda projenin iş hedefleri, veri yapısı, ölçeklenebilirlik gereksinimleri ve bütçesi dikkate alınarak yapılmalıdır.

🧱 İlişkisel Veritabanları (RDBMS): Yapı ve Özellikler

İlişkisel veritabanları, verileri satır ve sütunlardan oluşan tablolar şeklinde organize eder. Bu yapı, ilişkisel model olarak adlandırılır ve veri bütünlüğü, normalizasyon, anahtar-kısıt ilişkileri gibi katı yapısal kurallarıyla tanınır. Temel özellikleri şunlardır:

  • SQL Desteği: Verilere erişim için yapılandırılmış sorgu dili olan SQL kullanılır. Bu da karmaşık veri analizleri ve JOIN işlemleri gibi yetenekleri mümkün kılar.
  • ACID Uyumluluğu: Veritabanı işlemlerinin atomiklik, tutarlılık, izolasyon ve kalıcılık (ACID) ilkelerine göre gerçekleşmesi, güvenli ve hatasız işlemler sağlar.
  • Veri Tutarlılığı: Veriler arasındaki ilişkiler net olarak tanımlanır ve veri bütünlüğü sıkı bir şekilde korunur.

🎯 Öne Çıkan RDBMS Çözümleri:

  • MySQL: Açık kaynak, yaygın kullanım, kolay öğrenilebilirlik.
  • PostgreSQL: Gelişmiş özellikler, geniş veri tipi desteği, açık kaynak.
  • Oracle DB: Kurumsal çözümler için güçlü, kapsamlı yönetim araçları.
  • Microsoft SQL Server: .NET ekosistemiyle uyumlu, güçlü GUI araçlarıyla birlikte gelir.

🚫 Zorluklar:

  • Ölçeklendirme genellikle dikeydir (daha güçlü donanım), yatay ölçeklenebilirlik zordur.
  • Esnek veri yapıları ile çalışmak zor olabilir.
  • Yüksek hacimli, gerçek zamanlı veri işleme senaryolarında performans sınırlamaları görülebilir.

🔀 NoSQL Veritabanları: Esneklik ve Performans Odaklı Yaklaşım

“NoSQL” kavramı, “Not Only SQL” ifadesinin kısaltmasıdır. Geleneksel tablo yapısının ötesine geçerek daha esnek veri modelleri sunar. NoSQL veritabanları, özellikle yüksek hız, esneklik ve büyük veri senaryoları için tercih edilir.

🧩 NoSQL Kategorileri:

  1. Belge Tabanlı (Document): JSON ya da BSON belgeleriyle çalışır (örneğin MongoDB).
  2. Anahtar-Değer (Key-Value): Hızlı erişim için idealdir (örneğin Redis).
  3. Geniş Sütunlu (Wide-Column): Çok büyük veri kümeleri için optimize edilmiştir (örneğin Cassandra).
  4. Graf Veritabanları: Karmaşık ilişkileri grafik yapılarla modellenir (örneğin Neo4j).

🚀 Avantajları:

  • Yatay Ölçeklenebilirlik: Veri, birden çok sunucuya kolayca dağıtılabilir.
  • Şemadan Bağımsızlık: Veri yapısı dinamik olarak değiştirilebilir.
  • Yüksek Performans: Okuma ve yazma işlemlerinde düşük gecikme süresi sağlar.
  • Büyük Veri ve Gerçek Zamanlı Analiz İçin Uygun: IoT, log işleme ve sosyal medya uygulamaları gibi senaryolarda etkilidir.

🔎 Zorluklar:

  • Veri tutarlılığı, genellikle eventual consistency (sonunda tutarlılık) modeline dayanır.
  • Karmaşık ilişkisel sorgular zordur ya da mümkün değildir.
  • ACID yerine BASE (Basically Available, Soft state, Eventually consistent) modeline dayanır.

🔄 RDBMS vs NoSQL: Hangi Durumda Hangisi Tercih Edilmeli?

KriterRDBMSNoSQLVeri YapısıYapısal, ilişkiselYapısal olmayan, esnekÖlçeklenebilirlikDikeyYataySorgu KarmaşıklığıÇok güçlü (JOIN, subquery vs.)Kısıtlı (ya da yok)Veri TutarlılığıYüksek (ACID)Esnek (BASE)Performans (gerçek zamanlı)OrtaYüksekŞema DeğişikliğiZorKolayTipik Kullanım AlanıFinans, ERP, CRMIoT, sosyal medya, analitik


🧪 Gerçek Hayattan Senaryolar ve Öneriler

  • Bir e-ticaret platformu geliştiriyorsanız ve stok yönetimi, sipariş takibi gibi kritik işlemler söz konusuysa, ilişkisel veritabanı (örneğin PostgreSQL) tercih edilmelidir.
  • Gerçek zamanlı bildirimler, chat uygulamaları veya cache mekanizmaları için Redis gibi key-value tabanlı NoSQL çözümleri ideal olacaktır.
  • Blog, içerik yönetim sistemleri (CMS) gibi şeması zamanla değişebilecek uygulamalarda MongoDB öne çıkar.
  • Büyük veri işleme ve zaman serisi verileri için Cassandra veya Amazon DynamoDB kullanılabilir.

🎯 Sonuç: Stratejik Bir Tercih Olarak Veritabanı Seçimi

Doğru veritabanı mimarisi, yalnızca bugünkü ihtiyaçlara değil, gelecekteki büyüme hedeflerine de hizmet etmelidir. İlişkisel ve NoSQL veritabanları birbirinin alternatifi değil, çoğu zaman birbirini tamamlayıcı çözümler olabilir. Mikroservis mimarilerinde her servis kendi ihtiyacına uygun VTYS kullanabilir. Önemli olan, projenin doğasına, verinin yapısına ve iş gereksinimlerine uygun bir karar vermektir.

Unutmayın: Veri stratejiniz, büyüme stratejinizin temelidir.

", @@ -24272,11 +24487,10 @@ "Summary": "blog.posts.database.excerpt", "ReadTime": "8 dk", "CoverImage": "https://images.pexels.com/photos/325229/pexels-photo-325229.jpeg?auto=compress&cs=tinysrgb&w=1920", - "CategoryId": "741ef542-0591-5472-9bf2-593047eb4122", + "CategoryName": "blog.categories.database", "AuthorId": "8f49d028-69d0-5d2b-abc3-559b7dee180f" }, { - "TenantId": null, "Title": "blog.posts.digital.title", "Slug": "dijital-pazarlamada-veri-analizi", "ContentTr": "

Dijital pazarlama evreni; hızla evrilen algoritmalar, çeşitlenen dijital platformlar ve sürekli değişen tüketici davranışları ile her geçen gün daha da karmaşık bir yapıya bürünüyor. Bu yoğun rekabet ortamında markaların fark yaratabilmesi, yalnızca yaratıcı kampanyalar üretmekle değil, aynı zamanda bu kampanyaların ne kadar işe yaradığını bilimsel olarak analiz edebilmekle mümkün hale geliyor. İşte tam bu noktada veri analizi, dijital pazarlamanın kalbinde yer alan stratejik bir araç olarak devreye giriyor.

Neden Veri Analizi? Dijital Pazarlamanın Yeni Yakıtı

Modern dijital pazarlama, artık yalnızca sezgilere ya da geçmiş deneyimlere dayalı kararlarla yönetilmiyor. Kampanya performansını gerçek zamanlı ölçmek, müşteri davranışlarını detaylıca anlamak, farklı kanallarda elde edilen sonuçları kıyaslayabilmek ve bütçeyi en verimli şekilde yönlendirebilmek için veriye dayalı karar alma süreci vazgeçilmez hale geldi.

Veri analizi, markaların şu konularda rekabet avantajı elde etmesini sağlar:

  • Doğru hedef kitleye ulaşma: Kitle segmentasyonu, demografi, ilgi alanları ve dijital davranış kalıpları gibi verilere dayalı olarak kişiselleştirilmiş pazarlama yapılabilir.
  • Kampanya optimizasyonu: A/B testleri, dönüşüm oranı analizleri ve tıklama davranışları yardımıyla hangi stratejilerin işe yaradığı objektif biçimde anlaşılır.
  • ROI maksimizasyonu: Hangi kanalların, kampanyaların ya da içeriklerin yatırım geri dönüşü sağladığı net olarak görülebilir.
  • Gerçek zamanlı aksiyon alma: Anlık veriler sayesinde, kampanya sırasında rotayı değiştirmek mümkün olur.

Dijital Pazarlamada En Çok Kullanılan Temel Metrikler

Veri analizinin ilk adımı, neyi ölçtüğümüzü bilmekten geçer. Dijital pazarlamacılar için kritik olan bazı temel metrikler şunlardır:

  • Dönüşüm Oranı (Conversion Rate): Web sitesi ziyaretçilerinin yüzde kaçının hedeflenen aksiyonu (satın alma, form doldurma, üyelik vb.) gerçekleştirdiğini gösterir.
  • Tıklama Oranı (CTR): Görüntülenen reklam ya da içeriklere yapılan tıklama oranıdır; reklamların ya da içeriklerin ne kadar ilgi çekici olduğunu anlamaya yardımcı olur.
  • Müşteri Edinme Maliyeti (CAC): Yeni bir müşteriyi kazanmak için yapılan ortalama harcamayı ifade eder.
  • Yaşam Boyu Değer (CLV): Bir müşterinin, markayla ilişkisi boyunca sağlayacağı toplam gelir tahminidir.
  • Hemen Çıkma Oranı (Bounce Rate): Web sitesine giren kullanıcıların başka hiçbir sayfayı ziyaret etmeden ayrılma oranıdır.

Kullanılan Araçlar ve Sistemler

Verilerin sağlıklı bir şekilde toplanması, analiz edilmesi ve görselleştirilmesi için farklı araçlara ihtiyaç vardır. Bu araçlardan bazıları:

  • Google Analytics: Web trafiğini analiz etmek, kullanıcı davranışlarını izlemek ve hedefler belirlemek için en çok kullanılan araçlardan biridir.
  • Adobe Analytics: Daha kapsamlı kullanıcı yolculuğu analizleri ve derinlemesine segmentasyon özellikleri sunar.
  • Hotjar / Microsoft Clarity: Isı haritaları, kullanıcı tıklama davranışları ve oturum kayıtları ile kullanıcı deneyimi analizine odaklanır.
  • CRM Sistemleri (Salesforce, HubSpot, Zoho): Müşteri verilerinin merkezi olarak saklandığı ve analiz edildiği platformlardır.
  • Sosyal Medya Analiz Araçları: Sprout Social, Hootsuite veya Meta Business gibi araçlarla sosyal etkileşimler ve kampanya geri dönüşleri izlenebilir.

Veri Temizliği ve Kalite Kontrolü: Doğru Veri = Doğru Strateji

Analiz edilen verinin kalitesi, sonuçların güvenilirliğini doğrudan etkiler. Eksik, hatalı veya güncel olmayan veriler üzerine kurulmuş analizler, stratejik hatalara yol açabilir. Bu nedenle şu adımlar kritik önemdedir:

  • Veri temizliği: Çift kayıtların silinmesi, boş alanların doldurulması, hatalı girişlerin düzeltilmesi.
  • Veri normalizasyonu: Farklı kaynaklardan gelen verilerin ortak formatta uyumlandırılması.
  • Veri görselleştirme: Doğru grafikler ve dashboard’lar ile verinin daha kolay yorumlanabilir hale getirilmesi.

Farklı Analiz Yöntemleri ile Derin İçgörü

Veri analizi sadece sayıları okumaktan ibaret değildir; arkasındaki anlamı çözümlemek gerekir. Dijital pazarlamada kullanılan analiz yöntemlerinden bazıları:

  • Descriptive Analytics (Tanımlayıcı Analiz): Geçmiş verileri anlamaya yönelik temel analizler (örneğin, kaç kişi tıkladı?).
  • Diagnostic Analytics (Teşhis Analizi): Neden sorusuna yanıt arar (neden satışlar düştü?).
  • Predictive Analytics (Tahmine Dayalı Analiz): Gelecekte neler olabileceğini modellemeye çalışır (örneğin, AI destekli tahminleme).
  • Prescriptive Analytics (Önerisel Analiz): En iyi aksiyonun ne olması gerektiğini önerir.

Veri Görselleştirme: İçgörüyü Eyleme Dönüştürmek

Karmaşık verileri etkili bir şekilde iletmek için veri görselleştirme olmazsa olmazdır. Power BI, Tableau gibi araçlarla hazırlanan interaktif dashboard’lar, yöneticilere veya ekip üyelerine sezgisel olarak veri ile içgörü kazandırır. Bu sayede;

  • Trendler daha hızlı anlaşılır
  • Problemler daha kolay tespit edilir
  • Karar alma süreçleri hızlanır

İçgörüyü Stratejiye Dönüştürme: Pratik Öneriler

Veri analizinden elde edilen bulgular, ancak pazarlama stratejisine entegre edildiğinde anlam kazanır. İşte bazı öneriler:

  • Hedef kitle analizine göre içerik ve reklamları kişiselleştirin.
  • Etkileşim almayan içerikleri analiz ederek yeni stratejiler geliştirin.
  • A/B test sonuçlarına göre kampanya bütçelerini yeniden şekillendirin.
  • Satın alma sürecinde terk edilen adımları optimize edin.
  • Müşteri yolculuğunu haritalandırarak doğru temas noktalarında aksiyon alın.

Sonuç: Veri Odaklı Pazarlama ile Rekabette Öne Geçin

Günümüzde dijital pazarlamanın başarısı, yalnızca yaratıcı kampanyalarla değil, bu kampanyaların etkisini ölçümleyip sürekli olarak iyileştirme becerisiyle ölçülmektedir. Veri analizi, pazarlama ekiplerinin doğru zamanda, doğru mesajla, doğru kişiye ulaşmasını sağlayan güçlü bir rehberdir. Teknolojinin sunduğu analiz araçlarını stratejik yaklaşımlarla birleştirerek, hem marka değerini hem de yatırım geri dönüşünü maksimize edebilirsiniz.

Unutmayın: Veri konuşur, siz sadece onu doğru dinlemelisiniz.

", @@ -24284,7 +24498,7 @@ "Summary": "blog.posts.digital.excerpt", "ReadTime": "6 dk", "CoverImage": "https://images.pexels.com/photos/7681091/pexels-photo-7681091.jpeg?auto=compress&cs=tinysrgb&w=1920", - "CategoryId": "dbc8578c-1a99-594a-8997-bddd0eac8571", + "CategoryName": "blog.categories.digital", "AuthorId": "727ec3f0-75dd-54e2-8ae6-13d49727ff58" } ], @@ -24563,7 +24777,9 @@ "props": null, "description": null, "isActive": true, - "dependencies": ["AxiosListComponent"] + "dependencies": [ + "AxiosListComponent" + ] } ], "ReportCategories": [ @@ -25616,37 +25832,29 @@ ], "EventTypes": [ { - "Id": "81B52DE4-256C-46CF-8E03-40095A6A5617", "Name": "Gezi" }, { - "Id": "882C3C8C-8307-452B-B8A7-122E73EFBD12", "Name": "Sinema" }, { - "Id": "4689DA37-DE49-4A80-9192-6A1F770D36DE", "Name": "Tiyatro" } ], "EventCategories": [ { - "Id": "A1F2B3C4-D5E6-47F8-9123-456789ABCDEF", "Name": "Spor" }, { - "Id": "B2C3D4E5-F6A7-48B9-8234-56789ABCDEF1", "Name": "Sanat" }, { - "Id": "C3D4E5F6-A7B8-49CA-9345-6789ABCDEF12", "Name": "Müzik" }, { - "Id": "D4E5F6A7-B8C9-40DB-A456-789ABCDEF123", "Name": "Eğitim" }, { - "Id": "E5F6A7B8-C9D0-41EC-B567-89ABCDEF1234", "Name": "Kültür" } ], @@ -25794,113 +26002,48 @@ ], "RegistrationTypes": [ { - "Id": "1A2B3C4D-1111-2222-3333-444455556666", "Name": "GRUP", "Status": "Aktif" }, { - "Id": "7E8F9A0B-7777-8888-9999-AAAABBBBCCCC", "Name": "ÖZEL", "Status": "Aktif" } ], "RegistrationMethods": [ { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Erken Kayıt İnd.", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Engelli İnd.", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Peşin Ödeme İnd.", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", + "RegistrationTypeName": "GRUP", "Name": "Normal Paket", "Status": "Aktif" }, { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "MEB Personeli İnd.", + "RegistrationTypeName": "GRUP", + "Name": "Erken Kayıt", "Status": "Aktif" }, { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Yaz Okulu", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Personel İnd.", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Referans Program", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Üniversite Program", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "YÖS", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Öğrenci İnd.(Üni)", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Normal Kayıt", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", - "Name": "Kardeş İnd.", - "Status": "Aktif" - }, - { - "RegistrationTypeId": "7E8F9A0B-7777-8888-9999-AAAABBBBCCCC", + "RegistrationTypeName": "ÖZEL", "Name": "ÖZEL", "Status": "Aktif" - }, - { - "RegistrationTypeId": "7E8F9A0B-7777-8888-9999-AAAABBBBCCCC", - "Name": "Derece İndirimi", - "Status": "Aktif" } ], "ClassTypes": [ { - "Id": "11111111-AAAA-4444-BBBB-555555555555", - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", + "RegistrationTypeName": "GRUP", "Name": "3-6 Kişilik", "MinStudentCount": 3, "MaxStudentCount": 6, "Status": "Aktif" }, { - "Id": "22222222-BBBB-4444-CCCC-666666666666", - "RegistrationTypeId": "1A2B3C4D-1111-2222-3333-444455556666", + "RegistrationTypeName": "GRUP", "Name": "5-8 Kişilik", "MinStudentCount": 5, "MaxStudentCount": 8, "Status": "Aktif" }, { - "Id": "33333333-CCCC-4444-DDDD-777777777777", - "RegistrationTypeId": "7E8F9A0B-7777-8888-9999-AAAABBBBCCCC", + "RegistrationTypeName": "ÖZEL", "Name": "ÖZEL", "MinStudentCount": 1, "MaxStudentCount": 1, @@ -25909,79 +26052,34 @@ ], "Classes": [ { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "3-6 Kişilik", "Name": "201", "Status": "Aktif" }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "3-6 Kişilik", "Name": "202", "Status": "Aktif" }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", - "Name": "203", - "Status": "Aktif" - }, - { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", - "Name": "204", - "Status": "Aktif" - }, - { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", - "Name": "406", - "Status": "Aktif" - }, - { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", - "Name": "601", - "Status": "Aktif" - }, - { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", - "Name": "802", - "Status": "Aktif" - }, - { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "5-8 Kişilik", "Name": "BODRUM", "Status": "Aktif" }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "5-8 Kişilik", "Name": "FLORIDA", "Status": "Aktif" }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", - "Name": "MIAMI", - "Status": "Aktif" - }, - { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", - "Name": "İSTANBUL", - "Status": "Aktif" - }, - { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", - "Name": "CALIFORNIA", - "Status": "Aktif" - }, - { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", - "Name": "NEW YORK", - "Status": "Aktif" - }, - { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "ÖZEL", "Status": "Aktif" } ], "Levels": [ { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Seviye", "LevelType": "A1", "LessonCount": 80, @@ -25990,7 +26088,7 @@ "MonthlyPaymentRate": 20.0 }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Seviye", "LevelType": "A2", "LessonCount": 90, @@ -25999,7 +26097,7 @@ "MonthlyPaymentRate": 30.0 }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Seviye", "LevelType": "B1", "LessonCount": 90, @@ -26008,7 +26106,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Seviye", "LevelType": "B2", "LessonCount": 80, @@ -26017,7 +26115,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Seviye", "LevelType": "C1", "LessonCount": 80, @@ -26026,7 +26124,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Seviye", "LevelType": "C2", "LessonCount": 80, @@ -26035,7 +26133,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "BULATS", "LessonCount": 50, @@ -26044,7 +26142,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "GMAT", "LessonCount": 50, @@ -26053,7 +26151,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "YDS", "LessonCount": 50, @@ -26062,7 +26160,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "22222222-BBBB-4444-CCCC-666666666666", + "ClassTypeName": "3-6 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "ÜDS", "LessonCount": 50, @@ -26071,7 +26169,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Seviye", "LevelType": "A1", "LessonCount": 80, @@ -26080,7 +26178,7 @@ "MonthlyPaymentRate": 30.0 }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Seviye", "LevelType": "A2", "LessonCount": 80, @@ -26089,7 +26187,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Seviye", "LevelType": "B1", "LessonCount": 80, @@ -26098,7 +26196,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Seviye", "LevelType": "B2", "LessonCount": 80, @@ -26107,7 +26205,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Seviye", "LevelType": "C1", "LessonCount": 80, @@ -26116,7 +26214,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Seviye", "LevelType": "C2", "LessonCount": 80, @@ -26125,7 +26223,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "IELTS", "LessonCount": 50, @@ -26134,7 +26232,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "TOEFL", "LessonCount": 50, @@ -26143,7 +26241,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "BULATS", "LessonCount": 50, @@ -26152,7 +26250,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "GMAT", "LessonCount": 50, @@ -26161,7 +26259,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "YDS", "LessonCount": 50, @@ -26170,7 +26268,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "PROFICIENCY", "LessonCount": 50, @@ -26179,7 +26277,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "SAT", "LessonCount": 50, @@ -26188,7 +26286,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "TOEIC", "LessonCount": 50, @@ -26197,7 +26295,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "ÜDS", "LessonCount": 50, @@ -26206,7 +26304,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "11111111-AAAA-4444-BBBB-555555555555", + "ClassTypeName": "5-8 Kişilik", "Name": "Sınav Eğitimi", "LevelType": "SAT2", "LessonCount": 50, @@ -26215,7 +26313,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Seviye", "LevelType": "A1", "LessonCount": 60, @@ -26224,7 +26322,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Seviye", "LevelType": "A2", "LessonCount": 70, @@ -26233,7 +26331,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Seviye", "LevelType": "B1", "LessonCount": 80, @@ -26242,7 +26340,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Seviye", "LevelType": "B2", "LessonCount": 80, @@ -26251,7 +26349,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Seviye", "LevelType": "C1", "LessonCount": 90, @@ -26260,7 +26358,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Seviye", "LevelType": "C2", "LessonCount": 90, @@ -26269,7 +26367,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Sınav Eğitimi", "LevelType": "BULATS", "LessonCount": 80, @@ -26278,7 +26376,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Sınav Eğitimi", "LevelType": "GMAT", "LessonCount": 80, @@ -26287,7 +26385,7 @@ "MonthlyPaymentRate": null }, { - "ClassTypeId": "33333333-CCCC-4444-DDDD-777777777777", + "ClassTypeName": "ÖZEL", "Name": "Sınav Eğitimi", "LevelType": "ÜDS", "LessonCount": 80, @@ -26296,4 +26394,4 @@ "MonthlyPaymentRate": null } ] -} +} \ No newline at end of file diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs index c0052713..6154d796 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs @@ -157,7 +157,7 @@ public class UomSeedDto public decimal Ratio { get; set; } public bool IsActive { get; set; } public decimal Rounding { get; set; } - public Guid UomCategoryId { get; set; } + public string UomCategoryName { get; set; } } public class CurrencySeedDto @@ -170,14 +170,13 @@ public class CurrencySeedDto public class SkillTypeSeedDto { - public Guid Id { get; set; } public string Name { get; set; } } public class SkillSeedDto { public string Name { get; set; } - public Guid SkillTypeId { get; set; } + public string SkillTypeName { get; set; } } public class SkillLevelSeedDto @@ -185,7 +184,7 @@ public class SkillLevelSeedDto public string Name { get; set; } public int Progress { get; set; } public bool IsDefault { get; set; } - public Guid SkillTypeId { get; set; } + public string SkillTypeName { get; set; } } public class ContactTagSeedDto @@ -202,7 +201,6 @@ public class ContactTitleSeedDto public class BlogCategorySeedDto { - public Guid Id { get; set; } public string Name { get; set; } public string Slug { get; set; } public string Description { get; set; } @@ -219,7 +217,7 @@ public class BlogPostSeedDto public string ReadTime { get; set; } public string Summary { get; set; } public string CoverImage { get; set; } - public Guid CategoryId { get; set; } + public string CategoryName { get; set; } public Guid AuthorId { get; set; } public Boolean IsPublished { get; set; } public DateTime PublishedAt { get; set; } @@ -263,7 +261,6 @@ public class CustomEndpointSeedDto public class ProductSeedDto { - public Guid Id { get; set; } public string Name { get; set; } public string Description { get; set; } public string Category { get; set; } @@ -276,7 +273,6 @@ public class ProductSeedDto public class PaymentMethodSeedDto { - public string Id { get; set; } public string Name { get; set; } public decimal Commission { get; set; } public string Logo { get; set; } @@ -500,22 +496,20 @@ public class ProgramSeedDto public class RegistrationTypeSeedDto { - public Guid Id { get; set; } public string Name { get; set; } public string Status { get; set; } } public class RegistrationMethodSeedDto { - public Guid RegistrationTypeId { get; set; } + public string RegistrationTypeName { get; set; } public string Name { get; set; } public string Status { get; set; } } public class ClassTypeSeedDto { - public Guid Id { get; set; } - public Guid RegistrationTypeId { get; set; } + public string RegistrationTypeName { get; set; } public string Name { get; set; } public int? MinStudentCount { get; set; } public int? MaxStudentCount { get; set; } @@ -524,14 +518,14 @@ public class ClassTypeSeedDto public class ClassSeedDto { - public Guid ClassTypeId { get; set; } + public string ClassTypeName { get; set; } public string Name { get; set; } public string Status { get; set; } } public class LevelSeedDto { - public Guid ClassTypeId { get; set; } + public string ClassTypeName { get; set; } public string Name { get; set; } public string LevelType { get; set; } public int LessonCount { get; set; } diff --git a/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs b/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs index 2a72b037..e84ff516 100644 --- a/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs +++ b/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs @@ -367,6 +367,7 @@ public static class PlatformConsts { public static class Forms { + public const string FormTenant = "form-tenant"; public const string FormLanguage = "form-language"; public const string FormUomCategory = "form-uomcategory"; public const string FormSkillType = "form-skilltype"; diff --git a/api/src/Kurs.Platform.Domain/Entities/Administration/ClassType.cs b/api/src/Kurs.Platform.Domain/Entities/Administration/ClassType.cs index d54ae624..500b7650 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Administration/ClassType.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Administration/ClassType.cs @@ -22,20 +22,5 @@ public class ClassType : FullAuditedEntity, IMultiTenant // Navigation public RegistrationType RegistrationType { get; set; } public ICollection Classes { get; set; } - public ICollection Levels { get; set; } - - public ClassType() - { - - } - - public ClassType(Guid id, Guid registrationTypeId, string name, int? minStudentCount, int? maxStudentCount, string status) - { - Id = id; - RegistrationTypeId = registrationTypeId; - Name = name; - MinStudentCount = minStudentCount; - MaxStudentCount = maxStudentCount; - Status = status; - } + public ICollection Levels { get; set; } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Administration/EventCategory.cs b/api/src/Kurs.Platform.Domain/Entities/Administration/EventCategory.cs index 39606647..a4262532 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Administration/EventCategory.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Administration/EventCategory.cs @@ -15,15 +15,4 @@ public class EventCategory : FullAuditedEntity, IMultiTenant public ICollection Events { get; set; } Guid? IMultiTenant.TenantId => TenantId; - - public EventCategory() - { - - } - - public EventCategory(Guid id, string name) - { - Id = id; - Name = name; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Administration/EventType.cs b/api/src/Kurs.Platform.Domain/Entities/Administration/EventType.cs index b1111c04..1c116f7e 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Administration/EventType.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Administration/EventType.cs @@ -15,15 +15,4 @@ public class EventType : FullAuditedEntity, IMultiTenant public ICollection Events { get; set; } Guid? IMultiTenant.TenantId => TenantId; - - public EventType() - { - - } - - public EventType(Guid id, string name) - { - Id = id; - Name = name; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Administration/RegistrationType.cs b/api/src/Kurs.Platform.Domain/Entities/Administration/RegistrationType.cs index 70e96d6d..20fdc095 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Administration/RegistrationType.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Administration/RegistrationType.cs @@ -18,11 +18,4 @@ public class RegistrationType : FullAuditedEntity, IMultiTenant // Navigation public ICollection Methods { get; set; } public ICollection ClassTypes { get; set; } - - public RegistrationType(Guid id, string name, string status) - { - Id = id; - Name = name; - Status = status; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Administration/SkillType.cs b/api/src/Kurs.Platform.Domain/Entities/Administration/SkillType.cs index c9638060..40097cdb 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Administration/SkillType.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Administration/SkillType.cs @@ -15,13 +15,4 @@ public class SkillType : FullAuditedEntity, IMultiTenant public ICollection Skills { get; set; } public ICollection Levels { get; set; } - - public SkillType() - { - } - - public SkillType(Guid id, string name) : base(id) - { - Name = name; - } } \ No newline at end of file diff --git a/api/src/Kurs.Platform.Domain/Entities/Administration/UomCategory.cs b/api/src/Kurs.Platform.Domain/Entities/Administration/UomCategory.cs index 06026dad..a9492f13 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Administration/UomCategory.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Administration/UomCategory.cs @@ -14,11 +14,4 @@ public class UomCategory : FullAuditedEntity, IMultiTenant public ICollection Uoms { get; set; } Guid? IMultiTenant.TenantId => TenantId; - - protected UomCategory() { } - - public UomCategory(Guid id, string name) : base(id) - { - Name = name; - } } \ No newline at end of file diff --git a/api/src/Kurs.Platform.Domain/Entities/Coordinator/Classroom.cs b/api/src/Kurs.Platform.Domain/Entities/Coordinator/Classroom.cs index 915a6315..3f51c15d 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Coordinator/Classroom.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Coordinator/Classroom.cs @@ -22,44 +22,7 @@ public class Classroom : FullAuditedEntity public string SettingsJson { get; set; } [JsonIgnore] - public virtual ICollection Participants { get; set; } - public virtual ICollection AttendanceRecords { get; set; } - public virtual ICollection ChatMessages { get; set; } - - protected Classroom() - { - Participants = new HashSet(); - AttendanceRecords = new HashSet(); - ChatMessages = new HashSet(); - } - - public Classroom( - Guid id, - string name, - string description, - string subject, - Guid? teacherId, - string teacherName, - DateTime scheduledStartTime, - DateTime? scheduledEndTime, - int duration, - int maxParticipants, - string settingsJson - ) : base(id) - { - Name = name; - Description = description; - Subject = subject; - TeacherId = teacherId; - TeacherName = teacherName; - ScheduledStartTime = scheduledStartTime; - ScheduledEndTime = scheduledEndTime; - Duration = duration; - MaxParticipants = maxParticipants; - SettingsJson = settingsJson; - - Participants = new HashSet(); - AttendanceRecords = new HashSet(); - ChatMessages = new HashSet(); - } + public virtual ICollection Participants { get; set; } = new HashSet(); + public virtual ICollection AttendanceRecords { get; set; } = new HashSet(); + public virtual ICollection ChatMessages { get; set; } = new HashSet(); } diff --git a/api/src/Kurs.Platform.Domain/Entities/Platform/AiBot.cs b/api/src/Kurs.Platform.Domain/Entities/Platform/AiBot.cs index a8d3b4dc..ab8afd45 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Platform/AiBot.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Platform/AiBot.cs @@ -6,11 +6,5 @@ namespace Kurs.Platform.Entities; public class AiBot : Entity { public string BotName { get; set; } - - public AiBot(Guid id, string botName) - { - Id = Id; - BotName = botName; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Forum/ForumCategory.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Forum/ForumCategory.cs index 7b3fd1f8..d3330882 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Forum/ForumCategory.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Forum/ForumCategory.cs @@ -20,24 +20,7 @@ public class ForumCategory : FullAuditedEntity public Guid? LastPostUserId { get; set; } public string LastPostUserName { get; set; } - public ICollection Topics { get; set; } + public ICollection Topics { get; set; } = []; public Guid? TenantId { get; set; } - - protected ForumCategory() { } - - public ForumCategory(Guid id, string name, string slug, string description, string icon, int displayOrder, Guid? tenantId = null) : base(id) - { - Name = name; - Slug = slug; - Description = description; - Icon = icon; - DisplayOrder = displayOrder; - IsActive = true; - IsLocked = false; - TopicCount = 0; - PostCount = 0; - TenantId = tenantId; - Topics = []; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/About.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/About.cs index b42b9c2e..4478bce0 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/About.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/About.cs @@ -11,18 +11,4 @@ public class About : FullAuditedEntity, IMultiTenant public string StatsJson { get; set; } public string DescriptionsJson { get; set; } public string SectionsJson { get; set; } - - protected About() { } - - public About( - Guid id, - string statsJson, - string descriptionsJson, - string sectionsJson - ) : base(id) - { - StatsJson = statsJson; - DescriptionsJson = descriptionsJson; - SectionsJson = sectionsJson; - } } \ No newline at end of file diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogCategory.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogCategory.cs index c00197dd..7640c6d7 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogCategory.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogCategory.cs @@ -18,29 +18,6 @@ public class BlogCategory : FullAuditedEntity, IMultiTenant public virtual ICollection Posts { get; set; } - protected BlogCategory() - { - Posts = new HashSet(); - } - - public BlogCategory( - Guid id, - string name, - string slug, - string description = null, - Guid? tenantId = null) : base(id) - { - Name = name; - Slug = slug; - Description = description; - TenantId = tenantId; - Icon = null; - DisplayOrder = 0; - IsActive = true; - PostCount = 0; - Posts = new HashSet(); - } - public void IncrementPostCount() { PostCount++; diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogPost.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogPost.cs index 7ce3b26d..f0a7ef9c 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogPost.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/BlogPost.cs @@ -27,43 +27,6 @@ public class BlogPost : FullAuditedEntity, IMultiTenant public bool IsPublished { get; set; } = false; public DateTime? PublishedAt { get; set; } - protected BlogPost() - { - } - - public BlogPost( - Guid id, - string title, - string slug, - string contentTr, - string contentEn, - string summary, - string readTime, - string coverImage, - Guid categoryId, - Guid authorId, - bool isPublished, - DateTime? publishedAt = null, - Guid? tenantId = null) : base(id) - { - Title = title; - Slug = slug; - ContentTr = contentTr; - ContentEn = contentEn; - Summary = summary; - ReadTime = readTime; - CoverImage = coverImage; - CategoryId = categoryId; - AuthorId = authorId; - IsPublished = isPublished; - PublishedAt = publishedAt; - TenantId = tenantId; - - ViewCount = 0; - LikeCount = 0; - CommentCount = 0; - } - public void Publish() { IsPublished = true; diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Contact.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Contact.cs index be92cd95..d7b9ba24 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Contact.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Contact.cs @@ -18,28 +18,4 @@ public class Contact : FullAuditedEntity, IMultiTenant public string BankJson { get; set; } public string WorkHoursJson { get; set; } public string MapJson { get; set; } - - protected Contact() { } - - public Contact( - Guid id, - string address, - string phone, - string email, - string location, - string taxNumber, - string bankJson, - string workHoursJson, - string mapJson - ) : base(id) - { - Address = address; - Phone = phone; - Email = email; - Location = location; - TaxNumber = taxNumber; - BankJson = bankJson; - WorkHoursJson = workHoursJson; - MapJson = mapJson; - } } \ No newline at end of file diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/PaymentMethod.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/PaymentMethod.cs index 0bab49fd..fbf31826 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/PaymentMethod.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/PaymentMethod.cs @@ -1,20 +1,11 @@ -using Volo.Abp.Domain.Entities; +using System; +using Volo.Abp.Domain.Entities.Auditing; namespace Kurs.Platform.Entities; -public class PaymentMethod : Entity +public class PaymentMethod : FullAuditedEntity { public string Name { get; set; } public decimal Commission { get; set; } public string Logo { get; set; } - - public PaymentMethod() { } - - public PaymentMethod(string id, string name, decimal commission, string logo) - { - Id = id; - Name = name; - Commission = commission; - Logo = logo; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Product.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Product.cs index a4452aac..cf299246 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Product.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Product.cs @@ -13,30 +13,4 @@ public class Product : FullAuditedEntity public decimal? YearlyPrice { get; set; } public bool IsQuantityBased { get; set; } = false; public string ImageUrl { get; set; } - - public Product() - { - } - - public Product( - Guid id, - string name, - string description, - string category, - int order, - decimal? monthlyPrice, - decimal? yearlyPrice, - bool isQuantityBased, - string imageUrl - ) : base(id) - { - Name = name; - Description = description; - Category = category; - Order = order; - MonthlyPrice = monthlyPrice; - YearlyPrice = yearlyPrice; - IsQuantityBased = isQuantityBased; - ImageUrl = imageUrl; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Service.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Service.cs index b059e436..43c9ce64 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Service.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Public/Service.cs @@ -14,17 +14,5 @@ public class Service : FullAuditedEntity, IMultiTenant // JSON olarak saklanacak public string[] Features { get; set; } = []; - - protected Service() { } - - public Service(Guid id, string icon, string title, string description, string type, string[] features) - : base(id) - { - Icon = icon; - Title = title; - Description = description; - Type = type; - Features = features; - } } diff --git a/api/src/Kurs.Platform.Domain/Entities/Saas/Report/ReportCategory.cs b/api/src/Kurs.Platform.Domain/Entities/Saas/Report/ReportCategory.cs index 2ad513e6..ae9684af 100644 --- a/api/src/Kurs.Platform.Domain/Entities/Saas/Report/ReportCategory.cs +++ b/api/src/Kurs.Platform.Domain/Entities/Saas/Report/ReportCategory.cs @@ -11,21 +11,5 @@ namespace Kurs.Platform.Entities public string Icon { get; set; } public ICollection ReportTemplates { get; set; } - - public ReportCategory() - { - } - - public ReportCategory( - Guid id, - string name, - string description, - string icon = null - ) : base(id) - { - Name = name; - Description = description; - Icon = icon; - } } } diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs index 4291b163..f29a8303 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs @@ -855,8 +855,6 @@ public class PlatformDbContext : b.Property(x => x.Name).IsRequired().HasMaxLength(128); - b.HasIndex(x => x.Name).IsUnique(); - b.HasMany(x => x.Skills) .WithOne(x => x.SkillType) .HasForeignKey(x => x.SkillTypeId) @@ -897,7 +895,6 @@ public class PlatformDbContext : b.Property(x => x.Name).IsRequired().HasMaxLength(128); - b.HasIndex(x => x.Name).IsUnique(); }); builder.Entity(b => diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006121303_Initial.Designer.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006221403_Initial.Designer.cs similarity index 99% rename from api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006121303_Initial.Designer.cs rename to api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006221403_Initial.Designer.cs index 0ea58856..c1e0b2bf 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006121303_Initial.Designer.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006221403_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Kurs.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20251006121303_Initial")] + [Migration("20251006221403_Initial")] partial class Initial { /// @@ -3311,10 +3311,6 @@ namespace Kurs.Platform.Migrations .HasMaxLength(250) .HasColumnType("nvarchar(250)"); - b.Property("City") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - b.Property("ContactPerson") .HasMaxLength(50) .HasColumnType("nvarchar(50)"); @@ -4706,13 +4702,43 @@ namespace Kurs.Platform.Migrations modelBuilder.Entity("Kurs.Platform.Entities.PaymentMethod", b => { - b.Property("Id") - .HasColumnType("nvarchar(450)"); + b.Property("Id") + .HasColumnType("uniqueidentifier"); b.Property("Commission") .HasPrecision(5, 3) .HasColumnType("decimal(5,3)"); + 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("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + b.Property("Logo") .HasMaxLength(32) .HasColumnType("nvarchar(32)"); @@ -5860,9 +5886,6 @@ namespace Kurs.Platform.Migrations b.HasKey("Id"); - b.HasIndex("Name") - .IsUnique(); - b.ToTable("DSkillType", (string)null); }); @@ -6035,9 +6058,6 @@ namespace Kurs.Platform.Migrations b.HasKey("Id"); - b.HasIndex("Name") - .IsUnique(); - b.ToTable("DUomCategory", (string)null); }); diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006121303_Initial.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006221403_Initial.cs similarity index 99% rename from api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006121303_Initial.cs rename to api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006221403_Initial.cs index 61525f60..01d838a2 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006121303_Initial.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251006221403_Initial.cs @@ -719,7 +719,6 @@ namespace Kurs.Platform.Migrations ContactPerson = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), Email = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), Address = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), - City = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), TaxOffice = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), TaxNumber = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: true), Phone1 = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: true), @@ -1945,10 +1944,17 @@ namespace Kurs.Platform.Migrations name: "WPaymentMethod", columns: table => new { - Id = table.Column(type: "nvarchar(450)", nullable: false), + Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), Commission = table.Column(type: "decimal(5,3)", precision: 5, scale: 3, nullable: false), - Logo = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: true) + Logo = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: 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 => { @@ -3767,23 +3773,11 @@ namespace Kurs.Platform.Migrations table: "DSkillLevel", column: "SkillTypeId"); - migrationBuilder.CreateIndex( - name: "IX_DSkillType_Name", - table: "DSkillType", - column: "Name", - unique: true); - migrationBuilder.CreateIndex( name: "IX_DUom_UomCategoryId", table: "DUom", column: "UomCategoryId"); - migrationBuilder.CreateIndex( - name: "IX_DUomCategory_Name", - table: "DUomCategory", - column: "Name", - unique: true); - migrationBuilder.CreateIndex( name: "IX_OpenIddictApplications_ClientId", table: "OpenIddictApplications", diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index 8c3b0f37..88f9832b 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -3308,10 +3308,6 @@ namespace Kurs.Platform.Migrations .HasMaxLength(250) .HasColumnType("nvarchar(250)"); - b.Property("City") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - b.Property("ContactPerson") .HasMaxLength(50) .HasColumnType("nvarchar(50)"); @@ -4703,13 +4699,43 @@ namespace Kurs.Platform.Migrations modelBuilder.Entity("Kurs.Platform.Entities.PaymentMethod", b => { - b.Property("Id") - .HasColumnType("nvarchar(450)"); + b.Property("Id") + .HasColumnType("uniqueidentifier"); b.Property("Commission") .HasPrecision(5, 3) .HasColumnType("decimal(5,3)"); + 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("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + b.Property("Logo") .HasMaxLength(32) .HasColumnType("nvarchar(32)"); @@ -5857,9 +5883,6 @@ namespace Kurs.Platform.Migrations b.HasKey("Id"); - b.HasIndex("Name") - .IsUnique(); - b.ToTable("DSkillType", (string)null); }); @@ -6032,9 +6055,6 @@ namespace Kurs.Platform.Migrations b.HasKey("Id"); - b.HasIndex("Name") - .IsUnique(); - b.ToTable("DUomCategory", (string)null); }); diff --git a/ui/src/proxy/admin/list-form/options.ts b/ui/src/proxy/admin/list-form/options.ts index a48810fb..e667abc1 100644 --- a/ui/src/proxy/admin/list-form/options.ts +++ b/ui/src/proxy/admin/list-form/options.ts @@ -100,6 +100,7 @@ export const tabVisibilityConfig: Record = { 'legendSettings', 'exportSettings', 'crosshairOptions', + 'subForms', ], Form: [ 'details', diff --git a/ui/src/services/form.service.ts b/ui/src/services/form.service.ts index ce3449f8..018e6bf4 100644 --- a/ui/src/services/form.service.ts +++ b/ui/src/services/form.service.ts @@ -29,6 +29,9 @@ export const dynamicFetch = ( url: '/api/app/' + url, params, data, + headers: { + 'Content-Type': 'application/json', + }, }) } catch (error) { if (error instanceof AxiosError) { diff --git a/ui/src/views/form/FormDevExpress.tsx b/ui/src/views/form/FormDevExpress.tsx index fcb3c9db..0430a354 100644 --- a/ui/src/views/form/FormDevExpress.tsx +++ b/ui/src/views/form/FormDevExpress.tsx @@ -11,7 +11,6 @@ import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent' import { TagBoxEditorComponent } from './editors/TagBoxEditorComponent' import { RowMode, SimpleItemWithColData } from './types' import { PlatformEditorTypes } from '@/proxy/form/models' -import dxSelectBox from 'devextreme/ui/select_box' const FormDevExpress = (props: { listFormCode: string diff --git a/ui/src/views/form/useGridData.tsx b/ui/src/views/form/useGridData.tsx index d48c7fe3..a33fc248 100644 --- a/ui/src/views/form/useGridData.tsx +++ b/ui/src/views/form/useGridData.tsx @@ -251,7 +251,7 @@ const useGridData = (props: { ...editorOptions, ...(colData?.lookupDto?.dataSourceType ? { - dataSource: getLookupDataSource(colData?.editorOptions, colData), + dataSource: getLookupDataSource(colData?.editorOptions, colData, formData), valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(), displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(), } @@ -288,7 +288,7 @@ const useGridData = (props: { }) setFormItems(items) setGridReady(true) - }, [gridDto]) + }, [gridDto, formData]) useEffect(() => { if (!gridReady) { diff --git a/ui/src/views/form/useLookupDataSource.ts b/ui/src/views/form/useLookupDataSource.ts index e2f11502..35b578cf 100644 --- a/ui/src/views/form/useLookupDataSource.ts +++ b/ui/src/views/form/useLookupDataSource.ts @@ -30,7 +30,6 @@ const createLookupQueryDataSource = ( if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) { return } - try { const response = await dynamicFetch('list-form-select/lookup', 'POST', null, { listFormCode, @@ -107,9 +106,17 @@ export const useLookupDataSource = ({ isSubForm?: boolean }) => { const getLookupDataSource = useCallback( - (options: any, colData: any) => { + (options: any, colData: any, data: any) => { const { lookupDto } = colData const filters = [] + + //Eğer cascadeParentFields varsa ve data yoksa boş döneriz. + if (lookupDto.cascadeParentFields && !data) { + return { + store: [], + } + } + if (lookupDto.cascadeParentFields) { if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) { filters.push([ @@ -118,7 +125,6 @@ export const useLookupDataSource = ({ options?.data[lookupDto?.cascadeParentField], ]) } else { - const data = options?.data ?? options for (const cascadeParentField of lookupDto.cascadeParentFields.split(',')) { filters.push(data?.[cascadeParentField] ?? null) }