Compare commits

..

No commits in common. "main" and "1.1.06" have entirely different histories.
main ... 1.1.06

333 changed files with 11310 additions and 24341 deletions

View file

@ -107,31 +107,9 @@ public partial class LanguageTextCreateUpdateDtoToLanguageTextMapper : MapperBas
public partial class LanguageKeyToLanguageTextTranslatedDtoMapper : MapperBase<LanguageKey, LanguageTextTranslatedDto>
{
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.Id))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseCultureName))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseValue))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetCultureName))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetValue))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.IsDeleted))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeleterId))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeletionTime))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModificationTime))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModifierId))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreationTime))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreatorId))]
public override partial LanguageTextTranslatedDto Map(LanguageKey source);
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.Id))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseCultureName))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.BaseValue))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetCultureName))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.TargetValue))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.IsDeleted))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeleterId))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.DeletionTime))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModificationTime))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.LastModifierId))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreationTime))]
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.CreatorId))]
public override partial void Map(LanguageKey source, LanguageTextTranslatedDto destination);
public override void BeforeMap(LanguageKey source)

View file

@ -153,32 +153,6 @@ public class NotificationAppService : ReadOnlyAppService<
return ObjectMapper.Map<Notification, NotificationDto>(item);
}
public async Task<int> UpdateReadManyAsync(List<Guid> notificationIds, bool isRead)
{
if (notificationIds.Count == 0)
{
return 0;
}
var query = await repository.GetQueryableAsync();
return await query
.Where(a => a.UserId == CurrentUser.Id && notificationIds.Contains(a.Id) && a.IsRead != isRead)
.ExecuteUpdateAsync(setters => setters.SetProperty(a => a.IsRead, isRead));
}
public async Task<int> UpdateSentManyAsync(List<Guid> notificationIds, bool isSent)
{
if (notificationIds.Count == 0)
{
return 0;
}
var query = await repository.GetQueryableAsync();
return await query
.Where(a => a.UserId == CurrentUser.Id && notificationIds.Contains(a.Id) && a.IsSent != isSent)
.ExecuteUpdateAsync(setters => setters.SetProperty(a => a.IsSent, isSent));
}
[RemoteService(false)]
public override Task<NotificationDto> GetAsync(Guid id) => throw new NotImplementedException();
[RemoteService(false)]

View file

@ -5,7 +5,6 @@ using Sozsoft.Settings.Localization;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
using Volo.Abp.Threading;
using SettingDefinition = Sozsoft.Settings.Entities.SettingDefinition;
namespace Sozsoft.Settings;
@ -23,7 +22,8 @@ public class SettingsDefinitionProvider : SettingDefinitionProvider
public override void Define(ISettingDefinitionContext context)
{
repository.DisableTracking();
var settingDefinitions = AsyncHelper.RunSync(() => repository.GetListAsync());
var settingDefinitions = repository.GetListAsync().Result;
//var settingDefinitions = AsyncHelper.RunSync(() => repository.ToListAsync());
foreach (var item in settingDefinitions.OrderBy(a => a.Order))
{

View file

@ -1,5 +1,4 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;
namespace Sozsoft.Platform.DeveloperKit;
@ -7,7 +6,6 @@ namespace Sozsoft.Platform.DeveloperKit;
public class CustomComponentDto : FullAuditedEntityDto<Guid>
{
public string Name { get; set; } = string.Empty;
public string RoutePath { get; set; } = string.Empty;
public string Code { get; set; } = string.Empty;
public string? Props { get; set; }
public string? Description { get; set; }
@ -18,10 +16,6 @@ public class CustomComponentDto : FullAuditedEntityDto<Guid>
public class CreateUpdateCustomComponentDto
{
public string Name { get; set; } = string.Empty;
[Required]
[StringLength(512)]
[RegularExpression(@"^/.*", ErrorMessage = "RoutePath must start with '/'.")]
public string RoutePath { get; set; } = string.Empty;
public string Code { get; set; } = string.Empty;
public string? Props { get; set; }
public string? Description { get; set; }

View file

@ -93,10 +93,6 @@ public class ForumTopicDto : FullAuditedEntityDto<Guid>
public Guid CategoryId { get; set; }
public Guid AuthorId { get; set; }
public string AuthorName { get; set; }
public string AuthorTitle { get; set; }
public string AuthorEmail { get; set; }
public string AuthorPhoneNumber { get; set; }
public string AuthorDepartment { get; set; }
public int ViewCount { get; set; }
public int ReplyCount { get; set; }
public int LikeCount { get; set; }
@ -159,10 +155,6 @@ public class ForumPostDto : FullAuditedEntityDto<Guid>
public string Content { get; set; }
public Guid AuthorId { get; set; }
public string AuthorName { get; set; }
public string AuthorTitle { get; set; }
public string AuthorEmail { get; set; }
public string AuthorPhoneNumber { get; set; }
public string AuthorDepartment { get; set; }
public int LikeCount { get; set; }
public bool IsAcceptedAnswer { get; set; }

View file

@ -10,11 +10,6 @@ namespace Sozsoft.Platform.ListForms;
public class ColumnFormatDto : AuditedEntityDto<Guid>
{
private static readonly JsonSerializerOptions EditorOptionsSerializerOptions = new()
{
PropertyNameCaseInsensitive = true
};
public ColumnFormatDto() { }
public string FieldName { get; set; }
@ -244,42 +239,7 @@ public class ColumnFormatDto : AuditedEntityDto<Guid>
}
public string Alignment { get; set; }
public string Format { get; set; }
public int? EditOrderNo { get; set; }
public int? EditGroupOrderNo { get; set; }
public string EditorType2 { get; set; }
public int? ColSpan { get; set; }
public string EditorOptions { get; set; }
public GridBoxOptionsDto GridBoxOptions =>
DeserializeEditorOptions<GridBoxOptionsDto>(PlatformConsts.EditorTypes.dxGridBox);
public TagBoxOptionsDto TagBoxOptions =>
DeserializeEditorOptions<TagBoxOptionsDto>(PlatformConsts.EditorTypes.dxTagBox);
public ImageUploadOptionsDto ImageUploadOptions =>
DeserializeEditorOptions<ImageUploadOptionsDto>(
PlatformConsts.EditorTypes.dxImageUpload,
PlatformConsts.EditorTypes.dxImageViewer);
public string EditorScript { get; set; }
private T DeserializeEditorOptions<T>(params string[] editorTypes) where T : class
{
if (!Array.Exists(
editorTypes,
editorType => string.Equals(EditorType2, editorType, StringComparison.OrdinalIgnoreCase)) ||
string.IsNullOrWhiteSpace(EditorOptions))
{
return null;
}
try
{
return JsonSerializer.Deserialize<T>(EditorOptions, EditorOptionsSerializerOptions);
}
catch (JsonException)
{
return null;
}
}
public string Format { get; set; }
public string EditorOptions { get; set; }
}

View file

@ -1,10 +0,0 @@
using System;
namespace Sozsoft.Platform.ListForms.DynamicApi;
public class CreateTenantFromOrderInput
{
public Guid OrderId { get; set; }
public string Name { get; set; }
public string MenuGroup { get; set; }
}

View file

@ -28,5 +28,6 @@ public class CreateUpdateTenantInput
public string Email { get; set; }
public string Website { get; set; }
public string MenuGroup { get; set; }
public int MaxConcurrentUsers { get; set; }
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
namespace Sozsoft.Platform.ListForms.DynamicApi;
@ -12,5 +12,5 @@ public interface IListFormDynamicApiAppService
Task PostTenantInsertAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input);
Task PostTenantUpdateAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input);
Task PostTenantDeleteAsync(DynamicApiBaseInput<string> input);
Task<Guid> PostCreateTenantFromOrderAsync(DynamicApiBaseInput<CreateTenantFromOrderInput> input);
}

View file

@ -16,5 +16,35 @@ public class EditingFormDto
public string Caption { get; set; }
public int ColCount { get; set; } = 2;
public int ColSpan { get; set; } = 2;
/// <summary> Type: Array<Simple Form Item | Group Form Item | Tabbed Form Item | Empty Form Item | Button Form Item>
/// Bu kisma suan sadece string olarak doldurulacak
/// items: ['FirstName', 'LastName',
/// { dataField: 'Notes', editorType: 'dxTextArea', colSpan: 2, editorOptions: { height: 100, }, }
/// ],
/// </summary>
//[TextArea]
//public string[] Items { get; set; }
public EditingFormItemDto[] Items { get; set; }
}
public class EditingFormItemDto
{
/// <summary>
/// DataField Accepted Values: 'dxAutocomplete' | 'dxCalendar' | 'dxCheckBox' | 'dxColorBox' | 'dxDateBox' | 'dxDateRangeBox' | 'dxDropDownBox' | 'dxHtmlEditor' | 'dxLookup' | 'dxNumberBox' | 'dxRadioGroup' | 'dxRangeSlider' | 'dxSelectBox' | 'dxSlider' | 'dxSwitch' | 'dxTagBox' | 'dxTextArea' | 'dxTextBox' | 'dxImageViewer' | 'dxImageUpload';
/// </summary>
[JsonPropertyName("order")]
public int Order { get; set; }
[JsonPropertyName("dataField")]
public string DataField { get; set; }
[JsonPropertyName("editorType2")]
public string EditorType2 { get; set; }
[JsonPropertyName("colSpan")]
public int ColSpan { get; set; }
[JsonPropertyName("editorOptions")]
public string EditorOptions { get; set; }
public GridBoxOptionsDto GridBoxOptions { get; set; }
public TagBoxOptionsDto TagBoxOptions { get; set; }
[JsonPropertyName("editorScript")]
public string EditorScript { get; set; }
}

View file

@ -190,19 +190,6 @@ public class GridOptionsDto : AuditedEntityDto<Guid>
set { SchedulerOptionJson = JsonSerializer.Serialize(value); }
}
[JsonIgnore]
public string TodoOptionJson { get; set; }
public TodoOptionDto TodoOptionDto
{
get
{
if (!string.IsNullOrEmpty(TodoOptionJson))
return JsonSerializer.Deserialize<TodoOptionDto>(TodoOptionJson);
return new TodoOptionDto();
}
set { TodoOptionJson = JsonSerializer.Serialize(value); }
}
[JsonIgnore]
public string PagerOptionJson { get; set; }
public GridPagerOptionDto PagerOptionDto

View file

@ -1,11 +0,0 @@
namespace Sozsoft.Platform.ListForms;
public class ImageUploadOptionsDto
{
public string UploadUrl { get; set; }
public string Accept { get; set; }
public bool? Multiple { get; set; }
public long? MaxFileSize { get; set; }
public int? Width { get; set; }
public int? Height { get; set; }
}

View file

@ -3,13 +3,11 @@
public class LayoutDto
{
public bool Grid { get; set; } = true;
public bool Card { get; set; } = true;
public bool Pivot { get; set; } = true;
public bool Chart { get; set; } = true;
public bool Tree { get; set; } = true;
public bool Gantt { get; set; } = true;
public bool Scheduler { get; set; } = true;
public bool Todo { get; set; } = false;
public string DefaultLayout { get; set; } = "grid";
}

View file

@ -1,20 +0,0 @@
namespace Sozsoft.Platform.ListForms;
/// <summary>
/// Dinamik bir listeyi Todo/Kanban panosu olarak gostermek icin alan eslemeleri.
/// TitleExpr ve StatusExpr zorunlu, diger alanlar opsiyoneldir.
/// </summary>
public class TodoOptionDto
{
public string TitleExpr { get; set; }
public string StatusExpr { get; set; }
public string DescriptionExpr { get; set; }
public string DueDateExpr { get; set; }
public string TagExpr { get; set; }
public string AssigneeExpr { get; set; }
public string PriorityExpr { get; set; }
public string CompletedExpr { get; set; }
public string OrderExpr { get; set; }
public string StatusOrder { get; set; }
public bool AllowDragging { get; set; } = true;
}

View file

@ -5,10 +5,10 @@ namespace Sozsoft.Platform.ListForms;
public class WorkflowDto
{
public string ApprovalUserFieldName { get; set; }
public bool IsFilterUserName { get; set; }
public string ApprovalDateFieldName { get; set; }
public string ApprovalStatusFieldName { get; set; }
public string ApprovalDescriptionFieldName { get; set; }
public bool ApprovalIsFilterUserName { get; set; }
public List<ListFormWorkflowCriteriaDto> Criteria { get; set; } = [];
}

View file

@ -49,7 +49,6 @@ public class ListFormEditTabs
public const string TreeForm = "tree";
public const string GanttForm = "gantt";
public const string SchedulerForm = "scheduler";
public const string TodoForm = "todo";
public const string PagerForm = "pager";
public const string StateForm = "state";
public const string SubFormJsonRow = "subForm";

View file

@ -22,13 +22,11 @@ public class ListFormWizardDto
public string DefaultLayout { get; set; }
public bool Grid { get; set; }
public bool Card { get; set; }
public bool Pivot { get; set; }
public bool Tree { get; set; }
public bool Chart { get; set; }
public bool Gantt { get; set; }
public bool Scheduler { get; set; }
public bool Todo { get; set; }
public string LanguageTextMenuEn { get; set; }
public string LanguageTextMenuTr { get; set; }
@ -41,7 +39,6 @@ public class ListFormWizardDto
public string PermissionGroupName { get; set; }
public string MenuParentCode { get; set; }
public string MenuParentShortName { get; set; }
public string MenuParentIcon { get; set; }
public string MenuIcon { get; set; }
public string DataSourceCode { get; set; }
@ -71,28 +68,9 @@ public class ListFormWizardDto
public string SchedulerStartDateExpr { get; set; }
public string SchedulerEndDateExpr { get; set; }
// Todo options (required when DefaultLayout = "todo")
public string TodoTitleExpr { get; set; }
public string TodoStatusExpr { get; set; }
public string TodoDescriptionExpr { get; set; }
public string TodoDueDateExpr { get; set; }
public string TodoTagExpr { get; set; }
public string TodoAssigneeExpr { get; set; }
public string TodoPriorityExpr { get; set; }
public string TodoCompletedExpr { get; set; }
public string TodoOrderExpr { get; set; }
public string TodoStatusOrder { get; set; }
public bool TodoAllowDragging { get; set; } = true;
// Workflow options (required when DefaultLayout = "workflow")
public string ApprovalUserFieldName { get; set; }
public string ApprovalDateFieldName { get; set; }
public string ApprovalStatusFieldName { get; set; }
public string ApprovalDescriptionFieldName { get; set; }
public bool ApprovalIsFilterUserName { get; set; }
public List<ListFormWorkflowCriteriaDto> Criteria { get; set; } = [];
public List<WizardColumnGroupInputDto> Groups { get; set; } = new();
public List<SubFormDto> SubForms { get; set; } = new();
public List<WidgetEditDto> Widgets { get; set; } = new();
public WorkflowDto Workflow { get; set; } = new();
public List<ListFormWorkflowCriteriaDto> WorkflowCriteria { get; set; } = new();
}

View file

@ -5,7 +5,7 @@ namespace Sozsoft.Platform.ListForms;
public class WizardColumnItemInputDto
{
public string FieldName { get; set; }
public string DataField { get; set; }
public string CaptionName { get; set; }
public string EditorType { get; set; }
public string EditorOptions { get; set; }

View file

@ -52,13 +52,13 @@ public static class LookupQueryValues
$"\"AbpTenants\".\"Name\" AS \"Name\" " +
$"FROM \"AbpTenants\"" +
$") AS \"List\" " +
$"ORDER BY \"Name\"";
$"ORDER BY \"Name\"";
}
else
{
return $"SELECT * FROM (" +
// $"SELECT NULL AS \"Key\", 'Host' AS \"Name\" " +
// $"UNION ALL " +
$"SELECT NULL AS \"Key\", 'Host' AS \"Name\" " +
$"UNION ALL " +
$"SELECT " +
$"\"AbpTenants\".\"Id\" AS \"Key\", " +
$"\"AbpTenants\".\"Name\" AS \"Name\" " +
@ -118,15 +118,14 @@ public static class LookupQueryValues
public static string TownshipValues =
$"SELECT " +
$"\"Township\" AS \"Key\", " +
$"\"Township\" AS \"Name\", " +
$"\"PostalCode\" AS \"Group\" " +
$"\"Township\" AS \"Name\" " +
$"FROM \"{FullNameTable(TableNameEnum.District)}\" " +
$"WHERE " +
$"(\"Country\" = @param0 OR @param0 IS NULL) " +
$"AND (\"City\" = @param1 OR @param1 IS NULL) " +
$"AND (\"Name\" = @param2 OR @param2 IS NULL) " +
$"AND \"IsDeleted\" = 'false' " +
$"GROUP BY \"Township\", \"PostalCode\" " +
$"GROUP BY \"Township\" " +
$"ORDER BY \"Township\";";
public static string RoleValues =
@ -179,14 +178,11 @@ public static class LookupQueryValues
public static string ProductValues =
$"SELECT " +
$"\"{FullNameTable(TableNameEnum.Product)}\".\"Id\" AS \"Key\", " +
$"\"{FullNameTable(TableNameEnum.LanguageText)}\".\"Value\" AS \"Name\" " +
$"FROM \"{FullNameTable(TableNameEnum.Product)}\" " +
$"LEFT OUTER JOIN \"{FullNameTable(TableNameEnum.LanguageText)}\" " +
$"ON \"{FullNameTable(TableNameEnum.Product)}\".\"Name\" = \"{FullNameTable(TableNameEnum.LanguageText)}\".\"Key\" " +
$"WHERE \"{FullNameTable(TableNameEnum.Product)}\".\"IsDeleted\" = 'false' " +
$"AND \"{FullNameTable(TableNameEnum.LanguageText)}\".\"CultureName\" = 'tr' " +
$"ORDER BY \"{FullNameTable(TableNameEnum.LanguageText)}\".\"Value\";";
$"\"Id\" AS \"Key\", " +
$"\"Name\" AS \"Name\" " +
$"FROM \"{TableNameResolver.GetFullTableName(nameof(TableNameEnum.Product))}\" " +
$"WHERE \"IsDeleted\" = 'false' " +
$"ORDER BY \"Name\";";
public static string MenuCodeValues =
$"SELECT " +
@ -262,7 +258,7 @@ public static class LookupQueryValues
$"OR jp.\"ParentId\" IS NULL " +
$") " +
$"ORDER BY jp.\"Name\";";
public static string SurveyQuestionValues =
$"SELECT " +
$"\"Id\" AS \"Key\", " +

View file

@ -9,9 +9,6 @@ public class CountryDto : AuditedEntityDto<string>
public string GroupName { get; set; }
public string Currency { get; set; }
public int PhoneCode { get; set; }
public int? PhoneNumberMinLength { get; set; }
public int? PhoneNumberMaxLength { get; set; }
public string? PhoneNumberFormat { get; set; }
public string TaxLabel { get; set; }
public bool ZipRequired { get; set; }
public bool StateRequired { get; set; }

View file

@ -9,5 +9,4 @@ public class DistrictDto : AuditedEntityDto<Guid>
public string City { get; set; }
public string Name { get; set; }
public string Township { get; set; }
public string PostalCode { get; set; }
}

View file

@ -8,17 +8,10 @@ namespace Sozsoft.Platform.Public;
public class OrderDto : EntityDto<Guid>
{
public CustomTenantDto Tenant { get; set; }
public List<OrderItemDto> Items { get; set; }
public bool IsExisting { get; set; }
public string BillingCycle { get; set; }
public int Period { get; set; }
public DateTime? LicenseStartTime { get; set; }
public DateTime? LicenseEndTime { get; set; }
public decimal Subtotal { get; set; }
public decimal VatTotal { get; set; }
public decimal Commission { get; set; }
public decimal Total { get; set; }

View file

@ -8,8 +8,6 @@ public class OrderItemDto
public ProductDto Product { get; set; }
public string BillingCycle { get; set; } // monthly | yearly
public int Quantity { get; set; }
public decimal VatRate { get; set; }
public decimal VatAmount { get; set; }
public decimal TotalPrice { get; set; }
}

View file

@ -13,7 +13,6 @@ public class ProductDto : EntityDto<Guid>
public int Order { get; set; }
public decimal? MonthlyPrice { get; set; }
public decimal? YearlyPrice { get; set; }
public decimal VatRate { get; set; }
public bool IsQuantityBased { get; set; }
public string ImageUrl { get; set; }
public string Unit =>

View file

@ -4,8 +4,10 @@ namespace Sozsoft.Platform.Tenants;
public class CustomTenantDto
{
public Guid? Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public Guid? Id { get; set; }
public string OrganizationName { get; set; }
public string Founder { get; set; }
public long? VknTckn { get; set; }
@ -17,12 +19,11 @@ public class CustomTenantDto
public string Address1 { get; set; }
public string Address2 { get; set; }
public string PostalCode { get; set; }
public string PhoneNumber { get; set; }
public string MobileNumber { get; set; }
public string PhoneNumber { get; set; }
public string FaxNumber { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string MenuGroup { get; set; }
public string Reference { get; set; }
}

View file

@ -6,7 +6,6 @@ using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
namespace Sozsoft.Platform.AiBots;
@ -26,31 +25,16 @@ public class AiBotAppService : CrudAppService<
{
await CheckGetListPolicyAsync();
var query = await CreateFilteredQueryAsync(input);
if (CurrentTenant.IsAvailable && !string.IsNullOrWhiteSpace(CurrentTenant.Name))
{
var tenantName = CurrentTenant.Name;
List<AiBot> tenantEntities;
using (CurrentTenant.Change(null))
{
var hostQuery = await CreateFilteredQueryAsync(input);
tenantEntities = await AsyncExecuter.ToListAsync(hostQuery);
}
var filteredQuery = tenantEntities
.Where(aiBot => IsAvailableForTenant(aiBot.Tenants, tenantName))
.AsQueryable();
var tenantTotalCount = filteredQuery.LongCount();
filteredQuery = ApplySorting(filteredQuery, input);
filteredQuery = ApplyPaging(filteredQuery, input);
var tenantDtos = await MapToGetListOutputDtosAsync(filteredQuery.ToList());
return new PagedResultDto<AiBotDto>(tenantTotalCount, tenantDtos);
query = query.Where(aiBot =>
string.IsNullOrWhiteSpace(aiBot.Tenants) ||
aiBot.Tenants.Contains($"\"{tenantName}\""));
}
var query = await CreateFilteredQueryAsync(input);
var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
@ -60,17 +44,5 @@ public class AiBotAppService : CrudAppService<
return new PagedResultDto<AiBotDto>(totalCount, dtos);
}
private static bool IsAvailableForTenant(string tenants, string tenantName)
{
if (string.IsNullOrWhiteSpace(tenants))
{
return true;
}
return tenants
.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Any(name => string.Equals(name, tenantName, StringComparison.OrdinalIgnoreCase));
}
}

View file

@ -100,11 +100,13 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe
private string EncodePathAsId(string path)
{
// Path'deki '/' karakterlerini '|' ile değiştir URL-safe hale getirmek için
return path.Replace("/", "|");
}
private string DecodeIdAsPath(string id)
{
// ID'deki '|' karakterlerini '/' ile geri değiştir
return id.Replace("|", "/");
}

View file

@ -3,9 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Sozsoft.Platform.Entities;
using Sozsoft.Platform.Extensions;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Authorization;
using Volo.Abp.Domain.Entities;
@ -22,24 +19,19 @@ public class ForumAppService : PlatformAppService, IForumAppService
private readonly IRepository<ForumTopic, Guid> _topicRepository;
private readonly IRepository<ForumPost, Guid> _postRepository;
private readonly IIdentityUserRepository _identityUserRepository;
private readonly IRepository<Department, Guid> _departmentRepository;
private readonly IRepository<JobPosition, Guid> _jobPositionRepository;
public ForumAppService(
IRepository<ForumCategory, Guid> categoryRepository,
IRepository<ForumTopic, Guid> topicRepository,
IRepository<ForumPost, Guid> postRepository,
IIdentityUserRepository identityUserRepository,
IRepository<Department, Guid> departmentRepository,
IRepository<JobPosition, Guid> jobPositionRepository)
IIdentityUserRepository identityUserRepository)
{
_categoryRepository = categoryRepository;
_topicRepository = topicRepository;
_postRepository = postRepository;
_identityUserRepository = identityUserRepository;
_departmentRepository = departmentRepository;
_jobPositionRepository = jobPositionRepository;
}
// Search functionality
@ -56,7 +48,7 @@ public class ForumAppService : PlatformAppService, IForumAppService
if (string.IsNullOrWhiteSpace(input.Query))
return result;
var query = input.Query.Trim();
var query = input.Query.ToLower();
// Search in categories
if (input.SearchInCategories)
@ -64,8 +56,8 @@ public class ForumAppService : PlatformAppService, IForumAppService
var categoryQuery = await _categoryRepository.GetQueryableAsync();
var categories = await AsyncExecuter.ToListAsync(
categoryQuery.Where(c => c.IsActive &&
(c.Name.Contains(query) ||
c.Description.Contains(query)))
(c.Name.ToLower().Contains(query) ||
c.Description.ToLower().Contains(query)))
.Take(10)
);
@ -78,9 +70,9 @@ public class ForumAppService : PlatformAppService, IForumAppService
var topicQuery = await _topicRepository.GetQueryableAsync();
var topics = await AsyncExecuter.ToListAsync(
topicQuery.Where(t =>
t.Title.Contains(query) ||
t.Content.Contains(query) ||
t.AuthorName.Contains(query))
t.Title.ToLower().Contains(query) ||
t.Content.ToLower().Contains(query) ||
t.AuthorName.ToLower().Contains(query))
.OrderByDescending(t => t.CreationTime)
.Take(20)
);
@ -94,8 +86,8 @@ public class ForumAppService : PlatformAppService, IForumAppService
var postQuery = await _postRepository.GetQueryableAsync();
var posts = await AsyncExecuter.ToListAsync(
postQuery.Where(p =>
p.Content.Contains(query) ||
p.AuthorName.Contains(query))
p.Content.ToLower().Contains(query) ||
p.AuthorName.ToLower().Contains(query))
.OrderByDescending(p => p.CreationTime)
.Take(30)
);
@ -119,10 +111,10 @@ public class ForumAppService : PlatformAppService, IForumAppService
if (!string.IsNullOrWhiteSpace(input.Search))
{
var search = input.Search.Trim();
var search = input.Search.ToLower();
queryable = queryable.Where(c =>
c.Name.Contains(search) ||
c.Description.Contains(search));
c.Name.ToLower().Contains(search) ||
c.Description.ToLower().Contains(search));
}
queryable = queryable.OrderBy(c => c.DisplayOrder);
@ -133,34 +125,13 @@ public class ForumAppService : PlatformAppService, IForumAppService
var maxResultCount = input.MaxResultCount > 0 ? input.MaxResultCount : 10;
var categories = await AsyncExecuter.ToListAsync(
queryable.Skip(skipCount).Take(maxResultCount)
queryable.Skip(input.SkipCount).Take(input.MaxResultCount)
);
var categoryDtos = ObjectMapper.Map<List<ForumCategory>, List<ForumCategoryDto>>(categories);
var categoryIds = categories.Select(category => category.Id).ToList();
if (categoryIds.Count > 0)
{
var topicQuery = await _topicRepository.GetQueryableAsync();
var postQuery = await _postRepository.GetQueryableAsync();
var topicCountItems = await AsyncExecuter.ToListAsync(
topicQuery.Where(topic => categoryIds.Contains(topic.CategoryId))
.GroupBy(topic => topic.CategoryId)
.Select(group => new { CategoryId = group.Key, Count = group.Count() }));
var topicCounts = topicCountItems.ToDictionary(item => item.CategoryId, item => item.Count);
var postCountItems = await AsyncExecuter.ToListAsync(
postQuery.Where(post => categoryIds.Contains(post.Topic.CategoryId))
.GroupBy(post => post.Topic.CategoryId)
.Select(group => new { CategoryId = group.Key, Count = group.Count() }));
var postCounts = postCountItems.ToDictionary(item => item.CategoryId, item => item.Count);
foreach (var category in categoryDtos)
{
category.TopicCount = topicCounts.GetValueOrDefault(category.Id);
category.PostCount = postCounts.GetValueOrDefault(category.Id);
}
}
return new PagedResultDto<ForumCategoryDto>(totalCount, categoryDtos);
return new PagedResultDto<ForumCategoryDto>(
totalCount,
ObjectMapper.Map<List<ForumCategory>, List<ForumCategoryDto>>(categories)
);
}
public async Task<ForumCategoryDto> GetCategoryAsync(Guid id)
@ -279,10 +250,10 @@ public class ForumAppService : PlatformAppService, IForumAppService
if (!string.IsNullOrWhiteSpace(input.Search))
{
var search = input.Search.Trim();
var search = input.Search.ToLower();
queryable = queryable.Where(t =>
t.Title.Contains(search) ||
t.Content.Contains(search));
t.Title.ToLower().Contains(search) ||
t.Content.ToLower().Contains(search));
}
queryable = queryable.OrderByDescending(t => t.IsPinned)
@ -293,50 +264,24 @@ public class ForumAppService : PlatformAppService, IForumAppService
queryable.Skip(input.SkipCount).Take(input.MaxResultCount)
);
var topicDtos = ObjectMapper.Map<List<ForumTopic>, List<ForumTopicDto>>(topics);
var topicIds = topics.Select(topic => topic.Id).ToList();
if (topicIds.Count > 0)
{
var postQuery = await _postRepository.GetQueryableAsync();
var replyCountItems = await AsyncExecuter.ToListAsync(
postQuery.Where(post => topicIds.Contains(post.TopicId))
.GroupBy(post => post.TopicId)
.Select(group => new { TopicId = group.Key, Count = group.Count() }));
var replyCounts = replyCountItems.ToDictionary(item => item.TopicId, item => item.Count);
foreach (var topic in topicDtos)
{
topic.ReplyCount = replyCounts.GetValueOrDefault(topic.Id);
}
}
return new PagedResultDto<ForumTopicDto>(totalCount, topicDtos);
return new PagedResultDto<ForumTopicDto>(
totalCount,
ObjectMapper.Map<List<ForumTopic>, List<ForumTopicDto>>(topics)
);
}
public async Task<ForumTopicDto> GetTopicAsync(Guid id)
{
var queryable = await _topicRepository.GetQueryableAsync();
var affectedRows = await queryable
.Where(t => t.Id == id)
.ExecuteUpdateAsync(setters =>
setters.SetProperty(t => t.ViewCount, t => t.ViewCount + 1)
);
var topic = await _topicRepository.GetAsync(id);
if (affectedRows == 0)
// View count artırma işlemi arka planda yapılmalı (performans için)
// Her okumada update yapmak performans sorununa neden olur
_ = Task.Run(async () =>
{
throw new EntityNotFoundException(typeof(ForumTopic), id);
}
var topic = await AsyncExecuter.FirstOrDefaultAsync(
queryable
.AsNoTracking()
.Where(t => t.Id == id)
);
if (topic == null)
{
throw new EntityNotFoundException(typeof(ForumTopic), id);
}
var t = await _topicRepository.GetAsync(id);
t.ViewCount++;
await _topicRepository.UpdateAsync(t);
});
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
}
@ -344,32 +289,13 @@ public class ForumAppService : PlatformAppService, IForumAppService
[UnitOfWork]
public async Task<ForumTopicDto> CreateTopicAsync(CreateForumTopicDto input)
{
var author = await _identityUserRepository.FindAsync(CurrentUser.Id.Value)
?? throw new EntityNotFoundException(typeof(IdentityUser), CurrentUser.Id.Value);
var jobPositionId = author.GetJobPositionId();
var jobPosition = jobPositionId == Guid.Empty
? null
: await _jobPositionRepository.FindAsync(jobPositionId);
var departmentId = author.GetDepartmentId();
if (departmentId == Guid.Empty && jobPosition != null)
{
departmentId = jobPosition.DepartmentId;
}
var department = departmentId == Guid.Empty
? null
: await _departmentRepository.FindAsync(departmentId);
var topic = new ForumTopic(
GuidGenerator.Create(),
input.Title,
input.Content,
input.CategoryId,
CurrentUser.Id.Value,
author.GetFullName(),
jobPosition?.Name ?? string.Empty,
author.Email ?? string.Empty,
author.PhoneNumber ?? string.Empty,
department?.Name ?? string.Empty,
CurrentUser.Name,
input.TenantId
)
{
@ -429,6 +355,9 @@ public class ForumAppService : PlatformAppService, IForumAppService
if (input.TopicId.HasValue)
{
queryable = queryable.Where(p => p.TopicId == input.TopicId.Value);
// Increment view count
var topic = await _topicRepository.GetAsync(input.TopicId.Value);
}
if (input.IsAcceptedAnswer.HasValue)
@ -438,8 +367,8 @@ public class ForumAppService : PlatformAppService, IForumAppService
if (!string.IsNullOrWhiteSpace(input.Search))
{
var search = input.Search.Trim();
queryable = queryable.Where(p => p.Content.Contains(search));
var search = input.Search.ToLower();
queryable = queryable.Where(p => p.Content.ToLower().Contains(search));
}
queryable = queryable.OrderBy(p => p.CreationTime);
@ -464,31 +393,12 @@ public class ForumAppService : PlatformAppService, IForumAppService
[UnitOfWork]
public async Task<ForumPostDto> CreatePostAsync(CreateForumPostDto input)
{
var author = await _identityUserRepository.FindAsync(CurrentUser.Id.Value)
?? throw new EntityNotFoundException(typeof(IdentityUser), CurrentUser.Id.Value);
var jobPositionId = author.GetJobPositionId();
var jobPosition = jobPositionId == Guid.Empty
? null
: await _jobPositionRepository.FindAsync(jobPositionId);
var departmentId = author.GetDepartmentId();
if (departmentId == Guid.Empty && jobPosition != null)
{
departmentId = jobPosition.DepartmentId;
}
var department = departmentId == Guid.Empty
? null
: await _departmentRepository.FindAsync(departmentId);
var post = new ForumPost(
GuidGenerator.Create(),
input.TopicId,
input.Content,
CurrentUser.Id.Value,
author.GetFullName(),
jobPosition?.Name ?? string.Empty,
author.Email ?? string.Empty,
author.PhoneNumber ?? string.Empty,
department?.Name ?? string.Empty,
CurrentUser.Name,
input.ParentPostId,
input.TenantId
);
@ -542,15 +452,16 @@ public class ForumAppService : PlatformAppService, IForumAppService
await _postRepository.DeleteAsync(id);
topic.ReplyCount = Math.Max(0, topic.ReplyCount - 1);
category.PostCount = Math.Max(0, (category.PostCount ?? 0) - 1);
category.PostCount = Math.Max(0, category.PostCount ?? 0 - 1);
// Last post değişti mi kontrol et
var postsQueryable = await _postRepository.GetQueryableAsync();
var latestPost = await AsyncExecuter.FirstOrDefaultAsync(
postsQueryable
// 🔁 Last post değişti mi kontrol et
var latestPost = await _postRepository
.GetQueryableAsync()
.ContinueWith(q => q.Result
.Where(p => p.TopicId == topic.Id)
.OrderByDescending(p => p.CreationTime)
);
.FirstOrDefault()
);
if (latestPost != null)
{

View file

@ -1,5 +1,4 @@
using Sozsoft.Platform.Identity.Dto;
using Sozsoft.Platform.Extensions;
using Sozsoft.Platform.OrganizationUnits;
using Sozsoft.Platform.Tenants;
using Volo.Abp.Identity;
@ -77,44 +76,8 @@ public partial class CreateUpdateOrganizationUnitDtoToOrganizationUnitMapper : M
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class TenantToCustomTenantDtoMapper : MapperBase<Tenant, CustomTenantDto>
{
[MapperIgnoreTarget(nameof(CustomTenantDto.OrganizationName))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Founder))]
[MapperIgnoreTarget(nameof(CustomTenantDto.VknTckn))]
[MapperIgnoreTarget(nameof(CustomTenantDto.TaxOffice))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Country))]
[MapperIgnoreTarget(nameof(CustomTenantDto.City))]
[MapperIgnoreTarget(nameof(CustomTenantDto.District))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Township))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Address1))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Address2))]
[MapperIgnoreTarget(nameof(CustomTenantDto.PostalCode))]
[MapperIgnoreTarget(nameof(CustomTenantDto.MobileNumber))]
[MapperIgnoreTarget(nameof(CustomTenantDto.PhoneNumber))]
[MapperIgnoreTarget(nameof(CustomTenantDto.FaxNumber))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Email))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Website))]
[MapperIgnoreTarget(nameof(CustomTenantDto.MenuGroup))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Reference))]
public override partial CustomTenantDto Map(Tenant source);
[MapperIgnoreTarget(nameof(CustomTenantDto.OrganizationName))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Founder))]
[MapperIgnoreTarget(nameof(CustomTenantDto.VknTckn))]
[MapperIgnoreTarget(nameof(CustomTenantDto.TaxOffice))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Country))]
[MapperIgnoreTarget(nameof(CustomTenantDto.City))]
[MapperIgnoreTarget(nameof(CustomTenantDto.District))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Township))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Address1))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Address2))]
[MapperIgnoreTarget(nameof(CustomTenantDto.PostalCode))]
[MapperIgnoreTarget(nameof(CustomTenantDto.MobileNumber))]
[MapperIgnoreTarget(nameof(CustomTenantDto.PhoneNumber))]
[MapperIgnoreTarget(nameof(CustomTenantDto.FaxNumber))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Email))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Website))]
[MapperIgnoreTarget(nameof(CustomTenantDto.MenuGroup))]
[MapperIgnoreTarget(nameof(CustomTenantDto.Reference))]
public override partial void Map(Tenant source, CustomTenantDto destination);
public override void BeforeMap(Tenant source)
@ -123,23 +86,6 @@ public partial class TenantToCustomTenantDtoMapper : MapperBase<Tenant, CustomTe
public override void AfterMap(Tenant source, CustomTenantDto destination)
{
destination.OrganizationName = source.GetOrganizationName();
destination.Founder = source.GetFounder();
destination.VknTckn = source.GetVknTckn();
destination.TaxOffice = source.GetTaxOffice();
destination.Country = source.GetCountry();
destination.City = source.GetCity();
destination.District = source.GetDistrict();
destination.Township = source.GetTownship();
destination.Address1 = source.GetAddress1();
destination.Address2 = source.GetAddress2();
destination.PostalCode = source.GetPostalCode();
destination.MobileNumber = source.GetMobileNumber();
destination.PhoneNumber = source.GetPhoneNumber();
destination.FaxNumber = source.GetFaxNumber();
destination.Email = source.GetEmail();
destination.Website = source.GetWebsite();
destination.MenuGroup = source.GetMenuGroup();
}
}

