From 65af5fa231fc7ce659d83b55ea18204ebd43ca39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Wed, 22 Oct 2025 15:16:34 +0300 Subject: [PATCH] Hr Leave --- .../Seeds/HostData.json | 4 +- .../Seeds/ListFormsSeeder.cs | 657 +++++++++++++++++- .../Enums/TableNameEnum.cs | 3 +- .../PlatformConsts.cs | 1 + .../TableNameResolver.cs | 1 + .../Kurs.Platform.Domain/Data/SeedConsts.cs | 5 + .../Entities/Tenant/Hr/Leave.cs | 25 + .../Queries/QueryHelper.cs | 25 +- .../EntityFrameworkCore/PlatformDbContext.cs | 17 +- ....cs => 20251022102859_Initial.Designer.cs} | 94 ++- ...8_Initial.cs => 20251022102859_Initial.cs} | 35 + .../PlatformDbContextModelSnapshot.cs | 92 +++ .../JsonRowOpDialogEditForm.tsx | 3 + ui/src/views/list/Grid.tsx | 2 + .../DialogContext/DialogShowComponent.tsx | 8 + 15 files changed, 952 insertions(+), 20 deletions(-) create mode 100644 api/src/Kurs.Platform.Domain/Entities/Tenant/Hr/Leave.cs rename api/src/Kurs.Platform.EntityFrameworkCore/Migrations/{20251022080448_Initial.Designer.cs => 20251022102859_Initial.Designer.cs} (99%) rename api/src/Kurs.Platform.EntityFrameworkCore/Migrations/{20251022080448_Initial.cs => 20251022102859_Initial.cs} (99%) diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json index 150100f8..79825d5e 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json @@ -14498,7 +14498,7 @@ "DisplayName": "App.Coordinator.Assignments", "Order": 4, "Url": "/admin/coordinator/assignments", - "Icon": "FcTodoList", + "Icon": "FcTodoList", "RequiredPermissionName": "App.Coordinator.Assignments", "IsDisabled": false }, @@ -14508,7 +14508,7 @@ "DisplayName": "App.Coordinator.Tests", "Order": 5, "Url": "/admin/coordinator/tests", - "Icon": "FcCheckmark", + "Icon": "FcCheckmark", "RequiredPermissionName": "App.Coordinator.Tests", "IsDisabled": false }, diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs index c3e9047c..dedb202f 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs @@ -33489,15 +33489,6 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency Value = "true", CustomValueType = FieldCustomValueTypeEnum.Value } }), - CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] { - new CommandColumnDto() { - Hint = "Personel Listesi", - Text ="Personel Listesi", - UrlTarget="_blank", - AuthName = AppCodes.Hr.Employee, - Url="/admin/list/list-employees/@Id" - }, - }), } ); @@ -35284,6 +35275,654 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency } #endregion + #region Leave + if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == ListFormCodes.Lists.Leave)) + { + var listFormLeave = await _listFormRepository.InsertAsync( + new ListForm() + { + ListFormType = ListFormTypeEnum.List, + IsSubForm = true, + LayoutJson = JsonSerializer.Serialize(new LayoutDto() + { + Grid = true, + Card = true, + Pivot = true, + Chart = true, + DefaultLayout = "grid", + CardLayoutColumn = 3 + }), + CultureName = LanguageCodes.En, + ListFormCode = ListFormCodes.Lists.Leave, + Name = AppCodes.Hr.Leave, + Title = AppCodes.Hr.Leave, + DataSourceCode = SeedConsts.DataSources.DefaultCode, + IsTenant = true, + IsBranch = false, + IsOrganizationUnit = false, + Description = AppCodes.Hr.Leave, + SelectCommandType = SelectCommandTypeEnum.Table, + SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.Leave)), + KeyFieldName = "Id", + KeyFieldDbSourceType = DbType.Guid, + DefaultFilter = "\"IsDeleted\" = 'false'", + SortMode = GridOptions.SortModeSingle, + FilterRowJson = JsonSerializer.Serialize(new GridFilterRowDto { Visible = true }), + HeaderFilterJson = JsonSerializer.Serialize(new { Visible = true }), + SearchPanelJson = JsonSerializer.Serialize(new { Visible = true }), + GroupPanelJson = JsonSerializer.Serialize(new { Visible = true }), + SelectionJson = JsonSerializer.Serialize(new SelectionDto + { + Mode = GridOptions.SelectionModeSingle, + AllowSelectAll = false + }), + ColumnOptionJson = JsonSerializer.Serialize(new + { + ColumnFixingEnabled = true, + ColumnAutoWidth = true, + ColumnChooserEnabled = true, + AllowColumnResizing = true, + AllowColumnReordering = true, + ColumnResizingMode = "widget", + }), + PermissionJson = JsonSerializer.Serialize(new PermissionCrudDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + D = AppCodes.Hr.Leave + ".Delete", + E = AppCodes.Hr.Leave + ".Export", + I = AppCodes.Hr.Leave + ".Import", + A = AppCodes.Hr.Leave + ".Activity", + }), + DeleteCommand = $"UPDATE \"{TableNameResolver.GetFullTableName(nameof(TableNameEnum.Leave))}\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\"=@Id", + DeleteFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { + new() { + FieldName = "DeleterId", + FieldDbType = DbType.Guid, + Value = "@USERID", + CustomValueType = FieldCustomValueTypeEnum.CustomKey }, + new() { + FieldName = "Id", + FieldDbType = DbType.Guid, + Value = "@ID", + CustomValueType = FieldCustomValueTypeEnum.CustomKey } + }), + PagerOptionJson = JsonSerializer.Serialize(new GridPagerOptionDto + { + Visible = true, + AllowedPageSizes = "10,20,50,100", + ShowPageSizeSelector = true, + ShowNavigationButtons = true, + ShowInfo = false, + InfoText = "Page {0} of {1} ({2} items)", + DisplayMode = GridColumnOptions.PagerDisplayModeAdaptive, + ScrollingMode = GridColumnOptions.ScrollingModeStandard, + LoadPanelEnabled = "auto", + LoadPanelText = "Loading..." + }), + EditingOptionJson = JsonSerializer.Serialize(new GridEditingDto + { + Popup = new GridEditingPopupDto() + { + Title = "Leave Form", + Width = 500, + Height = 520 + }, + AllowDeleting = true, + AllowAdding = true, + AllowUpdating = true, + SendOnlyChangedFormValuesUpdate = false, + }), + InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { + new() { + FieldName = "CreationTime", + FieldDbType = DbType.DateTime, + Value = "@NOW", + CustomValueType = FieldCustomValueTypeEnum.CustomKey }, + new() { + FieldName = "CreatorId", + FieldDbType = DbType.Guid, + Value = "@USERID", + CustomValueType = FieldCustomValueTypeEnum.CustomKey }, + new() { + FieldName = "IsDeleted", + FieldDbType = DbType.Boolean, + Value = "false", + CustomValueType = FieldCustomValueTypeEnum.Value } + }), + EditingFormJson = JsonSerializer.Serialize(new List() + { + new() { + Order=1, ColCount=1, ColSpan=2, ItemType="group", Items = + [ + new EditingFormItemDto { Order = 1, DataField = "AppliedDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox}, + new EditingFormItemDto { Order = 2, DataField = "EmployeeId", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 3, DataField = "LeaveType", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 4, DataField = "StartDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox}, + new EditingFormItemDto { Order = 5, DataField = "EndDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox}, + new EditingFormItemDto { Order = 6, DataField = "TotalDays", ColSpan = 2, EditorType2 = EditorTypes.dxNumberBox}, + new EditingFormItemDto { Order = 7, DataField = "IsHalfDay", ColSpan = 2, EditorType2 = EditorTypes.dxCheckBox}, + new EditingFormItemDto { Order = 8, DataField = "Reason", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextArea}, + new EditingFormItemDto { Order = 9, DataField = "Status", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox}, + ] + } + }), + FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { + new() { + FieldName = "Status", + FieldDbType = DbType.String, + Value = "Pending", + CustomValueType = FieldCustomValueTypeEnum.Value }, + new() { + FieldName = "AppliedDate", + FieldDbType = DbType.Date, + Value = "@NOW", + CustomValueType = FieldCustomValueTypeEnum.CustomKey }, + new() { + FieldName = "IsHalfDay", + FieldDbType = DbType.Boolean, + Value = "false", + CustomValueType = FieldCustomValueTypeEnum.Value } + }), + CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] { + new() { + ButtonPosition = UiCommandButtonPositionTypeEnum.Toolbar, + Hint = "Toplu İzin", + Text ="Toplu İzin", + AuthName = AppCodes.Hr.Leave + ".Update", + DialogName = "CollectiveLeave", + DialogParameters = JsonSerializer.Serialize(new { + name = "@Name", + id = "@Id" + }) + }, + new() { + Hint = "Accept", + Text ="Accept", + UrlTarget="_blank", + AuthName = AppCodes.Hr.Leave + ".Update", + Url="/admin/list/list-employees/@Id" + }, + new() { + Hint = "Reject", + Text ="Reject", + UrlTarget="_blank", + AuthName = AppCodes.Hr.Leave + ".Update", + Url="/admin/list/list-employees/@Id" + }, + }), + } + ); + + #region Leave Fields + await _listFormFieldRepository.InsertManyAsync([ + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Guid, + FieldName = "Id", + Width = 100, + ListOrderNo = 1, + Visible = false, + IsActive = true, + IsDeleted = false, + SortIndex = 0, + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Guid, + FieldName = "EmployeeId", + Width = 200, + ListOrderNo = 2, + Visible = true, + IsActive = true, + IsDeleted = false, + SortIndex = 0, + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + LookupJson = JsonSerializer.Serialize(new LookupDto + { + DataSourceType = UiLookupDataSourceTypeEnum.Query, + DisplayExpr = "name", + ValueExpr = "key", + LookupQuery = LookUpQueryValues.EmployeeValues + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "LeaveType", + Width = 150, + ListOrderNo = 3, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + LookupJson = JsonSerializer.Serialize(new LookupDto + { + DataSourceType = UiLookupDataSourceTypeEnum.StaticData, + DisplayExpr = "name", + ValueExpr = "key", + LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] { + new () { Key= "Annual", Name= "ANNUAL" }, + new () { Key= "Sick", Name= "SICK" }, + new () { Key= "Maternity", Name= "MATERNITY"}, + new () { Key= "Paternity", Name= "PATERNITY" }, + new () { Key= "Personal", Name= "PERSONAL" }, + new () { Key= "Emergency", Name= "EMERGENCY" }, + new () { Key= "Study", Name= "STUDY" }, + new () { Key= "Unpaid", Name="UNPAID" } + }), + }), + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Date, + FieldName = "StartDate", + Width = 150, + ListOrderNo = 4, + Visible = true, + IsActive = true, + IsDeleted = false, + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Date, + FieldName = "EndDate", + Width = 150, + ListOrderNo = 5, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Int32, + FieldName = "TotalDays", + Width = 100, + ListOrderNo = 6, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Boolean, + FieldName = "IsHalfDay", + Width = 100, + ListOrderNo = 7, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Reason", + Width = 250, + ListOrderNo = 8, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "Status", + Width = 100, + ListOrderNo = 9, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] { + new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) } + }), + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + LookupJson = JsonSerializer.Serialize(new LookupDto + { + DataSourceType = UiLookupDataSourceTypeEnum.StaticData, + DisplayExpr = "name", + ValueExpr = "key", + LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] { + new () { Key= "Pending", Name= "PENDING" }, + new () { Key= "Approved", Name= "APPROVED" }, + new () { Key= "Rejected", Name= "REJECTED"}, + new () { Key= "Cancelled", Name= "CANCELLED" }, + }), + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Date, + FieldName = "AppliedDate", + Width = 100, + ListOrderNo = 10, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "ApprovedBy", + Width = 100, + ListOrderNo = 11, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Date, + FieldName = "ApprovedDate", + Width = 100, + ListOrderNo = 12, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + new() { + ListFormCode = listFormLeave.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "RejectionReason", + Width = 250, + ListOrderNo = 13, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto + { + AllowReordering = true, + }), + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.Hr.Leave + ".Create", + R = AppCodes.Hr.Leave, + U = AppCodes.Hr.Leave + ".Update", + E = true, + I = true, + Deny = false + }), + PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto + { + IsPivot = true + }) + }, + ]); + #endregion + } + #endregion + #endregion } } diff --git a/api/src/Kurs.Platform.Domain.Shared/Enums/TableNameEnum.cs b/api/src/Kurs.Platform.Domain.Shared/Enums/TableNameEnum.cs index 89c59a82..b9861d22 100644 --- a/api/src/Kurs.Platform.Domain.Shared/Enums/TableNameEnum.cs +++ b/api/src/Kurs.Platform.Domain.Shared/Enums/TableNameEnum.cs @@ -110,5 +110,6 @@ public enum TableNameEnum Department, Badge, CostCenter, - Employee + Employee, + Leave } \ No newline at end of file diff --git a/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs b/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs index 278e4050..81756991 100644 --- a/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs +++ b/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs @@ -505,6 +505,7 @@ public static class PlatformConsts public const string Badge = "list-badge"; public const string CostCenter = "list-costcenter"; public const string Employee = "list-employee"; + public const string Leave = "list-leave"; } } diff --git a/api/src/Kurs.Platform.Domain.Shared/TableNameResolver.cs b/api/src/Kurs.Platform.Domain.Shared/TableNameResolver.cs index 0be9e7d4..5ea0890d 100644 --- a/api/src/Kurs.Platform.Domain.Shared/TableNameResolver.cs +++ b/api/src/Kurs.Platform.Domain.Shared/TableNameResolver.cs @@ -128,6 +128,7 @@ public static class TableNameResolver { nameof(TableNameEnum.Badge), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) }, { nameof(TableNameEnum.CostCenter), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) }, { nameof(TableNameEnum.Employee), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) }, + { nameof(TableNameEnum.Leave), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) }, // 🔹 ACCOUNTING { nameof(TableNameEnum.Bank), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Accounting) }, diff --git a/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs b/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs index 30a3d1d9..b41c93bc 100644 --- a/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs +++ b/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs @@ -457,6 +457,11 @@ public static class SeedConsts public const string EmploymentType = Default + ".EmploymentType"; public const string Badge = Default + ".Badge"; public const string CostCenter = Default + ".CostCenter"; + public const string Leave = Default + ".Leave"; + public const string Overtime = Default + ".Overtime"; + public const string Payrool = Default + ".Payrool"; + public const string Template360 = Default + ".Template360"; + public const string Evulation360 = Default + ".Evulation360"; } public static class Accounting diff --git a/api/src/Kurs.Platform.Domain/Entities/Tenant/Hr/Leave.cs b/api/src/Kurs.Platform.Domain/Entities/Tenant/Hr/Leave.cs new file mode 100644 index 00000000..06339d3c --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Entities/Tenant/Hr/Leave.cs @@ -0,0 +1,25 @@ +// Domain/Entities/HrLeave.cs +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Entities; + +public class Leave : FullAuditedEntity, IMultiTenant +{ + public Guid? TenantId { get; set; } + + public Guid EmployeeId { get; set; } + public string LeaveType { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public double TotalDays { get; set; } + public bool IsHalfDay { get; set; } + public string? Reason { get; set; } + public string Status { get; set; } + public DateTime AppliedDate { get; set; } + public string? ApprovedBy { get; set; } + public DateTime? ApprovedDate { get; set; } + public string? RejectionReason { get; set; } + public string? Attachments { get; set; } // JSON string (from string[]) +} diff --git a/api/src/Kurs.Platform.Domain/Queries/QueryHelper.cs b/api/src/Kurs.Platform.Domain/Queries/QueryHelper.cs index d6e3011b..be90fbaf 100644 --- a/api/src/Kurs.Platform.Domain/Queries/QueryHelper.cs +++ b/api/src/Kurs.Platform.Domain/Queries/QueryHelper.cs @@ -1,5 +1,6 @@ using System; using System.Data; +using System.Globalization; using System.Linq; using System.Text.Json; @@ -57,12 +58,24 @@ public class QueryHelper case DbType.DateTime: case DbType.DateTime2: case DbType.DateTimeOffset: - //"2025-01-03" - // var dateValues = values.Select(a => DateTimeOffset.ParseExact(a.ToString(), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToUniversalTime()).ToArray(); - // value = isArray ? dateValues : dateValues[0]; - // break; - //"2025-01-03T11:58:00+03:00" - var dateTimeValues = values.Select(a => DateTimeOffset.Parse(a.ToString()).ToUniversalTime()).ToArray(); + var dateTimeValues = values.Select(a => + { + if (a == null) return (DateTimeOffset?)null; + + var s = a as string ?? a.ToString(); + if (string.IsNullOrWhiteSpace(s)) return (DateTimeOffset?)null; + + // İlk olarak TryParseExact ile kısa format "yyyy-MM-dd" kontrolü + if (DateTimeOffset.TryParseExact(s, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var dto)) + return dto.ToUniversalTime(); + + // Genel parse denemesi + if (DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out dto)) + return dto.ToUniversalTime(); + + // Başarısızsa null dön + return (DateTimeOffset?)null; + }).ToArray(); value = isArray ? dateTimeValues : dateTimeValues[0]; break; case DbType.Int16: diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs index 45547b72..78c3044e 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs @@ -1773,8 +1773,23 @@ public class PlatformDbContext : .HasForeignKey(x => x.BankAccountId) .OnDelete(DeleteBehavior.Restrict) .IsRequired(false); + }); - // b.HasOne(x => x.WorkSchedule).WithMany().HasForeignKey(x => x.WorkScheduleId); + builder.Entity(b => + { + b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.Leave)), Prefix.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.EmployeeId).IsRequired().HasMaxLength(20); + b.Property(x => x.LeaveType).IsRequired(); + b.Property(x => x.StartDate).IsRequired(); + b.Property(x => x.EndDate).IsRequired(); + b.Property(x => x.TotalDays).IsRequired(); + b.Property(x => x.Reason).HasMaxLength(500); + b.Property(x => x.Status).IsRequired().HasMaxLength(20); + b.Property(x => x.RejectionReason).HasMaxLength(500); + b.Property(x => x.ApprovedBy).HasMaxLength(100); + b.Property(x => x.Attachments).HasMaxLength(2000); }); } } diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022080448_Initial.Designer.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022102859_Initial.Designer.cs similarity index 99% rename from api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022080448_Initial.Designer.cs rename to api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022102859_Initial.Designer.cs index 1d59a607..e773f445 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022080448_Initial.Designer.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022102859_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Kurs.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20251022080448_Initial")] + [Migration("20251022102859_Initial")] partial class Initial { /// @@ -4243,6 +4243,98 @@ namespace Kurs.Platform.Migrations b.ToTable("T_Adm_Lawyer", (string)null); }); + modelBuilder.Entity("Kurs.Platform.Entities.Leave", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AppliedDate") + .HasColumnType("datetime2"); + + b.Property("ApprovedBy") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ApprovedDate") + .HasColumnType("datetime2"); + + b.Property("Attachments") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("EmployeeId") + .HasMaxLength(20) + .HasColumnType("uniqueidentifier"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsHalfDay") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LeaveType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("RejectionReason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TotalDays") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("T_Hr_Leave", (string)null); + }); + modelBuilder.Entity("Kurs.Platform.Entities.LessonPeriod", b => { b.Property("Id") diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022080448_Initial.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022102859_Initial.cs similarity index 99% rename from api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022080448_Initial.cs rename to api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022102859_Initial.cs index c769aa0d..6a80cb92 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022080448_Initial.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20251022102859_Initial.cs @@ -1798,6 +1798,38 @@ namespace Kurs.Platform.Migrations table.PrimaryKey("PK_T_Hr_EmploymentType", x => x.Id); }); + migrationBuilder.CreateTable( + name: "T_Hr_Leave", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + EmployeeId = table.Column(type: "uniqueidentifier", maxLength: 20, nullable: false), + LeaveType = table.Column(type: "nvarchar(max)", nullable: false), + StartDate = table.Column(type: "datetime2", nullable: false), + EndDate = table.Column(type: "datetime2", nullable: false), + TotalDays = table.Column(type: "float", nullable: false), + IsHalfDay = table.Column(type: "bit", nullable: false), + Reason = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + Status = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false), + AppliedDate = table.Column(type: "datetime2", nullable: false), + ApprovedBy = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ApprovedDate = table.Column(type: "datetime2", nullable: true), + RejectionReason = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + Attachments = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_T_Hr_Leave", x => x.Id); + }); + migrationBuilder.CreateTable( name: "T_P_Activity", columns: table => new @@ -4887,6 +4919,9 @@ namespace Kurs.Platform.Migrations migrationBuilder.DropTable( name: "T_Crd_QuestionTag"); + migrationBuilder.DropTable( + name: "T_Hr_Leave"); + migrationBuilder.DropTable( name: "T_P_Activity"); diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index b992b5f4..f74c2d23 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -4240,6 +4240,98 @@ namespace Kurs.Platform.Migrations b.ToTable("T_Adm_Lawyer", (string)null); }); + modelBuilder.Entity("Kurs.Platform.Entities.Leave", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AppliedDate") + .HasColumnType("datetime2"); + + b.Property("ApprovedBy") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ApprovedDate") + .HasColumnType("datetime2"); + + b.Property("Attachments") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("EmployeeId") + .HasMaxLength(20) + .HasColumnType("uniqueidentifier"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsHalfDay") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LeaveType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("RejectionReason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TotalDays") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("T_Hr_Leave", (string)null); + }); + modelBuilder.Entity("Kurs.Platform.Entities.LessonPeriod", b => { b.Property("Id") diff --git a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogEditForm.tsx b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogEditForm.tsx index dfccc008..22a350ca 100644 --- a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogEditForm.tsx +++ b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogEditForm.tsx @@ -299,6 +299,9 @@ function JsonRowOpDialogEditForm({ "• setFormData({ ...formData, Path: (v => v === '1' ? '1-deneme' : v === '0' ? '0-deneme' : '')(e.value) })" } +
+                              {`• (() => {const d=v=>!v?null:(v instanceof Date?v:new Date(v));const nf={...formData,[editor.dataField]:e?.value};const s=d(nf.StartDate),t=d(nf.EndDate);setFormData({...formData,TotalDays: s&&t?Math.max(0,Math.floor((Date.UTC(t.getFullYear(),t.getMonth(),t.getDate())-Date.UTC(s.getFullYear(),s.getMonth(),s.getDate()))/(24*60*60*1000))+1):null});})(); `}
+                            
diff --git a/ui/src/views/list/Grid.tsx b/ui/src/views/list/Grid.tsx index bb47966c..dc38968d 100644 --- a/ui/src/views/list/Grid.tsx +++ b/ui/src/views/list/Grid.tsx @@ -718,6 +718,8 @@ const Grid = (props: GridProps) => { .flatMap((group) => group.items || []) .find((i) => i.dataField === editor.dataField) + + console.log(formItem?.dataField, formItem?.script) if (formItem?.script) { const prevHandler = editor.editorOptions.onValueChanged // varsa önceki handler'ı sakla diff --git a/ui/src/views/shared/DialogContext/DialogShowComponent.tsx b/ui/src/views/shared/DialogContext/DialogShowComponent.tsx index dbbba07d..ab60cb7f 100644 --- a/ui/src/views/shared/DialogContext/DialogShowComponent.tsx +++ b/ui/src/views/shared/DialogContext/DialogShowComponent.tsx @@ -75,6 +75,14 @@ const DialogShowComponent = (): JSX.Element => { {...dialogContext.config?.props} > ) + case 'CollectiveLeave': + return ( + + ) default: return <> }