From f4d2be65e518d47ef36ffdf835c4aecb8c0b76ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Wed, 8 Jul 2026 14:53:23 +0300 Subject: [PATCH] Workflow problemleri giderildi. --- .../Tenants/CustomTenantDto.cs | 2 +- .../ListForms/ListFormWizardAppService.cs | 50 +++++++ .../ListForms/ListFormWorkflowAppService.cs | 96 ++++++++++--- .../Seeds/LanguagesData.json | 30 ++++ .../Seeds/ListFormSeeder_Administration.cs | 6 +- .../Seeds/ListFormSeeder_DefaultJsons.cs | 2 +- .../Seeds/ListFormSeeder_Saas.cs | 135 ++++++++++++++++-- .../Seeds/WizardDataSeeder.cs | 50 +++++++ .../Tenant/Administration/Website/Order.cs | 5 + .../EntityFrameworkCore/PlatformDbContext.cs | 18 ++- ....cs => 20260708113003_Initial.Designer.cs} | 54 +++++-- ...2_Initial.cs => 20260708113003_Initial.cs} | 67 +++++---- .../PlatformDbContextModelSnapshot.cs | 52 +++++-- .../Identity/PlatformSignInManager.cs | 2 +- ui/src/components/orders/BillingControls.tsx | 1 - ui/src/components/orders/OrderSuccess.tsx | 4 +- ui/src/components/orders/PaymentForm.tsx | 7 +- ui/src/components/orders/ProductCard.tsx | 1 - ui/src/components/orders/ProductCatalog.tsx | 1 - ui/src/components/orders/TenantForm.tsx | 45 ++++-- .../admin/listForm/edit/FormTabWorkflow.tsx | 5 + .../listForm/workflow/WorkflowCanvas.tsx | 12 ++ 22 files changed, 517 insertions(+), 128 deletions(-) rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20260707205022_Initial.Designer.cs => 20260708113003_Initial.Designer.cs} (99%) rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20260707205022_Initial.cs => 20260708113003_Initial.cs} (99%) diff --git a/api/src/Sozsoft.Platform.Application.Contracts/Tenants/CustomTenantDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/Tenants/CustomTenantDto.cs index 587ca66..ea638d6 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/Tenants/CustomTenantDto.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/Tenants/CustomTenantDto.cs @@ -17,8 +17,8 @@ public class CustomTenantDto public string Address1 { get; set; } public string Address2 { get; set; } public string PostalCode { get; set; } - public string MobileNumber { get; set; } public string PhoneNumber { get; set; } + public string MobileNumber { get; set; } public string FaxNumber { get; set; } public string Email { get; set; } public string Website { get; set; } diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs index ca891a7..84604cb 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs @@ -272,6 +272,7 @@ public class ListFormWizardAppService( input.Workflow ??= new WorkflowDto(); input.Workflow.Criteria = input.WorkflowCriteria; EnsureUniqueWorkflowCriteriaTitles(input.WorkflowCriteria); + NormalizeWorkflowCriteriaIds(listFormCode, input.WorkflowCriteria); await repoListForm.InsertAsync(new ListForm { @@ -469,6 +470,55 @@ public class ListFormWizardAppService( return string.IsNullOrWhiteSpace(kind) ? "Step" : kind.Trim(); } + private static void NormalizeWorkflowCriteriaIds(string listFormCode, List criteria) + { + if (string.IsNullOrWhiteSpace(listFormCode) || criteria == null || criteria.Count == 0) + { + return; + } + + foreach (var item in criteria) + { + item.Id = NormalizeWorkflowCriteriaId(listFormCode, item.Id); + item.ListFormCode = listFormCode; + item.NextOnStart = NormalizeWorkflowTargetId(listFormCode, item.NextOnStart); + item.NextOnTrue = NormalizeWorkflowTargetId(listFormCode, item.NextOnTrue); + item.NextOnFalse = NormalizeWorkflowTargetId(listFormCode, item.NextOnFalse); + item.NextOnApprove = NormalizeWorkflowTargetId(listFormCode, item.NextOnApprove); + item.NextOnReject = NormalizeWorkflowTargetId(listFormCode, item.NextOnReject); + + foreach (var outcome in item.CompareOutcomes ?? []) + { + outcome.TargetId = NormalizeWorkflowTargetId(listFormCode, outcome.TargetId); + } + } + } + + private static string NormalizeWorkflowTargetId(string listFormCode, string id) + { + return string.IsNullOrWhiteSpace(id) + ? string.Empty + : NormalizeWorkflowCriteriaId(listFormCode, id); + } + + private static string NormalizeWorkflowCriteriaId(string listFormCode, string id) + { + var trimmed = id?.Trim(); + if (string.IsNullOrWhiteSpace(trimmed)) + { + return string.Empty; + } + + if (trimmed.StartsWith($"{listFormCode}-", StringComparison.OrdinalIgnoreCase)) + { + return trimmed; + } + + return trimmed.StartsWith("N", StringComparison.OrdinalIgnoreCase) + ? $"{listFormCode}-{trimmed}" + : trimmed; + } + /// /// Wizard konfigürasyonunu JSON dosyası olarak kaydeder. /// Önce ContentRootPath'ten yukarı çıkarak Sozsoft.Platform.DbMigrator/Seeds/WizardData dizinini arar. diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs index aba05c4..9e013f9 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs @@ -186,7 +186,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA var code = input.ListFormCode; var isNew = input.Id.IsNullOrWhiteSpace(); var criteria = isNew - ? new ListFormWorkflow(await GenerateNextCriteriaIdAsync()) + ? new ListFormWorkflow(await GenerateNextCriteriaIdAsync(code)) : await criteriaRepository.GetAsync(input.Id); if (!isNew && criteria.ListFormCode != code) @@ -201,16 +201,16 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA criteria.CompareOperator = NormalizeRequired(input.CompareOperator, ">"); criteria.CompareValue = input.CompareValue; criteria.Approver = input.Approver ?? string.Empty; - criteria.NextOnStart = input.NextOnStart ?? string.Empty; - criteria.NextOnTrue = input.NextOnTrue ?? string.Empty; - criteria.NextOnFalse = input.NextOnFalse ?? string.Empty; - criteria.NextOnApprove = input.NextOnApprove ?? string.Empty; - criteria.NextOnReject = input.NextOnReject ?? string.Empty; + criteria.NextOnStart = NormalizeCriteriaTargetId(code, input.NextOnStart); + criteria.NextOnTrue = NormalizeCriteriaTargetId(code, input.NextOnTrue); + criteria.NextOnFalse = NormalizeCriteriaTargetId(code, input.NextOnFalse); + criteria.NextOnApprove = NormalizeCriteriaTargetId(code, input.NextOnApprove); + criteria.NextOnReject = NormalizeCriteriaTargetId(code, input.NextOnReject); criteria.PositionX = input.PositionX <= 0 ? 32 : input.PositionX; criteria.PositionY = input.PositionY <= 0 ? 150 : input.PositionY; - criteria.CompareOutcomesJson = SerializeCompareOutcomes(input.CompareOutcomes); + var outcomes = NormalizeCompareOutcomeTargets(code, input.CompareOutcomes); + criteria.CompareOutcomesJson = SerializeCompareOutcomes(outcomes); - var outcomes = input.CompareOutcomes ?? []; if (criteria.Kind == "Compare" && outcomes.Count > 0) { criteria.NextOnTrue = outcomes.ElementAtOrDefault(0)?.TargetId ?? criteria.NextOnTrue; @@ -1107,7 +1107,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA int positionY, string approver = "") { - var criteria = new ListFormWorkflow(await GenerateNextCriteriaIdAsync()) + var criteria = new ListFormWorkflow(await GenerateNextCriteriaIdAsync(listFormCode)) { ListFormCode = listFormCode, Kind = kind, @@ -1130,41 +1130,95 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA return criteria; } - private async Task GenerateNextCriteriaIdAsync() + private async Task GenerateNextCriteriaIdAsync(string listFormCode) { - var criteria = await criteriaRepository.GetListAsync(); + var criteria = await criteriaRepository.GetListAsync(x => x.ListFormCode == listFormCode); var maxNumber = criteria - .Select(x => TryParseCriteriaIdNumber(x.Id)) + .Select(x => TryParseCriteriaIdNumber(listFormCode, x.Id)) .DefaultIfEmpty(0) .Max(); var nextNumber = maxNumber + 1; - var nextId = FormatCriteriaId(nextNumber); - var existingIds = criteria.Select(x => x.Id).ToHashSet(); + var nextId = FormatCriteriaId(listFormCode, nextNumber); + var existingIds = criteria.Select(x => x.Id).ToHashSet(StringComparer.OrdinalIgnoreCase); while (existingIds.Contains(nextId)) { nextNumber++; - nextId = FormatCriteriaId(nextNumber); + nextId = FormatCriteriaId(listFormCode, nextNumber); } return nextId; } - private static int TryParseCriteriaIdNumber(string id) + private static int TryParseCriteriaIdNumber(string listFormCode, string id) { - if (id.IsNullOrWhiteSpace() || - !id.StartsWith(CriteriaIdPrefix, StringComparison.OrdinalIgnoreCase)) + var localId = GetLocalCriteriaId(listFormCode, id); + if (localId.IsNullOrWhiteSpace() || + !localId.StartsWith(CriteriaIdPrefix, StringComparison.OrdinalIgnoreCase)) { return 0; } - return int.TryParse(id[CriteriaIdPrefix.Length..], out var number) ? number : 0; + return int.TryParse(localId[CriteriaIdPrefix.Length..], out var number) ? number : 0; } - private static string FormatCriteriaId(int number) + private static string FormatCriteriaId(string listFormCode, int number) { - return $"{CriteriaIdPrefix}{number.ToString().PadLeft(CriteriaIdPadding, '0')}"; + return $"{listFormCode}-{CriteriaIdPrefix}{number.ToString().PadLeft(CriteriaIdPadding, '0')}"; + } + + private static string NormalizeCriteriaTargetId(string listFormCode, string id) + { + return id.IsNullOrWhiteSpace() + ? string.Empty + : NormalizeCriteriaId(listFormCode, id); + } + + private static List NormalizeCompareOutcomeTargets( + string listFormCode, + List outcomes) + { + return (outcomes ?? []) + .Select(outcome => new CompareOutcomeDto + { + Label = outcome.Label, + TargetId = NormalizeCriteriaTargetId(listFormCode, outcome.TargetId), + Conditions = outcome.Conditions ?? [] + }) + .ToList(); + } + + private static string NormalizeCriteriaId(string listFormCode, string id) + { + var trimmed = id?.Trim(); + if (trimmed.IsNullOrWhiteSpace()) + { + return string.Empty; + } + + if (trimmed.StartsWith($"{listFormCode}-", StringComparison.OrdinalIgnoreCase)) + { + return trimmed; + } + + return trimmed.StartsWith(CriteriaIdPrefix, StringComparison.OrdinalIgnoreCase) + ? $"{listFormCode}-{trimmed}" + : trimmed; + } + + private static string GetLocalCriteriaId(string listFormCode, string id) + { + var normalized = id?.Trim(); + if (normalized.IsNullOrWhiteSpace()) + { + return string.Empty; + } + + var prefix = $"{listFormCode}-"; + return normalized.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) + ? normalized[prefix.Length..] + : normalized; } private static bool ClearDeletedTarget(ListFormWorkflow criteria, string deletedId) diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json index 79efafd..7f82db4 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json @@ -8112,6 +8112,12 @@ "tr": "Referans", "en": "Reference" }, + { + "resourceName": "Platform", + "key": "Public.payment.customer.website", + "tr": "Web Sitesi", + "en": "Website" + }, { "resourceName": "Platform", "key": "Public.payment.method.title", @@ -17118,6 +17124,30 @@ "en": "Approval or Rejection Comment", "tr": "Onay veya red açıklaması" }, + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.ApprovalUserName", + "en": "Approval User Name", + "tr": "Onaylayan Kullanıcı Adı" + }, + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.ApprovalStatus", + "en": "Approval Status", + "tr": "Onay Durumu" + }, + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.ApprovalDate", + "en": "Approval Date", + "tr": "Onay Tarihi" + }, + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.ApprovalDescription", + "en": "Approval Description", + "tr": "Onay Açıklaması" + }, { "resourceName": "Platform", "key": "App.Listform.ListformField.WorkflowDecisionMessage", diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs index f668d5d..6be4b90 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs @@ -209,11 +209,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep HeaderFilterJson = DefaultHeaderFilterJson(), SearchPanelJson = DefaultSearchPanelJson(), GroupPanelJson = DefaultGroupPanelJson(), - SelectionJson = JsonSerializer.Serialize(new SelectionDto - { - Mode = GridOptions.SelectionAllModeAllPages, - AllowSelectAll = true - }), + SelectionJson = DefaultSelectionMultipleJson, ColumnOptionJson = DefaultColumnOptionJson(), PermissionJson = DefaultPermissionJson(AbpIdentity.Permissions.Create, listFormName, AbpIdentity.Permissions.Update, AbpIdentity.Permissions.Delete, AbpIdentity.Permissions.Export, AbpIdentity.Permissions.Import, AbpIdentity.Permissions.Note), PagerOptionJson = DefaultPagerOptionJson, diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs index 148cf8e..1e30caa 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_DefaultJsons.cs @@ -84,7 +84,7 @@ public static class ListFormSeeder_DefaultJsons }); public static readonly string DefaultSelectionSingleJson = JsonSerializer.Serialize(new SelectionDto { - Mode = GridOptions.SelectionModeNone, + Mode = GridOptions.SelectionModeSingle, AllowSelectAll = false }); public static readonly string DefaultSelectionMultipleJson = JsonSerializer.Serialize(new SelectionDto diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs index 78112af..7395f9f 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs @@ -26,6 +26,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency { private readonly IRepository _listFormRepository; private readonly IRepository _listFormFieldRepository; + private readonly IRepository _listFormWorkflowRepository; private readonly IdentityUserManager _identityUserManager; private readonly IdentityRoleManager _identityRoleManager; private readonly IConfiguration _configuration; @@ -34,6 +35,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency public ListFormSeeder_Saas( IRepository listFormRepository, IRepository listFormFieldRepository, + IRepository listFormWorkflowRepository, IdentityUserManager userManager, IdentityRoleManager roleManager, IConfiguration configuration, @@ -42,6 +44,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency { _listFormRepository = listFormRepository; _listFormFieldRepository = listFormFieldRepository; + _listFormWorkflowRepository = listFormWorkflowRepository; _identityUserManager = userManager; _identityRoleManager = roleManager; _configuration = configuration; @@ -452,15 +455,15 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency ListFormCode = listForm.ListFormCode, CultureName = LanguageCodes.En, SourceDbType = DbType.String, - FieldName = "MobileNumber", - CaptionName = "App.Listform.ListformField.MobileNumber", + FieldName = "PhoneNumber", + CaptionName = "Abp.Identity.User.UserInformation.PhoneNumber", Width = 0, ListOrderNo = 16, Visible = true, IsActive = true, AllowSearch = true, - ValidationRuleJson = DefaultValidationRuleRequiredJson, EditorOptions = EditorOptionValues.PhoneEditorOptions, + ValidationRuleJson = DefaultValidationRuleRequiredJson, ColumnCustomizationJson = DefaultColumnCustomizationJson, PermissionJson = DefaultFieldPermissionJson(TenantManagementPermissions.Tenants.Create, TenantManagementPermissions.Tenants.Default, TenantManagementPermissions.Tenants.Update, true, true, false), PivotSettingsJson = DefaultPivotSettingsJson @@ -470,8 +473,8 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency ListFormCode = listForm.ListFormCode, CultureName = LanguageCodes.En, SourceDbType = DbType.String, - FieldName = "PhoneNumber", - CaptionName = "Abp.Identity.User.UserInformation.PhoneNumber", + FieldName = "MobileNumber", + CaptionName = "App.Listform.ListformField.MobileNumber", Width = 0, ListOrderNo = 17, Visible = true, @@ -938,16 +941,16 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency ListFormCode = listForm.ListFormCode, CultureName = LanguageCodes.En, SourceDbType = DbType.String, - FieldName = "MobileNumber", - CaptionName = "App.Listform.ListformField.MobileNumber", + FieldName = "PhoneNumber", + CaptionName = "Abp.Identity.User.UserInformation.PhoneNumber", Width = 0, ListOrderNo = 15, Visible = true, IsActive = true, AllowSearch = true, - ValidationRuleJson = DefaultValidationRuleRequiredJson, EditorOptions = EditorOptionValues.PhoneEditorOptions, + ValidationRuleJson = DefaultValidationRuleRequiredJson, ColumnCustomizationJson = DefaultColumnCustomizationJson, PermissionJson = DefaultFieldPermissionJson(listForm.Name), PivotSettingsJson = DefaultPivotSettingsJson @@ -957,8 +960,8 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency ListFormCode = listForm.ListFormCode, CultureName = LanguageCodes.En, SourceDbType = DbType.String, - FieldName = "PhoneNumber", - CaptionName = "Abp.Identity.User.UserInformation.PhoneNumber", + FieldName = "MobileNumber", + CaptionName = "App.Listform.ListformField.MobileNumber", Width = 0, ListOrderNo = 16, Visible = true, @@ -6987,7 +6990,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency orderId = "@Id" }), IsVisible = true, - VisibleExpression = "(e) => !e.row?.data?.TenantId", + VisibleExpression = "(e) => !e.row?.data?.TenantId && e.row?.data?.ApprovalStatus === 'Approved'", }, }), EditingFormJson = JsonSerializer.Serialize(new List @@ -7051,8 +7054,25 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency } } }, - }) - }); + }), + WorkflowJson = JsonSerializer.Serialize(new WorkflowDto + { + ApprovalUserFieldName = "ApprovalUserName", + ApprovalStatusFieldName = "ApprovalStatus", + ApprovalDateFieldName = "ApprovalDate", + ApprovalDescriptionFieldName = "ApprovalDescription", + Criteria = [] + }), + }, autoSave: true); + + #region Sales Order Workflow + await _listFormWorkflowRepository.InsertManyAsync([ + new ListFormWorkflow($"{listFormName}-N001") { ListFormCode = listFormName, Kind = "Start", Title = "İş Akışı Başlat1", CompareColumn="Price", CompareOperator=">", CompareValue=5000, Approver= "", NextOnStart = $"{listFormName}-N002", NextOnTrue = "", NextOnFalse = "", NextOnApprove= "", NextOnReject = "", PositionX = 47, PositionY = 76 }, + new ListFormWorkflow($"{listFormName}-N002") { ListFormCode = listFormName, Kind = "Approval", Title = "Onay1", CompareColumn="Price", CompareOperator=">", CompareValue=5000, Approver = "system@sozsoft.com", NextOnStart = "", NextOnTrue = "", NextOnFalse = "", NextOnApprove = $"{listFormName}-N003", NextOnReject = $"{listFormName}-N004", PositionX = 391, PositionY = 76 }, + new ListFormWorkflow($"{listFormName}-N003") { ListFormCode = listFormName, Kind = "End", Title = "Approved", CompareColumn="Price", CompareOperator=">", CompareValue=5000, Approver= "", NextOnStart = "", NextOnTrue = "", NextOnFalse = "", NextOnApprove = "", NextOnReject = "", PositionX = 843, PositionY = 61 }, + new ListFormWorkflow($"{listFormName}-N004") { ListFormCode = listFormName, Kind = "End", Title = "Rejected", CompareColumn="Price", CompareOperator=">", CompareValue=5000, Approver= "", NextOnStart = "", NextOnTrue = "", NextOnFalse = "", NextOnApprove = "", NextOnReject = "", PositionX = 845, PositionY = 263 }, + ]); + #endregion #region Sales Order Fields await _listFormFieldRepository.InsertManyAsync([ @@ -7091,7 +7111,6 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency LookupQuery = LookupQueryValues.TenantValues(), }), AllowSearch = true, - ValidationRuleJson = DefaultValidationRuleRequiredJson, ColumnCustomizationJson = DefaultColumnCustomizationJson, PermissionJson = DefaultFieldPermissionJson(listForm.Name), PivotSettingsJson = DefaultPivotSettingsJson, @@ -7441,7 +7460,6 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency AllowSearch = true, EditorOptions = EditorOptionValues.PhoneEditorOptions, - ValidationRuleJson = DefaultValidationRuleRequiredJson, ColumnCustomizationJson = DefaultColumnCustomizationJson, PermissionJson = DefaultFieldPermissionJson(listForm.Name), PivotSettingsJson = DefaultPivotSettingsJson, @@ -7616,6 +7634,8 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency ColumnCustomizationJson = DefaultColumnCustomizationJson, PermissionJson = DefaultFieldPermissionJson(listForm.Name), PivotSettingsJson = DefaultPivotSettingsJson, + AllowAdding = false, + AllowEditing = false, }, new() { @@ -7652,6 +7672,74 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency ColumnCustomizationJson = DefaultColumnCustomizationJson, PermissionJson = DefaultFieldPermissionJson(listForm.Name), PivotSettingsJson = DefaultPivotSettingsJson, + }, + new() + { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "ApprovalUserName", + CaptionName = "App.Listform.ListformField.ApprovalUserName", + Width = 0, + ListOrderNo = 31, + Visible = true, + IsActive = true, + + AllowSearch = true, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson, + }, + new() + { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "ApprovalStatus", + CaptionName = "App.Listform.ListformField.ApprovalStatus", + Width = 0, + ListOrderNo = 32, + Visible = true, + IsActive = true, + + AllowSearch = true, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson, + }, + new() + { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.DateTime, + FieldName = "ApprovalDate", + CaptionName = "App.Listform.ListformField.ApprovalDate", + Width = 0, + ListOrderNo = 33, + Visible = true, + IsActive = true, + + AllowSearch = true, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson, + }, + new() + { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "ApprovalDescription", + CaptionName = "App.Listform.ListformField.ApprovalDescription", + Width = 0, + ListOrderNo = 34, + Visible = true, + IsActive = true, + + AllowSearch = true, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson, } ]); #endregion @@ -7907,6 +7995,23 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency EditorOptions=EditorOptionValues.NumberStandartFormat(), TotalSummaryJson = DefaultColumnTotalSummaryJson("TotalPrice") }, + new() + { + ListFormCode = listForm.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Guid, + FieldName = "OrderId", + CaptionName = "App.Listform.ListformField.OrderId", + Width = 0, + ListOrderNo = 10, + Visible = false, + IsActive = true, + + AllowSearch = true, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PivotSettingsJson = DefaultPivotSettingsJson, + } ], autoSave: true); #endregion } diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs index fb4fb49..7cc5d0c 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs @@ -148,6 +148,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency var listFormCode = string.IsNullOrWhiteSpace(input.ListFormCode) ? code : input.ListFormCode.Trim(); + NormalizeWorkflowCriteriaIds(listFormCode, input.WorkflowCriteria); var titleLangKey = $"{listFormCode}.Title"; var nameLangKey = code; var descLangKey = $"{listFormCode}.Desc"; @@ -559,6 +560,55 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency return string.IsNullOrWhiteSpace(kind) ? "Step" : kind.Trim(); } + private static void NormalizeWorkflowCriteriaIds(string listFormCode, List criteria) + { + if (string.IsNullOrWhiteSpace(listFormCode) || criteria == null || criteria.Count == 0) + { + return; + } + + foreach (var item in criteria) + { + item.Id = NormalizeWorkflowCriteriaId(listFormCode, item.Id); + item.ListFormCode = listFormCode; + item.NextOnStart = NormalizeWorkflowTargetId(listFormCode, item.NextOnStart); + item.NextOnTrue = NormalizeWorkflowTargetId(listFormCode, item.NextOnTrue); + item.NextOnFalse = NormalizeWorkflowTargetId(listFormCode, item.NextOnFalse); + item.NextOnApprove = NormalizeWorkflowTargetId(listFormCode, item.NextOnApprove); + item.NextOnReject = NormalizeWorkflowTargetId(listFormCode, item.NextOnReject); + + foreach (var outcome in item.CompareOutcomes ?? []) + { + outcome.TargetId = NormalizeWorkflowTargetId(listFormCode, outcome.TargetId); + } + } + } + + private static string NormalizeWorkflowTargetId(string listFormCode, string id) + { + return string.IsNullOrWhiteSpace(id) + ? string.Empty + : NormalizeWorkflowCriteriaId(listFormCode, id); + } + + private static string NormalizeWorkflowCriteriaId(string listFormCode, string id) + { + var trimmed = id?.Trim(); + if (string.IsNullOrWhiteSpace(trimmed)) + { + return string.Empty; + } + + if (trimmed.StartsWith($"{listFormCode}-", StringComparison.OrdinalIgnoreCase)) + { + return trimmed; + } + + return trimmed.StartsWith("N", StringComparison.OrdinalIgnoreCase) + ? $"{listFormCode}-{trimmed}" + : trimmed; + } + private async Task CreateLangKeyAsync(string key, string textEn, string textTr) { if (string.IsNullOrWhiteSpace(key)) return; diff --git a/api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/Website/Order.cs b/api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/Website/Order.cs index d259321..7270bba 100644 --- a/api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/Website/Order.cs +++ b/api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/Website/Order.cs @@ -42,6 +42,11 @@ public class Order : FullAuditedEntity public int? Installment { get; set; } public string PaymentDataJson { get; set; } // JSON olarak saklanacak + public string ApprovalUserName { get; set; } + public string ApprovalStatus { get; set; } + public DateTime? ApprovalDate { get; set; } + public string ApprovalDescription { get; set; } + public List Items { get; set; } = new(); public Order() diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs index 801a422..dbb5ad4 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs @@ -406,6 +406,7 @@ public class PlatformDbContext : b.HasMany().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired(); b.HasMany().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired(); b.HasMany().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired(); + b.HasMany().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired(); }); builder.Entity(b => @@ -498,7 +499,7 @@ public class PlatformDbContext : b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ListFormWorkflow)), Prefix.DbSchema); b.ConfigureByConvention(); - b.Property(x => x.Id).HasMaxLength(50); + b.Property(x => x.Id).HasMaxLength(128); b.Property(x => x.ListFormCode).IsRequired().HasMaxLength(64); b.Property(x => x.Kind).IsRequired().HasMaxLength(50); b.Property(x => x.Title).IsRequired().HasMaxLength(250); @@ -506,15 +507,14 @@ public class PlatformDbContext : b.Property(x => x.CompareOperator).IsRequired().HasMaxLength(20); b.Property(x => x.CompareValue).HasPrecision(18, 2); b.Property(x => x.Approver).IsRequired().HasMaxLength(250); - b.Property(x => x.NextOnStart).IsRequired().HasMaxLength(50); - b.Property(x => x.NextOnTrue).IsRequired().HasMaxLength(50); - b.Property(x => x.NextOnFalse).IsRequired().HasMaxLength(50); - b.Property(x => x.NextOnApprove).IsRequired().HasMaxLength(50); - b.Property(x => x.NextOnReject).IsRequired().HasMaxLength(50); + b.Property(x => x.NextOnStart).IsRequired().HasMaxLength(128); + b.Property(x => x.NextOnTrue).IsRequired().HasMaxLength(128); + b.Property(x => x.NextOnFalse).IsRequired().HasMaxLength(128); + b.Property(x => x.NextOnApprove).IsRequired().HasMaxLength(128); + b.Property(x => x.NextOnReject).IsRequired().HasMaxLength(128); b.Property(x => x.PositionX).IsRequired(); b.Property(x => x.PositionY).IsRequired(); b.Property(x => x.CompareOutcomesJson).HasColumnType("text"); - b.HasIndex(x => new { x.ListFormCode, x.Title }).IsUnique(); }); builder.Entity(b => @@ -1047,6 +1047,10 @@ public class PlatformDbContext : b.Property(o => o.PaymentDataJson).HasMaxLength(4096); + b.Property(o => o.ApprovalUserName).HasMaxLength(256); + b.Property(o => o.ApprovalStatus).HasMaxLength(64); + b.Property(o => o.ApprovalDescription).HasMaxLength(256); + b.HasMany(o => o.Items) .WithOne(i => i.Order) .HasForeignKey(i => i.OrderId) diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260707205022_Initial.Designer.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260708113003_Initial.Designer.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260707205022_Initial.Designer.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260708113003_Initial.Designer.cs index 009a262..92ea33f 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260707205022_Initial.Designer.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260708113003_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Sozsoft.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20260707205022_Initial")] + [Migration("20260708113003_Initial")] partial class Initial { /// @@ -3652,8 +3652,8 @@ namespace Sozsoft.Platform.Migrations modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b => { b.Property("Id") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("Approver") .IsRequired() @@ -3689,28 +3689,28 @@ namespace Sozsoft.Platform.Migrations b.Property("NextOnApprove") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnFalse") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnReject") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnStart") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnTrue") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("PositionX") .HasColumnType("int"); @@ -3725,8 +3725,7 @@ namespace Sozsoft.Platform.Migrations b.HasKey("Id"); - b.HasIndex("ListFormCode", "Title") - .IsUnique(); + b.HasIndex("ListFormCode"); b.ToTable("Sas_H_ListFormWorkflow", (string)null); }); @@ -4088,6 +4087,21 @@ namespace Sozsoft.Platform.Migrations .HasMaxLength(512) .HasColumnType("nvarchar(512)"); + b.Property("ApprovalDate") + .HasColumnType("datetime2"); + + b.Property("ApprovalDescription") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ApprovalStatus") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ApprovalUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + b.Property("BillingCycle") .HasMaxLength(32) .HasColumnType("nvarchar(32)"); @@ -8728,6 +8742,16 @@ namespace Sozsoft.Platform.Migrations .IsRequired(); }); + modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b => + { + b.HasOne("Sozsoft.Platform.Entities.ListForm", null) + .WithMany() + .HasForeignKey("ListFormCode") + .HasPrincipalKey("ListFormCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Sozsoft.Platform.Entities.MessengerConversationMessage", b => { b.HasOne("Sozsoft.Platform.Entities.MessengerConversation", "Conversation") diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260707205022_Initial.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260708113003_Initial.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260707205022_Initial.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260708113003_Initial.cs index dfc62eb..10499d1 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260707205022_Initial.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260708113003_Initial.cs @@ -1465,32 +1465,6 @@ namespace Sozsoft.Platform.Migrations table.UniqueConstraint("AK_Sas_H_ListForm_ListFormCode", x => x.ListFormCode); }); - migrationBuilder.CreateTable( - name: "Sas_H_ListFormWorkflow", - columns: table => new - { - Id = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - ListFormCode = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - Kind = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - Title = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - CompareColumn = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - CompareOperator = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false), - CompareValue = table.Column(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false), - Approver = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - NextOnStart = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - NextOnTrue = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - NextOnFalse = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - NextOnApprove = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - NextOnReject = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - PositionX = table.Column(type: "int", nullable: false), - PositionY = table.Column(type: "int", nullable: false), - CompareOutcomesJson = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Sas_H_ListFormWorkflow", x => x.Id); - }); - migrationBuilder.CreateTable( name: "Sas_H_LogEntry", columns: table => new @@ -1601,6 +1575,10 @@ namespace Sozsoft.Platform.Migrations PaymentMethodId = table.Column(type: "uniqueidentifier", nullable: false), Installment = table.Column(type: "int", nullable: true), PaymentDataJson = table.Column(type: "nvarchar(max)", maxLength: 4096, nullable: true), + ApprovalUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ApprovalStatus = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ApprovalDate = table.Column(type: "datetime2", nullable: true), + ApprovalDescription = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -2852,6 +2830,38 @@ namespace Sozsoft.Platform.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "Sas_H_ListFormWorkflow", + columns: table => new + { + Id = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ListFormCode = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Kind = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + Title = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + CompareColumn = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + CompareOperator = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false), + CompareValue = table.Column(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false), + Approver = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + NextOnStart = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + NextOnTrue = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + NextOnFalse = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + NextOnApprove = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + NextOnReject = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + PositionX = table.Column(type: "int", nullable: false), + PositionY = table.Column(type: "int", nullable: false), + CompareOutcomesJson = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Sas_H_ListFormWorkflow", x => x.Id); + table.ForeignKey( + name: "FK_Sas_H_ListFormWorkflow_Sas_H_ListForm_ListFormCode", + column: x => x.ListFormCode, + principalTable: "Sas_H_ListForm", + principalColumn: "ListFormCode", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "Sas_H_NotificationRule", columns: table => new @@ -4094,10 +4104,9 @@ namespace Sozsoft.Platform.Migrations column: "ImportId"); migrationBuilder.CreateIndex( - name: "IX_Sas_H_ListFormWorkflow_ListFormCode_Title", + name: "IX_Sas_H_ListFormWorkflow_ListFormCode", table: "Sas_H_ListFormWorkflow", - columns: new[] { "ListFormCode", "Title" }, - unique: true); + column: "ListFormCode"); migrationBuilder.CreateIndex( name: "IX_Sas_H_Menu_Code", diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index 8a0761e..ba0de3d 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -3649,8 +3649,8 @@ namespace Sozsoft.Platform.Migrations modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b => { b.Property("Id") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("Approver") .IsRequired() @@ -3686,28 +3686,28 @@ namespace Sozsoft.Platform.Migrations b.Property("NextOnApprove") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnFalse") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnReject") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnStart") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("NextOnTrue") .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.Property("PositionX") .HasColumnType("int"); @@ -3722,8 +3722,7 @@ namespace Sozsoft.Platform.Migrations b.HasKey("Id"); - b.HasIndex("ListFormCode", "Title") - .IsUnique(); + b.HasIndex("ListFormCode"); b.ToTable("Sas_H_ListFormWorkflow", (string)null); }); @@ -4085,6 +4084,21 @@ namespace Sozsoft.Platform.Migrations .HasMaxLength(512) .HasColumnType("nvarchar(512)"); + b.Property("ApprovalDate") + .HasColumnType("datetime2"); + + b.Property("ApprovalDescription") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ApprovalStatus") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ApprovalUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + b.Property("BillingCycle") .HasMaxLength(32) .HasColumnType("nvarchar(32)"); @@ -8725,6 +8739,16 @@ namespace Sozsoft.Platform.Migrations .IsRequired(); }); + modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b => + { + b.HasOne("Sozsoft.Platform.Entities.ListForm", null) + .WithMany() + .HasForeignKey("ListFormCode") + .HasPrincipalKey("ListFormCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Sozsoft.Platform.Entities.MessengerConversationMessage", b => { b.HasOne("Sozsoft.Platform.Entities.MessengerConversation", "Conversation") diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs b/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs index c20dd93..22cae52 100644 --- a/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs +++ b/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs @@ -376,7 +376,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager { var orderQuery = await orderRepository.WithDetailsAsync(order => order.Items); var activeOrders = await orderQuery - .Where(order => order.TenantId == tenantId && order.IsActive) + .Where(order => order.TenantId == tenantId && order.ApprovalStatus == "Approved" && order.IsActive) .ToListAsync(); return activeOrders diff --git a/ui/src/components/orders/BillingControls.tsx b/ui/src/components/orders/BillingControls.tsx index da1e0d2..738c08f 100644 --- a/ui/src/components/orders/BillingControls.tsx +++ b/ui/src/components/orders/BillingControls.tsx @@ -26,7 +26,6 @@ export const BillingControls: React.FC = ({ cartItemsCount, cartState, }) => { - // Check if cart has items to prevent billing cycle changes const hasCartItems = cartState.items.length > 0 const isScrolled = useScroll() const { translate } = useLocalization() diff --git a/ui/src/components/orders/OrderSuccess.tsx b/ui/src/components/orders/OrderSuccess.tsx index 3a50fdf..5f5de1b 100644 --- a/ui/src/components/orders/OrderSuccess.tsx +++ b/ui/src/components/orders/OrderSuccess.tsx @@ -50,9 +50,9 @@ export const OrderSuccess: React.FC = ({ orderId, order }) => const billingCycleLabel = order?.billingCycle === 'monthly' - ? 'Aylık' + ? translate('::Public.products.billingcycle.monthly') : order?.billingCycle === 'yearly' - ? 'Yıllık' + ? translate('::Public.products.billingcycle.yearly') : '-' const getItemPrice = (item: BasketItem) => diff --git a/ui/src/components/orders/PaymentForm.tsx b/ui/src/components/orders/PaymentForm.tsx index ea050d2..1ec60d8 100644 --- a/ui/src/components/orders/PaymentForm.tsx +++ b/ui/src/components/orders/PaymentForm.tsx @@ -140,7 +140,12 @@ export const PaymentForm: React.FC = ({ onBack, onComplete, ca year: 'numeric', }).format(date) - const billingCycleLabel = billingCycle === 'monthly' ? 'Aylık' : 'Yıllık' + const billingCycleLabel = + billingCycle === 'monthly' + ? translate('::Public.products.billingcycle.monthly') + : billingCycle === 'yearly' + ? translate('::Public.products.billingcycle.yearly') + : '-' return (
diff --git a/ui/src/components/orders/ProductCard.tsx b/ui/src/components/orders/ProductCard.tsx index b8073c2..8b4e9c5 100644 --- a/ui/src/components/orders/ProductCard.tsx +++ b/ui/src/components/orders/ProductCard.tsx @@ -87,7 +87,6 @@ export const ProductCard: React.FC = ({ return globalPeriod > 1 ? ` (${globalPeriod} ${periodText})` : '' } - // Check if product has valid price for current billing cycle const hasValidPrice = () => { if (globalBillingCycle === 'monthly' && !product.monthlyPrice) return false if (globalBillingCycle === 'yearly' && !product.yearlyPrice) return false diff --git a/ui/src/components/orders/ProductCatalog.tsx b/ui/src/components/orders/ProductCatalog.tsx index a607d98..5518a72 100644 --- a/ui/src/components/orders/ProductCatalog.tsx +++ b/ui/src/components/orders/ProductCatalog.tsx @@ -48,7 +48,6 @@ export const ProductCatalog: React.FC = ({ setCartState((currentState) => addItemToCart(currentState, product, quantity, billingCycle)) } - // Filter products based on billing cycle - only show products that have pricing for the selected cycle const availableProducts = useMemo(() => { return products.filter((product) => { // If monthly billing is selected, only show products with monthlyPrice diff --git a/ui/src/components/orders/TenantForm.tsx b/ui/src/components/orders/TenantForm.tsx index 2e99b18..0353b83 100644 --- a/ui/src/components/orders/TenantForm.tsx +++ b/ui/src/components/orders/TenantForm.tsx @@ -15,6 +15,7 @@ import { FaUser, FaUserPlus, FaCheckCircle, + FaSitemap, } from 'react-icons/fa' import React, { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' @@ -1031,19 +1032,37 @@ export const TenantForm: React.FC = ({ onSubmit }) => {
-
- -
- - handleInputChange('reference', e.target.value)} - className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg bg-white text-gray-900 placeholder-gray-500 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent" - /> +
+
+ +
+ + handleInputChange('website', e.target.value)} + className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg bg-white text-gray-900 placeholder-gray-500 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent" + /> +
+
+
+ +
+ + handleInputChange('reference', e.target.value)} + className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg bg-white text-gray-900 placeholder-gray-500 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent" + /> +
diff --git a/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx b/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx index 09ef9c8..14d2196 100644 --- a/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx +++ b/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx @@ -302,6 +302,11 @@ export function FormTabWorkflow( } const beginLink = (sourceId: string, outcome: string) => { + if (pendingLink && pendingLink.sourceId !== sourceId) { + connectNodes(pendingLink.sourceId, pendingLink.outcome, sourceId) + return + } + setPendingLink({ sourceId, outcome }) setSelectedId(sourceId) } diff --git a/ui/src/views/admin/listForm/workflow/WorkflowCanvas.tsx b/ui/src/views/admin/listForm/workflow/WorkflowCanvas.tsx index 65e2ac1..573dd1f 100644 --- a/ui/src/views/admin/listForm/workflow/WorkflowCanvas.tsx +++ b/ui/src/views/admin/listForm/workflow/WorkflowCanvas.tsx @@ -36,6 +36,7 @@ type FlowNodeProps = { onOpenDetails: () => void onDelete: () => void onBeginLink: (sourceId: string, outcome: string) => void + onConnect: (sourceId: string, outcome: string, targetId: string) => void } export function WorkflowCanvas({ @@ -241,6 +242,7 @@ export function WorkflowCanvas({ onOpenDetails={() => onOpenDetails(item.id)} onDelete={() => onDelete(item.id)} onBeginLink={onBeginLink} + onConnect={onConnect} /> ))} event.stopPropagation()} + onPointerUp={(event) => event.stopPropagation()} onClick={(event) => { event.preventDefault() event.stopPropagation() + if (pendingLink && pendingLink.sourceId !== item.id) { + onConnect(pendingLink.sourceId, pendingLink.outcome, item.id) + return + } onBeginLink(item.id, outcome.field) }} onKeyDown={(event) => { if (event.key !== 'Enter' && event.key !== ' ') return event.preventDefault() event.stopPropagation() + if (pendingLink && pendingLink.sourceId !== item.id) { + onConnect(pendingLink.sourceId, pendingLink.outcome, item.id) + return + } onBeginLink(item.id, outcome.field) }} >