View file

@ -95,8 +95,7 @@ public class PlatformIdentityAppService : ApplicationService
//Branch
var queryBranch = await branchUsersRepository.GetQueryableAsync();
var branchUsers = await AsyncExecuter.ToListAsync(
queryBranch.Where(a => a.UserId == UserId).Select(r => r.BranchId));
var branchUsers = queryBranch.Where(a => a.UserId == UserId).Select(r => r.BranchId).ToList();
var branchList = await branchRepository.GetListAsync(a => a.TenantId == currentTenantId);
var branches = branchList.Select(branch => new AssignedBranchViewModel
{
@ -130,7 +129,7 @@ public class PlatformIdentityAppService : ApplicationService
}).ToArray();
var departmentList = await departmentRepository.GetListAsync();
var departments = departmentList.Select(department => new AssignedDepartmentViewModel
var departments = (await departmentRepository.GetListAsync()).Select(department => new AssignedDepartmentViewModel
{
Id = department.Id,
Name = department.Name,
@ -138,7 +137,7 @@ public class PlatformIdentityAppService : ApplicationService
}).ToArray();
var jobPositionList = await jobPositionRepository.GetListAsync();
var jobPositions = jobPositionList.Select(jobPosition => new AssignedJobPoisitionViewModel
var jobPositions = (await jobPositionRepository.GetListAsync()).Select(jobPosition => new AssignedJobPoisitionViewModel
{
Id = jobPosition.Id,
Name = jobPosition.Name,

View file

@ -58,10 +58,6 @@ public static class PlatformSignInResultExtensions
{
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_WorkHour;
}
if (resultP.IsNotAllowed_BranchLimit)
{
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_BranchLimit;
}
if (resultP.IsNotAllowed_ConcurrentUserLimit)
{
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_ConcurrentUserLimit;

View file

@ -25,8 +25,6 @@ namespace Sozsoft.Platform.Intranet;
[Authorize]
public class IntranetAppService : PlatformAppService, IIntranetAppService
{
private const int DashboardItemLimit = 50;
private Task<(Dictionary<Guid, string> DepartmentDict, Dictionary<Guid, JobPosition> JobPositionDict)>? _userLookupDictionariesTask;
private readonly ICurrentTenant _currentTenant;
private readonly BlobManager _blobContainer;
private readonly IConfiguration _configuration;
@ -34,7 +32,6 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
private readonly IRepository<Event, Guid> _eventRepository;
private readonly IIdentityUserAppService _identityUserAppService;
private readonly IIdentityUserRepository _identityUserRepository;
private readonly IRepository<Volo.Abp.Identity.IdentityUser, Guid> _identityUserEntityRepository;
private readonly IRepository<Department, Guid> _departmentRepository;
private readonly IRepository<JobPosition, Guid> _jobPositionRepository;
private readonly IRepository<Announcement, Guid> _announcementRepository;
@ -60,7 +57,6 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
IRepository<Event, Guid> eventRepository,
IIdentityUserAppService identityUserAppService,
IIdentityUserRepository identityUserRepository,
IRepository<Volo.Abp.Identity.IdentityUser, Guid> identityUserEntityRepository,
IRepository<Department, Guid> departmentRepository,
IRepository<JobPosition, Guid> jobPositionRepository,
IRepository<Announcement, Guid> announcementRepository,
@ -85,7 +81,6 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
_eventRepository = eventRepository;
_identityUserAppService = identityUserAppService;
_identityUserRepository = identityUserRepository;
_identityUserEntityRepository = identityUserEntityRepository;
_departmentRepository = departmentRepository;
_jobPositionRepository = jobPositionRepository;
_announcementRepository = announcementRepository;
@ -116,12 +111,7 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
};
}
private Task<(Dictionary<Guid, string> DepartmentDict, Dictionary<Guid, JobPosition> JobPositionDict)> GetUserLookupDictionariesAsync()
{
return _userLookupDictionariesTask ??= LoadUserLookupDictionariesAsync();
}
private async Task<(Dictionary<Guid, string> DepartmentDict, Dictionary<Guid, JobPosition> JobPositionDict)> LoadUserLookupDictionariesAsync()
private async Task<(Dictionary<Guid, string> DepartmentDict, Dictionary<Guid, JobPosition> JobPositionDict)> GetUserLookupDictionariesAsync()
{
var departments = await _departmentRepository.GetListAsync();
var jobPositions = await _jobPositionRepository.GetListAsync();
@ -132,17 +122,6 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
);
}
private async Task<List<Volo.Abp.Identity.IdentityUser>> GetUsersByIdsAsync(IEnumerable<Guid> userIds)
{
var ids = userIds.Where(id => id != Guid.Empty).Distinct().ToList();
if (ids.Count == 0)
{
return [];
}
return await _identityUserEntityRepository.GetListAsync(user => ids.Contains(user.Id));
}
private UserInfoViewModel MapUserInfoViewModel(
Volo.Abp.Identity.IdentityUser user,
IReadOnlyDictionary<Guid, string> departmentDict,
@ -174,10 +153,7 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
.WithDetailsAsync(e => e.Category, e => e.Type);
var events = await AsyncExecuter.ToListAsync(
queryable
.Where(e => e.isPublished)
.OrderByDescending(e => e.CreationTime)
.Take(DashboardItemLimit)
queryable.Where(e => e.isPublished).OrderByDescending(e => e.CreationTime)
);
if (events.Count == 0)
@ -194,8 +170,7 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
// Load all likes for these events
var likesQueryable = await _eventLikeRepository.GetQueryableAsync();
var allLikes = await AsyncExecuter.ToListAsync(
likesQueryable.Where(l =>
eventIds.Contains(l.EventId) && l.UserId == CurrentUser.Id)
likesQueryable.Where(l => eventIds.Contains(l.EventId))
);
var likedEventIds = allLikes
.Where(l => l.UserId == CurrentUser.Id)
@ -217,8 +192,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
var (departmentDict, jobPositionDict) = await GetUserLookupDictionariesAsync();
var fallbackUser = await GetDashboardFallbackUserAsync(departmentDict, jobPositionDict);
var users = await GetUsersByIdsAsync(userIds);
var users = await _identityUserRepository.GetListAsync();
var userDict = users
.Where(u => userIds.Contains(u.Id))
.ToDictionary(u => u.Id, u => MapUserInfoViewModel(u, departmentDict, jobPositionDict));
var commentsByEvent = allComments.GroupBy(c => c.EventId)
@ -288,8 +264,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
var userIds = comments.Select(c => c.UserId).Distinct().ToList();
var (departmentDict, jobPositionDict) = await GetUserLookupDictionariesAsync();
var users = await GetUsersByIdsAsync(userIds);
var users = await _identityUserRepository.GetListAsync();
var userDict = users
.Where(u => userIds.Contains(u.Id))
.ToDictionary(u => u.Id, u => MapUserInfoViewModel(u, departmentDict, jobPositionDict));
return comments.Select(c => new EventCommentDto
@ -394,11 +371,7 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
private async Task<List<AnnouncementDto>> GetAnnouncementsAsync()
{
var announcementQueryable = await _announcementRepository.GetQueryableAsync();
var announcements = await AsyncExecuter.ToListAsync(
announcementQueryable
.OrderByDescending(announcement => announcement.CreationTime)
.Take(DashboardItemLimit));
var announcements = await _announcementRepository.GetListAsync();
var announcementDtos = new List<AnnouncementDto>();
if (announcements.Count == 0)
@ -413,8 +386,7 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
var likesQueryable = await _announcementLikeRepository.GetQueryableAsync();
var allLikes = await AsyncExecuter.ToListAsync(
likesQueryable.Where(l =>
announcementIds.Contains(l.AnnouncementId) && l.UserId == CurrentUser.Id)
likesQueryable.Where(l => announcementIds.Contains(l.AnnouncementId))
);
var likedAnnouncementIds = allLikes
@ -431,8 +403,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
var (departmentDict, jobPositionDict) = await GetUserLookupDictionariesAsync();
var fallbackUser = await GetDashboardFallbackUserAsync(departmentDict, jobPositionDict);
var users = await GetUsersByIdsAsync(userIds);
var users = await _identityUserRepository.GetListAsync();
var userDict = users
.Where(u => userIds.Contains(u.Id))
.ToDictionary(u => u.Id, u => MapUserInfoViewModel(u, departmentDict, jobPositionDict));
var commentsByAnnouncement = allComments
@ -481,8 +454,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
var userIds = comments.Select(c => c.UserId).Distinct().ToList();
var (departmentDict, jobPositionDict) = await GetUserLookupDictionariesAsync();
var users = await GetUsersByIdsAsync(userIds);
var users = await _identityUserRepository.GetListAsync();
var userDict = users
.Where(u => userIds.Contains(u.Id))
.ToDictionary(u => u.Id, u => MapUserInfoViewModel(u, departmentDict, jobPositionDict));
return comments.Select(c => new AnnouncementCommentDto
@ -643,8 +617,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
{
var (departmentDict, jobPositionDict) = await GetUserLookupDictionariesAsync();
var users = await GetUsersByIdsAsync(userIds);
var users = await _identityUserRepository.GetListAsync();
var userMap = users
.Where(u => userIds.Contains(u.Id))
.ToDictionary(u => u.Id, u => MapUserInfoViewModel(u, departmentDict, jobPositionDict));
foreach (var dto in dtos)
@ -972,8 +947,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
if (userIds.Count > 0)
{
var (departmentDict, jobPositionDict) = await GetUserLookupDictionariesAsync();
var users = await GetUsersByIdsAsync(userIds);
var users = await _identityUserRepository.GetListAsync();
var userMap = users
.Where(u => userIds.Contains(u.Id))
.ToDictionary(u => u.Id, u => MapUserInfoViewModel(u, departmentDict, jobPositionDict));
if (dto.UserId.HasValue && userMap.TryGetValue(dto.UserId.Value, out var postUser))

View file

@ -47,33 +47,26 @@ public class ListFormFieldsAppService : CrudAppService<
protected override void MapToEntity(ColumnFormatEditDto updateInput, ListFormField entity)
{
entity.CultureName = updateInput.CultureName;
entity.RoleId = updateInput.RoleId;
entity.ListFormCode = updateInput.ListFormCode;
entity.FieldName = updateInput.FieldName;
entity.CultureName = updateInput.CultureName;
entity.CaptionName = updateInput.CaptionName;
entity.PlaceHolder = updateInput.PlaceHolder;
entity.BandName = updateInput.BandName;
entity.IsActive = updateInput.IsActive;
entity.Visible = updateInput.Visible;
entity.AllowSearch = updateInput.AllowSearch;
entity.SourceDbType = updateInput.SourceDbType;
entity.Alignment = updateInput.Alignment;
entity.Format = updateInput.Format;
entity.EditorOptions = updateInput.EditorOptions;
entity.EditorScript = updateInput.EditorScript;
entity.AllowEditing = updateInput.AllowEditing;
entity.AllowAdding = updateInput.AllowAdding;
entity.ListOrderNo = updateInput.ListOrderNo;
entity.SourceDbType = updateInput.SourceDbType;
entity.Width = updateInput.Width;
entity.SortDirection = updateInput.SortDirection;
entity.SortIndex = updateInput.SortIndex;
entity.EditOrderNo = updateInput.EditOrderNo;
entity.EditGroupOrderNo = updateInput.EditGroupOrderNo;
entity.ColSpan = updateInput.ColSpan;
entity.EditorType2 = updateInput.EditorType2;
entity.AllowEditing = updateInput.AllowEditing;
entity.AllowAdding = updateInput.AllowAdding;
entity.PermissionJson = JsonSerializer.Serialize(updateInput.PermissionDto);
entity.LookupJson = JsonSerializer.Serialize(updateInput.LookupDto);
entity.Format = updateInput.Format;
entity.Alignment = updateInput.Alignment;
entity.EditorOptions = updateInput.EditorOptions;
entity.ColumnCustomizationJson = JsonSerializer.Serialize(updateInput.ColumnCustomizationDto);
entity.ColumnFilterJson = JsonSerializer.Serialize(updateInput.ColumnFilterDto);
entity.ColumnHeaderJson = JsonSerializer.Serialize(updateInput.ColumnHeaderDto);
@ -81,10 +74,12 @@ public class ListFormFieldsAppService : CrudAppService<
entity.GroupSummaryJson = updateInput.ColumnGroupSummaryDto.SummaryType.IsNullOrEmpty() ? "" : JsonSerializer.Serialize(updateInput.ColumnGroupSummaryDto);
entity.TotalSummaryJson = updateInput.ColumnTotalSummaryDto.SummaryType.IsNullOrEmpty() ? "" : JsonSerializer.Serialize(updateInput.ColumnTotalSummaryDto);
entity.JoinTableJson = JsonSerializer.Serialize(updateInput.ColumnJoinTableDto);
entity.LookupJson = JsonSerializer.Serialize(updateInput.LookupDto);
entity.ColumnCssClass = updateInput.ColumnCssClass;
entity.ColumnCssValue = updateInput.ColumnCssValue;
entity.ValidationRuleJson = JsonSerializer.Serialize(updateInput.ValidationRuleDto);
entity.ColumnStylingJson = JsonSerializer.Serialize(updateInput.ColumnStylingDto);
entity.PermissionJson = JsonSerializer.Serialize(updateInput.PermissionDto);
entity.PivotSettingsJson = JsonSerializer.Serialize(updateInput.PivotSettingsDto);
}
@ -141,9 +136,6 @@ public class ListFormFieldsAppService : CrudAppService<
item.Alignment = input.Alignment;
item.Format = input.Format;
item.EditorOptions = input.EditorOptions;
item.IsActive = input.IsActive;
item.Visible = input.Visible;
item.AllowSearch = input.AllowSearch;
}
else if (input.EditType == ListFormFieldEditTabs.PermissionsForm)
{
@ -160,11 +152,6 @@ public class ListFormFieldsAppService : CrudAppService<
item.AllowSearch = input.AllowSearch;
item.AllowEditing = input.AllowEditing;
item.AllowAdding = input.AllowAdding;
item.EditGroupOrderNo = input.EditGroupOrderNo;
item.EditOrderNo = input.EditOrderNo;
item.ColSpan = input.ColSpan;
item.EditorType2 = input.EditorType2;
item.EditorScript = input.EditorScript;
}
else if (input.EditType == ListFormFieldEditTabs.CustomizationForm)
{
@ -270,9 +257,6 @@ public class ListFormFieldsAppService : CrudAppService<
field.CaptionName = sourceField.CaptionName;
field.PlaceHolder = sourceField.PlaceHolder;
field.SourceDbType = sourceField.SourceDbType;
field.Alignment = sourceField.Alignment;
field.Format = sourceField.Format;
field.EditorOptions = sourceField.EditorOptions;
}
if (input.CopiedFields.All || input.CopiedFields.Options)
{
@ -285,40 +269,35 @@ public class ListFormFieldsAppService : CrudAppService<
field.AllowSearch = sourceField.AllowSearch;
field.AllowEditing = sourceField.AllowEditing;
field.AllowAdding = sourceField.AllowAdding;
field.EditGroupOrderNo = sourceField.EditGroupOrderNo;
field.EditOrderNo = sourceField.EditOrderNo;
field.ColSpan = sourceField.ColSpan;
field.EditorType2 = sourceField.EditorType2;
field.EditorScript = sourceField.EditorScript;
}
if (input.CopiedFields.All || input.CopiedFields.Permission)
else if (input.CopiedFields.All || input.CopiedFields.Permission)
{
field.PermissionJson = sourceField.PermissionJson;
}
if (input.CopiedFields.All || input.CopiedFields.Customization)
else if (input.CopiedFields.All || input.CopiedFields.Customization)
field.ColumnCustomizationJson = sourceField.ColumnCustomizationJson;
if (input.CopiedFields.All || input.CopiedFields.Filtering)
else if (input.CopiedFields.All || input.CopiedFields.Filtering)
field.ColumnFilterJson = sourceField.ColumnFilterJson;
if (input.CopiedFields.All || input.CopiedFields.Headering)
else if (input.CopiedFields.All || input.CopiedFields.Headering)
field.ColumnHeaderJson = sourceField.ColumnHeaderJson;
if (input.CopiedFields.All || input.CopiedFields.Grouping)
else if (input.CopiedFields.All || input.CopiedFields.Grouping)
field.GroupingJson = sourceField.GroupingJson;
if (input.CopiedFields.All || input.CopiedFields.GroupSummary)
else if (input.CopiedFields.All || input.CopiedFields.GroupSummary)
field.GroupSummaryJson = sourceField.GroupSummaryJson;
if (input.CopiedFields.All || input.CopiedFields.TotalSummary)
else if (input.CopiedFields.All || input.CopiedFields.TotalSummary)
field.TotalSummaryJson = sourceField.TotalSummaryJson;
if (input.CopiedFields.All || input.CopiedFields.JoinOptions)
else if (input.CopiedFields.All || input.CopiedFields.JoinOptions)
field.JoinTableJson = sourceField.JoinTableJson;
if (input.CopiedFields.All || input.CopiedFields.CssOptions)
else if (input.CopiedFields.All || input.CopiedFields.CssOptions)
{
field.ColumnCssClass = sourceField.ColumnCssClass;
field.ColumnCssValue = sourceField.ColumnCssValue;
}
if (input.CopiedFields.All || input.CopiedFields.ValidationRules)
else if (input.CopiedFields.All || input.CopiedFields.ValidationRules)
field.ValidationRuleJson = sourceField.ValidationRuleJson;
if (input.CopiedFields.All || input.CopiedFields.Formatting)
else if (input.CopiedFields.All || input.CopiedFields.Formatting)
field.ColumnStylingJson = sourceField.ColumnStylingJson;
if (input.CopiedFields.All || input.CopiedFields.PivotSetting)
else if (input.CopiedFields.All || input.CopiedFields.PivotSetting)
field.PivotSettingsJson = sourceField.PivotSettingsJson;
await Repository.InsertAsync(field);

View file

@ -73,7 +73,7 @@ public class ListFormQueryPreviewAppService : PlatformAppService
var (_, _, dataSourceType) = await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode);
await selectQueryManager.PrepareQueriesAsync(listForm, readableFields, dataSourceType, customizations);
selectQueryManager.PrepareQueries(listForm, readableFields, dataSourceType, customizations);
return selectQueryManager.SelectQuery;
}

View file

@ -166,10 +166,6 @@ public class ListFormsAppService : CrudAppService<
{
item.SchedulerOptionJson = JsonSerializer.Serialize(input.SchedulerOptionDto);
}
else if (input.EditType == ListFormEditTabs.TodoForm)
{
item.TodoOptionJson = JsonSerializer.Serialize(input.TodoOptionDto);
}
else if (input.EditType == ListFormEditTabs.PagerForm)
{
item.PageSize = input.PageSize;

View file

@ -55,12 +55,12 @@ public class ListFormDataAppService : PlatformAppService
var queryParameters = httpContext.Request.Query.ToDictionary(x => x.Key, x => x.Value);
object[] filter = [input.Data[0], "=", input.Keys[0]];
object filter = new object[] { input.Data[0], "=", input.Keys[0] };
var selectRequest = new SelectRequestDto
{
ListFormCode = input.ListFormCode,
Filter = JsonSerializer.Serialize(filter),
Filter = filter.ToString(),
Skip = 0,
Take = 1,
RequireTotalCount = false,

View file

@ -16,8 +16,6 @@ using Sozsoft.Platform.BlobStoring;
using Sozsoft.Platform.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Sozsoft.Platform.Entities;
using Volo.Abp.Domain.Repositories;
namespace Sozsoft.Platform.ListForms.DynamicApi;
@ -37,7 +35,6 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
private readonly IConfiguration configuration;
private readonly IHostEnvironment hostEnvironment;
private readonly IOptions<IdentityOptions> identityOptions;
private readonly IRepository<Order, Guid> orderRepository;
public ListFormDynamicApiAppService(
ITenantRepository tenantRepository,
@ -48,8 +45,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
BlobManager blobCdnManager,
IConfiguration configuration,
IHostEnvironment hostEnvironment,
IOptions<IdentityOptions> identityOptions,
IRepository<Order, Guid> orderRepository)
IOptions<IdentityOptions> identityOptions)
{
this.tenantRepository = tenantRepository;
this.tenantManager = tenantManager;
@ -60,7 +56,6 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
this.configuration = configuration;
this.hostEnvironment = hostEnvironment;
this.identityOptions = identityOptions;
this.orderRepository = orderRepository;
}
private static Guid ParseGuid(string value)
@ -238,90 +233,30 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
[Authorize(TenantManagementPermissions.Tenants.Create)]
public async Task PostTenantInsertAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input)
{
await CreateTenantAsync(input.Data);
}
[Authorize(TenantManagementPermissions.Tenants.Create)]
public async Task<Guid> PostCreateTenantFromOrderAsync(DynamicApiBaseInput<CreateTenantFromOrderInput> input)
{
if (input.Data == null || input.Data.OrderId == Guid.Empty)
{
throw new UserFriendlyException(L["RecordNotFound"]);
}
if (input.Data.Name.IsNullOrWhiteSpace())
{
throw new UserFriendlyException("Tenant name is required.");
}
if (input.Data.MenuGroup.IsNullOrWhiteSpace())
{
throw new UserFriendlyException("Menu group is required.");
}
var order = await orderRepository.GetAsync(input.Data.OrderId)
?? throw new EntityNotFoundException(L["RecordNotFound"]);
if (order.TenantId.HasValue)
{
throw new UserFriendlyException("This order already has a tenant.");
}
var tenant = await CreateTenantAsync(new CreateUpdateTenantInput
{
Name = input.Data.Name,
IsActive = order.IsActive,
OrganizationName = order.OrganizationName,
Founder = order.Founder,
VknTckn = order.VknTckn ?? 0,
TaxOffice = order.TaxOffice,
Country = order.Country,
City = order.City,
District = order.District,
Township = order.Township,
Address1 = order.Address1,
Address2 = order.Address2,
PostalCode = order.PostalCode,
PhoneNumber = order.PhoneNumber,
MobileNumber = order.MobileNumber,
FaxNumber = order.FaxNumber,
Email = order.Email,
Website = order.Website,
MenuGroup = input.Data.MenuGroup,
});
order.TenantId = tenant.Id;
order.MenuGroup = input.Data.MenuGroup;
await orderRepository.UpdateAsync(order, autoSave: true);
return tenant.Id;
}
private async Task<Tenant> CreateTenantAsync(CreateUpdateTenantInput input)
{
var tenant = await tenantManager.CreateAsync(input.Name);
var tenant = await tenantManager.CreateAsync(input.Data.Name);
var entity = await tenantRepository.InsertAsync(tenant, autoSave: true);
entity.SetIsActive(input.IsActive);
entity.SetOrganizationName(input.OrganizationName);
entity.SetFounder(input.Founder);
entity.SetVknTckn(input.VknTckn);
entity.SetTaxOffice(input.TaxOffice);
entity.SetCountry(input.Country);
entity.SetCity(input.City);
entity.SetDistrict(input.District);
entity.SetTownship(input.Township);
entity.SetAddress1(input.Address1);
entity.SetAddress2(input.Address2);
entity.SetPostalCode(input.PostalCode);
entity.SetPhoneNumber(input.PhoneNumber);
entity.SetMobileNumber(input.MobileNumber);
entity.SetFaxNumber(input.FaxNumber);
entity.SetEmail(input.Email);
entity.SetWebsite(input.Website);
entity.SetMenuGroup(input.MenuGroup);
entity.SetIsActive(input.Data.IsActive);
entity.SetOrganizationName(input.Data.OrganizationName);
entity.SetFounder(input.Data.Founder);
entity.SetVknTckn(input.Data.VknTckn);
entity.SetTaxOffice(input.Data.TaxOffice);
entity.SetCountry(input.Data.Country);
entity.SetCity(input.Data.City);
entity.SetDistrict(input.Data.District);
entity.SetTownship(input.Data.Township);
entity.SetAddress1(input.Data.Address1);
entity.SetAddress2(input.Data.Address2);
entity.SetPostalCode(input.Data.PostalCode);
entity.SetPhoneNumber(input.Data.PhoneNumber);
entity.SetMobileNumber(input.Data.MobileNumber);
entity.SetFaxNumber(input.Data.FaxNumber);
entity.SetEmail(input.Data.Email);
entity.SetWebsite(input.Data.Website);
entity.SetMenuGroup(input.Data.MenuGroup);
entity.SetMaxConcurrentUsers(input.Data.MaxConcurrentUsers);
return await tenantRepository.UpdateAsync(entity, autoSave: true);
await tenantRepository.UpdateAsync(entity, autoSave: true);
}
[Authorize(TenantManagementPermissions.Tenants.Update)]
@ -355,6 +290,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
entity.SetEmail(input.Data.Email);
entity.SetWebsite(input.Data.Website);
entity.SetMenuGroup(input.Data.MenuGroup);
entity.SetMaxConcurrentUsers(input.Data.MaxConcurrentUsers);
await tenantRepository.UpdateAsync(entity, autoSave: true);
}

View file

@ -160,7 +160,7 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe
var (dynamicDataRepository, connectionString, dataSourceType) = await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode);
await selectQueryManager.PrepareQueriesAsync(listForm, fields, dataSourceType, customizations, queryParams);
selectQueryManager.PrepareQueries(listForm, fields, dataSourceType, customizations, queryParams);
var param = selectQueryManager.SelectQueryParameters;
if (!string.IsNullOrEmpty(queryParams.Group) && !string.IsNullOrEmpty(selectQueryManager.GroupQuery))
@ -293,6 +293,11 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe
//kullaniciya ait ListFormField verilerini al
var fields = await listFormFieldManager.GetUserListFormFields(ListFormCode);
// selectQueryManager.PrepareQueries(listForm, fields);
// fields = fields.Where(c => selectQueryManager.SelectFields.Any(sc => sc.FieldName == c.FieldName))
// .OrderBy(c => c.ListOrderNo)
// .ThenBy(c => c.CaptionName)
// .ToList();
fields = fields.OrderBy(c => c.ListOrderNo)
.ThenBy(c => c.CaptionName)
.ToList();

View file

@ -180,18 +180,11 @@ public class ListFormWizardAppService(
Code = input.MenuParentCode,
DisplayName = input.MenuParentCode,
IsDisabled = false,
ShortName = input.MenuParentShortName?.Trim(),
Icon = menuParentIcon,
Order = maxRootOrder + 1,
}, autoSave: false);
inserted.MenuCodes.Add(input.MenuParentCode);
}
else if (string.IsNullOrWhiteSpace(menuParent.ShortName) &&
!string.IsNullOrWhiteSpace(input.MenuParentShortName))
{
menuParent.ShortName = input.MenuParentShortName.Trim();
await repoMenu.UpdateAsync(menuParent, autoSave: false);
}
//Menu
var maxChildOrder = menuQueryable.Where(a => a.ParentCode == menuParent.Code).Select(a => (int?)a.Order).Max() ?? 0;
@ -237,9 +230,21 @@ public class ListFormWizardAppService(
Caption = g.Caption,
ColCount = g.ColCount,
ColSpan = g.ColCount,
ItemType = "group"
ItemType = "group",
Items = g.Items
.Where(i => i.IncludeInEditingForm && i.DataField != input.KeyFieldName)
.Select((it, ii) => new EditingFormItemDto
{
Order = ii + 1,
DataField = it.DataField,
EditorType2 = it.EditorType,
ColSpan = it.ColSpan,
EditorOptions = string.IsNullOrWhiteSpace(it.EditorOptions) ? null : it.EditorOptions,
EditorScript = string.IsNullOrWhiteSpace(it.EditorScript) ? null : it.EditorScript,
})
.ToArray()
})
.Where((_, index) => input.Groups[index].Items.Any(i => i.IncludeInEditingForm && i.FieldName != input.KeyFieldName))
.Where(g => g.Items.Length > 0)
.ToList();
//ListForm - varsa sil, yeniden ekle
@ -264,18 +269,9 @@ public class ListFormWizardAppService(
var tableColumns = await GetTableColumnNamesAsync(input.DataSourceCode, input.SelectCommandType, input.SelectCommand);
var isDeleted = tableColumns.Contains("IsDeleted");
var isCreated = tableColumns.Contains("CreatorId");
input.Criteria ??= [];
EnsureUniqueWorkflowCriteriaTitles(input.Criteria);
NormalizeWorkflowCriteriaIds(listFormCode, input.Criteria);
var workflow = new WorkflowDto
{
ApprovalUserFieldName = input.ApprovalUserFieldName,
ApprovalIsFilterUserName = input.ApprovalIsFilterUserName,
ApprovalDateFieldName = input.ApprovalDateFieldName,
ApprovalStatusFieldName = input.ApprovalStatusFieldName,
ApprovalDescriptionFieldName = input.ApprovalDescriptionFieldName,
Criteria = input.Criteria,
};
input.Workflow ??= new WorkflowDto();
input.Workflow.Criteria = input.WorkflowCriteria;
EnsureUniqueWorkflowCriteriaTitles(input.WorkflowCriteria);
await repoListForm.InsertAsync(new ListForm
{
@ -283,8 +279,8 @@ public class ListFormWizardAppService(
PageSize = 10,
ExportJson = WizardConsts.DefaultExportJson,
IsSubForm = false,
ShowNote = input.SubForms.Count > 0 || input.Criteria.Count > 0,
LayoutJson = WizardConsts.DefaultLayoutJson(input.DefaultLayout, input.Grid, input.Card, input.Pivot, input.Tree, input.Chart, input.Gantt, input.Scheduler, input.Todo),
ShowNote = input.SubForms.Count > 0 || input.WorkflowCriteria.Count > 0,
LayoutJson = WizardConsts.DefaultLayoutJson(input.DefaultLayout, input.Grid, input.Pivot, input.Tree, input.Chart, input.Gantt, input.Scheduler),
CultureName = LanguageCodes.En,
ListFormCode = input.ListFormCode,
Name = nameLangKey,
@ -304,18 +300,18 @@ public class ListFormWizardAppService(
HeaderFilterJson = WizardConsts.DefaultHeaderFilterJson(),
SearchPanelJson = WizardConsts.DefaultSearchPanelJson(),
GroupPanelJson = WizardConsts.DefaultGroupPanelJson(),
SelectionJson = WizardConsts.DefaultSelectionSingleJson(input.Criteria.Count > 0 ? PlatformConsts.GridOptions.SelectionModeSingle : PlatformConsts.GridOptions.SelectionModeNone),
SelectionJson = WizardConsts.DefaultSelectionSingleJson(input.WorkflowCriteria.Count > 0 ? PlatformConsts.GridOptions.SelectionModeSingle : PlatformConsts.GridOptions.SelectionModeNone),
ColumnOptionJson = WizardConsts.DefaultColumnOptionJson(),
PermissionJson = WizardConsts.DefaultPermissionJson(code),
DeleteCommand = isDeleted ? WizardConsts.DefaultDeleteCommand(input.SelectCommand) : null,
DeleteFieldsDefaultValueJson = isDeleted ? WizardConsts.DefaultDeleteFieldsDefaultValueJson(input.KeyFieldDbSourceType) : WizardConsts.DefaultDeleteFieldsJsonOnlyId(input.KeyFieldDbSourceType),
InsertFieldsDefaultValueJson = isCreated ? WizardConsts.DefaultInsertFieldsDefaultValueJson(input.KeyFieldDbSourceType) : WizardConsts.DefaultInsertFieldsJsonOnlyId(input.KeyFieldDbSourceType),
DeleteFieldsDefaultValueJson = isDeleted ? WizardConsts.DefaultDeleteFieldsDefaultValueJson(input.KeyFieldDbSourceType) : WizardConsts.DefaultFieldsJsonOnlyId(input.KeyFieldDbSourceType),
InsertFieldsDefaultValueJson = isCreated ? WizardConsts.DefaultInsertFieldsDefaultValueJson(input.KeyFieldDbSourceType) : WizardConsts.DefaultFieldsJsonOnlyId(input.KeyFieldDbSourceType),
PagerOptionJson = WizardConsts.DefaultPagerOptionJson,
EditingOptionJson = WizardConsts.DefaultEditingOptionJson(titleLangKey, 600, 500, input.AllowDeleting, input.AllowAdding, input.AllowUpdating, input.ConfirmDelete, false, input.AllowDetail),
EditingFormJson = editingFormDtos.Count > 0 ? JsonSerializer.Serialize(editingFormDtos) : null,
SubFormsJson = input.SubForms.Count > 0 ? JsonSerializer.Serialize(input.SubForms) : null,
WidgetsJson = input.Widgets.Count > 0 ? JsonSerializer.Serialize(input.Widgets) : null,
WorkflowJson = HasWorkflow(workflow, input.Criteria) ? JsonSerializer.Serialize(workflow) : null,
WorkflowJson = HasWorkflow(input.Workflow, input.WorkflowCriteria) ? JsonSerializer.Serialize(input.Workflow) : null,
TreeOptionJson = (input.Tree || input.DefaultLayout == "tree") && !string.IsNullOrEmpty(input.TreeParentIdExpr)
? JsonSerializer.Serialize(new TreeOptionDto
{
@ -344,58 +340,25 @@ public class ListFormWizardAppService(
EndDateExpr = input.SchedulerEndDateExpr,
})
: null,
TodoOptionJson = (input.Todo || input.DefaultLayout == "todo") &&
!string.IsNullOrEmpty(input.TodoTitleExpr) &&
!string.IsNullOrEmpty(input.TodoStatusExpr)
? JsonSerializer.Serialize(new TodoOptionDto
{
TitleExpr = input.TodoTitleExpr,
StatusExpr = input.TodoStatusExpr,
DescriptionExpr = input.TodoDescriptionExpr,
DueDateExpr = input.TodoDueDateExpr,
TagExpr = input.TodoTagExpr,
AssigneeExpr = input.TodoAssigneeExpr,
PriorityExpr = input.TodoPriorityExpr,
CompletedExpr = input.TodoCompletedExpr,
OrderExpr = input.TodoOrderExpr,
StatusOrder = input.TodoStatusOrder,
AllowDragging = input.TodoAllowDragging,
})
: null,
}, autoSave: true);
// ListFormField - each item in each group becomes a visible field record
var fieldOrder = 0;
var editGroupOrder = 0;
foreach (var group in input.Groups)
{
editGroupOrder++;
var editOrder = 0;
foreach (var item in group.Items)
{
fieldOrder++;
if (item.IncludeInEditingForm && item.FieldName != input.KeyFieldName)
{
editOrder++;
}
await repoListFormField.InsertAsync(new ListFormField
{
ListFormCode = input.ListFormCode,
FieldName = item.FieldName,
FieldName = item.DataField,
CaptionName = item.CaptionName,
Visible = item.FieldName != input.KeyFieldName,
Visible = item.DataField != input.KeyFieldName,
IsActive = true,
AllowSearch = true,
Width = 0,
ListOrderNo = fieldOrder,
EditGroupOrderNo = item.IncludeInEditingForm ? editGroupOrder : null,
EditOrderNo = item.IncludeInEditingForm && item.FieldName != input.KeyFieldName
? editOrder
: null,
EditorType2 = item.EditorType,
ColSpan = item.ColSpan,
EditorOptions = string.IsNullOrWhiteSpace(item.EditorOptions) ? null : item.EditorOptions,
EditorScript = string.IsNullOrWhiteSpace(item.EditorScript) ? null : item.EditorScript,
SourceDbType = item.DbSourceType,
CultureName = PlatformConsts.DefaultLanguage,
PermissionJson = WizardConsts.DefaultFieldPermissionJson(code),
@ -409,7 +372,7 @@ public class ListFormWizardAppService(
}
}
foreach (var criteria in input.Criteria)
foreach (var criteria in input.WorkflowCriteria)
{
if (string.IsNullOrWhiteSpace(criteria.Id))
{
@ -506,55 +469,6 @@ public class ListFormWizardAppService(
return string.IsNullOrWhiteSpace(kind) ? "Step" : kind.Trim();
}
private static void NormalizeWorkflowCriteriaIds(string listFormCode, List<ListFormWorkflowCriteriaDto> 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;
}
/// <summary>
/// Wizard konfigürasyonunu JSON dosyası olarak kaydeder.
/// Önce ContentRootPath'ten yukarı çıkarak Sozsoft.Platform.DbMigrator/Seeds/WizardData dizinini arar.

View file

@ -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(code))
? new ListFormWorkflow(await GenerateNextCriteriaIdAsync())
: 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 = 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.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.PositionX = input.PositionX <= 0 ? 32 : input.PositionX;
criteria.PositionY = input.PositionY <= 0 ? 150 : input.PositionY;
var outcomes = NormalizeCompareOutcomeTargets(code, input.CompareOutcomes);
criteria.CompareOutcomesJson = SerializeCompareOutcomes(outcomes);
criteria.CompareOutcomesJson = SerializeCompareOutcomes(input.CompareOutcomes);
var outcomes = input.CompareOutcomes ?? [];
if (criteria.Kind == "Compare" && outcomes.Count > 0)
{
criteria.NextOnTrue = outcomes.ElementAtOrDefault(0)?.TargetId ?? criteria.NextOnTrue;
@ -357,10 +357,6 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
{
throw new UserFriendlyException("Seçili kayıt bu onay adımında beklemiyor.");
}
if (!IsCurrentUserWorkflowApprover(context, current))
{
throw new UserFriendlyException("Bu kayıt için onay yetkiniz yok.");
}
var update = new Dictionary<string, object>();
if (!context.Workflow.ApprovalUserFieldName.IsNullOrWhiteSpace())
@ -552,7 +548,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
private async Task SendInformEmailAsync(WorkflowRunContext context, ListFormWorkflow node)
{
var recipientEmails = await ResolveApproverEmailsAsync(node.Approver);
var recipientEmail = await ResolveApproverEmailAsync(node.Approver);
var senderName = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromDisplayName);
var senderEmail = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromAddress);
KeyValuePair<string, string>? sender = null;
@ -561,42 +557,22 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
sender = new KeyValuePair<string, string>(senderName, senderEmail);
}
var body = BuildInformEmailBody(context, node, await BuildPreviousWorkflowNotesHtmlAsync(context));
foreach (var recipientEmail in recipientEmails)
{
var result = await erpEmailSender.SendEmailAsync(
recipientEmail,
sender,
new { },
body,
$"Workflow Bilgilendirme: {node.Title}",
null,
true);
var result = await erpEmailSender.SendEmailAsync(
recipientEmail,
sender,
new { },
BuildInformEmailBody(context, node, await BuildPreviousWorkflowNotesHtmlAsync(context)),
$"Workflow Bilgilendirme: {node.Title}",
null,
true);
if (!result.Success)
{
throw new UserFriendlyException($"Bilgilendirme maili gonderilemedi: {result.ErrorMessage}");
}
if (!result.Success)
{
throw new UserFriendlyException($"Bilgilendirme maili gonderilemedi: {result.ErrorMessage}");
}
}
private async Task<List<string>> ResolveApproverEmailsAsync(string approver)
{
var emails = new List<string>();
foreach (var item in SplitWorkflowApprovers(approver))
{
emails.Add(await ResolveApproverEmailAsync(item));
}
if (emails.Count == 0)
{
throw new UserFriendlyException("Bilgilendirme dugumu icin approver tanimli degil.");
}
return emails;
}
private async Task<string> ResolveApproverEmailAsync(string approver)
{
if (approver.IsNullOrWhiteSpace())
@ -618,45 +594,6 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
return user.Email;
}
private bool IsCurrentUserWorkflowApprover(WorkflowRunContext context, ListFormWorkflow current)
{
if (context.Workflow.ApprovalUserFieldName.IsNullOrWhiteSpace())
{
return true;
}
var approverValue = GetRowValue(context.Row, context.Workflow.ApprovalUserFieldName)?.ToString();
if (approverValue.IsNullOrWhiteSpace())
{
approverValue = current.Approver;
}
var approvers = SplitWorkflowApprovers(approverValue)
.ToHashSet(StringComparer.OrdinalIgnoreCase);
if (approvers.Count == 0)
{
return true;
}
return GetCurrentUserWorkflowIdentities().Any(approvers.Contains);
}
private IEnumerable<string> GetCurrentUserWorkflowIdentities()
{
return new[] { CurrentUser.UserName, CurrentUser.Email, CurrentUser.Name }
.Where(identity => !identity.IsNullOrWhiteSpace())
.Select(identity => identity.Trim());
}
private static IEnumerable<string> SplitWorkflowApprovers(string value)
{
return (value ?? string.Empty)
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries)
.Select(item => item.Trim())
.Where(item => !item.IsNullOrWhiteSpace());
}
private async Task<string> BuildPreviousWorkflowNotesHtmlAsync(WorkflowRunContext context)
{
var key = context.Keys?.FirstOrDefault()?.ToString();
@ -696,7 +633,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
var keyText = string.Join(", ", context.Keys.Select(key => WebUtility.HtmlEncode(key?.ToString() ?? string.Empty)));
var listFormCode = WebUtility.HtmlEncode(context.ListFormCode ?? string.Empty);
var nodeTitle = WebUtility.HtmlEncode(node.Title ?? string.Empty);
var recipient = WebUtility.HtmlEncode(FormatWorkflowApprovers(node.Approver));
var recipient = WebUtility.HtmlEncode(node.Approver ?? string.Empty);
var processRows = BuildWorkflowNoteContent(context.WorkflowNoteRows);
var previousNotesSection = previousWorkflowNotesHtml.IsNullOrWhiteSpace()
? string.Empty
@ -760,7 +697,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
if (!node.Approver.IsNullOrWhiteSpace())
{
context.WorkflowNoteRows.Add((node.Kind == "Inform" ? "Inform: " : "Approver: ", FormatWorkflowApprovers(node.Approver)));
context.WorkflowNoteRows.Add((node.Kind == "Inform" ? "Inform: " : "Approver: ", node.Approver));
}
}
@ -853,12 +790,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
{
return userName.IsNullOrWhiteSpace()
? localizer["ListForms.ListForm.Workflow.UndefinedUser"].Value
: FormatWorkflowApprovers(userName);
}
private static string FormatWorkflowApprovers(string value)
{
return string.Join(", ", SplitWorkflowApprovers(value));
: userName;
}
private async Task InsertWorkflowNoteAsync(
@ -1107,7 +1039,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
int positionY,
string approver = "")
{
var criteria = new ListFormWorkflow(await GenerateNextCriteriaIdAsync(listFormCode))
var criteria = new ListFormWorkflow(await GenerateNextCriteriaIdAsync())
{
ListFormCode = listFormCode,
Kind = kind,
@ -1130,95 +1062,41 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
return criteria;
}
private async Task<string> GenerateNextCriteriaIdAsync(string listFormCode)
private async Task<string> GenerateNextCriteriaIdAsync()
{
var criteria = await criteriaRepository.GetListAsync(x => x.ListFormCode == listFormCode);
var criteria = await criteriaRepository.GetListAsync();
var maxNumber = criteria
.Select(x => TryParseCriteriaIdNumber(listFormCode, x.Id))
.Select(x => TryParseCriteriaIdNumber(x.Id))
.DefaultIfEmpty(0)
.Max();
var nextNumber = maxNumber + 1;
var nextId = FormatCriteriaId(listFormCode, nextNumber);
var existingIds = criteria.Select(x => x.Id).ToHashSet(StringComparer.OrdinalIgnoreCase);
var nextId = FormatCriteriaId(nextNumber);
var existingIds = criteria.Select(x => x.Id).ToHashSet();
while (existingIds.Contains(nextId))
{
nextNumber++;
nextId = FormatCriteriaId(listFormCode, nextNumber);
nextId = FormatCriteriaId(nextNumber);
}
return nextId;
}
private static int TryParseCriteriaIdNumber(string listFormCode, string id)
private static int TryParseCriteriaIdNumber(string id)
{
var localId = GetLocalCriteriaId(listFormCode, id);
if (localId.IsNullOrWhiteSpace() ||
!localId.StartsWith(CriteriaIdPrefix, StringComparison.OrdinalIgnoreCase))
if (id.IsNullOrWhiteSpace() ||
!id.StartsWith(CriteriaIdPrefix, StringComparison.OrdinalIgnoreCase))
{
return 0;
}
return int.TryParse(localId[CriteriaIdPrefix.Length..], out var number) ? number : 0;
return int.TryParse(id[CriteriaIdPrefix.Length..], out var number) ? number : 0;
}
private static string FormatCriteriaId(string listFormCode, int number)
private static string FormatCriteriaId(int number)
{
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<CompareOutcomeDto> NormalizeCompareOutcomeTargets(
string listFormCode,
List<CompareOutcomeDto> 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;
return $"{CriteriaIdPrefix}{number.ToString().PadLeft(CriteriaIdPadding, '0')}";
}
private static bool ClearDeletedTarget(ListFormWorkflow criteria, string deletedId)

View file

@ -15,8 +15,6 @@ using Volo.Abp.PermissionManagement;
using Volo.Abp.TenantManagement;
using static Sozsoft.Platform.Data.Seeds.SeedConsts;
using Sozsoft.Languages;
using Sozsoft.Languages.Languages;
using Sozsoft.Platform.ListForms;
namespace Sozsoft.Platform.Menus;
@ -33,7 +31,6 @@ public class MenuAppService : CrudAppService<
private readonly ITenantRepository _tenantRepository;
private readonly IPermissionDefinitionRecordRepository _permissionRepository;
private readonly LanguageTextAppService _languageTextAppService;
private readonly IRepository<MenuGroup, string> _menuGroupRepository;
public MenuAppService(
IRepository<Menu, Guid> menuRepository,
@ -41,8 +38,7 @@ public class MenuAppService : CrudAppService<
IRepository<LanguageText, Guid> languageTextRepository,
ITenantRepository tenantRepository,
IPermissionDefinitionRecordRepository permissionRepository,
LanguageTextAppService languageTextAppService,
IRepository<MenuGroup, string> menuGroupRepository
LanguageTextAppService languageTextAppService
) : base(menuRepository)
{
_menuRepository = menuRepository;
@ -51,7 +47,6 @@ public class MenuAppService : CrudAppService<
_tenantRepository = tenantRepository;
_permissionRepository = permissionRepository;
_languageTextAppService = languageTextAppService;
_menuGroupRepository = menuGroupRepository;
CreatePolicyName = $"{AppCodes.Menus.Menu}.Create";
UpdatePolicyName = $"{AppCodes.Menus.Menu}.Update";
@ -132,30 +127,6 @@ public class MenuAppService : CrudAppService<
.ToList();
entityDtos = await base.MapToGetListOutputDtosAsync(entities);
var languageKeys = entityDtos
.Select(item => string.IsNullOrWhiteSpace(item.DisplayName) ? item.Code : item.DisplayName)
.Where(key => !string.IsNullOrWhiteSpace(key))
.Distinct()
.ToList();
var languageTexts = await _repositoryText.GetListAsync(text =>
text.ResourceName == PlatformConsts.AppName &&
languageKeys.Contains(text.Key) &&
(text.CultureName == PlatformConsts.DefaultLanguage ||
text.CultureName == LanguageCodes.Tr));
foreach (var menu in entityDtos)
{
var languageKey = string.IsNullOrWhiteSpace(menu.DisplayName)
? menu.Code
: menu.DisplayName;
menu.MenuTextEn = languageTexts.FirstOrDefault(text =>
text.Key == languageKey &&
text.CultureName == PlatformConsts.DefaultLanguage)?.Value;
menu.MenuTextTr = languageTexts.FirstOrDefault(text =>
text.Key == languageKey &&
text.CultureName == LanguageCodes.Tr)?.Value;
}
}
return new PagedResultDto<MenuDto>(
@ -347,18 +318,4 @@ public class MenuAppService : CrudAppService<
return await base.CreateAsync(input);
}
public async Task<List<LookupDataDto>> GetMenuGroupsAsync()
{
var menuGroups = await _menuGroupRepository.GetListAsync();
return menuGroups
.OrderBy(menuGroup => menuGroup.Name)
.Select(menuGroup => new LookupDataDto
{
Key = menuGroup.Id,
Name = menuGroup.Name
})
.ToList();
}
}

View file

@ -28,7 +28,7 @@ public class MessengerAppService : ApplicationService
private readonly IRepository<IdentityUser, Guid> _userRepository;
private readonly IRepository<MessengerConversation, Guid> _conversationRepository;
private readonly IRepository<MessengerConversationMessage, Guid> _messageRepository;
private readonly IRepository<IdentitySession, Guid> _identitySessionRepository;
private readonly IIdentitySessionRepository _identitySessionRepository;
private readonly BlobManager _blobManager;
private readonly IConfiguration _configuration;
private readonly IHubContext<MessengerHub> _messengerHubContext;
@ -37,7 +37,7 @@ public class MessengerAppService : ApplicationService
IRepository<IdentityUser, Guid> userRepository,
IRepository<MessengerConversation, Guid> conversationRepository,
IRepository<MessengerConversationMessage, Guid> messageRepository,
IRepository<IdentitySession, Guid> identitySessionRepository,
IIdentitySessionRepository identitySessionRepository,
BlobManager blobManager,
IConfiguration configuration,
IHubContext<MessengerHub> messengerHubContext)
@ -450,14 +450,11 @@ public class MessengerAppService : ApplicationService
return new HashSet<Guid>();
}
var sessionsQuery = await _identitySessionRepository.GetQueryableAsync();
var onlineUserIds = await AsyncExecuter.ToListAsync(
sessionsQuery
.Where(session => normalizedUserIds.Contains(session.UserId))
.Select(session => session.UserId)
.Distinct());
return onlineUserIds.ToHashSet();
var sessions = await _identitySessionRepository.GetListAsync();
return sessions
.Where(session => normalizedUserIds.Contains(session.UserId))
.Select(session => session.UserId)
.ToHashSet();
}
private async Task<MessengerConversation?> FindConversationByParticipantKeyAsync(string participantKey)

View file

@ -37,15 +37,15 @@ public class OrgChartAppService : PlatformAppService
var users = await _userRepository.GetListAsync();
var jobById = jobPositions.ToDictionary(x => x.Id);
var positionsByDepartment = jobPositions
.GroupBy(position => position.DepartmentId)
.ToDictionary(group => group.Key, group => group.OrderBy(position => position.Name).ToList());
var usersByJobPosition = GroupUsersByJobPosition(users);
var topPositionByDepartment = new Dictionary<Guid, JobPosition>();
foreach (var department in departments)
{
if (!positionsByDepartment.TryGetValue(department.Id, out var departmentPositions))
var departmentPositions = jobPositions
.Where(x => x.DepartmentId == department.Id)
.ToList();
if (!departmentPositions.Any())
{
continue;
}
@ -77,9 +77,19 @@ public class OrgChartAppService : PlatformAppService
ParentId = d.ParentId,
JobPositionId = topPosition?.Id,
JobPositionName = topPosition?.Name,
Users = topPosition != null && usersByJobPosition.TryGetValue(topPosition.Id, out var positionUsers)
? positionUsers
: [],
Users = users
.Where(u =>
topPosition != null &&
u.GetJobPositionId() == topPosition.Id)
.Select(u => new OrgChartUserDto
{
Id = u.Id,
FullName = u.GetFullName(),
Email = u.Email,
UserName = u.UserName,
PhoneNumber = u.PhoneNumber
})
.ToList(),
};
}).ToList();
@ -94,7 +104,6 @@ public class OrgChartAppService : PlatformAppService
var users = await _userRepository.GetListAsync();
var deptDict = departments.ToDictionary(d => d.Id, d => d.Name);
var usersByJobPosition = GroupUsersByJobPosition(users);
var nodes = jobPositions.Select(jp => new OrgChartNodeDto
{
@ -105,28 +114,19 @@ public class OrgChartAppService : PlatformAppService
DepartmentName = deptDict.TryGetValue(jp.DepartmentId, out var name) ? name : null,
JobPositionId = jp.Id,
JobPositionName = jp.Name,
Users = usersByJobPosition.TryGetValue(jp.Id, out var positionUsers)
? positionUsers
: [],
Users = users
.Where(u => u.GetJobPositionId() == jp.Id)
.Select(u => new OrgChartUserDto
{
Id = u.Id,
FullName = u.GetFullName(),
Email = u.Email,
UserName = u.UserName,
PhoneNumber = u.PhoneNumber
})
.ToList(),
}).ToList();
return nodes;
}
private static Dictionary<Guid, List<OrgChartUserDto>> GroupUsersByJobPosition(
IEnumerable<IdentityUser> users)
{
return users
.GroupBy(user => user.GetJobPositionId())
.ToDictionary(
group => group.Key,
group => group.Select(user => new OrgChartUserDto
{
Id = user.Id,
FullName = user.GetFullName(),
Email = user.Email,
UserName = user.UserName,
PhoneNumber = user.PhoneNumber
}).ToList());
}
}

View file

@ -8,10 +8,8 @@ using Sozsoft.Platform.Data.Seeds;
using Sozsoft.Sender.Mail;
using Volo.Abp.Settings;
using Sozsoft.Platform.Demos;
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Entities;
using System.Linq;
using System.Net;
using Volo.Abp.Application.Dtos;
using System.Text.Json;
using Volo.Abp.Identity;
@ -36,8 +34,6 @@ public class PublicAppService : PlatformAppService
private readonly IRepository<Home, Guid> _homeRepository;
private readonly IRepository<Contact, Guid> _contactRepository;
private readonly IRepository<Country, string> _countryRepository;
private readonly IRepository<City, Guid> _cityRepository;
private readonly IRepository<District, Guid> _districtRepository;
private readonly IIdentityUserRepository _identityUserRepository;
private readonly IRepository<LanguageKey, Guid> _languageKeyRepository;
private readonly IRepository<LanguageText, Guid> _languageTextRepository;
@ -58,8 +54,6 @@ public class PublicAppService : PlatformAppService
IRepository<Home, Guid> homeRepository,
IRepository<Contact, Guid> contactRepository,
IRepository<Country, string> countryRepository,
IRepository<City, Guid> cityRepository,
IRepository<District, Guid> districtRepository,
IIdentityUserRepository identityUserRepository,
IRepository<LanguageKey, Guid> languageKeyRepository,
IRepository<LanguageText, Guid> languageTextRepository,
@ -84,8 +78,6 @@ public class PublicAppService : PlatformAppService
_languageTextRepository = languageTextRepository;
_languageTextAppService = languageTextAppService;
_countryRepository = countryRepository;
_cityRepository = cityRepository;
_districtRepository = districtRepository;
}
public async Task<List<ServiceDto>> GetServicesListAsync()
@ -465,91 +457,51 @@ public class PublicAppService : PlatformAppService
public async Task<OrderDto> CreateOrderAsync(OrderDto input)
{
var entity = new Order(GuidGenerator.Create())
var entity = new Order()
{
TenantId = input.Tenant.Id,
Name = input.Tenant.Name,
IsActive = input.Tenant.IsActive,
OrganizationName = input.Tenant.OrganizationName,
Founder = input.Tenant.Founder,
VknTckn = input.Tenant.VknTckn,
TaxOffice = input.Tenant.TaxOffice,
Address1 = input.Tenant.Address1,
Address2 = input.Tenant.Address2,
District = input.Tenant.District,
Country = input.Tenant.Country,
City = input.Tenant.City,
District = input.Tenant.District,
Township = input.Tenant.Township,
PostalCode = input.Tenant.PostalCode,
MobileNumber = NormalizePhoneNumber(input.Tenant.MobileNumber, input.Tenant.Country),
PhoneNumber = NormalizePhoneNumber(input.Tenant.PhoneNumber, input.Tenant.Country),
FaxNumber = NormalizePhoneNumber(input.Tenant.FaxNumber, input.Tenant.Country),
MobileNumber = input.Tenant.MobileNumber,
PhoneNumber = input.Tenant.PhoneNumber,
FaxNumber = input.Tenant.FaxNumber,
Email = input.Tenant.Email,
Website = input.Tenant.Website,
MenuGroup = input.Tenant.MenuGroup,
BillingCycle = input.BillingCycle,
Period = input.Period,
LicenseStartTime = input.LicenseStartTime,
LicenseEndTime = input.LicenseEndTime,
Subtotal = input.Subtotal,
VatTotal = input.VatTotal,
Commission = input.Commission,
Total = input.Total,
PaymentMethodId = input.PaymentMethodId,
Installment = input.Installment,
PaymentDataJson = JsonSerializer.Serialize(input.PaymentData),
IsExisting = input.IsExisting,
};
decimal subtotal = 0;
decimal vatTotal = 0;
foreach (var item in input.Items)
{
var productId = item.ProductId != Guid.Empty ? item.ProductId : item.Product.Id;
var product = await _productRepository.FindAsync(productId);
if (product == null && !item.Product.Name.IsNullOrWhiteSpace())
{
product = await _productRepository.FirstOrDefaultAsync(x => x.Name == item.Product.Name);
}
if (product == null)
{
throw new EntityNotFoundException(typeof(Product), productId);
}
var vatRate = product.VatRate;
var price = GetOrderItemPrice(product, item.BillingCycle);
var grossTotal = Math.Round(item.TotalPrice, 2, MidpointRounding.AwayFromZero);
var netTotal = vatRate > 0
? Math.Round(grossTotal / (1 + vatRate), 2, MidpointRounding.AwayFromZero)
: grossTotal;
var vatAmount = Math.Round(grossTotal - netTotal, 2, MidpointRounding.AwayFromZero);
subtotal += netTotal;
vatTotal += vatAmount;
entity.Items.Add(new OrderItem
{
OrderId = entity.Id,
Order = entity,
ProductId = product.Id,
ProductName = product.Name,
ProductId = item.Product.Id,
ProductName = item.Product.Name,
BillingCycle = item.BillingCycle,
Period = input.Period,
Quantity = item.Quantity,
Price = price,
VatRate = vatRate,
VatAmount = vatAmount,
TotalPrice = grossTotal
TotalPrice = item.TotalPrice
});
}
entity.Subtotal = Math.Round(subtotal, 2, MidpointRounding.AwayFromZero);
entity.VatTotal = Math.Round(vatTotal, 2, MidpointRounding.AwayFromZero);
entity.Total = Math.Round(entity.Subtotal + entity.VatTotal + entity.Commission, 2, MidpointRounding.AwayFromZero);
await _orderRepository.InsertAsync(entity, autoSave: true);
await SendOrderCreatedEmailsAsync(entity);
return new OrderDto
{
@ -559,318 +511,6 @@ public class PublicAppService : PlatformAppService
};
}
private static decimal GetOrderItemPrice(Product product, string billingCycle)
{
return string.Equals(billingCycle, "monthly", StringComparison.OrdinalIgnoreCase)
? product.MonthlyPrice ?? 0
: product.YearlyPrice ?? 0;
}
private async Task SendOrderCreatedEmailsAsync(Order order)
{
var recipients = new List<string>();
if (!order.Email.IsNullOrWhiteSpace())
{
recipients.Add(order.Email.Trim());
}
var notificationEmails = await _settingProvider.GetOrNullAsync("App.SiteManagement.General.NewTenantNotificationEmails");
if (!notificationEmails.IsNullOrWhiteSpace())
{
recipients.AddRange(notificationEmails
.Split(new[] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)
.Select(email => email.Trim())
.Where(email => !email.IsNullOrWhiteSpace()));
}
recipients = recipients
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (recipients.Count == 0)
{
return;
}
var senderName = await _settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromDisplayName);
var senderEmail = await _settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromAddress);
KeyValuePair<string, string>? sender = null;
if (!senderEmail.IsNullOrWhiteSpace())
{
sender = new KeyValuePair<string, string>(senderName ?? string.Empty, senderEmail);
}
var body = BuildOrderEmailBody(order);
var subject = $"{PlatformConsts.AppName} : Yeni Sipariş #{order.Id}";
foreach (var recipient in recipients)
{
try
{
await _emailSender.SendEmailAsync(
recipient,
sender,
new { },
body,
subject,
null,
true);
}
catch (Exception ex)
{
Logger.LogError(ex, "Order email could not be sent to {Recipient}", recipient);
}
}
}
private string BuildOrderEmailBody(Order order)
{
var itemRows = string.Join(string.Empty, order.Items.Select(item => $@"
<tr>
<td style=""padding:16px 14px;border-bottom:1px solid #e5e7eb;font-weight:700;color:#111827;line-height:20px;"">{Html(Translate(item.ProductName))}</td>
<td align=""right"" style=""padding:16px 14px;border-bottom:1px solid #e5e7eb;text-align:right;color:#374151;white-space:nowrap;line-height:20px;"">{FormatPrice(item.Price)}</td>
<td align=""right"" style=""padding:16px 14px;border-bottom:1px solid #e5e7eb;text-align:right;color:#374151;white-space:nowrap;line-height:20px;"">{item.Period}</td>
<td align=""right"" style=""padding:16px 14px;border-bottom:1px solid #e5e7eb;text-align:right;color:#374151;white-space:nowrap;line-height:20px;"">{item.Quantity}</td>
<td align=""right"" style=""padding:16px 14px;border-bottom:1px solid #e5e7eb;text-align:right;color:#374151;white-space:nowrap;line-height:20px;"">{BillingCycleLabel(item.BillingCycle)}</td>
<td align=""right"" style=""padding:16px 14px;border-bottom:1px solid #e5e7eb;text-align:right;color:#374151;white-space:nowrap;line-height:20px;"">%{item.VatRate * 100:0.##} / {FormatPrice(item.VatAmount)}</td>
<td align=""right"" style=""padding:16px 14px;border-bottom:1px solid #e5e7eb;text-align:right;font-weight:800;color:#111827;white-space:nowrap;line-height:20px;"">{FormatPrice(item.TotalPrice)}</td>
</tr>"));
return $@"
<!doctype html>
<html>
<head>
<meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" />
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"" />
<meta name=""x-apple-disable-message-reformatting"" />
</head>
<body bgcolor=""#f3f4f6"" style=""margin:0;padding:0;background-color:#f3f4f6;font-family:Arial,Helvetica,sans-serif;color:#111827;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;"">
<div style=""display:none;font-size:1px;color:#f3f4f6;line-height:1px;max-height:0;max-width:0;opacity:0;overflow:hidden;"">
{Html(Translate("Public.order.success.title"))} #{order.Id}
</div>
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" bgcolor=""#f3f4f6"" style=""width:100%;background-color:#f3f4f6;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td align=""center"" style=""padding:24px 12px;"">
<table role=""presentation"" width=""980"" cellpadding=""0"" cellspacing=""0"" border=""0"" align=""center"" bgcolor=""#ffffff"" style=""width:100%;max-width:980px;background-color:#ffffff;border:1px solid #e5e7eb;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td bgcolor=""#f9fafb"" style=""padding:24px;background-color:#f9fafb;border-bottom:1px solid #e5e7eb;"">
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td style=""vertical-align:middle;"">
<table role=""presentation"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td style=""width:46px;vertical-align:middle;"">
<table role=""presentation"" width=""40"" height=""40"" cellpadding=""0"" cellspacing=""0"" border=""0"" bgcolor=""#22c55e"" style=""width:40px;height:40px;background-color:#22c55e;border-collapse:collapse;"">
<tr>
<td align=""center"" valign=""middle"" style=""font-size:22px;line-height:40px;font-weight:800;color:#ffffff;"">&#10003;</td>
</tr>
</table>
</td>
<td style=""vertical-align:middle;"">
<table role=""presentation"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""border-collapse:collapse;"">
<tr>
<td style=""font-size:22px;line-height:28px;font-weight:800;color:#111827;"">{Html(Translate("Public.order.success.title"))}</td>
</tr>
<tr>
<td style=""padding-top:6px;color:#4b5563;font-size:14px;line-height:20px;"">{Html(Translate("Public.order.success.number"))} <strong style=""color:#2563eb;"">#{order.Id}</strong></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td align=""right"" style=""text-align:right;vertical-align:middle;color:#4b5563;"">
<table role=""presentation"" cellpadding=""0"" cellspacing=""0"" border=""0"" align=""right"" style=""border-collapse:collapse;"">
<tr>
<td align=""right"" style=""font-size:12px;line-height:16px;text-transform:uppercase;letter-spacing:.08em;color:#6b7280;"">Invoice</td>
</tr>
<tr>
<td align=""right"" style=""padding-top:4px;font-size:14px;line-height:20px;font-weight:700;color:#111827;"">{FormatDate(DateTime.Now)}</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style=""padding:24px;"">
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:separate;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td width=""50%"" style=""vertical-align:top;padding:0 10px 20px 0;"">
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" bgcolor=""#ffffff"" style=""width:100%;background-color:#ffffff;border:1px solid #e5e7eb;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td style=""padding:18px;"">
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:collapse;"">
<tr>
<td style=""font-size:18px;line-height:24px;font-weight:800;color:#111827;padding-bottom:14px;"">Customer Information</td>
</tr>
<tr>
<td style=""line-height:24px;color:#374151;font-size:14px;"">
<strong style=""color:#111827;"">{Html(order.OrganizationName)}</strong><br />
<a href=""mailto:{Html(order.Email)}"" style=""color:#2563eb;text-decoration:none;"">{Html(order.Email)}</a><br />
{Html(FormatPhoneNumber(order.PhoneNumber ?? order.MobileNumber))}<br />
{Html(order.Address1)}<br />
{Html(order.Township)} / {Html(order.District)} / {Html(order.City)} / {Html(order.Country)}
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td width=""50%"" style=""vertical-align:top;padding:0 0 20px 10px;"">
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" bgcolor=""#ffffff"" style=""width:100%;background-color:#ffffff;border:1px solid #e5e7eb;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td style=""padding:18px;"">
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:collapse;"">
<tr>
<td style=""font-size:18px;line-height:24px;font-weight:800;color:#111827;padding-bottom:14px;"">License Information</td>
</tr>
</table>
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:collapse;font-size:14px;color:#374151;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td bgcolor=""#f9fafb"" style=""padding:8px;background-color:#f9fafb;color:#6b7280;line-height:20px;"">License Start Time</td>
<td bgcolor=""#f9fafb"" align=""right"" style=""padding:8px;background-color:#f9fafb;text-align:right;font-weight:700;color:#111827;line-height:20px;"">{FormatDate(order.LicenseStartTime)}</td>
</tr>
<tr>
<td style=""padding:8px;color:#6b7280;line-height:20px;"">License End Time</td>
<td align=""right"" style=""padding:8px;text-align:right;font-weight:700;color:#111827;line-height:20px;"">{FormatDate(order.LicenseEndTime)}</td>
</tr>
<tr>
<td bgcolor=""#f9fafb"" style=""padding:8px;background-color:#f9fafb;color:#6b7280;line-height:20px;"">Billing Cycle</td>
<td bgcolor=""#f9fafb"" align=""right"" style=""padding:8px;background-color:#f9fafb;text-align:right;font-weight:700;color:#111827;line-height:20px;"">{BillingCycleLabel(order.BillingCycle)}</td>
</tr>
<tr>
<td style=""padding:8px;color:#6b7280;line-height:20px;"">Period</td>
<td align=""right"" style=""padding:8px;text-align:right;font-weight:700;color:#111827;line-height:20px;"">{order.Period}</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:collapse;border:1px solid #e5e7eb;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<thead>
<tr style=""background:#f9fafb;color:#6b7280;font-size:12px;text-transform:uppercase;letter-spacing:.06em;"">
<th bgcolor=""#f9fafb"" style=""padding:12px 14px;text-align:left;background-color:#f9fafb;line-height:16px;"">Product</th>
<th bgcolor=""#f9fafb"" align=""right"" style=""padding:12px 14px;text-align:right;background-color:#f9fafb;line-height:16px;"">Price</th>
<th bgcolor=""#f9fafb"" align=""right"" style=""padding:12px 14px;text-align:right;background-color:#f9fafb;line-height:16px;"">Period</th>
<th bgcolor=""#f9fafb"" align=""right"" style=""padding:12px 14px;text-align:right;background-color:#f9fafb;line-height:16px;"">Qty</th>
<th bgcolor=""#f9fafb"" align=""right"" style=""padding:12px 14px;text-align:right;background-color:#f9fafb;line-height:16px;"">Cycle</th>
<th bgcolor=""#f9fafb"" align=""right"" style=""padding:12px 14px;text-align:right;background-color:#f9fafb;line-height:16px;"">VAT</th>
<th bgcolor=""#f9fafb"" align=""right"" style=""padding:12px 14px;text-align:right;background-color:#f9fafb;line-height:16px;"">Amount</th>
</tr>
</thead>
<tbody>{itemRows}</tbody>
</table>
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:collapse;margin-top:20px;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td style=""width:58%;"">&nbsp;</td>
<td style=""width:42%;vertical-align:top;"">
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:100%;border-collapse:collapse;color:#374151;font-size:14px;mso-table-lspace:0pt;mso-table-rspace:0pt;"">
<tr>
<td style=""padding:8px 0;text-align:left;line-height:20px;"">{Html(Translate("Public.payment.summary.subtotal"))}</td>
<td align=""right"" style=""padding:8px 0;text-align:right;font-weight:700;color:#111827;white-space:nowrap;line-height:20px;"">{FormatPrice(order.Subtotal)}</td>
</tr>
<tr>
<td style=""padding:8px 0;text-align:left;line-height:20px;"">{Html(Translate("Public.products.kdv"))}</td>
<td align=""right"" style=""padding:8px 0;text-align:right;font-weight:700;color:#111827;white-space:nowrap;line-height:20px;"">{FormatPrice(order.VatTotal)}</td>
</tr>
<tr>
<td style=""padding:8px 0;text-align:left;line-height:20px;"">{Html(Translate("Public.payment.installments.commission"))}</td>
<td align=""right"" style=""padding:8px 0;text-align:right;font-weight:700;color:#111827;white-space:nowrap;line-height:20px;"">{FormatPrice(order.Commission)}</td>
</tr>
<tr>
<td style=""padding:14px 0 0;border-top:1px solid #e5e7eb;text-align:left;font-size:18px;line-height:24px;font-weight:800;color:#111827;"">{Html(Translate("App.Listform.ListformField.Total"))}</td>
<td align=""right"" style=""padding:14px 0 0;border-top:1px solid #e5e7eb;text-align:right;font-size:18px;line-height:24px;font-weight:800;color:#2563eb;white-space:nowrap;"">{FormatPrice(order.Total)}</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>";
}
private string Translate(string key)
{
if (key.IsNullOrWhiteSpace())
{
return string.Empty;
}
var normalizedKey = key.StartsWith("::", StringComparison.Ordinal) ? key[2..] : key;
var text = L[normalizedKey];
return text.ResourceNotFound ? key : text.Value;
}
private static string BillingCycleLabel(string billingCycle)
{
return billingCycle == "monthly" ? "Aylık" : "Yıllık";
}
private static string NormalizePhoneNumber(string value, string country)
{
if (value.IsNullOrWhiteSpace())
{
return value;
}
var digits = new string(value.Where(char.IsDigit).ToArray());
if (country == "Türkiye" || digits.StartsWith("90"))
{
if (digits.StartsWith("90") && digits.Length > 10)
{
digits = digits[^10..];
}
if (digits.StartsWith("0") && digits.Length > 10)
{
digits = digits[^10..];
}
}
return digits;
}
private static string FormatPhoneNumber(string value)
{
var digits = NormalizePhoneNumber(value, string.Empty);
if (digits?.Length != 10)
{
return value;
}
return $"({digits[..3]}) {digits[3..6]}-{digits[6..]}";
}
private static string FormatDate(DateTime? value)
{
return value.HasValue ? value.Value.ToString("dd.MM.yyyy") : "-";
}
private static string FormatPrice(decimal value)
{
return string.Format(new System.Globalization.CultureInfo("tr-TR"), "{0:C2}", value);
}
private static string Html(string value)
{
return WebUtility.HtmlEncode(value ?? string.Empty);
}
public async Task<AboutDto> GetAboutAsync()
{
var entity = await _aboutRepository.FirstOrDefaultAsync() ?? throw new EntityNotFoundException(typeof(About));
@ -886,74 +526,9 @@ public class PublicAppService : PlatformAppService
public async Task<List<CountryDto>> GetCountryAsync()
{
var queryable = await _countryRepository.GetQueryableAsync();
var entities = await _countryRepository.GetListAsync() ?? throw new EntityNotFoundException(typeof(Country));
return await AsyncExecuter.ToListAsync(
queryable
.OrderBy(country => country.Name)
.Select(country => new CountryDto
{
Id = country.Id,
Name = country.Name,
GroupName = country.GroupName,
Currency = country.Currency,
PhoneCode = country.PhoneCode,
PhoneNumberMinLength = country.PhoneNumberMinLength,
PhoneNumberMaxLength = country.PhoneNumberMaxLength,
PhoneNumberFormat = country.PhoneNumberFormat,
TaxLabel = country.TaxLabel,
ZipRequired = country.ZipRequired,
StateRequired = country.StateRequired,
Cities = new List<CityDto>()
}));
}
public async Task<List<CityDto>> GetCityAsync(string country)
{
if (string.IsNullOrWhiteSpace(country))
{
return [];
}
var queryable = await _cityRepository.GetQueryableAsync();
return await AsyncExecuter.ToListAsync(
queryable
.Where(city => city.Country == country)
.OrderBy(city => city.Name)
.Select(city => new CityDto
{
Id = city.Id,
Country = city.Country,
Name = city.Name,
PlateCode = city.PlateCode
}));
}
public async Task<List<DistrictDto>> GetDistrictAsync(string country, string city)
{
if (string.IsNullOrWhiteSpace(country) || string.IsNullOrWhiteSpace(city))
{
return [];
}
var queryable = await _districtRepository.GetQueryableAsync();
var entities = await AsyncExecuter.ToListAsync(
queryable
.Where(district => district.Country == country && district.City == city)
.OrderBy(district => district.Name));
return entities
.Select(district => new DistrictDto
{
Id = district.Id,
Country = district.Country,
City = district.City,
Name = district.Name,
Township = district.Township,
PostalCode = district.PostalCode
})
.ToList();
return ObjectMapper.Map<List<Country>, List<CountryDto>>(entities);
}
public async Task SaveContactPageAsync(SaveContactPageInput input)

View file

@ -74,7 +74,7 @@ public class PlatformTenantAppService : TenantAppService, IPlatformTenantAppServ
}
var dto = ObjectMapper.Map<Tenant, CustomTenantDto>(tenant);
dto.Name = tenant.Name;
dto.IsActive = tenant.GetIsActive();
dto.OrganizationName = tenant.GetOrganizationName();
dto.Founder = tenant.GetFounder();
dto.VknTckn = tenant.GetVknTckn();

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -40,22 +40,6 @@
"selectOptions": {},
"order": 2
},
{
"code": "App.SiteManagement.General.NewTenantNotificationEmails",
"nameKey": "App.SiteManagement.General.NewTenantNotificationEmails",
"descriptionKey": "App.SiteManagement.General.NewTenantNotificationEmails.Description",
"defaultValue": "destek@sozsoft.com",
"isVisibleToClients": false,
"providers": "T|G|D",
"isInherited": false,
"isEncrypted": false,
"mainGroupKey": "App.SiteManagement",
"subGroupKey": "App.SiteManagement.General",
"requiredPermissionName": "App.SiteManagement.General",
"dataType": "Text",
"selectOptions": {},
"order": 3
},
{
"code": "App.SiteManagement.Theme.Style",
"nameKey": "App.SiteManagement.Theme.Style",

View file

@ -248,9 +248,6 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
groupName,
item.Currency,
item.PhoneCode,
item.PhoneNumberMinLength,
item.PhoneNumberMaxLength,
item.PhoneNumberFormat,
item.TaxLabel
));
@ -342,11 +339,11 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
// 1. Mevcut kayıtları çek (tek sorguda)
var existingDistricts = await dbCtx.Set<District>()
.Select(d => new { d.Country, d.City, d.Name, d.Township, d.PostalCode })
.Select(d => new { d.Country, d.City, d.Name, d.Township })
.ToListAsync();
var existingSet = existingDistricts
.Select(d => $"{d.Country}:{d.City}:{d.Name}:{d.Township}:{d.PostalCode}")
.Select(d => $"{d.Country}:{d.City}:{d.Name}:{d.Township}")
.ToHashSet();
var options = new JsonSerializerOptions
@ -362,7 +359,7 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
{
if (item == null) continue;
var key = $"{item.Country}:{item.City}:{item.Name}:{item.Township}:{item.PostalCode}";
var key = $"{item.Country}:{item.City}:{item.Name}:{item.Township}";
if (existingSet.Contains(key)) continue;
buffer.Add(new District(
@ -370,8 +367,7 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
item.Country,
item.City,
item.Name,
item.Township,
item.PostalCode
item.Township
));
if (buffer.Count >= 5000) // 3. Batch

File diff suppressed because it is too large Load diff

View file

@ -67,13 +67,11 @@ public static class ListFormSeeder_DefaultJsons
public static string DefaultLayoutJson(string DefaultLayout = "grid") => JsonSerializer.Serialize(new LayoutDto()
{
Grid = true,
Card = true,
Pivot = true,
Chart = true,
Tree = true,
Gantt = true,
Scheduler = true,
Todo = true,
DefaultLayout = DefaultLayout,
});
public static readonly string DefaultExportJson = JsonSerializer.Serialize(new ChartExportDto
@ -86,7 +84,7 @@ public static class ListFormSeeder_DefaultJsons
});
public static readonly string DefaultSelectionSingleJson = JsonSerializer.Serialize(new SelectionDto
{
Mode = GridOptions.SelectionModeSingle,
Mode = GridOptions.SelectionModeNone,
AllowSelectAll = false
});
public static readonly string DefaultSelectionMultipleJson = JsonSerializer.Serialize(new SelectionDto
@ -124,14 +122,6 @@ public static class ListFormSeeder_DefaultJsons
{
IsPivot = true
});
public static string DefaultColumnTotalSummaryJson(string showInColumn, string summaryType = "sum") => JsonSerializer.Serialize(new ColumnTotalSummaryDto
{
SummaryType = summaryType,
DisplayFormat = "{0}",
ValueFormat = "#,##0.00",
ShowInColumn = showInColumn
});
public static string DefaultGroupingJson(int groupIndex) => JsonSerializer.Serialize(new ColumnGroupingDto
{
AllowGrouping = true,

View file

@ -1,5 +1,13 @@
{
"Routes": [
{
"key": "roleListComponent",
"path": "/admin/RoleListComponent",
"componentType": "dynamic",
"componentPath": "RoleListComponent",
"routeType": "protected",
"authority": []
},
{
"key": "home",
"path": "/home",
@ -501,11 +509,31 @@
"IsDisabled": false,
"ShortName": "Sas"
},
{
"ParentCode": "App.Saas",
"Code": "AbpTenantManagement.Tenants",
"DisplayName": "AbpTenantManagement.Tenants",
"Order": 1,
"Url": "/admin/list/AbpTenantManagement.Tenants",
"Icon": "FcDepartment",
"RequiredPermissionName": "AbpTenantManagement.Tenants",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Branches",
"DisplayName": "App.Branches",
"Order": 2,
"Url": "/admin/list/App.Branches",
"Icon": "FcTreeStructure",
"RequiredPermissionName": "App.Branches",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Saas.Definitions",
"DisplayName": "App.Definitions",
"Order": 1,
"Order": 3,
"Url": null,
"Icon": "FcFilingCabinet",
"RequiredPermissionName": null,
@ -621,146 +649,6 @@
"RequiredPermissionName": "App.Definitions.Sequence",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Public",
"DisplayName": "App.Public",
"Order": 2,
"Url": null,
"Icon": "FcTemplate",
"RequiredPermissionName": null,
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Home",
"DisplayName": "App.Home",
"Order": 0,
"Url": "/admin/public/home/designer",
"Icon": "FcHome",
"RequiredPermissionName": "App.Home",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.About",
"DisplayName": "App.About",
"Order": 1,
"Url": "/admin/public/about/designer",
"Icon": "FcAbout",
"RequiredPermissionName": "App.About",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Services",
"DisplayName": "App.Services",
"Order": 2,
"Url": "/admin/public/services/designer",
"Icon": "FcServices",
"RequiredPermissionName": "App.Services",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.Products",
"DisplayName": "App.Orders.Products",
"Order": 3,
"Url": "/admin/list/App.Orders.Products",
"Icon": "FcDiploma1",
"RequiredPermissionName": "App.Orders.Products",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.PaymentMethods",
"DisplayName": "App.Orders.PaymentMethods",
"Order": 4,
"Url": "/admin/list/App.Orders.PaymentMethods",
"Icon": "FcFeedIn",
"RequiredPermissionName": "App.Orders.PaymentMethods",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.InstallmentOptions",
"DisplayName": "App.Orders.InstallmentOptions",
"Order": 5,
"Url": "/admin/list/App.Orders.InstallmentOptions",
"Icon": "FcProcess",
"RequiredPermissionName": "App.Orders.InstallmentOptions",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.SalesOrders",
"DisplayName": "App.Orders.SalesOrders",
"Order": 6,
"Url": "/admin/list/App.Orders.SalesOrders",
"Icon": "FcCollect",
"RequiredPermissionName": "App.Orders.SalesOrders",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Category",
"DisplayName": "App.BlogManagement.Category",
"Order": 7,
"Url": "/admin/list/App.BlogManagement.Category",
"Icon": "FaCertificate",
"RequiredPermissionName": "App.BlogManagement.Category",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Posts",
"DisplayName": "App.BlogManagement.Posts",
"Order": 8,
"Url": "/admin/list/App.BlogManagement.Posts",
"Icon": "FaWeixin",
"RequiredPermissionName": "App.BlogManagement.Posts",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Demos",
"DisplayName": "App.Demos",
"Order": 9,
"Url": "/admin/list/App.Demos",
"Icon": "FcMissedCall",
"RequiredPermissionName": "App.Demos",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Contact",
"DisplayName": "App.Contact",
"Order": 10,
"Url": "/admin/public/contact/designer",
"Icon": "FcContacts",
"RequiredPermissionName": "App.Contact",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "AbpTenantManagement.Tenants",
"DisplayName": "AbpTenantManagement.Tenants",
"Order": 3,
"Url": "/admin/list/AbpTenantManagement.Tenants",
"Icon": "FcDepartment",
"RequiredPermissionName": "AbpTenantManagement.Tenants",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Branches",
"DisplayName": "App.Branches",
"Order": 4,
"Url": "/admin/list/App.Branches",
"Icon": "FcTreeStructure",
"RequiredPermissionName": "App.Branches",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.SettingDefinitions",
@ -892,11 +780,131 @@
"RequiredPermissionName": "App.BackgroundWorkers.Jobs",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Public",
"DisplayName": "App.Public",
"Order": 12,
"Url": null,
"Icon": "FcTemplate",
"RequiredPermissionName": null,
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Home",
"DisplayName": "App.Home",
"Order": 0,
"Url": "/admin/public/home/designer",
"Icon": "FcHome",
"RequiredPermissionName": "App.Home",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.About",
"DisplayName": "App.About",
"Order": 1,
"Url": "/admin/public/about/designer",
"Icon": "FcAbout",
"RequiredPermissionName": "App.About",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Services",
"DisplayName": "App.Services",
"Order": 2,
"Url": "/admin/public/services/designer",
"Icon": "FcServices",
"RequiredPermissionName": "App.Services",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.Products",
"DisplayName": "App.Orders.Products",
"Order": 3,
"Url": "/admin/list/App.Orders.Products",
"Icon": "FcDiploma1",
"RequiredPermissionName": "App.Orders.Products",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.PaymentMethods",
"DisplayName": "App.Orders.PaymentMethods",
"Order": 4,
"Url": "/admin/list/App.Orders.PaymentMethods",
"Icon": "FcFeedIn",
"RequiredPermissionName": "App.Orders.PaymentMethods",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.InstallmentOptions",
"DisplayName": "App.Orders.InstallmentOptions",
"Order": 5,
"Url": "/admin/list/App.Orders.InstallmentOptions",
"Icon": "FcProcess",
"RequiredPermissionName": "App.Orders.InstallmentOptions",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.SalesOrders",
"DisplayName": "App.Orders.SalesOrders",
"Order": 6,
"Url": "/admin/list/App.Orders.SalesOrders",
"Icon": "FcCollect",
"RequiredPermissionName": "App.Orders.SalesOrders",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Category",
"DisplayName": "App.BlogManagement.Category",
"Order": 7,
"Url": "/admin/list/App.BlogManagement.Category",
"Icon": "FaCertificate",
"RequiredPermissionName": "App.BlogManagement.Category",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Posts",
"DisplayName": "App.BlogManagement.Posts",
"Order": 8,
"Url": "/admin/list/App.BlogManagement.Posts",
"Icon": "FaWeixin",
"RequiredPermissionName": "App.BlogManagement.Posts",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Demos",
"DisplayName": "App.Demos",
"Order": 9,
"Url": "/admin/list/App.Demos",
"Icon": "FcMissedCall",
"RequiredPermissionName": "App.Demos",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Contact",
"DisplayName": "App.Contact",
"Order": 10,
"Url": "/admin/public/contact/designer",
"Icon": "FcContacts",
"RequiredPermissionName": "App.Contact",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Menus",
"DisplayName": "App.Menus",
"Order": 12,
"Order": 13,
"Url": null,
"Icon": "FcParallelTasks",
"RequiredPermissionName": null,
@ -984,22 +992,22 @@
},
{
"ParentCode": "App.DeveloperKit",
"Code": "App.DeveloperKit.DynamicServices",
"DisplayName": "App.DeveloperKit.DynamicServices",
"Code": "App.DeveloperKit.Components",
"DisplayName": "App.DeveloperKit.Components",
"Order": 4,
"Url": "/admin/developerkit/dynamic-services",
"Icon": "FcCommandLine",
"RequiredPermissionName": "App.DeveloperKit.DynamicServices",
"Url": "/admin/developerkit/components",
"Icon": "FcBiohazard",
"RequiredPermissionName": "App.DeveloperKit.Components",
"IsDisabled": false
},
{
"ParentCode": "App.DeveloperKit",
"Code": "App.DeveloperKit.Components",
"DisplayName": "App.DeveloperKit.Components",
"Code": "App.DeveloperKit.DynamicServices",
"DisplayName": "App.DeveloperKit.DynamicServices",
"Order": 5,
"Url": "/admin/developerkit/components",
"Icon": "FcBiohazard",
"RequiredPermissionName": "App.DeveloperKit.Components",
"Url": "/admin/developerkit/dynamic-services",
"Icon": "FcCommandLine",
"RequiredPermissionName": "App.DeveloperKit.DynamicServices",
"IsDisabled": false
},
{
@ -1033,11 +1041,21 @@
"IsDisabled": false,
"ShortName": "Adm"
},
{
"ParentCode": "App.Administration",
"Code": "App.Setting",
"DisplayName": "App.Setting",
"Order": 1,
"Url": "/admin/settings",
"Icon": "FcSettings",
"RequiredPermissionName": "App.Setting",
"IsDisabled": false
},
{
"ParentCode": "App.Administration",
"Code": "App.Administration.Definitions",
"DisplayName": "App.Definitions",
"Order": 1,
"Order": 2,
"Url": null,
"Icon": "FcFilingCabinet",
"RequiredPermissionName": null,
@ -1083,31 +1101,11 @@
"RequiredPermissionName": "App.Definitions.OrgChart",
"IsDisabled": false
},
{
"ParentCode": "App.Administration",
"Code": "App.Licence",
"DisplayName": "App.Licence",
"Order": 2,
"Url": "/admin/form/App.Licence",
"Icon": "FcRules",
"RequiredPermissionName": "App.Licence",
"IsDisabled": false
},
{
"ParentCode": "App.Administration",
"Code": "App.Setting",
"DisplayName": "App.Setting",
"Order": 3,
"Url": "/admin/settings",
"Icon": "FcSettings",
"RequiredPermissionName": "App.Setting",
"IsDisabled": false
},
{
"ParentCode": "App.Administration",
"Code": "App.Administration.Intranet",
"DisplayName": "App.Intranet",
"Order": 4,
"Order": 3,
"Url": null,
"Icon": "FcConferenceCall",
"RequiredPermissionName": null,
@ -1177,7 +1175,7 @@
"ParentCode": "App.Administration",
"Code": "App.Administration.Restrictions",
"DisplayName": "App.Restrictions",
"Order": 5,
"Order": 4,
"Url": null,
"Icon": "FaLock",
"RequiredPermissionName": null,
@ -1207,7 +1205,7 @@
"ParentCode": "App.Administration",
"Code": "Abp.Identity",
"DisplayName": "Abp.Identity",
"Order": 6,
"Order": 5,
"Url": null,
"Icon": "FcConferenceCall",
"RequiredPermissionName": null,
@ -1297,7 +1295,7 @@
"ParentCode": "App.Administration",
"Code": "App.Reports.Management",
"DisplayName": "App.Reports.Management",
"Order": 7,
"Order": 6,
"Url": null,
"Icon": "FcDocument",
"RequiredPermissionName": null,
@ -1327,7 +1325,7 @@
"ParentCode": "App.Administration",
"Code": "App.Videoroom.Dashboard",
"DisplayName": "App.Videoroom.Dashboard",
"Order": 8,
"Order": 7,
"Url": "/admin/videoroom/dashboard",
"Icon": "FcVideoCall",
"RequiredPermissionName": "App.Videoroom.Dashboard",
@ -1337,7 +1335,7 @@
"ParentCode": "App.Administration",
"Code": "App.Files",
"DisplayName": "App.Files",
"Order": 9,
"Order": 8,
"Url": "/admin/files",
"Icon": "FcFolder",
"RequiredPermissionName": "App.Files",
@ -1347,7 +1345,7 @@
"ParentCode": "App.Administration",
"Code": "App.Forum",
"DisplayName": "App.Forum",
"Order": 10,
"Order": 9,
"Url": "/admin/forum",
"Icon": "FcLink",
"RequiredPermissionName": "App.ForumManagement.Publish",

View file

@ -4175,7 +4175,7 @@
"DisplayName": "App.Intranet.Survey",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4184,7 +4184,7 @@
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4193,7 +4193,7 @@
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4202,7 +4202,7 @@
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4211,7 +4211,7 @@
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4220,7 +4220,7 @@
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4229,7 +4229,7 @@
"DisplayName": "Note",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4238,7 +4238,7 @@
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4247,7 +4247,7 @@
"DisplayName": "App.Intranet.SurveyQuestion",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4256,7 +4256,7 @@
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4265,7 +4265,7 @@
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4274,7 +4274,7 @@
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4283,7 +4283,7 @@
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4292,7 +4292,7 @@
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4301,7 +4301,7 @@
"DisplayName": "Note",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4310,7 +4310,7 @@
"DisplayName": "App.Intranet.SurveyQuestionOption",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4319,7 +4319,7 @@
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4328,7 +4328,7 @@
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4337,7 +4337,7 @@
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4346,7 +4346,7 @@
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4355,7 +4355,7 @@
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4364,7 +4364,7 @@
"DisplayName": "App.Intranet.SurveyResponse",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4373,7 +4373,7 @@
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4382,7 +4382,7 @@
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4391,7 +4391,7 @@
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4400,7 +4400,7 @@
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4409,7 +4409,7 @@
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4418,7 +4418,7 @@
"DisplayName": "Note",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4427,7 +4427,7 @@
"DisplayName": "App.Intranet.SurveyAnswer",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4436,7 +4436,7 @@
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4445,7 +4445,7 @@
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4454,7 +4454,7 @@
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4463,7 +4463,7 @@
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4472,7 +4472,7 @@
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MenuGroup": "Erp"
},
{
"GroupName": "App.Administration",
@ -4480,8 +4480,8 @@
"ParentName": null,
"DisplayName": "App.Videoroom",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MultiTenancySide": 2,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Administration",
@ -4489,8 +4489,8 @@
"ParentName": "App.Videoroom",
"DisplayName": "App.Videoroom.Dashboard",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MultiTenancySide": 2,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Administration",
@ -4498,8 +4498,8 @@
"ParentName": "App.Videoroom",
"DisplayName": "App.Videoroom.List",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MultiTenancySide": 2,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Administration",
@ -4507,116 +4507,8 @@
"ParentName": "App.Videoroom",
"DisplayName": "App.Videoroom.RoomDetail",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Licence",
"ParentName": null,
"DisplayName": "App.Licence",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Licence.Create",
"ParentName": "App.Licence",
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Licence.Update",
"ParentName": "App.Licence",
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Licence.Delete",
"ParentName": "App.Licence",
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Licence.Export",
"ParentName": "App.Licence",
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Licence.Import",
"ParentName": "App.Licence",
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.LicenceItem",
"ParentName": null,
"DisplayName": "App.LicenceItem",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.LicenceItem.Create",
"ParentName": "App.LicenceItem",
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.LicenceItem.Update",
"ParentName": "App.LicenceItem",
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.LicenceItem.Delete",
"ParentName": "App.LicenceItem",
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.LicenceItem.Export",
"ParentName": "App.LicenceItem",
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.LicenceItem.Import",
"ParentName": "App.LicenceItem",
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
"MultiTenancySide": 2,
"MenuGroup": "Kurs"
}
]
}

View file

@ -1,917 +0,0 @@
CREATE OR REPLACE FUNCTION dbo."Sas_H_ListFormFieldsDictionaryJson"
(
p_definition_culture_name VARCHAR(10) DEFAULT 'en',
p_ui_culture_name VARCHAR(10) DEFAULT 'tr',
p_list_form_code VARCHAR(64) DEFAULT NULL,
p_only_base_definitions BOOLEAN DEFAULT TRUE,
p_resource_name VARCHAR(64) DEFAULT NULL
)
RETURNS JSONB
LANGUAGE plpgsql
AS $$
DECLARE
v_result JSONB;
BEGIN
WITH list_form_source AS
(
SELECT
l."Id",
l."ListFormCode",
l."CultureName",
l."Name",
lt_name."Value" AS name_value,
l."Title",
lt_title."Value" AS title_value,
l."Description",
lt_desc."Value" AS description_value,
l."TableName",
NULLIF(
BTRIM(l."SelectCommand"::TEXT),
''
) AS select_command_text,
l."KeyFieldName",
l."UserId",
l."RoleId"
FROM dbo."Sas_H_ListForm" l
/*
SQL Server OUTER APPLY TOP (1)
PostgreSQL LEFT JOIN LATERAL ... LIMIT 1
*/
LEFT JOIN LATERAL
(
SELECT lt."Value"
FROM dbo."Sas_H_LanguageText" lt
WHERE lt."CultureName" = p_ui_culture_name
AND lt."Key" = l."Name"
AND
(
p_resource_name IS NULL
OR lt."ResourceName" = p_resource_name
)
ORDER BY lt."ResourceName"
LIMIT 1
) lt_name ON TRUE
LEFT JOIN LATERAL
(
SELECT lt."Value"
FROM dbo."Sas_H_LanguageText" lt
WHERE lt."CultureName" = p_ui_culture_name
AND lt."Key" = l."Title"
AND
(
p_resource_name IS NULL
OR lt."ResourceName" = p_resource_name
)
ORDER BY lt."ResourceName"
LIMIT 1
) lt_title ON TRUE
LEFT JOIN LATERAL
(
SELECT lt."Value"
FROM dbo."Sas_H_LanguageText" lt
WHERE lt."CultureName" = p_ui_culture_name
AND lt."Key" = l."Description"
AND
(
p_resource_name IS NULL
OR lt."ResourceName" = p_resource_name
)
ORDER BY lt."ResourceName"
LIMIT 1
) lt_desc ON TRUE
WHERE
(
p_definition_culture_name IS NULL
OR l."CultureName" = p_definition_culture_name
)
AND
(
p_list_form_code IS NULL
OR l."ListFormCode" = p_list_form_code
)
AND
(
p_only_base_definitions = FALSE
OR
(
l."UserId" IS NULL
AND l."RoleId" IS NULL
)
)
),
list_forms_json AS
(
SELECT
jsonb_build_object
(
'listFormCode',
l."ListFormCode",
'displayName',
COALESCE(
l.name_value::TEXT,
l."Name",
''
),
'title',
COALESCE(
l.title_value::TEXT,
l."Title",
''
),
'description',
COALESCE(
l.description_value::TEXT,
l."Description",
''
),
'tableName',
COALESCE(
l."TableName",
''
),
'sqlSourceName',
COALESCE(
NULLIF(
l."TableName",
''
),
l.select_command_text,
''
),
'sourceKind',
CASE
WHEN COALESCE(
NULLIF(
l."TableName",
''
),
l.select_command_text
) IS NULL
THEN 'unknown'
WHEN UPPER(
BTRIM(
COALESCE(
NULLIF(
l."TableName",
''
),
l.select_command_text
)
)
) LIKE 'SELECT%'
THEN 'selectSql'
ELSE 'table'
END,
'keyFieldName',
COALESCE(
l."KeyFieldName",
''
),
'searchText',
CONCAT_WS(
' ',
l."ListFormCode",
l."TableName",
l.select_command_text,
COALESCE(
l.name_value::TEXT,
l."Name"
),
COALESCE(
l.title_value::TEXT,
l."Title"
),
COALESCE(
l.description_value::TEXT,
l."Description"
)
),
'fields',
COALESCE
(
(
SELECT
jsonb_agg
(
jsonb_build_object
(
'field',
f."FieldName",
'displayName',
COALESCE(
lt_cap."Value"::TEXT,
f."CaptionName",
''
),
'sqlDataType',
sc.sql_data_type,
'listOrderNo',
f."ListOrderNo",
'isVisible',
COALESCE(
f."Visible",
TRUE
),
'isBooleanColumn',
CASE
WHEN sc.sql_data_type = 'boolean'
THEN TRUE
WHEN f."FieldName" LIKE 'Is%'
THEN TRUE
WHEN f."FieldName" LIKE 'Has%'
THEN TRUE
WHEN f."FieldName" IN
(
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday'
)
THEN TRUE
WHEN f."FieldName" IN
(
'EmailConfirmed',
'TwoFactorEnabled',
'IsVerified',
'IsDefault',
'IsPublic',
'IsEnabled',
'IsPublished',
'IsPinned',
'IsAnonymous',
'IsFixed',
'IsCustomized',
'IsEncrypted',
'IsInherited',
'ZipRequired',
'StateRequired'
)
THEN TRUE
ELSE FALSE
END,
'lookupJsonText',
lj.lookup_json_text_decoded,
'lookupTableName',
COALESCE
(
CASE
WHEN lj.lookup_json IS NOT NULL
THEN COALESCE
(
lj.lookup_json ->> 'tableName',
lj.lookup_json ->> 'sqlTableName',
lj.lookup_json ->> 'lookupTableName',
lj.lookup_json #>> '{dataSource,tableName}',
lj.lookup_json #>> '{dataSource,sqlTableName}'
)
END,
lkp.parsed_lookup_table_name
),
'lookupValueColumn',
COALESCE
(
CASE
WHEN lj.lookup_json IS NOT NULL
THEN COALESCE
(
lj.lookup_json ->> 'valueExpr',
lj.lookup_json ->> 'valueField',
lj.lookup_json ->> 'valueColumn',
lj.lookup_json ->> 'keyField',
lj.lookup_json ->> 'keyFieldName'
)
END,
lkp.parsed_lookup_value_column
),
'lookupDisplayColumn',
COALESCE
(
CASE
WHEN lj.lookup_json IS NOT NULL
THEN COALESCE
(
lj.lookup_json ->> 'displayExpr',
lj.lookup_json ->> 'displayField',
lj.lookup_json ->> 'displayColumn',
lj.lookup_json ->> 'textField',
lj.lookup_json ->> 'textColumn',
lj.lookup_json ->> 'nameField',
lj.lookup_json ->> 'nameColumn'
)
END,
lkp.parsed_lookup_display_column
),
'lookupJoinMode',
CASE
WHEN lj.lookup_json_text_decoded IS NOT NULL
AND f."FieldName" NOT LIKE '%Id'
AND COALESCE(
lkp.parsed_lookup_value_column,
''
) IN
(
'Name',
'Code',
'Key',
'Value',
'key',
'value'
)
THEN 'direct-string'
WHEN lj.lookup_json_text_decoded IS NOT NULL
AND f."FieldName" NOT LIKE '%Id'
THEN 'direct-string'
WHEN lj.lookup_json_text_decoded IS NOT NULL
OR f."FieldName" LIKE '%Id'
THEN 'convert-nvarchar-safe'
ELSE NULL
END,
'lookupFallbackToSourceColumn',
CASE
WHEN
lj.lookup_json_text_decoded IS NOT NULL
AND f."FieldName" NOT LIKE '%Id'
THEN TRUE
ELSE FALSE
END,
'lookupSearchText',
CASE
WHEN lj.lookup_json_text_decoded IS NOT NULL
THEN CONCAT_WS
(
' ',
f."FieldName",
f."CaptionName",
lt_cap."Value"::TEXT,
lj.lookup_json_text_decoded
)
END,
'isActiveStatusColumn',
f."FieldName" IN
(
'IsActive',
'IsEnabled',
'IsPublished'
),
'isDeletedStatusColumn',
f."FieldName" IN
(
'IsDeleted',
'Deleted',
'IsRemoved'
),
'isSensitive',
CASE
WHEN f."FieldName" LIKE '%Password%'
OR f."FieldName" LIKE '%ConnectionString%'
OR f."FieldName" LIKE '%Token%'
OR f."FieldName" LIKE '%Secret%'
OR f."FieldName" LIKE '%ApiKey%'
OR f."FieldName" LIKE '%PrivateKey%'
THEN TRUE
ELSE FALSE
END,
'isDefaultSelectColumn',
CASE
WHEN
COALESCE(
f."Visible",
TRUE
) = TRUE
AND COALESCE(
f."IsActive",
TRUE
) = TRUE
AND f."FieldName" NOT LIKE '%Password%'
AND f."FieldName" NOT LIKE '%ConnectionString%'
AND f."FieldName" NOT LIKE '%Token%'
AND f."FieldName" NOT LIKE '%Secret%'
AND f."FieldName" NOT LIKE '%ApiKey%'
AND f."FieldName" NOT LIKE '%PrivateKey%'
AND f."FieldName" NOT IN
(
'Avatar',
'ExtraProperties'
)
THEN TRUE
ELSE FALSE
END
)
ORDER BY
COALESCE(
f."ListOrderNo",
999999
),
f."FieldName"
)
FROM dbo."Sas_H_ListFormField" f
/*
SQL Server:
sys.tables
sys.columns
TYPE_NAME()
PostgreSQL:
information_schema.columns
*/
LEFT JOIN LATERAL
(
SELECT
c.data_type AS sql_data_type
FROM information_schema.columns c
WHERE
c.table_schema = 'dbo'
AND c.table_name =
l."TableName"
AND c.column_name =
f."FieldName"
LIMIT 1
) sc ON TRUE
/*
LookupJson decode
*/
LEFT JOIN LATERAL
(
SELECT
NULLIF
(
BTRIM
(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
NULLIF(
BTRIM(
f."LookupJson"::TEXT
),
''
),
'\\u0022',
'"'
),
'\u0022',
'"'
),
'\\u0027',
''''
),
'\u0027',
''''
),
'&quot;',
'"'
)
),
''
) AS lookup_json_text_decoded
) lj_text ON TRUE
/*
PostgreSQL'de ISJSON yerine
güvenli JSON parse işlemi gerekiyor.
LookupJson kolonu zaten JSON/JSONB ise
doğrudan kullanılabilir.
*/
LEFT JOIN LATERAL
(
SELECT
lj_text.lookup_json_text_decoded,
CASE
WHEN
lj_text.lookup_json_text_decoded
~ '^\s*[\{\[]'
THEN
lj_text.lookup_json_text_decoded::JSONB
ELSE NULL
END AS lookup_json
) lj ON TRUE
/*
LookupQuery değerini al
*/
LEFT JOIN LATERAL
(
SELECT
CASE
WHEN lj.lookup_json IS NOT NULL
THEN
lj.lookup_json
->> 'LookupQuery'
END AS lookup_query_text
) lq ON TRUE
/*
LookupQuery temizleme
*/
LEFT JOIN LATERAL
(
SELECT
NULLIF
(
BTRIM
(
REGEXP_REPLACE
(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
COALESCE(
lq.lookup_query_text,
''
),
'"',
''
),
'[',
''
),
']',
''
),
'`',
''
),
'\s+',
' ',
'g'
)
),
''
) AS clean_lookup_query
) lqc ON TRUE
/*
SQL Server prosedürü LookupQuery içerisindeki
SELECT ... FROM ... ifadesini string işlemleri
ile parse ediyor.
PostgreSQL'de regexp_match daha temiz.
*/
LEFT JOIN LATERAL
(
SELECT
(
REGEXP_MATCH
(
lqc.clean_lookup_query,
'(?i)\bFROM\s+([a-zA-Z0-9_\."]+)'
)
)[1] AS parsed_table,
COALESCE
(
NULLIF(
lj.lookup_json
->> 'ValueExpr',
''
),
NULLIF(
lj.lookup_json
->> 'valueExpr',
''
),
NULLIF(
lj.lookup_json
->> 'valueField',
''
),
NULLIF(
lj.lookup_json
->> 'valueColumn',
''
),
NULLIF(
lj.lookup_json
->> 'keyField',
''
),
NULLIF(
lj.lookup_json
->> 'keyFieldName',
''
)
)
AS parsed_lookup_value_column,
COALESCE
(
NULLIF(
lj.lookup_json
->> 'DisplayExpr',
''
),
NULLIF(
lj.lookup_json
->> 'displayExpr',
''
),
NULLIF(
lj.lookup_json
->> 'displayField',
''
),
NULLIF(
lj.lookup_json
->> 'displayColumn',
''
),
NULLIF(
lj.lookup_json
->> 'textField',
''
),
NULLIF(
lj.lookup_json
->> 'textColumn',
''
),
NULLIF(
lj.lookup_json
->> 'nameField',
''
),
NULLIF(
lj.lookup_json
->> 'nameColumn',
''
)
)
AS parsed_lookup_display_column
) parsed ON TRUE
LEFT JOIN LATERAL
(
SELECT
NULLIF
(
REGEXP_REPLACE
(
COALESCE(
parsed.parsed_table,
''
),
'^(?i:dbo\.)',
''
),
''
)
AS parsed_lookup_table_name,
parsed.parsed_lookup_value_column,
parsed.parsed_lookup_display_column
) lkp ON TRUE
/*
Caption translation
*/
LEFT JOIN LATERAL
(
SELECT
lt."Value"
FROM dbo."Sas_H_LanguageText" lt
WHERE
lt."CultureName" =
p_ui_culture_name
AND lt."Key" =
f."CaptionName"
AND
(
p_resource_name IS NULL
OR lt."ResourceName" =
p_resource_name
)
ORDER BY
lt."ResourceName"
LIMIT 1
) lt_cap ON TRUE
WHERE
f."ListFormCode" =
l."ListFormCode"
AND f."CultureName" =
l."CultureName"
AND
(
p_definition_culture_name IS NULL
OR f."CultureName" =
p_definition_culture_name
)
AND
(
p_only_base_definitions = FALSE
OR
(
f."UserId" IS NULL
AND f."RoleId" IS NULL
)
)
),
'[]'::JSONB
)
)
AS form_json,
l."ListFormCode"
FROM list_form_source l
)
SELECT
jsonb_build_object
(
'listForms',
COALESCE
(
jsonb_agg
(
form_json
ORDER BY
"ListFormCode"
),
'[]'::JSONB
)
)
INTO v_result
FROM list_forms_json;
RETURN COALESCE
(
v_result,
jsonb_build_object
(
'listForms',
'[]'::JSONB
)
);
END;
$$;

View file

@ -1,239 +0,0 @@
CREATE OR REPLACE FUNCTION dbo."Sas_H_ListFormFieldsDictionaryJson_SaveDbTableColumns"
(
p_tenant_name VARCHAR(128) DEFAULT 'Sozsoft',
p_definition_culture_name VARCHAR(10) DEFAULT 'en',
p_ui_culture_name VARCHAR(10) DEFAULT 'tr',
p_list_form_code VARCHAR(64) DEFAULT NULL,
p_only_base_definitions BOOLEAN DEFAULT TRUE,
p_resource_name VARCHAR(64) DEFAULT NULL,
p_max_forms INTEGER DEFAULT 500,
p_deactivate_previous BOOLEAN DEFAULT TRUE,
p_note VARCHAR(4000) DEFAULT NULL
)
RETURNS TABLE
(
"TenantName" VARCHAR,
"DictionaryType" VARCHAR,
"DefinitionCultureName" VARCHAR,
"UiCultureName" VARCHAR,
"ListFormCode" VARCHAR,
"OnlyBaseDefinitions" BOOLEAN,
"ResourceName" VARCHAR,
"MaxForms" INTEGER,
"CacheKey" TEXT,
"FormCount" INTEGER,
"FieldCount" INTEGER,
"JsonLength" INTEGER,
"IsActive" BOOLEAN,
"RefreshedAt" TIMESTAMP,
"SourceProcedure" VARCHAR,
"Note" VARCHAR
)
LANGUAGE plpgsql
AS $$
DECLARE
v_json_data JSONB;
v_cache_key TEXT;
v_form_count INTEGER := 0;
v_field_count INTEGER := 0;
v_json_length INTEGER := 0;
BEGIN
/*
SQL Server:
EXEC dbo.Sas_H_ListFormFieldsDictionaryJson
PostgreSQL tarafında bunun JSON / JSONB döndüren bir FUNCTION
olduğu varsayılmıştır.
*/
SELECT dbo."Sas_H_ListFormFieldsDictionaryJson"
(
p_definition_culture_name,
p_ui_culture_name,
p_list_form_code,
p_only_base_definitions,
p_resource_name
)
INTO v_json_data;
/*
JSON boş kontrolü
*/
IF v_json_data IS NULL THEN
RAISE EXCEPTION
'JSON veri sözlüğü boş döndü. dbo.Sas_H_ListFormFieldsDictionaryJson çıktısını kontrol edin.'
USING ERRCODE = 'P0001';
END IF;
/*
CacheKey oluşturulması
*/
v_cache_key :=
'ListFormJson|'
|| COALESCE(p_tenant_name, '')
|| '|'
|| COALESCE(p_definition_culture_name, '')
|| '|'
|| COALESCE(p_ui_culture_name, '')
|| '|'
|| COALESCE(p_list_form_code, '')
|| '|'
|| CASE
WHEN COALESCE(p_only_base_definitions, TRUE)
THEN '1'
ELSE '0'
END
|| '|'
|| COALESCE(p_resource_name, '')
|| '|'
|| COALESCE(p_max_forms, 500)::TEXT;
/*
Form sayısı
JSON:
{
"listForms": [...]
}
*/
IF jsonb_typeof(v_json_data -> 'listForms') = 'array' THEN
v_form_count :=
jsonb_array_length(v_json_data -> 'listForms');
END IF;
/*
Toplam Field sayısı
Her listForms elemanının:
{
"fields": [...]
}
alanındaki kayıtlar sayılır.
*/
SELECT COUNT(*)::INTEGER
INTO v_field_count
FROM jsonb_array_elements(
COALESCE(
v_json_data -> 'listForms',
'[]'::JSONB
)
) AS lf
CROSS JOIN LATERAL jsonb_array_elements(
CASE
WHEN jsonb_typeof(lf -> 'fields') = 'array'
THEN lf -> 'fields'
ELSE '[]'::JSONB
END
) AS ff;
/*
JSON karakter uzunluğu
*/
v_json_length := LENGTH(v_json_data::TEXT);
/*
PostgreSQL function çağrısı kendi transaction'ı içerisinde
çalıştığı için SQL Server'daki BEGIN TRAN / COMMIT burada
ayrıca kullanılmaz.
*/
/*
Önceki aktif kaydı pasif yap
*/
IF p_deactivate_previous THEN
UPDATE dbo."Sas_H_DbTableColumn"
SET "IsActive" = FALSE
WHERE "DictionaryType" = 'ListFormJson'
AND "CacheKey" = v_cache_key
AND COALESCE("IsActive", FALSE) = TRUE;
END IF;
/*
Yeni JSON kaydını ekle
*/
INSERT INTO dbo."Sas_H_DbTableColumn"
(
"TenantName",
"DictionaryType",
"DefinitionCultureName",
"UiCultureName",
"ListFormCode",
"OnlyBaseDefinitions",
"ResourceName",
"MaxForms",
"CacheKey",
"JsonData",
"FormCount",
"FieldCount",
"JsonLength",
"IsActive",
"RefreshedAt",
"SourceProcedure",
"Note"
)
VALUES
(
COALESCE(p_tenant_name, 'Sozsoft'),
'ListFormJson',
COALESCE(p_definition_culture_name, 'en'),
COALESCE(p_ui_culture_name, 'tr'),
p_list_form_code,
COALESCE(p_only_base_definitions, TRUE),
p_resource_name,
COALESCE(p_max_forms, 500),
v_cache_key,
v_json_data,
v_form_count,
v_field_count,
v_json_length,
TRUE,
CURRENT_TIMESTAMP,
'dbo.Sas_H_ListFormFieldsDictionaryJson',
p_note
);
/*
Eklenen aktif kaydı döndür
*/
RETURN QUERY
SELECT
T."TenantName",
T."DictionaryType",
T."DefinitionCultureName",
T."UiCultureName",
T."ListFormCode",
T."OnlyBaseDefinitions",
T."ResourceName",
T."MaxForms",
T."CacheKey",
T."FormCount",
T."FieldCount",
T."JsonLength",
T."IsActive",
T."RefreshedAt",
T."SourceProcedure",
T."Note"
FROM dbo."Sas_H_DbTableColumn" T
WHERE T."DictionaryType" = 'ListFormJson'
AND T."CacheKey" = v_cache_key
AND T."IsActive" = TRUE
ORDER BY T."RefreshedAt" DESC
LIMIT 1;
END;
$$;

View file

@ -1,22 +0,0 @@
CREATE OR REPLACE VIEW dbo."Sas_H_OrderItem_ByTenantId"
AS
SELECT
oi."Id",
o."TenantId",
oi."ProductId",
oi."ProductName",
oi."BillingCycle",
oi."Period",
oi."Quantity",
oi."Price",
oi."VatRate",
oi."VatAmount",
oi."TotalPrice",
oi."OrderId",
o."IsActive"
FROM dbo."Sas_H_Order" o
INNER JOIN dbo."Sas_H_OrderItem" oi
ON o."Id" = oi."OrderId";

View file

@ -1,8 +0,0 @@
-- Create View
CREATE OR ALTER VIEW [dbo].[Sas_H_OrderItem_ByTenantId]
AS
SELECT dbo.Sas_H_OrderItem.Id, dbo.Sas_H_Order.TenantId, dbo.Sas_H_OrderItem.ProductId, dbo.Sas_H_OrderItem.ProductName, dbo.Sas_H_OrderItem.BillingCycle, dbo.Sas_H_OrderItem.Period, dbo.Sas_H_OrderItem.Quantity,
dbo.Sas_H_OrderItem.Price, dbo.Sas_H_OrderItem.VatRate, dbo.Sas_H_OrderItem.VatAmount, dbo.Sas_H_OrderItem.TotalPrice, dbo.Sas_H_OrderItem.OrderId, dbo.Sas_H_Order.IsActive
FROM dbo.Sas_H_Order INNER JOIN
dbo.Sas_H_OrderItem ON dbo.Sas_H_Order.Id = dbo.Sas_H_OrderItem.OrderId

View file

@ -1,18 +0,0 @@
IF OBJECT_ID(N'[dbo].[Pro_T_Approval]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Pro_T_Approval]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[ApprovalUserName] nvarchar(256) NULL,
[ApprovalStatus] nvarchar(50) NULL,
[ApprovalDate] datetime NULL,
[ApprovalDescription] nvarchar(200) NULL,
[TenantId] uniqueidentifier NULL,
[Title] nvarchar(100) NULL,
CONSTRAINT [PK_Pro_T_Approval] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -1,22 +0,0 @@
IF OBJECT_ID(N'[dbo].[Pro_T_Todo]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Pro_T_Todo]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[Title] nvarchar(300) NOT NULL,
[Status] nvarchar(50) NOT NULL DEFAULT N'Inbox',
[Description] nvarchar(MAX) NULL,
[DueDate] datetime2 NULL,
[Tags] nvarchar(500) NULL,
[Assignees] nvarchar(500) NULL,
[Priority] nvarchar(50) NULL,
[Completed] bit NOT NULL DEFAULT 0,
[SortOrder] int NOT NULL DEFAULT 0,
[TenantId] uniqueidentifier NULL,
CONSTRAINT [PK_Table] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -0,0 +1,25 @@
IF OBJECT_ID(N'[dbo].[Sal_T_Approval]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Sal_T_Approval]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
[TenantId] uniqueidentifier NULL,
[ApprovalUserName] nvarchar(256) NULL,
[ApprovalStatus] nvarchar(50) NULL,
[ApprovalDate] datetime NULL,
[ApprovalDescription] nvarchar(200) NULL,
[Name] nvarchar(100) NULL,
CONSTRAINT [PK_Sal_T_Approval] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -13,30 +13,27 @@
"ConfirmDelete": true,
"DefaultLayout": "grid",
"Grid": true,
"Card": true,
"Pivot": true,
"Tree": true,
"Chart": true,
"Gantt": true,
"Scheduler": true,
"Todo": false,
"LanguageTextMenuEn": "Approval",
"LanguageTextMenuTr": "Onaylama",
"LanguageTextMenuTr": "Approval",
"LanguageTextTitleEn": "Approval",
"LanguageTextTitleTr": "Onaylama",
"LanguageTextDescEn": "Approval",
"LanguageTextDescTr": "Onaylama",
"LanguageTextMenuParentEn": "Project",
"LanguageTextMenuParentTr": "Project",
"PermissionGroupName": "App.Wizard.Project",
"MenuParentCode": "App.Wizard.Project",
"MenuParentShortName": "Pro",
"MenuParentIcon": "FcVideoProjector",
"MenuIcon": "FcApproval",
"LanguageTextMenuParentEn": "Sales",
"LanguageTextMenuParentTr": "Sat\u0131\u015F",
"PermissionGroupName": "App.Wizard.Sales",
"MenuParentCode": "App.Wizard.Sales",
"MenuParentIcon": "FcAssistant",
"MenuIcon": "FcAndroidOs",
"DataSourceCode": "Default",
"DataSourceConnectionString": "",
"SelectCommandType": 1,
"SelectCommand": "Pro_T_Approval",
"SelectCommand": "Sal_T_Approval",
"KeyFieldName": "Id",
"KeyFieldDbSourceType": 9,
"TreeKeyExpr": "",
@ -52,103 +49,13 @@
"SchedulerTextExpr": "",
"SchedulerStartDateExpr": "",
"SchedulerEndDateExpr": "",
"TodoTitleExpr": "",
"TodoStatusExpr": "",
"TodoDescriptionExpr": "",
"TodoDueDateExpr": "",
"TodoTagExpr": "",
"TodoAssigneeExpr": "",
"TodoPriorityExpr": "",
"TodoCompletedExpr": "",
"TodoOrderExpr": "",
"TodoStatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging",
"TodoAllowDragging": true,
"ApprovalUserFieldName": "ApprovalUserName",
"ApprovalDateFieldName": "ApprovalDate",
"ApprovalStatusFieldName": "ApprovalStatus",
"ApprovalDescriptionFieldName": "ApprovalDescription",
"ApprovalIsFilterUserName": false,
"Criteria": [
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Start",
"Title": "\u0130\u015F Ak\u0131\u015F\u0131 Ba\u015Flat1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "",
"NextOnStart": "App.Wizard.Approval-N002",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 46,
"PositionY": 46,
"CompareOutcomes": [],
"Id": "App.Wizard.Approval-N001"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Approval",
"Title": "Onay1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "system@sozsoft.com",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "App.Wizard.Approval-N003",
"NextOnReject": "App.Wizard.Approval-N004",
"PositionX": 337,
"PositionY": 39,
"CompareOutcomes": [],
"Id": "App.Wizard.Approval-N002"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Inform",
"Title": "Bilgilendirme1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "system@sozsoft.com",
"NextOnStart": "App.Wizard.Approval-N004",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 538,
"PositionY": 324,
"CompareOutcomes": [],
"Id": "App.Wizard.Approval-N003"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "End",
"Title": "\u0130\u015F Ak\u0131\u015F\u0131 Bitir1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 852,
"PositionY": 26,
"CompareOutcomes": [],
"Id": "App.Wizard.Approval-N004"
}
],
"Groups": [
{
"Caption": "",
"ColCount": 1,
"Items": [
{
"FieldName": "Id",
"DataField": "Id",
"CaptionName": "App.Listform.ListformField.Id",
"EditorType": "dxTextBox",
"EditorOptions": "",
@ -165,7 +72,24 @@
"LookupQuery": ""
},
{
"FieldName": "ApprovalUserName",
"DataField": "Name",
"CaptionName": "App.Listform.ListformField.Name",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": true,
"IncludeInEditingForm": true,
"DbSourceType": 16,
"TurkishCaption": "Name",
"EnglishCaption": "Name",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"DataField": "ApprovalUserName",
"CaptionName": "App.Listform.ListformField.ApprovalUserName",
"EditorType": "dxTextBox",
"EditorOptions": "",
@ -182,7 +106,7 @@
"LookupQuery": ""
},
{
"FieldName": "ApprovalStatus",
"DataField": "ApprovalStatus",
"CaptionName": "App.Listform.ListformField.ApprovalStatus",
"EditorType": "dxTextBox",
"EditorOptions": "",
@ -199,7 +123,7 @@
"LookupQuery": ""
},
{
"FieldName": "ApprovalDate",
"DataField": "ApprovalDate",
"CaptionName": "App.Listform.ListformField.ApprovalDate",
"EditorType": "dxDateBox",
"EditorOptions": "",
@ -216,7 +140,7 @@
"LookupQuery": ""
},
{
"FieldName": "ApprovalDescription",
"DataField": "ApprovalDescription",
"CaptionName": "App.Listform.ListformField.ApprovalDescription",
"EditorType": "dxTextBox",
"EditorOptions": "",
@ -231,39 +155,219 @@
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Title",
"CaptionName": "App.Listform.ListformField.Title",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": false,
"IncludeInEditingForm": true,
"DbSourceType": 16,
"TurkishCaption": "Title",
"EnglishCaption": "Title",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
}
]
}
],
"SubForms": [],
"Widgets": []
"Widgets": [],
"Workflow": {
"ApprovalUserFieldName": "ApprovalUserName",
"IsFilterUserName": true,
"ApprovalDateFieldName": "ApprovalDate",
"ApprovalStatusFieldName": "ApprovalStatus",
"ApprovalDescriptionFieldName": "ApprovalDescription",
"Criteria": [
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Start",
"Title": "\u0130\u015F Ak\u0131\u015F\u0131 Ba\u015Flat1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "",
"NextOnStart": "N002",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 34,
"PositionY": 104,
"CompareOutcomes": [],
"Id": "N001"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Approval",
"Title": "Onay1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "admin@sozsoft.com",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "N003",
"NextOnReject": "N004",
"PositionX": 323,
"PositionY": 104,
"CompareOutcomes": [],
"Id": "N002"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Approval",
"Title": "Onay2",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "demo@sozsoft.com",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "N004",
"NextOnReject": "N004",
"PositionX": 586,
"PositionY": 104,
"CompareOutcomes": [],
"Id": "N003"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Inform",
"Title": "Bilgilendirme1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "system@sozsoft.com",
"NextOnStart": "N005",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 458,
"PositionY": 411,
"CompareOutcomes": [],
"Id": "N004"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "End",
"Title": "\u0130\u015F Ak\u0131\u015F\u0131 Bitir1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 792,
"PositionY": 412,
"CompareOutcomes": [],
"Id": "N005"
}
]
},
"WorkflowCriteria": [
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Start",
"Title": "\u0130\u015F Ak\u0131\u015F\u0131 Ba\u015Flat1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "",
"NextOnStart": "N002",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 34,
"PositionY": 104,
"CompareOutcomes": [],
"Id": "N001"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Approval",
"Title": "Onay1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "admin@sozsoft.com",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "N003",
"NextOnReject": "N004",
"PositionX": 323,
"PositionY": 104,
"CompareOutcomes": [],
"Id": "N002"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Approval",
"Title": "Onay2",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "demo@sozsoft.com",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "N004",
"NextOnReject": "N004",
"PositionX": 586,
"PositionY": 104,
"CompareOutcomes": [],
"Id": "N003"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "Inform",
"Title": "Bilgilendirme1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "system@sozsoft.com",
"NextOnStart": "N005",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 458,
"PositionY": 411,
"CompareOutcomes": [],
"Id": "N004"
},
{
"ListFormCode": "App.Wizard.Approval",
"Kind": "End",
"Title": "\u0130\u015F Ak\u0131\u015F\u0131 Bitir1",
"CompareColumn": "Price",
"CompareOperator": "\u003E",
"CompareValue": 5000,
"Approver": "",
"NextOnStart": "",
"NextOnTrue": "",
"NextOnFalse": "",
"NextOnApprove": "",
"NextOnReject": "",
"PositionX": 792,
"PositionY": 412,
"CompareOutcomes": [],
"Id": "N005"
}
]
},
"IsDeletedField": false,
"IsCreatedField": false,
"IsDeletedField": true,
"IsCreatedField": true,
"InsertedRecords": {
"LanguageKeys": [
"App.Wizard.Approval",
"App.Wizard.Approval.Title",
"App.Wizard.Approval.Desc"
"App.Wizard.Approval.Desc",
"App.Listform.ListformField.ApprovalUserName",
"App.Listform.ListformField.ApprovalStatus",
"App.Listform.ListformField.ApprovalDate",
"App.Listform.ListformField.ApprovalDescription"
],
"PermissionGroupNames": [
"App.Wizard.Sales"
],
"PermissionGroupNames": [],
"PermissionNames": [
"App.Wizard.Approval",
"App.Wizard.Approval.Create",

View file

@ -1,281 +0,0 @@
{
"Wizard": {
"WizardName": "Todo",
"ListFormCode": "App.Wizard.Todo",
"MenuCode": "App.Wizard.Todo",
"IsTenant": true,
"IsBranch": false,
"IsOrganizationUnit": false,
"AllowAdding": true,
"AllowUpdating": true,
"AllowDeleting": true,
"AllowDetail": false,
"ConfirmDelete": true,
"DefaultLayout": "todo",
"Grid": true,
"Card": true,
"Pivot": true,
"Tree": true,
"Chart": true,
"Gantt": true,
"Scheduler": true,
"Todo": true,
"LanguageTextMenuEn": "Todo",
"LanguageTextMenuTr": "\u0130\u015Fler",
"LanguageTextTitleEn": "Todo",
"LanguageTextTitleTr": "\u0130\u015Fler",
"LanguageTextDescEn": "Todo",
"LanguageTextDescTr": "\u0130\u015Fler",
"LanguageTextMenuParentEn": "Project",
"LanguageTextMenuParentTr": "Project",
"PermissionGroupName": "App.Wizard.Project",
"MenuParentCode": "App.Wizard.Project",
"MenuParentShortName": "Pro",
"MenuParentIcon": "FcVideoProjector",
"MenuIcon": "FcTodoList",
"DataSourceCode": "Default",
"DataSourceConnectionString": "",
"SelectCommandType": 1,
"SelectCommand": "Pro_T_Todo",
"KeyFieldName": "Id",
"KeyFieldDbSourceType": 9,
"TreeKeyExpr": "",
"TreeParentIdExpr": "",
"TreeAutoExpandAll": false,
"GanttKeyExpr": "",
"GanttParentIdExpr": "",
"GanttAutoExpandAll": false,
"GanttTitleExpr": "",
"GanttStartExpr": "",
"GanttEndExpr": "",
"GanttProgressExpr": "",
"SchedulerTextExpr": "",
"SchedulerStartDateExpr": "",
"SchedulerEndDateExpr": "",
"TodoTitleExpr": "Title",
"TodoStatusExpr": "Status",
"TodoDescriptionExpr": "Description",
"TodoDueDateExpr": "DueDate",
"TodoTagExpr": "Tags",
"TodoAssigneeExpr": "Assignees",
"TodoPriorityExpr": "Priority",
"TodoCompletedExpr": "Completed",
"TodoOrderExpr": "SortOrder",
"TodoStatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging",
"TodoAllowDragging": true,
"ApprovalUserFieldName": "",
"ApprovalDateFieldName": "",
"ApprovalStatusFieldName": "",
"ApprovalDescriptionFieldName": "",
"ApprovalIsFilterUserName": false,
"Criteria": [],
"Groups": [
{
"Caption": "",
"ColCount": 1,
"Items": [
{
"FieldName": "Id",
"CaptionName": "App.Listform.ListformField.Id",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": true,
"IncludeInEditingForm": true,
"DbSourceType": 9,
"TurkishCaption": "Id",
"EnglishCaption": "Id",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Title",
"CaptionName": "App.Listform.ListformField.Title",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": true,
"IncludeInEditingForm": true,
"DbSourceType": 16,
"TurkishCaption": "Title",
"EnglishCaption": "Title",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Status",
"CaptionName": "App.Listform.ListformField.Status",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": true,
"IncludeInEditingForm": false,
"DbSourceType": 16,
"TurkishCaption": "Status",
"EnglishCaption": "Status",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Description",
"CaptionName": "App.Listform.ListformField.Description",
"EditorType": "dxHtmlEditor",
"EditorOptions": "{\u0022mediaResizing\u0022:{\u0022enabled\u0022:true},\u0022imageUpload\u0022:{\u0022tabs\u0022:[\u0022file\u0022,\u0022url\u0022],\u0022fileUploadMode\u0022:\u0022base64\u0022},\u0022toolbar\u0022:{\u0022multiline\u0022:true,\u0022items\u0022:[{\u0022name\u0022:\u0022undo\u0022},{\u0022name\u0022:\u0022redo\u0022},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022size\u0022,\u0022acceptedValues\u0022:[\u00228pt\u0022,\u002210pt\u0022,\u002212pt\u0022,\u002214pt\u0022,\u002218pt\u0022,\u002224pt\u0022,\u002236pt\u0022],\u0022options\u0022:{\u0022inputAttr\u0022:{\u0022aria-label\u0022:\u0022Font size\u0022}}},{\u0022name\u0022:\u0022font\u0022,\u0022acceptedValues\u0022:[\u0022Arial\u0022,\u0022Courier New\u0022,\u0022Georgia\u0022,\u0022Impact\u0022,\u0022Lucida Console\u0022,\u0022Tahoma\u0022,\u0022Times New Roman\u0022,\u0022Verdana\u0022],\u0022options\u0022:{\u0022inputAttr\u0022:{\u0022aria-label\u0022:\u0022Font family\u0022}}},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022bold\u0022},{\u0022name\u0022:\u0022italic\u0022},{\u0022name\u0022:\u0022strike\u0022},{\u0022name\u0022:\u0022underline\u0022},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022alignLeft\u0022},{\u0022name\u0022:\u0022alignCenter\u0022},{\u0022name\u0022:\u0022alignRight\u0022},{\u0022name\u0022:\u0022alignJustify\u0022},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022orderedList\u0022},{\u0022name\u0022:\u0022bulletList\u0022},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022header\u0022,\u0022acceptedValues\u0022:[false,1,2,3,4,5]},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022color\u0022},{\u0022name\u0022:\u0022background\u0022},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022link\u0022},{\u0022name\u0022:\u0022image\u0022},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022clear\u0022},{\u0022name\u0022:\u0022codeBlock\u0022},{\u0022name\u0022:\u0022blockquote\u0022},{\u0022name\u0022:\u0022separator\u0022},{\u0022name\u0022:\u0022insertTable\u0022},{\u0022name\u0022:\u0022deleteTable\u0022},{\u0022name\u0022:\u0022insertRowAbove\u0022},{\u0022name\u0022:\u0022insertRowBelow\u0022},{\u0022name\u0022:\u0022deleteRow\u0022},{\u0022name\u0022:\u0022insertColumnLeft\u0022},{\u0022name\u0022:\u0022insertColumnRight\u0022},{\u0022name\u0022:\u0022deleteColumn\u0022},{\u0022name\u0022:\u0022cellProperties\u0022},{\u0022name\u0022:\u0022tableProperties\u0022}]}}",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": false,
"IncludeInEditingForm": false,
"DbSourceType": 16,
"TurkishCaption": "Description",
"EnglishCaption": "Description",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "DueDate",
"CaptionName": "App.Listform.ListformField.DueDate",
"EditorType": "dxDateBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": false,
"IncludeInEditingForm": false,
"DbSourceType": 6,
"TurkishCaption": "Due Date",
"EnglishCaption": "Due Date",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Tags",
"CaptionName": "App.Listform.ListformField.Tags",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": false,
"IncludeInEditingForm": false,
"DbSourceType": 16,
"TurkishCaption": "Tags",
"EnglishCaption": "Tags",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Assignees",
"CaptionName": "App.Listform.ListformField.Assignees",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": false,
"IncludeInEditingForm": false,
"DbSourceType": 16,
"TurkishCaption": "Assignees",
"EnglishCaption": "Assignees",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Priority",
"CaptionName": "App.Listform.ListformField.Priority",
"EditorType": "dxTextBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": false,
"IncludeInEditingForm": false,
"DbSourceType": 16,
"TurkishCaption": "Priority",
"EnglishCaption": "Priority",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "Completed",
"CaptionName": "App.Listform.ListformField.Completed",
"EditorType": "dxCheckBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": true,
"IncludeInEditingForm": false,
"DbSourceType": 3,
"TurkishCaption": "Completed",
"EnglishCaption": "Completed",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
},
{
"FieldName": "SortOrder",
"CaptionName": "App.Listform.ListformField.SortOrder",
"EditorType": "dxNumberBox",
"EditorOptions": "",
"EditorScript": "",
"ColSpan": 1,
"IsRequired": true,
"IncludeInEditingForm": false,
"DbSourceType": 11,
"TurkishCaption": "Sort Order",
"EnglishCaption": "Sort Order",
"LookupDataSourceType": 1,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"LookupQuery": ""
}
]
}
],
"SubForms": [],
"Widgets": []
},
"IsDeletedField": false,
"IsCreatedField": false,
"InsertedRecords": {
"LanguageKeys": [
"App.Wizard.Todo",
"App.Wizard.Todo.Title",
"App.Wizard.Todo.Desc",
"App.Listform.ListformField.Assignees",
"App.Listform.ListformField.Completed",
"App.Listform.ListformField.SortOrder"
],
"PermissionGroupNames": [
"App.Wizard.Project"
],
"PermissionNames": [
"App.Wizard.Todo",
"App.Wizard.Todo.Create",
"App.Wizard.Todo.Update",
"App.Wizard.Todo.Delete",
"App.Wizard.Todo.Export",
"App.Wizard.Todo.Import",
"App.Wizard.Todo.Note"
],
"MenuCodes": [
"App.Wizard.Todo"
],
"DataSourceCodes": []
}
}

View file

@ -107,8 +107,6 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
var fileName = Path.GetFileName(filePath);
await BackfillMenuParentShortNameAsync(seedFile.Wizard);
// Zaten seeded mi kontrol et (ListForm var mı?)
if (await _repoListForm.AnyAsync(a => a.ListFormCode == seedFile.Wizard.ListFormCode))
{
@ -134,17 +132,14 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
var isCreated = seedFile.IsCreatedField;
input.SubForms ??= new List<SubFormDto>();
input.Widgets ??= new List<WidgetEditDto>();
input.Criteria ??= [];
EnsureUniqueWorkflowCriteriaTitles(input.Criteria);
var workflow = new WorkflowDto
input.Workflow ??= new WorkflowDto();
input.WorkflowCriteria ??= new List<ListFormWorkflowCriteriaDto>();
if (input.WorkflowCriteria.Count == 0 && input.Workflow.Criteria?.Count > 0)
{
ApprovalUserFieldName = input.ApprovalUserFieldName,
ApprovalIsFilterUserName = input.ApprovalIsFilterUserName,
ApprovalDateFieldName = input.ApprovalDateFieldName,
ApprovalStatusFieldName = input.ApprovalStatusFieldName,
ApprovalDescriptionFieldName = input.ApprovalDescriptionFieldName,
Criteria = input.Criteria,
};
input.WorkflowCriteria = input.Workflow.Criteria;
}
input.Workflow.Criteria = input.WorkflowCriteria;
EnsureUniqueWorkflowCriteriaTitles(input.WorkflowCriteria);
var wizardName = input.WizardName.Trim();
var code = string.IsNullOrWhiteSpace(input.MenuCode)
@ -153,7 +148,6 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
var listFormCode = string.IsNullOrWhiteSpace(input.ListFormCode)
? code
: input.ListFormCode.Trim();
NormalizeWorkflowCriteriaIds(listFormCode, input.Criteria);
var titleLangKey = $"{listFormCode}.Title";
var nameLangKey = code;
var descLangKey = $"{listFormCode}.Desc";
@ -255,7 +249,6 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
Code = input.MenuParentCode,
DisplayName = input.MenuParentCode,
IsDisabled = false,
ShortName = input.MenuParentShortName,
Icon = menuParentIcon,
Order = maxRootOrder + 1,
}, autoSave: true);
@ -305,9 +298,21 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
Caption = g.Caption,
ColCount = g.ColCount,
ColSpan = g.ColCount,
ItemType = "group"
ItemType = "group",
Items = g.Items
.Where(i => i.IncludeInEditingForm && i.DataField != input.KeyFieldName)
.Select((it, ii) => new EditingFormItemDto
{
Order = ii + 1,
DataField = it.DataField,
EditorType2 = it.EditorType,
ColSpan = it.ColSpan,
EditorOptions = string.IsNullOrWhiteSpace(it.EditorOptions) ? null : it.EditorOptions,
EditorScript = string.IsNullOrWhiteSpace(it.EditorScript) ? null : it.EditorScript,
})
.ToArray()
})
.Where((_, index) => input.Groups[index].Items.Any(i => i.IncludeInEditingForm && i.FieldName != input.KeyFieldName))
.Where(g => g.Items.Length > 0)
.ToList();
// ListForm - varsa sil, yeniden ekle
@ -332,8 +337,8 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
// EditingForm'da required olan alanları tespit et, ValidationRuleJson eklemek için
var editingFormFieldNames = input.Groups
.SelectMany(g => g.Items)
.Where(i => i.IncludeInEditingForm && i.FieldName != input.KeyFieldName)
.Select(i => new { FieldName = i.FieldName, Isrequired = i.IsRequired })
.Where(i => i.IncludeInEditingForm && i.DataField != input.KeyFieldName)
.Select(i => new { FieldName = i.DataField, Isrequired = i.IsRequired })
.ToList();
// Heigth ve Width hesaplama
@ -341,7 +346,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
.Select(g =>
{
var items = g.Items
.Where(i => i.IncludeInEditingForm && i.FieldName != input.KeyFieldName)
.Where(i => i.IncludeInEditingForm && i.DataField != input.KeyFieldName)
.ToList();
var columnCount = g.ColCount;
@ -386,8 +391,8 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
PageSize = 10,
ExportJson = WizardConsts.DefaultExportJson,
IsSubForm = false,
ShowNote = input.SubForms.Count > 0 || input.Criteria.Count > 0,
LayoutJson = WizardConsts.DefaultLayoutJson(input.DefaultLayout, input.Grid, input.Card, input.Pivot, input.Tree, input.Chart, input.Gantt, input.Scheduler, input.Todo),
ShowNote = input.SubForms.Count > 0 || input.WorkflowCriteria.Count > 0,
LayoutJson = WizardConsts.DefaultLayoutJson(input.DefaultLayout, input.Grid, input.Pivot, input.Tree, input.Chart, input.Gantt, input.Scheduler),
CultureName = LanguageCodes.En,
ListFormCode = input.ListFormCode,
Name = nameLangKey,
@ -407,74 +412,41 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
HeaderFilterJson = WizardConsts.DefaultHeaderFilterJson(),
SearchPanelJson = WizardConsts.DefaultSearchPanelJson(),
GroupPanelJson = WizardConsts.DefaultGroupPanelJson(),
SelectionJson = WizardConsts.DefaultSelectionSingleJson(input.Criteria.Count > 0 ? GridOptions.SelectionModeSingle : GridOptions.SelectionModeNone),
SelectionJson = WizardConsts.DefaultSelectionSingleJson(input.WorkflowCriteria.Count > 0 ? GridOptions.SelectionModeSingle : GridOptions.SelectionModeNone),
ColumnOptionJson = WizardConsts.DefaultColumnOptionJson(),
PermissionJson = WizardConsts.DefaultPermissionJson(code),
DeleteCommand = isDeleted ? WizardConsts.DefaultDeleteCommand(input.SelectCommand) : null,
DeleteFieldsDefaultValueJson = isDeleted
? WizardConsts.DefaultDeleteFieldsDefaultValueJson(input.KeyFieldDbSourceType)
: WizardConsts.DefaultDeleteFieldsJsonOnlyId(input.KeyFieldDbSourceType),
: WizardConsts.DefaultFieldsJsonOnlyId(input.KeyFieldDbSourceType),
InsertFieldsDefaultValueJson = isCreated
? WizardConsts.DefaultInsertFieldsDefaultValueJson(input.KeyFieldDbSourceType)
: WizardConsts.DefaultInsertFieldsJsonOnlyId(input.KeyFieldDbSourceType),
: WizardConsts.DefaultFieldsJsonOnlyId(input.KeyFieldDbSourceType),
PagerOptionJson = WizardConsts.DefaultPagerOptionJson,
EditingOptionJson = WizardConsts.DefaultEditingOptionJson(titleLangKey, formWidth, formHeight, input.AllowDeleting, input.AllowAdding, input.AllowUpdating, input.ConfirmDelete, false, input.AllowDetail),
EditingFormJson = editingFormDtos.Count > 0 ? JsonSerializer.Serialize(editingFormDtos) : null,
SubFormsJson = input.SubForms.Count > 0 ? JsonSerializer.Serialize(input.SubForms) : null,
WidgetsJson = input.Widgets.Count > 0 ? JsonSerializer.Serialize(input.Widgets) : null,
WorkflowJson = HasWorkflow(workflow, input.Criteria) ? JsonSerializer.Serialize(workflow) : null,
TodoOptionJson = (input.Todo || input.DefaultLayout == "todo") &&
!string.IsNullOrEmpty(input.TodoTitleExpr) &&
!string.IsNullOrEmpty(input.TodoStatusExpr)
? JsonSerializer.Serialize(new TodoOptionDto
{
TitleExpr = input.TodoTitleExpr,
StatusExpr = input.TodoStatusExpr,
DescriptionExpr = input.TodoDescriptionExpr,
DueDateExpr = input.TodoDueDateExpr,
TagExpr = input.TodoTagExpr,
AssigneeExpr = input.TodoAssigneeExpr,
PriorityExpr = input.TodoPriorityExpr,
CompletedExpr = input.TodoCompletedExpr,
OrderExpr = input.TodoOrderExpr,
StatusOrder = input.TodoStatusOrder,
AllowDragging = input.TodoAllowDragging,
})
: null,
WorkflowJson = HasWorkflow(input.Workflow, input.WorkflowCriteria) ? JsonSerializer.Serialize(input.Workflow) : null,
}, autoSave: true);
// ListFormFields
var fieldOrder = 0;
var editGroupOrder = 0;
foreach (var group in input.Groups)
{
editGroupOrder++;
var editOrder = 0;
foreach (var item in group.Items)
{
fieldOrder++;
if (item.IncludeInEditingForm && item.FieldName != input.KeyFieldName)
{
editOrder++;
}
await _repoListFormField.InsertAsync(new ListFormField
{
ListFormCode = input.ListFormCode,
FieldName = item.FieldName,
FieldName = item.DataField,
CaptionName = item.CaptionName,
Visible = item.FieldName != input.KeyFieldName,
Visible = item.DataField != input.KeyFieldName,
IsActive = true,
Width = 0, //Fit columns için hepsine sıfır veriyorum.
AllowSearch = true,
ListOrderNo = fieldOrder,
EditGroupOrderNo = item.IncludeInEditingForm ? editGroupOrder : null,
EditOrderNo = item.IncludeInEditingForm && item.FieldName != input.KeyFieldName
? editOrder
: null,
EditorType2 = item.EditorType,
ColSpan = item.ColSpan,
EditorOptions = string.IsNullOrWhiteSpace(item.EditorOptions) ? null : item.EditorOptions,
EditorScript = string.IsNullOrWhiteSpace(item.EditorScript) ? null : item.EditorScript,
SourceDbType = item.DbSourceType,
CultureName = PlatformConsts.DefaultLanguage,
PermissionJson = WizardConsts.DefaultFieldPermissionJson(code),
@ -484,7 +456,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
LookupJson = !string.IsNullOrWhiteSpace(item.LookupQuery)
? WizardConsts.DefaultLookupJson(item.LookupDataSourceType, item.DisplayExpr, item.ValueExpr, item.LookupQuery)
: null,
ValidationRuleJson = editingFormFieldNames.Any(f => f.FieldName == item.FieldName && f.Isrequired)
ValidationRuleJson = editingFormFieldNames.Any(f => f.FieldName == item.DataField && f.Isrequired)
? WizardConsts.DefaultValidationRuleRequiredJson
: null
}, autoSave: true);
@ -493,7 +465,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
}
}
foreach (var criteria in input.Criteria)
foreach (var criteria in input.WorkflowCriteria)
{
if (string.IsNullOrWhiteSpace(criteria.Id))
{
@ -522,24 +494,6 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
}
}
private async Task BackfillMenuParentShortNameAsync(ListFormWizardDto input)
{
if (string.IsNullOrWhiteSpace(input.MenuParentCode) ||
string.IsNullOrWhiteSpace(input.MenuParentShortName))
return;
var menuParent = await _repoMenu.FirstOrDefaultAsync(a => a.Code == input.MenuParentCode);
if (menuParent == null || !string.IsNullOrWhiteSpace(menuParent.ShortName))
return;
menuParent.ShortName = input.MenuParentShortName.Trim();
await _repoMenu.UpdateAsync(menuParent, autoSave: true);
_logger.LogInformation(
"Menu parent '{MenuParentCode}' ShortName backfilled as '{ShortName}'.",
input.MenuParentCode,
menuParent.ShortName);
}
private static bool HasWorkflow(WorkflowDto workflow, List<ListFormWorkflowCriteriaDto> criteria)
{
return workflow != null && (
@ -605,55 +559,6 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
return string.IsNullOrWhiteSpace(kind) ? "Step" : kind.Trim();
}
private static void NormalizeWorkflowCriteriaIds(string listFormCode, List<ListFormWorkflowCriteriaDto> 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;

View file

@ -63,7 +63,6 @@ public enum TableNameEnum
InstallmentOption,
Order,
OrderItem,
OrderItem_ByTenantId,
BlogCategory,
BlogPost,
Demo,
@ -95,5 +94,5 @@ public enum TableNameEnum
VideoroomAttandance,
VideoroomChat,
Sequence,
DbTableColumn,
DbTableColumn
}

View file

@ -36,7 +36,6 @@ public static class PlatformConsts
public static string CalcTotalHoursFromTimes = "(()=>{const toD=v=>!v?null:(v instanceof Date?v:new Date(v));const next={...formData,[e.dataField]:e.value};const s=toD(next.StartTime),t=toD(next.EndTime);let h=null;if(s&&t){h=(t-s)/36e5;if(h<0)h+=24;h=Math.round(h*10)/10;}setFormData({...next,TotalHours:h});})();";
public static string MaterialOnChange = "(() => { const p=e.component.option('selectedItem')||{}; const q=Math.round((parseFloat(p.Quantity)||0)*100); const u=Math.round((parseFloat(p.UnitPrice)||0)*100); setFormData({ ...formData, Quantity:q/100, UnitPrice:u/100, UomId:p.UomId, TotalAmount:Math.round((q*u)/100)/100 }); })();";
public static string CalcTotalAmount = "(() => { const n={...formData,[e.dataField]:e.value}; const q=Math.round((parseFloat(n.Quantity)||0)*100); const u=Math.round((parseFloat(n.UnitPrice)||0)*100); setFormData({ ...n, TotalAmount:Math.round((q*u)/100)/100 }); })();";
public static string SourceFieldItemWritetoDestination(string sourceField = "Township", string itemName = "Group", string destinationField = "PostalCode") => $"(async()=>{{const townshipField=\"{sourceField}\",groupField=\"{itemName}\",postalCodeField=\"{destinationField}\";const currentField=(typeof editor!=='undefined'&&editor?.dataField)||e?.dataField||townshipField;const next={{...formData,[currentField]:e?.value}};const isReady=e?.scriptEvent===\"contentReady\";const selectedItem=(()=>{{try{{return e?.component?.option?e.component.option(\"selectedItem\"):null;}}catch{{return null;}}}})();if(!isReady)next[postalCodeField]=selectedItem?selectedItem[groupField]:next[postalCodeField];if(!isReady&&typeof setFormData===\"function\")setFormData(next);}})();";
}
public static class Prefix
@ -71,6 +70,7 @@ public static class PlatformConsts
public const string Email = "Email";
public const string Website = "Website";
public const string MenuGroup = "MenuGroup";
public const string MaxConcurrentUsers = "MaxConcurrentUsers";
}
public static class Branches
@ -163,7 +163,6 @@ public static class PlatformConsts
public const string TenantIsPassive = GroupName + ".TenantIsPassive";
public const string LoginNotAllowed_WorkHour = GroupName + ".LoginNotAllowed_WorkHour";
public const string ConcurrentUserLimitError = GroupName + ".ConcurrentUserLimitError";
public const string BranchLimitError = GroupName + ".BranchLimitError";
public const string CaptchaWrongCode = GroupName + ".CaptchaWrongCode";
public const string TwoFactorWrongCode = GroupName + ".TwoFactorWrongCode";
public const string SignOut = GroupName + ".SignOut";
@ -550,7 +549,6 @@ public static class PlatformConsts
public static string LoginNotAllowed_TenantIsPassive { get; set; } = "UserCannotSignInTenantIsPassive";
public static string LoginNotAllowed_TenantNotFound { get; set; } = "UserCannotSignInTenantNotFound";
public static string LoginNotAllowed_WorkHour { get; set; } = "UserCannotSignInWorkHour";
public static string LoginNotAllowed_BranchLimit { get; set; } = "UserCannotSignInBranchLimit";
public static string LoginNotAllowed_ConcurrentUserLimit { get; set; } = "UserCannotSignInConcurrentUserLimit";
}
@ -758,7 +756,6 @@ public static class PlatformConsts
public const string dxDateBox = "dxDateBox";
public const string dxDateRangeBox = "dxDateRangeBox";
public const string dxDropDownBox = "dxDropDownBox";
public const string dxGridBox = "dxGridBox";
public const string dxHtmlEditor = "dxHtmlEditor";
public const string dxLookup = "dxHtmlEdidxLookuptor";
public const string dxNumberBox = "dxNumberBox";

View file

@ -116,6 +116,7 @@ public static class PlatformModuleExtensionConfigurator
tenantConfig.ConfigureTenant(entity =>
{
entity.AddOrUpdateProperty<bool>("IsActive");
entity.AddOrUpdateProperty<int?>("MaxConcurrentUsers");
});
});

View file

@ -59,7 +59,6 @@ public static class TableNameResolver
{ nameof(TableNameEnum.InstallmentOption), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.Order), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.OrderItem), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.OrderItem_ByTenantId), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.BlogCategory), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.BlogPost), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.Demo), (TablePrefix.PlatformByName, MenuPrefix.Saas) },

View file

@ -84,16 +84,14 @@ public static class WizardConsts
Margin = 10
});
public static string DefaultLayoutJson(string DefaultLayout = "grid", bool Grid = true, bool Card = true, bool Pivot = true, bool Chart = true, bool Tree = true, bool Gantt = true, bool Scheduler = true, bool Todo = true) => JsonSerializer.Serialize(new
public static string DefaultLayoutJson(string DefaultLayout = "grid", bool Grid = true, bool Pivot = true, bool Chart = true, bool Tree = true, bool Gantt = true, bool Scheduler = true) => JsonSerializer.Serialize(new
{
Grid = Grid,
Card = Card,
Pivot = Pivot,
Chart = Chart,
Tree = Tree,
Gantt = Gantt,
Scheduler = Scheduler,
Todo = Todo,
DefaultLayout = DefaultLayout,
});
@ -198,14 +196,6 @@ public static class WizardConsts
});
}
public static string DefaultInsertFieldsJsonOnlyId(DbType dbType = DbType.Guid)
{
return JsonSerializer.Serialize(new[]
{
new { FieldName = "Id", FieldDbType = dbType, Value = "@NEWID", CustomValueType = FieldCustomValueTypeEnum.CustomKey }
});
}
public static string DefaultDeleteFieldsDefaultValueJson(DbType dbType = DbType.Guid)
{
return JsonSerializer.Serialize(new[]
@ -215,11 +205,11 @@ public static class WizardConsts
});
}
public static string DefaultDeleteFieldsJsonOnlyId(DbType dbType = DbType.Guid)
public static string DefaultFieldsJsonOnlyId(DbType dbType = DbType.Guid)
{
return JsonSerializer.Serialize(new[]
{
new { FieldName = "Id", FieldDbType = dbType, Value = "@ID", CustomValueType = FieldCustomValueTypeEnum.CustomKey }
new { FieldName = "Id", FieldDbType = dbType, Value = "@NEWID", CustomValueType = FieldCustomValueTypeEnum.CustomKey }
});
}

View file

@ -416,8 +416,6 @@ public static class SeedConsts
public const string RecurringJobs = Default + ".RecurringJobs";
public const string Jobs = Default + ".Jobs";
}
public const string Licence = Prefix.App + ".Licence";
public const string LicenceItem = Prefix.App + ".LicenceItem";
//Web Site
public const string Home = Prefix.App + ".Home";

View file

@ -9,9 +9,6 @@ public class Country : FullAuditedEntity<string>
public string GroupName { get; set; }
public string Currency { get; set; }
public int PhoneCode { get; set; }
public int? PhoneNumberMinLength { get; set; }
public int? PhoneNumberMaxLength { get; set; }
public string? PhoneNumberFormat { get; set; }
public string TaxLabel { get; set; }
public bool ZipRequired { get; set; }
public bool StateRequired { get; set; }
@ -26,9 +23,6 @@ public class Country : FullAuditedEntity<string>
string groupName,
string currency,
int phoneCode,
int? phoneNumberMinLength,
int? phoneNumberMaxLength,
string? phoneNumberFormat,
string taxLabel,
bool zipRequired = false,
bool stateRequired = false)
@ -38,9 +32,6 @@ public class Country : FullAuditedEntity<string>
GroupName = groupName;
Currency = currency;
PhoneCode = phoneCode;
PhoneNumberMinLength = phoneNumberMinLength;
PhoneNumberMaxLength = phoneNumberMaxLength;
PhoneNumberFormat = phoneNumberFormat;
TaxLabel = taxLabel;
ZipRequired = zipRequired;
StateRequired = stateRequired;

View file

@ -9,18 +9,16 @@ public class District : FullAuditedEntity<Guid>
public string City { get; set; }
public string Name { get; set; }
public string Township { get; set; }
public string PostalCode { get; set; }
protected District() { }
public District(Guid id, string country, string city, string name, string township, string postalCode)
public District(Guid id, string country, string city, string name, string township)
: base(id)
{
Country = country;
City = city;
Name = name;
Township = township;
PostalCode = postalCode;
}
}

View file

@ -10,10 +10,6 @@ public class ForumPost : FullAuditedEntity<Guid>
public string Content { get; set; }
public Guid AuthorId { get; set; }
public string AuthorName { get; set; }
public string AuthorTitle { get; set; }
public string AuthorEmail { get; set; }
public string AuthorPhoneNumber { get; set; }
public string AuthorDepartment { get; set; }
public int? LikeCount { get; set; }
public bool? IsAcceptedAnswer { get; set; } = false;
public Guid? ParentPostId { get; set; }
@ -25,27 +21,12 @@ public class ForumPost : FullAuditedEntity<Guid>
protected ForumPost() { }
public ForumPost(
Guid id,
Guid topicId,
string content,
Guid authorId,
string authorName,
string authorTitle,
string authorEmail,
string authorPhoneNumber,
string authorDepartment,
Guid? parentPostId = null,
Guid? tenantId = null) : base(id)
public ForumPost(Guid id, Guid topicId, string content, Guid authorId, string authorName, Guid? parentPostId = null, Guid? tenantId = null) : base(id)
{
TopicId = topicId;
Content = content;
AuthorId = authorId;
AuthorName = authorName;
AuthorTitle = authorTitle;
AuthorEmail = authorEmail;
AuthorPhoneNumber = authorPhoneNumber;
AuthorDepartment = authorDepartment;
ParentPostId = parentPostId;
LikeCount = 0;
IsAcceptedAnswer = false;

View file

@ -12,10 +12,6 @@ public class ForumTopic : FullAuditedEntity<Guid>
public ForumCategory Category { get; set; }
public Guid AuthorId { get; set; }
public string AuthorName { get; set; }
public string AuthorTitle { get; set; }
public string AuthorEmail { get; set; }
public string AuthorPhoneNumber { get; set; }
public string AuthorDepartment { get; set; }
public int ViewCount { get; set; }
public int ReplyCount { get; set; }
public int LikeCount { get; set; }
@ -32,28 +28,13 @@ public class ForumTopic : FullAuditedEntity<Guid>
protected ForumTopic() { }
public ForumTopic(
Guid id,
string title,
string content,
Guid categoryId,
Guid authorId,
string authorName,
string authorTitle,
string authorEmail,
string authorPhoneNumber,
string authorDepartment,
Guid? tenantId = null) : base(id)
public ForumTopic(Guid id, string title, string content, Guid categoryId, Guid authorId, string authorName, Guid? tenantId = null) : base(id)
{
Title = title;
Content = content;
CategoryId = categoryId;
AuthorId = authorId;
AuthorName = authorName;
AuthorTitle = authorTitle;
AuthorEmail = authorEmail;
AuthorPhoneNumber = authorPhoneNumber;
AuthorDepartment = authorDepartment;
ViewCount = 0;
ReplyCount = 0;
LikeCount = 0;

View file

@ -9,17 +9,15 @@ public class CustomComponent : FullAuditedEntity<Guid>, IMultiTenant
public virtual Guid? TenantId { get; protected set; }
public string Name { get; set; } = string.Empty;
public string RoutePath { get; set; } = string.Empty;
public string Code { get; set; } = string.Empty;
public string? Props { get; set; }
public string? Description { get; set; }
public bool IsActive { get; set; } = true;
public string? Dependencies { get; set; } // JSON string of component names
public CustomComponent(string name, string routePath, string code, string? props, string? description, bool isActive, string? dependencies)
public CustomComponent(string name, string code, string? props, string? description, bool isActive, string? dependencies)
{
Name = name;
RoutePath = routePath;
Code = code;
Props = props;
Description = description;

View file

@ -5,7 +5,7 @@ using Volo.Abp.MultiTenancy;
namespace Sozsoft.Platform.Entities
{
public class ReportCategory : FullAuditedEntity<Guid>, IMultiTenant
public class ReportCategory : FullAuditedEntity<string>, IMultiTenant
{
public Guid? TenantId { get; set; }
@ -15,12 +15,9 @@ namespace Sozsoft.Platform.Entities
public ICollection<ReportTemplate> ReportTemplates { get; set; }
protected ReportCategory()
{
}
public ReportCategory(Guid id) : base(id)
public ReportCategory(string id)
{
Id = id;
}
}
}

View file

@ -12,7 +12,7 @@ namespace Sozsoft.Platform.Entities
public string Description { get; set; }
public string HtmlContent { get; set; }
public Guid CategoryId { get; set; }
public string CategoryId { get; set; }
public ReportCategory ReportCategory { get; set; }
public string Status { get; set; }
@ -23,7 +23,7 @@ namespace Sozsoft.Platform.Entities
string name,
string description,
string htmlContent,
Guid categoryId,
string categoryId,
string status
) : base(id)
{

View file

@ -6,18 +6,19 @@ namespace Sozsoft.Platform.Entities;
public class Order : FullAuditedEntity<Guid>
{
public Guid? TenantId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public string OrganizationName { get; set; }
public string Founder { get; set; }
public long? VknTckn { get; set; }
public string TaxOffice { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string District { get; set; }
public string Township { get; set; }
public string PostalCode { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string District { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
public string MobileNumber { get; set; }
public string PhoneNumber { get; set; }
public string FaxNumber { get; set; }
@ -25,38 +26,19 @@ public class Order : FullAuditedEntity<Guid>
public string Website { get; set; }
public string MenuGroup { get; set; }
public bool IsExisting { get; set; }
public bool IsActive { get; set; }
public string BillingCycle { get; set; }
public int Period { get; set; }
public DateTime? LicenseStartTime { get; set; }
public DateTime? LicenseEndTime { get; set; }
public List<OrderItem> Items { get; set; } = new();
public decimal Subtotal { get; set; }
public decimal VatTotal { get; set; }
public decimal Commission { get; set; }
public decimal Total { get; set; }
public Guid PaymentMethodId { get; set; }
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<OrderItem> Items { get; set; } = new();
public Order()
{
}
public Order(Guid id)
: base(id)
{
}
}
public class OrderItem : FullAuditedEntity<Guid>
@ -66,11 +48,7 @@ public class OrderItem : FullAuditedEntity<Guid>
public Guid ProductId { get; set; }
public string ProductName { get; set; }
public string BillingCycle { get; set; }
public int Period { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal VatRate { get; set; }
public decimal VatAmount { get; set; }
public decimal TotalPrice { get; set; }
public OrderItem()

View file

@ -11,7 +11,6 @@ public class Product : FullAuditedEntity<Guid>
public int Order { get; set; }
public decimal? MonthlyPrice { get; set; }
public decimal? YearlyPrice { get; set; }
public decimal VatRate { get; set; } = 0.20m;
public bool IsQuantityBased { get; set; } = false;
public string ImageUrl { get; set; }
}

View file

@ -36,7 +36,6 @@ public class ListForm : Entity<Guid>
public string TreeOptionJson { get; set; } // Tree yapisi ile ilgili ayarlar
public string GanttOptionJson { get; set; } // Gantt yapisi ile ilgili ayarlar
public string SchedulerOptionJson { get; set; } // Scheduler yapisi ile ilgili ayarlar
public string TodoOptionJson { get; set; } // Todo board alan esleme ayarlari
public string FilterRowJson { get; set; } // Filtre ayarlari, Json olarak tutulur, donus sinifi FilterRowDto
public string RowJson { get; set; } // Row ayarları, Json olarak tutulur, donus sinifi FilterRowDto
public string HeaderFilterJson { get; set; } // Header filtreleme ayarlari, Json olarak tutulur

View file

@ -53,13 +53,7 @@ public class ListFormField : Entity<Guid>
public string Alignment { get; set; } = "left"; // Sütunun Sağa, sola veya ortalama gösterimi
public string Format { get; set; } // Cell bazında sütunun formatlanması
public int? EditOrderNo { get; set; }
public int? EditGroupOrderNo { get; set; }
public string EditorType2 { get; set; }
public int? ColSpan { get; set; }
public string EditorScript { get; set; } //Sütunun ekstra javascript ile yönetilmesi
public string EditorOptions { get; set; } //Sütunun ekstra özellikleri yönetilmesi
public string EditorOptions { get; set; } //Sütunun ekstra özellikleri yönetilmesi
}

View file

@ -20,9 +20,9 @@ public static class AbpPermissionsExtensions
// 🔹 Gereksiz boşlukları temizle
var cleaned = string.Join(
"|",
'|',
menuGroup
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Distinct()
);
@ -44,7 +44,7 @@ public static class AbpPermissionsExtensions
// 🔹 "Erp|Kurs" -> ["Erp", "Kurs"]
return value
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Distinct()
.ToArray();
}

View file

@ -165,5 +165,14 @@ public static class AbpTenantExtensions
{
return tenant.GetProperty<string>(PlatformConsts.Tenants.MenuGroup);
}
public static void SetMaxConcurrentUsers(this Tenant tenant, int? maxConcurrentUsers)
{
tenant.SetProperty(PlatformConsts.Tenants.MaxConcurrentUsers, maxConcurrentUsers.HasValue ? (object)maxConcurrentUsers.Value : null);
}
public static int? GetMaxConcurrentUsers(this Tenant tenant)
{
return tenant.GetProperty<int?>(PlatformConsts.Tenants.MaxConcurrentUsers);
}
}

View file

@ -30,8 +30,6 @@ public class PlatformSignInResult : SignInResult
public bool IsNotAllowed_WorkHour { get; set; }
public bool IsNotAllowed_BranchLimit { get; set; }
public bool IsNotAllowed_ConcurrentUserLimit { get; set; }
public override string ToString()
@ -44,7 +42,6 @@ public class PlatformSignInResult : SignInResult
ShouldChangePasswordPeriodic ? "ShouldChangePasswordPeriodic" :
IsNotAllowed_TenantIsPassive ? "NotAllowed_TenantIsPassive" :
IsNotAllowed_WorkHour ? "NotAllowed_WorkHour" :
IsNotAllowed_BranchLimit ? "NotAllowed_BranchLimit" :
IsNotAllowed_ConcurrentUserLimit ? "NotAllowed_ConcurrentUserLimit" :
base.ToString();
}

View file

@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Volo.Abp.Domain.Values;
namespace Sozsoft.Platform.Queries;
// public class EditingForm : ValueObject
// {
// public int Order { get; set; }
// public string ItemType { get; set; }
// public string Caption { get; set; }
// public int ColCount { get; set; }
// public int ColSpan { get; set; }
// /// <summary> Type: Array<Simple Form Item | Group Form Item | Tabbed Form Item | Empty Form Item | Button Form Item>
// /// Bu kisma suan sadece string olarak doldurulacak
// /// items: ['FirstName', 'LastName',
// /// { dataField: 'Notes', editorType: 'dxTextArea', colSpan: 2, editorOptions: { height: 100, }, }
// /// ],
// /// </summary>
// //[TextArea]
// //public string[] Items { get; set; }
// public EditingFormItem[] Items { get; set; }
// protected override IEnumerable<object> GetAtomicValues()
// {
// yield return ItemType;
// yield return Caption;
// yield return ColCount;
// yield return ColSpan;
// yield return Items;
// }
// }
// public class EditingFormItem : ValueObject
// {
// [JsonPropertyName("order")]
// public int Order { get; set; }
// [JsonPropertyName("dataField")]
// public string DataField { get; set; }
// [JsonPropertyName("editorType2")]
// public string EditorType2 { get; set; }
// [JsonPropertyName("colSpan")]
// public int ColSpan { get; set; }
// [JsonPropertyName("editorOptions")]
// public string EditorOptions { get; set; }
// [JsonPropertyName("isRequired")]
// public bool IsRequired { get; set; }
// protected override IEnumerable<object> GetAtomicValues()
// {
// yield return DataField;
// yield return EditorType2;
// yield return ColSpan;
// yield return EditorOptions;
// yield return IsRequired;
// }
// }

View file

@ -52,9 +52,7 @@ public class QueryHelper
case DbType.String:
case DbType.AnsiString:
var strValues = values.Select(a => a?.ToString()).ToArray();
value = isArray
? string.Join(PlatformConsts.MultiValueDelimiter, strValues)
: strValues[0];
value = string.Join(PlatformConsts.MultiValueDelimiter, strValues);
break;
case DbType.Date:
case DbType.DateTime:

View file

@ -170,8 +170,7 @@ public class QueryManager : PlatformDomainService, IQueryManager
// oncelik Command alanindadir, dolu ise silme islemi buradaki sorguya yonlendirilir
if (!string.IsNullOrEmpty(command))
{
// sql = NormalizeCollectionParameterCommand(command, parameters, dataSourceType);
sql = command;
sql = NormalizeCollectionParameterCommand(command, parameters, dataSourceType);
}
else
{
@ -189,6 +188,12 @@ public class QueryManager : PlatformDomainService, IQueryManager
}
else if (op == OperationEnum.Update)
{
var where = dataSourceType switch
{
DataSourceTypeEnum.Mssql => $"\"{listForm.KeyFieldName}\" IN @{listForm.KeyFieldName}",
DataSourceTypeEnum.Postgresql => $"\"{listForm.KeyFieldName}\" = ANY(@{listForm.KeyFieldName})",
_ => string.Empty,
};
var updateFields = parameters.Select(a => $"\"{a.Key}\" = @{a.Key}").ToList();
var val = QueryHelper.GetFormattedValue(listForm.KeyFieldDbSourceType, keys);
if (!parameters.ContainsKey(listForm.KeyFieldName))
@ -197,18 +202,6 @@ public class QueryManager : PlatformDomainService, IQueryManager
listForm.KeyFieldName,
val.GetType().IsArray ? val : new object[] { val });
}
var where = BuildWhereCondition(
listForm.KeyFieldName,
parameters[listForm.KeyFieldName],
dataSourceType);
if (parameters.TryGetValue("TenantId", out var tenantId)
&& !string.Equals(listForm.KeyFieldName, "TenantId", StringComparison.OrdinalIgnoreCase))
{
where += $" AND {BuildWhereCondition("TenantId", tenantId, dataSourceType)}";
}
sql = $"UPDATE \"{listForm.SelectCommand}\" SET {string.Join(',', updateFields)} WHERE {where}";
}
else if (op == OperationEnum.Delete)
@ -219,7 +212,12 @@ public class QueryManager : PlatformDomainService, IQueryManager
{
where = string.Join(
" AND ",
parameters.Select(a => BuildWhereCondition(a.Key, a.Value, dataSourceType)).ToList());
parameters.Select(a => dataSourceType switch
{
DataSourceTypeEnum.Mssql => $"\"{a.Key}\" IN @{a.Key}",
DataSourceTypeEnum.Postgresql => $"\"{a.Key}\" = ANY(@{a.Key})",
_ => "1 = 0",
}).ToList());
}
else
{
@ -242,101 +240,77 @@ public class QueryManager : PlatformDomainService, IQueryManager
return sql;
}
private static bool IsCollectionValue(object value)
private static string NormalizeCollectionParameterCommand(
string command,
Dictionary<string, object> parameters,
DataSourceTypeEnum dataSourceType)
{
if (string.IsNullOrWhiteSpace(command) || parameters == null || parameters.Count == 0)
{
return command;
}
var sql = command;
foreach (var parameter in parameters)
{
if (!IsCollectionParameter(parameter.Value))
{
continue;
}
var escapedParameterName = Regex.Escape(parameter.Key);
sql = dataSourceType switch
{
DataSourceTypeEnum.Mssql => NormalizeMssqlCollectionParameter(sql, escapedParameterName, parameter.Key),
DataSourceTypeEnum.Postgresql => NormalizePostgresqlCollectionParameter(sql, escapedParameterName, parameter.Key),
_ => sql
};
}
return sql;
}
private static bool IsCollectionParameter(object value)
{
return value is System.Collections.IEnumerable
&& value is not string
&& value is not byte[];
}
private static string BuildWhereCondition(
string fieldName,
object value,
DataSourceTypeEnum dataSourceType)
private static string NormalizeMssqlCollectionParameter(
string sql,
string escapedParameterName,
string parameterName)
{
return dataSourceType switch
{
DataSourceTypeEnum.Mssql when value is null or DBNull => $"\"{fieldName}\" IS NULL",
DataSourceTypeEnum.Postgresql when value is null or DBNull => $"\"{fieldName}\" IS NULL",
DataSourceTypeEnum.Mssql when IsCollectionValue(value) => $"\"{fieldName}\" IN @{fieldName}",
DataSourceTypeEnum.Postgresql when IsCollectionValue(value) => $"\"{fieldName}\" = ANY(@{fieldName})",
DataSourceTypeEnum.Mssql => $"\"{fieldName}\" = @{fieldName}",
DataSourceTypeEnum.Postgresql => $"\"{fieldName}\" = @{fieldName}",
_ => "1 = 0",
};
sql = Regex.Replace(
sql,
$@"IN\s*\(\s*@{escapedParameterName}\s*\)",
$"IN @{parameterName}",
RegexOptions.IgnoreCase);
return Regex.Replace(
sql,
$@"(?<column>(""[^""]+""|\[[^\]]+\]|`[^`]+`|\w+))\s*=\s*@{escapedParameterName}\b",
match => $"{match.Groups["column"].Value} IN @{parameterName}",
RegexOptions.IgnoreCase);
}
// private static string NormalizeCollectionParameterCommand(
// string command,
// Dictionary<string, object> parameters,
// DataSourceTypeEnum dataSourceType)
// {
// if (string.IsNullOrWhiteSpace(command) || parameters == null || parameters.Count == 0)
// {
// return command;
// }
private static string NormalizePostgresqlCollectionParameter(
string sql,
string escapedParameterName,
string parameterName)
{
sql = Regex.Replace(
sql,
$@"IN\s*\(\s*@{escapedParameterName}\s*\)",
$"= ANY(@{parameterName})",
RegexOptions.IgnoreCase);
// var sql = command;
// foreach (var parameter in parameters)
// {
// if (!IsCollectionParameter(parameter.Value))
// {
// continue;
// }
// var escapedParameterName = Regex.Escape(parameter.Key);
// sql = dataSourceType switch
// {
// DataSourceTypeEnum.Mssql => NormalizeMssqlCollectionParameter(sql, escapedParameterName, parameter.Key),
// DataSourceTypeEnum.Postgresql => NormalizePostgresqlCollectionParameter(sql, escapedParameterName, parameter.Key),
// _ => sql
// };
// }
// return sql;
// }
// private static bool IsCollectionParameter(object value)
// {
// return value is System.Collections.IEnumerable
// && value is not string
// && value is not byte[];
// }
// private static string NormalizeMssqlCollectionParameter(
// string sql,
// string escapedParameterName,
// string parameterName)
// {
// sql = Regex.Replace(
// sql,
// $@"IN\s*\(\s*@{escapedParameterName}\s*\)",
// $"IN @{parameterName}",
// RegexOptions.IgnoreCase);
// return Regex.Replace(
// sql,
// $@"(?<column>(""[^""]+""|\[[^\]]+\]|`[^`]+`|\w+))\s*=\s*@{escapedParameterName}\b",
// match => $"{match.Groups["column"].Value} IN @{parameterName}",
// RegexOptions.IgnoreCase);
// }
// private static string NormalizePostgresqlCollectionParameter(
// string sql,
// string escapedParameterName,
// string parameterName)
// {
// sql = Regex.Replace(
// sql,
// $@"IN\s*\(\s*@{escapedParameterName}\s*\)",
// $"= ANY(@{parameterName})",
// RegexOptions.IgnoreCase);
// return Regex.Replace(
// sql,
// $@"(?<column>(""[^""]+""|\[[^\]]+\]|`[^`]+`|\w+))\s*=\s*@{escapedParameterName}\b",
// match => $"{match.Groups["column"].Value} = ANY(@{parameterName})",
// RegexOptions.IgnoreCase);
// }
return Regex.Replace(
sql,
$@"(?<column>(""[^""]+""|\[[^\]]+\]|`[^`]+`|\w+))\s*=\s*@{escapedParameterName}\b",
match => $"{match.Groups["column"].Value} = ANY(@{parameterName})",
RegexOptions.IgnoreCase);
}
}

View file

@ -4,7 +4,6 @@ using System.Data;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Sozsoft.Platform.Entities;
using Sozsoft.Platform.Enums;
using Sozsoft.Platform.Extensions;
@ -33,11 +32,11 @@ public interface ISelectQueryManager
List<string> SummaryQueries { get; }
public bool IsAppliedGridFilter { get; }
public bool IsAppliedServerFilter { get; }
Task PrepareQueriesAsync(ListForm listform,
List<ListFormField> listFormFields,
DataSourceTypeEnum dataSourceType,
List<ListFormCustomization> listFormCustomizations = null,
QueryParameters queryParams = null);
void PrepareQueries(ListForm listform,
List<ListFormField> listFormFields,
DataSourceTypeEnum dataSourceType,
List<ListFormCustomization> listFormCustomizations = null,
QueryParameters queryParams = null);
}
public class SelectField
@ -130,11 +129,11 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
DefaultValueHelper = defaultValueHelper;
}
public async Task PrepareQueriesAsync(ListForm listform,
List<ListFormField> listFormFields,
DataSourceTypeEnum dataSourceType,
List<ListFormCustomization> listFormCustomizations = null,
QueryParameters queryParams = null)
public void PrepareQueries(ListForm listform,
List<ListFormField> listFormFields,
DataSourceTypeEnum dataSourceType,
List<ListFormCustomization> listFormCustomizations = null,
QueryParameters queryParams = null)
{
ResetQueryState();
@ -171,7 +170,7 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
var joinParts = SelectFields.Where(c => !string.IsNullOrEmpty(c.JoinSql)).Select(c => c.JoinSql).Distinct();
JoinParts.AddRange(joinParts);
List<string> whereFields = await GetWhereFieldsAsync(listform, listFormFields, queryParams);
List<string> whereFields = GetWhereFields(listform, listFormFields, queryParams);
WhereParts.AddRange(whereFields);
List<string> sortFields = GetSortFields(listform, listFormFields, queryParams?.Sort);
@ -344,7 +343,7 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
}
}
private async Task<List<string>> GetWhereFieldsAsync(ListForm listform, List<ListFormField> listFormFields, QueryParameters queryParams = null)
private List<string> GetWhereFields(ListForm listform, List<ListFormField> listFormFields, QueryParameters queryParams = null)
{
var whereParts = new List<string>();
@ -437,7 +436,7 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
whereParts.Add("AND");
}
var ids = await BranchUsersRepository.GetListAsync((a) => a.UserId == CurrentUser.Id.Value);
var ids = BranchUsersRepository.GetListAsync((a) => a.UserId == CurrentUser.Id.Value).Result;
if (ids.Count > 0)
{
whereParts.Add($"\"BranchId\" IN ({string.Join(",", ids.Select(a => $"'{a.BranchId}'"))})");
@ -455,7 +454,7 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
whereParts.Add("AND");
}
var ids = await OuRepository.GetOrganizationUnitIdsWithChildren(CurrentUser.Id.Value);
var ids = OuRepository.GetOrganizationUnitIdsWithChildren(CurrentUser.Id.Value).Result;
if (ids.Count > 0)
{
whereParts.Add($"\"OrganizationUnitId\" IN ({string.Join(",", ids.Select(a => $"'{a}'"))})");
@ -469,7 +468,7 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
if (listform.WorkflowJson.IsNullOrWhiteSpace() == false)
{
var workflow = JsonSerializer.Deserialize<Workflow>(listform.WorkflowJson);
if (workflow != null && workflow.ApprovalIsFilterUserName)
if (workflow != null && workflow.IsFilterUserName)
{
if (whereParts.Any())
{
@ -480,7 +479,11 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
// hem de ApprovalUserFieldName alanı CurrentUserName'e eşit olan kayıtları getirmek istiyoruz,
// Boş olanları getirmemizin sebebi workflow start edebilmektir.
// İlk kayıt eklenince onaylayacak kişi atanmaz, böylece o kayıt onaysız olarak kalmaz ve workflow başlatılabilir olur.
whereParts.Add(GetWorkflowApproverFilter(workflow.ApprovalUserFieldName));
whereParts.Add(
$"(\"{workflow.ApprovalUserFieldName}\" = '{CurrentUser.UserName}' " +
$"OR \"{workflow.ApprovalUserFieldName}\" IS NULL " +
$"OR \"{workflow.ApprovalUserFieldName}\" = '')"
);
}
}
@ -492,38 +495,6 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
return whereParts;
}
private string GetWorkflowApproverFilter(string approvalUserFieldName)
{
if (approvalUserFieldName.IsNullOrWhiteSpace())
{
return "1 = 1";
}
var field = $"\"{approvalUserFieldName}\"";
var identities = new[] { CurrentUser.UserName, CurrentUser.Email, CurrentUser.Name }
.Where(identity => !identity.IsNullOrWhiteSpace())
.Select(EscapeSqlLiteral)
.Distinct()
.ToList();
if (identities.Count == 0)
{
return $"({field} IS NULL OR {field} = '')";
}
var identityList = string.Join(",", identities.Select(identity => $"'{identity}'"));
var approverMatch = DataSourceType == DataSourceTypeEnum.Postgresql
? $"EXISTS (SELECT 1 FROM unnest(string_to_array(CAST({field} AS TEXT), '{PlatformConsts.MultiValueDelimiter}')) AS split(value) WHERE btrim(split.value) IN ({identityList}))"
: $"EXISTS (SELECT 1 FROM STRING_SPLIT(CAST({field} AS NVARCHAR(MAX)), N'{PlatformConsts.MultiValueDelimiter}') AS split WHERE LTRIM(RTRIM(split.value)) IN ({identityList}))";
return $"({approverMatch} OR {field} IS NULL OR {field} = '')";
}
private static string EscapeSqlLiteral(string value)
{
return (value ?? string.Empty).Replace("'", "''");
}
/// <summary> FieldName operator Id seklinde olan filtreleri ayirir
/// </summary>
/// <param name="filter"></param>
@ -858,7 +829,8 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
}
else
{
argumentExpression = string.Join(PlatformConsts.MultiValueDelimiter, argumentFields.Select(f => $"[{f}]"));
// Birden fazla → '|' ile birleştir
argumentExpression = string.Join(" + '|' + ", argumentFields.Select(f => $"[{f}]"));
}
// Select sütunlarını oluştur

View file

@ -6,18 +6,18 @@ namespace Sozsoft.Platform.Queries;
public class Workflow : ValueObject
{
public string ApprovalUserFieldName { get; set; }
public bool IsFilterUserName { get; set; }
public string ApprovalDateFieldName { get; set; }
public string ApprovalStatusFieldName { get; set; }
public string ApprovalDescriptionFieldName { get; set; }
public bool ApprovalIsFilterUserName { get; set; }
protected override IEnumerable<object> GetAtomicValues()
{
yield return ApprovalUserFieldName;
yield return IsFilterUserName;
yield return ApprovalDateFieldName;
yield return ApprovalStatusFieldName;
yield return ApprovalDescriptionFieldName;
yield return ApprovalIsFilterUserName;
}
}

View file

@ -378,7 +378,6 @@ public class PlatformDbContext :
b.Property(a => a.WorkflowJson).HasColumnType("text");
b.Property(a => a.ExtraFilterJson).HasColumnType("text");
b.Property(a => a.LayoutJson).HasColumnType("text");
b.Property(a => a.TodoOptionJson).HasColumnType("text");
b.Property(a => a.CommonJson).HasColumnType("text");
b.Property(a => a.DataSourceJson).HasColumnType("text");
b.Property(a => a.AdaptiveLayoutJson).HasColumnType("text");
@ -407,7 +406,6 @@ public class PlatformDbContext :
b.HasMany<ListFormField>().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired();
b.HasMany<ListFormCustomization>().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired();
b.HasMany<ListFormImport>().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired();
b.HasMany<ListFormWorkflow>().WithOne().HasForeignKey(x => x.ListFormCode).HasPrincipalKey(x => x.ListFormCode).IsRequired();
});
builder.Entity<ListFormField>(b =>
@ -455,8 +453,6 @@ public class PlatformDbContext :
b.Property(a => a.Alignment).HasMaxLength(20).HasDefaultValue("left");
b.Property(a => a.Format).HasMaxLength(128);
b.Property(a => a.EditorOptions).HasColumnType("text");
b.Property(a => a.EditorType2).HasMaxLength(64);
b.Property(a => a.EditorScript).HasColumnType("text");
b.HasIndex(x => new { x.ListFormCode, x.UserId, x.RoleId, x.CultureName, x.FieldName }).IsUnique().HasFilter(null);
});
@ -502,7 +498,7 @@ public class PlatformDbContext :
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ListFormWorkflow)), Prefix.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.Id).HasMaxLength(128);
b.Property(x => x.Id).HasMaxLength(50);
b.Property(x => x.ListFormCode).IsRequired().HasMaxLength(64);
b.Property(x => x.Kind).IsRequired().HasMaxLength(50);
b.Property(x => x.Title).IsRequired().HasMaxLength(250);
@ -510,14 +506,15 @@ 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(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.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.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<Note>(b =>
@ -576,10 +573,6 @@ public class PlatformDbContext :
b.Property(x => x.Title).IsRequired().HasMaxLength(256);
b.Property(x => x.Content).IsRequired();
b.Property(x => x.AuthorName).HasMaxLength(128);
b.Property(x => x.AuthorTitle).HasMaxLength(128);
b.Property(x => x.AuthorEmail).HasMaxLength(256);
b.Property(x => x.AuthorPhoneNumber).HasMaxLength(32);
b.Property(x => x.AuthorDepartment).HasMaxLength(128);
b.Property(x => x.LastPostUserName).HasMaxLength(128);
b.HasMany(x => x.Posts)
@ -595,10 +588,6 @@ public class PlatformDbContext :
b.Property(x => x.Content).IsRequired();
b.Property(x => x.AuthorName).HasMaxLength(128);
b.Property(x => x.AuthorTitle).HasMaxLength(128);
b.Property(x => x.AuthorEmail).HasMaxLength(256);
b.Property(x => x.AuthorPhoneNumber).HasMaxLength(32);
b.Property(x => x.AuthorDepartment).HasMaxLength(128);
b.HasOne(x => x.Topic)
.WithMany(x => x.Posts)
@ -648,14 +637,12 @@ public class PlatformDbContext :
b.ConfigureByConvention();
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
b.Property(x => x.RoutePath).IsRequired().HasMaxLength(512);
b.Property(x => x.Code).IsRequired();
b.Property(x => x.Props).HasMaxLength(1024);
b.Property(x => x.Description).HasMaxLength(512);
b.Property(x => x.Dependencies).HasMaxLength(2048);
b.HasIndex(x => new { x.TenantId, x.Name }).IsUnique().HasFilter("[IsDeleted] = 0");
b.HasIndex(x => new { x.TenantId, x.RoutePath }).IsUnique().HasFilter("[IsDeleted] = 0");
});
builder.Entity<ReportCategory>(b =>
@ -663,6 +650,7 @@ public class PlatformDbContext :
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ReportCategory)), Prefix.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.Id).HasMaxLength(256);
b.Property(x => x.Name).IsRequired().HasMaxLength(256);
b.Property(x => x.Description).HasMaxLength(4096); // JSON string
b.Property(x => x.Icon).HasMaxLength(64);
@ -676,6 +664,7 @@ public class PlatformDbContext :
b.ConfigureByConvention();
b.Property(x => x.Name).IsRequired().HasMaxLength(256);
b.Property(x => x.CategoryId).HasMaxLength(256);
b.Property(x => x.Description).HasMaxLength(1024);
b.Property(x => x.HtmlContent).IsRequired();
b.Property(x => x.Status).HasMaxLength(20);
@ -758,9 +747,6 @@ public class PlatformDbContext :
b.Property(x => x.GroupName).HasMaxLength(128);
b.Property(x => x.TaxLabel).HasMaxLength(64);
b.Property(x => x.Currency).IsRequired().HasMaxLength(8);
b.Property(x => x.PhoneNumberMinLength).HasDefaultValue(0);
b.Property(x => x.PhoneNumberMaxLength).HasDefaultValue(0);
b.Property(x => x.PhoneNumberFormat).HasMaxLength(64);
b.HasIndex(x => new { x.Name }).IsUnique().HasFilter("[IsDeleted] = 0");
@ -991,7 +977,6 @@ public class PlatformDbContext :
b.Property(x => x.Category).IsRequired().HasMaxLength(64);
b.Property(x => x.MonthlyPrice).HasPrecision(18, 2);
b.Property(x => x.YearlyPrice).HasPrecision(18, 2);
b.Property(x => x.VatRate).IsRequired().HasPrecision(5, 3).HasDefaultValue(0.20m);
b.Property(x => x.ImageUrl).HasMaxLength(512);
b.HasIndex(x => new { x.Name }).IsUnique().HasFilter("[IsDeleted] = 0");
@ -1025,43 +1010,29 @@ public class PlatformDbContext :
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.Order)), Prefix.DbSchema);
b.ConfigureByConvention();
var isActiveComputedColumnSql = _isPostgreSql
? "CASE WHEN \"LicenseEndTime\" IS NOT NULL AND CURRENT_DATE > \"LicenseEndTime\"::date THEN false ELSE true END"
: "CONVERT(bit, CASE WHEN [LicenseEndTime] IS NOT NULL AND CONVERT(date, GETDATE()) > CONVERT(date, [LicenseEndTime]) THEN 0 ELSE 1 END)";
b.Property(o => o.IsActive)
.HasComputedColumnSql(isActiveComputedColumnSql, stored: false);
b.Property(o => o.IsExisting).IsRequired().HasDefaultValue(false);
b.Property(o => o.Name).HasMaxLength(64);
b.Property(o => o.OrganizationName).HasMaxLength(128);
b.Property(o => o.Founder).HasMaxLength(128);
b.Property(o => o.TaxOffice).HasMaxLength(128);
b.Property(o => o.Country).HasMaxLength(128);
b.Property(o => o.City).HasMaxLength(128);
b.Property(o => o.District).HasMaxLength(128);
b.Property(o => o.Township).HasMaxLength(128);
b.Property(o => o.PostalCode).HasMaxLength(16);
b.Property(o => o.Address1).HasMaxLength(512);
b.Property(o => o.Address2).HasMaxLength(512);
b.Property(o => o.District).HasMaxLength(128);
b.Property(o => o.Country).HasMaxLength(128);
b.Property(o => o.City).HasMaxLength(128);
b.Property(o => o.PostalCode).HasMaxLength(16);
b.Property(o => o.MobileNumber).HasMaxLength(20);
b.Property(o => o.PhoneNumber).HasMaxLength(20);
b.Property(o => o.FaxNumber).HasMaxLength(20);
b.Property(o => o.Email).HasMaxLength(128);
b.Property(o => o.Website).HasMaxLength(128);
b.Property(o => o.MenuGroup).HasMaxLength(64);
b.Property(o => o.BillingCycle).HasMaxLength(32);
b.Property(o => o.Period).IsRequired().HasDefaultValue(1);
b.Property(o => o.Subtotal).IsRequired().HasPrecision(18, 2);
b.Property(o => o.VatTotal).IsRequired().HasPrecision(18, 2);
b.Property(o => o.Commission).IsRequired().HasPrecision(18, 2);
b.Property(o => o.Total).IsRequired().HasPrecision(18, 2);
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)
@ -1075,10 +1046,6 @@ public class PlatformDbContext :
b.Property(i => i.ProductName).IsRequired().HasMaxLength(128);
b.Property(i => i.BillingCycle).IsRequired().HasMaxLength(32);
b.Property(i => i.Period).IsRequired().HasDefaultValue(1);
b.Property(i => i.Price).IsRequired().HasPrecision(18, 2);
b.Property(i => i.VatRate).IsRequired().HasPrecision(5, 3);
b.Property(i => i.VatAmount).IsRequired().HasPrecision(18, 2);
b.Property(i => i.TotalPrice).IsRequired().HasPrecision(18, 2);
});

View file

@ -460,6 +460,15 @@ public static class PlatformEfCoreEntityExtensionMappings
}
);
ObjectExtensionManager.Instance
.MapEfCoreProperty<Tenant, int?>(
PlatformConsts.Tenants.MaxConcurrentUsers,
(entityBuilder, propertyBuilder) =>
{
propertyBuilder.HasDefaultValue(0);
}
);
ObjectExtensionManager.Instance
.MapEfCoreProperty<PermissionDefinitionRecord, string>(
PlatformConsts.Permissions.MenuGroup,

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Sozsoft.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20260717065637_Initial")]
[Migration("20260625183130_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1542,20 +1542,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<int>("PhoneCode")
.HasColumnType("int");
b.Property<string>("PhoneNumberFormat")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<int?>("PhoneNumberMaxLength")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(0);
b.Property<int?>("PhoneNumberMinLength")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(0);
b.Property<bool>("StateRequired")
.HasColumnType("bit");
@ -1826,11 +1812,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.Property<string>("RoutePath")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
@ -1841,10 +1822,6 @@ namespace Sozsoft.Platform.Migrations
.IsUnique()
.HasFilter("[IsDeleted] = 0");
b.HasIndex("TenantId", "RoutePath")
.IsUnique()
.HasFilter("[IsDeleted] = 0");
b.ToTable("Sas_H_CustomComponent", (string)null);
});
@ -2269,9 +2246,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("PostalCode")
.HasColumnType("nvarchar(max)");
b.Property<string>("Township")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -3264,9 +3238,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<string>("TitleJson")
.HasColumnType("text");
b.Property<string>("TodoOptionJson")
.HasColumnType("text");
b.Property<string>("TooltipJson")
.HasColumnType("text");
@ -3415,9 +3386,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<int?>("ColSpan")
.HasColumnType("int");
b.Property<string>("ColumnCssClass")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -3443,22 +3411,9 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<int?>("EditGroupOrderNo")
.HasColumnType("int");
b.Property<int?>("EditOrderNo")
.HasColumnType("int");
b.Property<string>("EditorOptions")
.HasColumnType("text");
b.Property<string>("EditorScript")
.HasColumnType("text");
b.Property<string>("EditorType2")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("FieldName")
.IsRequired()
.HasMaxLength(128)
@ -3680,8 +3635,8 @@ namespace Sozsoft.Platform.Migrations
modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b =>
{
b.Property<string>("Id")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Approver")
.IsRequired()
@ -3717,28 +3672,28 @@ namespace Sozsoft.Platform.Migrations
b.Property<string>("NextOnApprove")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnFalse")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnReject")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnStart")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnTrue")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("PositionX")
.HasColumnType("int");
@ -3753,7 +3708,8 @@ namespace Sozsoft.Platform.Migrations
b.HasKey("Id");
b.HasIndex("ListFormCode");
b.HasIndex("ListFormCode", "Title")
.IsUnique();
b.ToTable("Sas_H_ListFormWorkflow", (string)null);
});
@ -4115,25 +4071,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<DateTime?>("ApprovalDate")
.HasColumnType("datetime2");
b.Property<string>("ApprovalDescription")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ApprovalStatus")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ApprovalUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("BillingCycle")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("City")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -4182,9 +4119,7 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("int");
b.Property<bool>("IsActive")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("bit")
.HasComputedColumnSql("CONVERT(bit, CASE WHEN [LicenseEndTime] IS NOT NULL AND CONVERT(date, GETDATE()) > CONVERT(date, [LicenseEndTime]) THEN 0 ELSE 1 END)", false);
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
@ -4192,11 +4127,6 @@ namespace Sozsoft.Platform.Migrations
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsExisting")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
@ -4205,12 +4135,6 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<DateTime?>("LicenseEndTime")
.HasColumnType("datetime2");
b.Property<DateTime?>("LicenseStartTime")
.HasColumnType("datetime2");
b.Property<string>("MenuGroup")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
@ -4219,6 +4143,10 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.Property<string>("Name")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("OrganizationName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -4230,11 +4158,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("PaymentMethodId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Period")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(1);
b.Property<string>("PhoneNumber")
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
@ -4251,21 +4174,10 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier");
b.Property<decimal>("Total")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<string>("Township")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<decimal>("VatTotal")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<long?>("VknTckn")
.HasColumnType("bigint");
@ -4321,15 +4233,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Period")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(1);
b.Property<decimal>("Price")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<Guid>("ProductId")
.HasColumnType("uniqueidentifier");
@ -4345,14 +4248,6 @@ namespace Sozsoft.Platform.Migrations
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<decimal>("VatAmount")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<decimal>("VatRate")
.HasPrecision(5, 3)
.HasColumnType("decimal(5,3)");
b.HasKey("Id");
b.HasIndex("OrderId");
@ -4480,12 +4375,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<int>("Order")
.HasColumnType("int");
b.Property<decimal>("VatRate")
.ValueGeneratedOnAdd()
.HasPrecision(5, 3)
.HasColumnType("decimal(5,3)")
.HasDefaultValue(0.20m);
b.Property<decimal?>("YearlyPrice")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
@ -4501,8 +4390,9 @@ namespace Sozsoft.Platform.Migrations
modelBuilder.Entity("Sozsoft.Platform.Entities.ReportCategory", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("Id")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
@ -4565,8 +4455,9 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("CategoryId")
.HasColumnType("uniqueidentifier");
b.Property<string>("CategoryId")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
@ -6320,14 +6211,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("AuthorDepartment")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
@ -6335,14 +6218,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorPhoneNumber")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("AuthorTitle")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("nvarchar(max)");
@ -6406,14 +6281,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("AuthorDepartment")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
@ -6421,14 +6288,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorPhoneNumber")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("AuthorTitle")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid>("CategoryId")
.HasColumnType("uniqueidentifier");
@ -8509,6 +8368,11 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<int?>("MaxConcurrentUsers")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(0);
b.Property<string>("MenuGroup")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
@ -8800,16 +8664,6 @@ 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")
@ -8837,8 +8691,7 @@ namespace Sozsoft.Platform.Migrations
b.HasOne("Sozsoft.Platform.Entities.ReportCategory", "ReportCategory")
.WithMany("ReportTemplates")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("ReportCategory");
});

View file

@ -368,6 +368,7 @@ namespace Sozsoft.Platform.Migrations
FaxNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
Founder = table.Column<string>(type: "nvarchar(max)", nullable: true),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
MaxConcurrentUsers = table.Column<int>(type: "int", nullable: true, defaultValue: 0),
MenuGroup = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
MobileNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
OrganizationName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
@ -650,7 +651,7 @@ namespace Sozsoft.Platform.Migrations
name: "Adm_T_ReportCategory",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Id = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(max)", maxLength: 4096, nullable: true),
@ -1128,7 +1129,6 @@ namespace Sozsoft.Platform.Migrations
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
RoutePath = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: false),
Code = table.Column<string>(type: "nvarchar(max)", nullable: false),
Props = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
@ -1392,7 +1392,6 @@ namespace Sozsoft.Platform.Migrations
TreeOptionJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
GanttOptionJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
SchedulerOptionJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
TodoOptionJson = table.Column<string>(type: "text", nullable: true),
FilterRowJson = table.Column<string>(type: "text", nullable: true),
RowJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
HeaderFilterJson = table.Column<string>(type: "text", nullable: true),
@ -1467,6 +1466,32 @@ 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<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
ListFormCode = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Kind = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
Title = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
CompareColumn = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
CompareOperator = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
CompareValue = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
Approver = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
NextOnStart = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
NextOnTrue = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
NextOnFalse = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
NextOnApprove = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
NextOnReject = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
PositionX = table.Column<int>(type: "int", nullable: false),
PositionY = table.Column<int>(type: "int", nullable: false),
CompareOutcomesJson = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Sas_H_ListFormWorkflow", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Sas_H_LogEntry",
columns: table => new
@ -1546,41 +1571,30 @@ namespace Sozsoft.Platform.Migrations
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
IsActive = table.Column<bool>(type: "bit", nullable: false),
OrganizationName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Founder = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
VknTckn = table.Column<long>(type: "bigint", nullable: true),
TaxOffice = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Country = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
City = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
District = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Township = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
PostalCode = table.Column<string>(type: "nvarchar(16)", maxLength: 16, nullable: true),
Address1 = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
Address2 = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
District = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Country = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
City = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
PostalCode = table.Column<string>(type: "nvarchar(16)", maxLength: 16, nullable: true),
MobileNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
PhoneNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
FaxNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
Email = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Website = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
MenuGroup = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
IsExisting = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
IsActive = table.Column<bool>(type: "bit", nullable: false, computedColumnSql: "CONVERT(bit, CASE WHEN [LicenseEndTime] IS NOT NULL AND CONVERT(date, GETDATE()) > CONVERT(date, [LicenseEndTime]) THEN 0 ELSE 1 END)", stored: false),
BillingCycle = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: true),
Period = table.Column<int>(type: "int", nullable: false, defaultValue: 1),
LicenseStartTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LicenseEndTime = table.Column<DateTime>(type: "datetime2", nullable: true),
Subtotal = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
VatTotal = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
Commission = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
Total = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
PaymentMethodId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Installment = table.Column<int>(type: "int", nullable: true),
PaymentDataJson = table.Column<string>(type: "nvarchar(max)", maxLength: 4096, nullable: true),
ApprovalUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ApprovalStatus = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
ApprovalDate = table.Column<DateTime>(type: "datetime2", nullable: true),
ApprovalDescription = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
@ -1626,7 +1640,6 @@ namespace Sozsoft.Platform.Migrations
Order = table.Column<int>(type: "int", nullable: false),
MonthlyPrice = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: true),
YearlyPrice = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: true),
VatRate = table.Column<decimal>(type: "decimal(5,3)", precision: 5, scale: 3, nullable: false, defaultValue: 0.20m),
IsQuantityBased = table.Column<bool>(type: "bit", nullable: false),
ImageUrl = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
@ -2260,7 +2273,7 @@ namespace Sozsoft.Platform.Migrations
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
HtmlContent = table.Column<string>(type: "nvarchar(max)", nullable: false),
CategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
CategoryId = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Status = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
@ -2670,9 +2683,6 @@ namespace Sozsoft.Platform.Migrations
GroupName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Currency = table.Column<string>(type: "nvarchar(8)", maxLength: 8, nullable: false),
PhoneCode = table.Column<int>(type: "int", nullable: false),
PhoneNumberMinLength = table.Column<int>(type: "int", nullable: true, defaultValue: 0),
PhoneNumberMaxLength = table.Column<int>(type: "int", nullable: true, defaultValue: 0),
PhoneNumberFormat = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
TaxLabel = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
ZipRequired = table.Column<bool>(type: "bit", nullable: false),
StateRequired = table.Column<bool>(type: "bit", nullable: false),
@ -2791,11 +2801,6 @@ namespace Sozsoft.Platform.Migrations
PivotSettingsJson = table.Column<string>(type: "text", nullable: true),
Alignment = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true, defaultValue: "left"),
Format = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
EditOrderNo = table.Column<int>(type: "int", nullable: true),
EditGroupOrderNo = table.Column<int>(type: "int", nullable: true),
EditorType2 = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
ColSpan = table.Column<int>(type: "int", nullable: true),
EditorScript = table.Column<string>(type: "text", nullable: true),
EditorOptions = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
@ -2837,38 +2842,6 @@ namespace Sozsoft.Platform.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Sas_H_ListFormWorkflow",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
ListFormCode = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
Kind = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
Title = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
CompareColumn = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
CompareOperator = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
CompareValue = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
Approver = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
NextOnStart = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
NextOnTrue = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
NextOnFalse = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
NextOnApprove = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
NextOnReject = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
PositionX = table.Column<int>(type: "int", nullable: false),
PositionY = table.Column<int>(type: "int", nullable: false),
CompareOutcomesJson = table.Column<string>(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
@ -2909,11 +2882,7 @@ namespace Sozsoft.Platform.Migrations
ProductId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ProductName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
BillingCycle = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
Period = table.Column<int>(type: "int", nullable: false, defaultValue: 1),
Quantity = table.Column<int>(type: "int", nullable: false),
Price = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
VatRate = table.Column<decimal>(type: "decimal(5,3)", precision: 5, scale: 3, nullable: false),
VatAmount = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
TotalPrice = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
@ -3028,10 +2997,6 @@ namespace Sozsoft.Platform.Migrations
CategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
AuthorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
AuthorName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
AuthorTitle = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
AuthorEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
AuthorPhoneNumber = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: true),
AuthorDepartment = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
ViewCount = table.Column<int>(type: "int", nullable: false),
ReplyCount = table.Column<int>(type: "int", nullable: false),
LikeCount = table.Column<int>(type: "int", nullable: false),
@ -3402,10 +3367,6 @@ namespace Sozsoft.Platform.Migrations
Content = table.Column<string>(type: "nvarchar(max)", nullable: false),
AuthorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
AuthorName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
AuthorTitle = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
AuthorEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
AuthorPhoneNumber = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: true),
AuthorDepartment = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
LikeCount = table.Column<int>(type: "int", nullable: true),
IsAcceptedAnswer = table.Column<bool>(type: "bit", nullable: true),
ParentPostId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
@ -3444,7 +3405,6 @@ namespace Sozsoft.Platform.Migrations
City = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Township = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
PostalCode = table.Column<string>(type: "nvarchar(max)", nullable: true),
CityId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
@ -4035,13 +3995,6 @@ namespace Sozsoft.Platform.Migrations
unique: true,
filter: "[IsDeleted] = 0");
migrationBuilder.CreateIndex(
name: "IX_Sas_H_CustomComponent_TenantId_RoutePath",
table: "Sas_H_CustomComponent",
columns: new[] { "TenantId", "RoutePath" },
unique: true,
filter: "[IsDeleted] = 0");
migrationBuilder.CreateIndex(
name: "IX_Sas_H_CustomEndpoint_TenantId_Name",
table: "Sas_H_CustomEndpoint",
@ -4126,9 +4079,10 @@ namespace Sozsoft.Platform.Migrations
column: "ImportId");
migrationBuilder.CreateIndex(
name: "IX_Sas_H_ListFormWorkflow_ListFormCode",
name: "IX_Sas_H_ListFormWorkflow_ListFormCode_Title",
table: "Sas_H_ListFormWorkflow",
column: "ListFormCode");
columns: new[] { "ListFormCode", "Title" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Sas_H_Menu_Code",

View file

@ -1539,20 +1539,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<int>("PhoneCode")
.HasColumnType("int");
b.Property<string>("PhoneNumberFormat")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<int?>("PhoneNumberMaxLength")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(0);
b.Property<int?>("PhoneNumberMinLength")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(0);
b.Property<bool>("StateRequired")
.HasColumnType("bit");
@ -1823,11 +1809,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.Property<string>("RoutePath")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
@ -1838,10 +1819,6 @@ namespace Sozsoft.Platform.Migrations
.IsUnique()
.HasFilter("[IsDeleted] = 0");
b.HasIndex("TenantId", "RoutePath")
.IsUnique()
.HasFilter("[IsDeleted] = 0");
b.ToTable("Sas_H_CustomComponent", (string)null);
});
@ -2266,9 +2243,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("PostalCode")
.HasColumnType("nvarchar(max)");
b.Property<string>("Township")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -3261,9 +3235,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<string>("TitleJson")
.HasColumnType("text");
b.Property<string>("TodoOptionJson")
.HasColumnType("text");
b.Property<string>("TooltipJson")
.HasColumnType("text");
@ -3412,9 +3383,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<int?>("ColSpan")
.HasColumnType("int");
b.Property<string>("ColumnCssClass")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -3440,22 +3408,9 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<int?>("EditGroupOrderNo")
.HasColumnType("int");
b.Property<int?>("EditOrderNo")
.HasColumnType("int");
b.Property<string>("EditorOptions")
.HasColumnType("text");
b.Property<string>("EditorScript")
.HasColumnType("text");
b.Property<string>("EditorType2")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("FieldName")
.IsRequired()
.HasMaxLength(128)
@ -3677,8 +3632,8 @@ namespace Sozsoft.Platform.Migrations
modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b =>
{
b.Property<string>("Id")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Approver")
.IsRequired()
@ -3714,28 +3669,28 @@ namespace Sozsoft.Platform.Migrations
b.Property<string>("NextOnApprove")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnFalse")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnReject")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnStart")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("NextOnTrue")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("PositionX")
.HasColumnType("int");
@ -3750,7 +3705,8 @@ namespace Sozsoft.Platform.Migrations
b.HasKey("Id");
b.HasIndex("ListFormCode");
b.HasIndex("ListFormCode", "Title")
.IsUnique();
b.ToTable("Sas_H_ListFormWorkflow", (string)null);
});
@ -4112,25 +4068,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<DateTime?>("ApprovalDate")
.HasColumnType("datetime2");
b.Property<string>("ApprovalDescription")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ApprovalStatus")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ApprovalUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("BillingCycle")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("City")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -4179,9 +4116,7 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("int");
b.Property<bool>("IsActive")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("bit")
.HasComputedColumnSql("CONVERT(bit, CASE WHEN [LicenseEndTime] IS NOT NULL AND CONVERT(date, GETDATE()) > CONVERT(date, [LicenseEndTime]) THEN 0 ELSE 1 END)", false);
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
@ -4189,11 +4124,6 @@ namespace Sozsoft.Platform.Migrations
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsExisting")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
@ -4202,12 +4132,6 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<DateTime?>("LicenseEndTime")
.HasColumnType("datetime2");
b.Property<DateTime?>("LicenseStartTime")
.HasColumnType("datetime2");
b.Property<string>("MenuGroup")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
@ -4216,6 +4140,10 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.Property<string>("Name")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("OrganizationName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
@ -4227,11 +4155,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("PaymentMethodId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Period")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(1);
b.Property<string>("PhoneNumber")
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
@ -4248,21 +4171,10 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier");
b.Property<decimal>("Total")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<string>("Township")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<decimal>("VatTotal")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<long?>("VknTckn")
.HasColumnType("bigint");
@ -4318,15 +4230,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Period")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(1);
b.Property<decimal>("Price")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<Guid>("ProductId")
.HasColumnType("uniqueidentifier");
@ -4342,14 +4245,6 @@ namespace Sozsoft.Platform.Migrations
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<decimal>("VatAmount")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<decimal>("VatRate")
.HasPrecision(5, 3)
.HasColumnType("decimal(5,3)");
b.HasKey("Id");
b.HasIndex("OrderId");
@ -4477,12 +4372,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<int>("Order")
.HasColumnType("int");
b.Property<decimal>("VatRate")
.ValueGeneratedOnAdd()
.HasPrecision(5, 3)
.HasColumnType("decimal(5,3)")
.HasDefaultValue(0.20m);
b.Property<decimal?>("YearlyPrice")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
@ -4498,8 +4387,9 @@ namespace Sozsoft.Platform.Migrations
modelBuilder.Entity("Sozsoft.Platform.Entities.ReportCategory", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("Id")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
@ -4562,8 +4452,9 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("CategoryId")
.HasColumnType("uniqueidentifier");
b.Property<string>("CategoryId")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
@ -6317,14 +6208,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("AuthorDepartment")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
@ -6332,14 +6215,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorPhoneNumber")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("AuthorTitle")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("nvarchar(max)");
@ -6403,14 +6278,6 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("AuthorDepartment")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("AuthorId")
.HasColumnType("uniqueidentifier");
@ -6418,14 +6285,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("AuthorPhoneNumber")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("AuthorTitle")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid>("CategoryId")
.HasColumnType("uniqueidentifier");
@ -8506,6 +8365,11 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<int?>("MaxConcurrentUsers")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(0);
b.Property<string>("MenuGroup")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
@ -8797,16 +8661,6 @@ 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")
@ -8834,8 +8688,7 @@ namespace Sozsoft.Platform.Migrations
b.HasOne("Sozsoft.Platform.Entities.ReportCategory", "ReportCategory")
.WithMany("ReportTemplates")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("ReportCategory");
});

View file

@ -349,8 +349,7 @@
"CustomComponents": [
{
"name": "DynamicEntityComponent",
"routePath": "/admin/dynamic-entity",
"code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344\",\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/crudendpoint/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600 dark:text-red-400\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 shadow-sm rounded-lg\">\n <thead className=\"bg-slate-100 dark:bg-slate-800\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 dark:border-slate-700 text-sm font-medium text-slate-700 dark:text-slate-200\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={item.id ?? rowIndex} className=\"hover:bg-slate-50 dark:hover:bg-slate-800\">\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800\">\n <Button\n type=\"button\"\n color=\"blue-500\"\n onClick={() => alert(item.name)}\n shape=\"round\"\n size=\"xs\"\n variant=\"solid\"\n id=\"c_mrix4c1a_qrybhk\"\n >\n Show Name\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;",
"code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344\",\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/crudendpoint/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600 dark:text-red-400\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 shadow-sm rounded-lg\">\n <thead className=\"bg-slate-100 dark:bg-slate-800\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 dark:border-slate-700 text-sm font-medium text-slate-700 dark:text-slate-200\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={rowIndex} className=\"hover:bg-slate-50 dark:hover:bg-slate-800\">\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800\">\n <button\n type=\"button\"\n onClick={() => alert(item.name)}\n className=\"bg-blue-600 hover:bg-blue-700 dark:bg-blue-800 dark:hover:bg-blue-900 text-white text-sm px-3 py-1 rounded-lg shadow-sm transition\"\n >\n Show Name\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;",
"props": null,
"description": null,
"isActive": true,
@ -358,12 +357,13 @@
},
{
"name": "RoleListComponent",
"routePath": "/admin/roles-list",
"code": "const RoleListComponent = ({\n title = \"AbpRoles\"\n}) => {\n return (\n <DynamicEntityComponent id=\"c_mdljvvmq_fno52v\" title={title} />\n );\n};\n\nexport default RoleListComponent;",
"props": null,
"description": null,
"isActive": true,
"dependencies": ["DynamicEntityComponent"]
"dependencies": [
"DynamicEntityComponent"
]
}
],
"Abouts": [
@ -1805,7 +1805,9 @@
{
"postContent": "CI/CD pipeline güncellememiz tamamlandı! Deployment süremiz %40 azaldı. Otomasyonun gücü 💪",
"type": "video",
"urls": ["https://www.w3schools.com/html/mov_bbb.mp4"]
"urls": [
"https://www.w3schools.com/html/mov_bbb.mp4"
]
}
],
"SocialPollOptions": [

View file

@ -354,7 +354,6 @@ public class InstallmentOptionSeedDto
public class CustomComponentSeedDto
{
public string Name { get; set; }
public string RoutePath { get; set; }
public string Code { get; set; }
public string Props { get; set; }
public string Description { get; set; }
@ -491,7 +490,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
private readonly IRepository<GlobalSearch, int> _globalSearch;
private readonly IRepository<CustomEndpoint, Guid> _customEndpointRepository;
private readonly IRepository<CustomComponent, Guid> _customComponentRepository;
private readonly IRepository<ReportCategory, Guid> _reportCategoriesRepository;
private readonly IRepository<ReportCategory, string> _reportCategoriesRepository;
private readonly IRepository<ReportTemplate, Guid> _reportTemplatesRepository;
private readonly IRepository<Home, Guid> _homeRepository;
private readonly IRepository<About, Guid> _aboutRepository;
@ -548,7 +547,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
IRepository<SkillLevel, string> skillLevelRepository,
IRepository<CustomEndpoint, Guid> customEndpointRepository,
IRepository<CustomComponent, Guid> customComponentRepository,
IRepository<ReportCategory, Guid> reportCategoriesRepository,
IRepository<ReportCategory, string> reportCategoriesRepository,
IRepository<ReportTemplate, Guid> reportTemplatesRepository,
IRepository<Home, Guid> homeRepository,
IRepository<About, Guid> aboutRepository,
@ -852,7 +851,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
{
await _customComponentRepository.InsertAsync(new CustomComponent(
item.Name,
item.RoutePath,
item.Code,
item.Props,
item.Description,
@ -867,7 +865,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
if (!exists)
{
await _reportCategoriesRepository.InsertAsync(new ReportCategory(Guid.NewGuid())
await _reportCategoriesRepository.InsertAsync(new ReportCategory(item.Name)
{
Name = item.Name,
Description = item.Description,

View file

@ -64,11 +64,6 @@ public class PlatformLoginResult : AbpLoginResult
PResult = PlatformLoginResultType.NotAllowedWorkHour;
Description = L[PlatformConsts.AbpIdentity.User.LoginNotAllowed_WorkHour];
}
else if (resultP.IsNotAllowed_BranchLimit)
{
PResult = PlatformLoginResultType.BranchLimit;
Description = L[PlatformConsts.AbpIdentity.User.BranchLimitError];
}
else if (resultP.IsNotAllowed_ConcurrentUserLimit)
{
PResult = PlatformLoginResultType.ConcurrentUserLimit;

View file

@ -16,7 +16,6 @@ public enum PlatformLoginResultType : byte
ShowCaptcha,
TenantIsPassive,
NotAllowedWorkHour,
BranchLimit,
ConcurrentUserLimit
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
using Sozsoft.Platform.Entities;
@ -7,7 +8,6 @@ using Sozsoft.Platform.Extensions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Domain.Repositories;
@ -31,9 +31,6 @@ public interface IPlatformSignInManager
public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
{
private const string UserLicenseProductName = "Public.products.userLicense";
private const string BranchLicenseProductName = "Public.products.branchHosting";
private readonly IClock clock;
private readonly IRepository<IpRestriction, Guid> repositoryIp;
private readonly IRepository<WorkHour, Guid> repositoryWorkHour;
@ -42,8 +39,6 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
private readonly IIdentitySessionRepository identitySessionRepository;
private readonly ICurrentTenant currentTenant;
private readonly IUnitOfWorkManager unitOfWorkManager;
private readonly IRepository<Order, Guid> orderRepository;
private readonly IRepository<Branch, Guid> branchRepository;
public PlatformSignInManager(
IdentityUserManager userManager,
@ -61,9 +56,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
ITenantRepository tenantRepository,
IIdentitySessionRepository identitySessionRepository,
ICurrentTenant currentTenant,
IUnitOfWorkManager unitOfWorkManager,
IRepository<Order, Guid> orderRepository,
IRepository<Branch, Guid> branchRepository
IUnitOfWorkManager unitOfWorkManager
) : base(
userManager,
contextAccessor,
@ -83,8 +76,6 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
this.identitySessionRepository = identitySessionRepository;
this.currentTenant = currentTenant;
this.unitOfWorkManager = unitOfWorkManager;
this.orderRepository = orderRepository;
this.branchRepository = branchRepository;
}
public async Task<bool> PreSignInCheckAsync(IdentityUser user)
@ -119,10 +110,6 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
{
return new PlatformSignInResult() { IsNotAllowed_WorkHour = true };
}
if (!await CheckBranchLicenseLimitAsync(user))
{
return new PlatformSignInResult() { IsNotAllowed_BranchLimit = true };
}
if (!await CheckConcurrentLimitAsync(user))
{
return new PlatformSignInResult() { IsNotAllowed_ConcurrentUserLimit = true };
@ -286,20 +273,28 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
}
/// <summary>
/// Tenant'a ait aktif Order'lardaki kullanıcı lisansı limitini aşmamak için login'i engeller.
/// Tenant'a tanımlı MaxConcurrentUsers limitini aşmamak için login'i engeller.
/// AbpSessions tablosundaki aktif oturumları sayar (farklı UserId'lere göre distinct).
/// Kullanıcının kendisinin zaten oturumu varsa (refresh senaryosu) yeni concurrent user sayılmaz.
/// </summary>
public async Task<bool> CheckConcurrentLimitAsync(IdentityUser user)
{
// Eğer tenantId yoksa, kullanıcı tenant'a bağlı değil demektir.
// Bu durumda concurrent limit kontrolü yapılmaz.
if (!user.TenantId.HasValue)
{
return true;
}
var maxConcurrentUsers = await GetActiveUserLicenseQuantityAsync(user.TenantId.Value);
var tenant = await tenantRepository.FindAsync(user.TenantId.Value);
if (tenant == null)
{
return true;
}
var maxConcurrentUsers = tenant.GetMaxConcurrentUsers();
if (!maxConcurrentUsers.HasValue || maxConcurrentUsers.Value == 0)
{
return true;
}
// Tenant bağlamını explicit olarak set et — hem password hem refresh token akışlarında
// doğru tenant izolasyonu için güvenli bir şekilde değiştirilir.
@ -316,11 +311,11 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
.Distinct()
.Count();
if (otherActiveUserCount >= maxConcurrentUsers)
if (otherActiveUserCount >= maxConcurrentUsers.Value)
{
Logger.LogWarning(PlatformEventIds.UserCannotSignInConcurrentUserLimit,
"Tenant {TenantId} concurrent user limit of {Limit} reached. Active users: {ActiveCount}.",
user.TenantId, maxConcurrentUsers, otherActiveUserCount);
user.TenantId, maxConcurrentUsers.Value, otherActiveUserCount);
return false;
}
@ -330,60 +325,5 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
return true;
}
private async Task<bool> CheckBranchLicenseLimitAsync(IdentityUser user)
{
if (!user.TenantId.HasValue)
{
return true;
}
var tenantId = user.TenantId.Value;
var activeBranchCount = await GetActiveBranchCountAsync(tenantId);
var branchLicenseQuantity = await GetActiveBranchLicenseQuantityAsync(tenantId);
if (activeBranchCount > branchLicenseQuantity)
{
Logger.LogWarning(PlatformEventIds.UserCannotSignInConcurrentUserLimit,
"Tenant {TenantId} branch license quantity of {Limit} is lower than active branch count {ActiveCount}.",
tenantId, branchLicenseQuantity, activeBranchCount);
return false;
}
return true;
}
private async Task<int> GetActiveBranchCountAsync(Guid tenantId)
{
using (currentTenant.Change(tenantId))
{
return await branchRepository.CountAsync(branch => branch.TenantId == tenantId && branch.IsActive == true);
}
}
private async Task<int> GetActiveUserLicenseQuantityAsync(Guid tenantId)
{
return await GetActiveOrderItemQuantityAsync(tenantId, UserLicenseProductName);
}
private async Task<int> GetActiveBranchLicenseQuantityAsync(Guid tenantId)
{
return await GetActiveOrderItemQuantityAsync(tenantId, BranchLicenseProductName);
}
private async Task<int> GetActiveOrderItemQuantityAsync(Guid tenantId, string productName)
{
using (currentTenant.Change(null))
{
var orderQuery = await orderRepository.WithDetailsAsync(order => order.Items);
var activeOrders = await orderQuery
.Where(order => order.TenantId == tenantId && order.ApprovalStatus == "Approved" && order.IsActive)
.ToListAsync();
return activeOrders
.SelectMany(order => order.Items)
.Where(item => item.ProductName == productName)
.Sum(item => item.Quantity);
}
}
}

Some files were not shown because too many files have changed in this diff Show more