Hr Expense

This commit is contained in:
Sedat Öztürk 2025-10-26 23:27:01 +03:00
parent 78cce3d4fb
commit d10763c4ea
20 changed files with 1289 additions and 48 deletions

View file

@ -2205,6 +2205,12 @@
"en": "Update",
"tr": "Değiştir"
},
{
"resourceName": "Platform",
"key": "Widget",
"en": "Widget",
"tr": "Widget"
},
{
"resourceName": "Platform",
"key": "Manager",
@ -7827,6 +7833,12 @@
"tr": "Eğitimler",
"en": "Trainings"
},
{
"resourceName": "Platform",
"key": "App.Hr.Expense",
"tr": "Harcama Talepleri",
"en": "Expense Requests"
},
{
"resourceName": "Platform",
"key": "App.Intranet.Meal",
@ -15412,11 +15424,21 @@
"RequiredPermissionName": "App.Hr.Overtime",
"IsDisabled": false
},
{
"ParentCode": "App.Hr",
"Code": "App.Hr.Expense",
"DisplayName": "App.Hr.Expense",
"Order": 10,
"Url": "/admin/list/list-expense",
"Icon": "FaFileInvoiceDollar",
"RequiredPermissionName": "App.Hr.Expense",
"IsDisabled": false
},
{
"ParentCode": "App.Hr",
"Code": "App.Hr.Payroll",
"DisplayName": "App.Hr.Payroll",
"Order": 10,
"Order": 11,
"Url": "/admin/list/list-payroll",
"Icon": "FcMoneyTransfer",
"RequiredPermissionName": "App.Hr.Payroll",
@ -15426,7 +15448,7 @@
"ParentCode": "App.Hr",
"Code": "App.Hr.Template360",
"DisplayName": "App.Hr.Template360",
"Order": 11,
"Order": 12,
"Url": "/admin/list/list-template360",
"Icon": "FcInspection",
"RequiredPermissionName": "App.Hr.Template360",
@ -15436,7 +15458,7 @@
"ParentCode": "App.Hr",
"Code": "App.Hr.Performance360",
"DisplayName": "App.Hr.Performance360",
"Order": 12,
"Order": 13,
"Url": "/admin/list/list-performance360",
"Icon": "FcSurvey",
"RequiredPermissionName": "App.Hr.Performance360",
@ -15446,7 +15468,7 @@
"ParentCode": "App.Hr",
"Code": "App.Hr.Training",
"DisplayName": "App.Hr.Training",
"Order": 13,
"Order": 14,
"Url": "/admin/list/list-training",
"Icon": "FcGraduationCap",
"RequiredPermissionName": "App.Hr.Training",
@ -20012,6 +20034,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Files.Widget",
"ParentName": "App.Files",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Definitions.Sector",
@ -23864,6 +23895,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Projects",
"Name": "App.Projects.Tasks.Widget",
"ParentName": "App.Projects.Tasks",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Projects",
"Name": "App.Projects.Phases",
@ -24242,6 +24282,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Employee.Widget",
"ParentName": "App.Hr.Employee",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Department",
@ -24620,6 +24669,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Leave.Widget",
"ParentName": "App.Hr.Leave",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Overtime",
@ -24683,6 +24741,87 @@
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Overtime.Widget",
"ParentName": "App.Hr.Overtime",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense",
"ParentName": null,
"DisplayName": "App.Hr.Expense",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense.Create",
"ParentName": "App.Hr.Expense",
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense.Update",
"ParentName": "App.Hr.Expense",
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense.Delete",
"ParentName": "App.Hr.Expense",
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense.Export",
"ParentName": "App.Hr.Expense",
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense.Import",
"ParentName": "App.Hr.Expense",
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense.Activity",
"ParentName": "App.Hr.Expense",
"DisplayName": "Activity",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Expense.Widget",
"ParentName": "App.Hr.Expense",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Payroll",
@ -24809,6 +24948,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Training.Widget",
"ParentName": "App.Hr.Training",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CostCenter",
@ -25187,6 +25335,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Events.Event.Widget",
"ParentName": "App.Intranet.Events.Event",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Meal",
@ -25250,6 +25407,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Meal.Widget",
"ParentName": "App.Intranet.Meal",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Reservation",
@ -25313,6 +25479,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Reservation.Widget",
"ParentName": "App.Intranet.Reservation",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.ShuttleRoute",
@ -25376,6 +25551,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.ShuttleRoute.Widget",
"ParentName": "App.Intranet.ShuttleRoute",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Announcement",
@ -25439,6 +25623,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Announcement.Widget",
"ParentName": "App.Intranet.Announcement",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Visitor",
@ -25502,6 +25695,15 @@
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Intranet",
"Name": "App.Intranet.Visitor.Widget",
"ParentName": "App.Intranet.Visitor",
"DisplayName": "Widget",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Kurs"
},
{
"GroupName": "App.Crm",
"Name": "App.Crm.Customer",

View file

@ -21,7 +21,7 @@ using AppCodes = Kurs.Platform.Data.Seeds.SeedConsts.AppCodes;
namespace Kurs.Platform.Data.Seeds;
public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
public class ListFormSeeder : IDataSeedContributor, ITransientDependency
{
private readonly IRepository<ListForm, Guid> _listFormRepository;
private readonly IRepository<ListFormField, Guid> _listFormFieldRepository;
@ -29,7 +29,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
private readonly IdentityRoleManager _identityRoleManager;
private readonly IConfiguration _configuration;
public ListFormsSeeder(
public ListFormSeeder(
IRepository<ListForm, Guid> listFormRepository,
IRepository<ListFormField, Guid> listFormFieldRepository,
IdentityUserManager userManager,
@ -40884,6 +40884,571 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
}
#endregion
#region Expense Request
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == ListFormCodes.Lists.Expense))
{
var listFormExpense = 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.Expense,
Name = AppCodes.Hr.Expense,
Title = AppCodes.Hr.Expense,
DataSourceCode = SeedConsts.DataSources.DefaultCode,
IsTenant = true,
IsBranch = false,
IsOrganizationUnit = false,
Description = AppCodes.Hr.Expense,
SelectCommandType = SelectCommandTypeEnum.Table,
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.Expense)),
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.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
D = AppCodes.Hr.Expense + ".Delete",
E = AppCodes.Hr.Expense + ".Export",
I = AppCodes.Hr.Expense + ".Import",
A = AppCodes.Hr.Expense + ".Activity",
}),
DeleteCommand = $"UPDATE \"{TableNameResolver.GetFullTableName(nameof(TableNameEnum.Expense))}\" 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 = "Expnse Request Form",
Width = 500,
Height = 450
},
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<EditingFormDto>()
{
new() {
Order=1, ColCount=1, ColSpan=2, ItemType="group", Items =
[
new EditingFormItemDto { Order = 1, DataField = "EmployeeId", IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
new EditingFormItemDto { Order = 2, DataField = "Category", IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
new EditingFormItemDto { Order = 3, DataField = "Amount", IsRequired = true, EditorType2 = EditorTypes.dxNumberBox },
new EditingFormItemDto { Order = 4, DataField = "CurrencyId", IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
new EditingFormItemDto { Order = 5, DataField = "RequestDate", IsRequired = true, EditorType2 = EditorTypes.dxDateBox },
new EditingFormItemDto { Order = 6, DataField = "Description", EditorType2 = EditorTypes.dxTextArea },
new EditingFormItemDto { Order = 7, DataField = "Project", EditorType2 = EditorTypes.dxTextBox },
new EditingFormItemDto { Order = 8, DataField = "Status", IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
new EditingFormItemDto { Order = 9, DataField = "Notes", EditorType2 = EditorTypes.dxTextArea },
]
}
}),
FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
{
new() {
FieldName = "RequestDate",
FieldDbType = DbType.Date,
Value = "@NOW",
CustomValueType = FieldCustomValueTypeEnum.CustomKey }
}),
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
new() {
Hint = "Accept",
Text ="Accept",
UrlTarget="_blank",
AuthName = AppCodes.Hr.Expense + ".Update",
Url="/admin/list/list-employees/@Id"
},
new() {
Hint = "Reject",
Text ="Reject",
UrlTarget="_blank",
AuthName = AppCodes.Hr.Expense + ".Update",
Url="/admin/list/list-employees/@Id"
},
}),
}
);
#region Expense Request Fields
await _listFormFieldRepository.InsertManyAsync([
new() {
ListFormCode = listFormExpense.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.Intranet.Announcement + ".Create",
R = AppCodes.Intranet.Announcement,
U = AppCodes.Intranet.Announcement + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.Guid,
FieldName = "EmployeeId",
Width = 100,
ListOrderNo = 2,
Visible = true,
IsActive = true,
IsDeleted = false,
AllowSearch = true,
ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] {
new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) }
}),
LookupJson = JsonSerializer.Serialize(new LookupDto
{
DataSourceType = UiLookupDataSourceTypeEnum.Query,
DisplayExpr = "name",
ValueExpr = "key",
LookupQuery = LookUpQueryValues.EmployeeValues
}),
ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto
{
AllowReordering = true,
}),
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
{
C = AppCodes.Hr.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Category",
Width = 100,
ListOrderNo = 3,
Visible = true,
IsActive = true,
IsDeleted = false,
AllowSearch = true,
ValidationRuleJson = JsonSerializer.Serialize(new ValidationRuleDto[] {
new ValidationRuleDto() { Type = Enum.GetName(UiColumnValidationRuleTypeEnum.required) }
}),
LookupJson = JsonSerializer.Serialize(new LookupDto
{
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
DisplayExpr = "name",
ValueExpr = "key",
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
new () { Key= "travel", Name= "Travel" },
new () { Key= "meal", Name= "Meal" },
new () { Key= "accommodation", Name= "Accommodation" },
}),
}),
ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto
{
AllowReordering = true,
}),
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
{
C = AppCodes.Hr.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.Decimal,
FieldName = "Amount",
Width = 100,
ListOrderNo = 4,
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.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.Guid,
FieldName = "CurrencyId",
Width = 100,
ListOrderNo = 5,
Visible = true,
IsActive = true,
IsDeleted = false,
AllowSearch = true,
LookupJson = JsonSerializer.Serialize(new LookupDto
{
DataSourceType = UiLookupDataSourceTypeEnum.Query,
DisplayExpr = "name",
ValueExpr = "key",
LookupQuery = LookUpQueryValues.CurrencyValues
}),
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.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.Date,
FieldName = "RequestDate",
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.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Description",
Width = 250,
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.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Project",
Width = 100,
ListOrderNo = 8,
Visible = true,
IsActive = true,
IsDeleted = false,
AllowSearch = true,
ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto
{
AllowReordering = true,
}),
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
{
C = AppCodes.Hr.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.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) }
}),
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" },
}),
}),
ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto
{
AllowReordering = true,
}),
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
{
C = AppCodes.Hr.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Notes",
Width = 200,
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.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
new() {
ListFormCode = listFormExpense.ListFormCode,
RoleId = null,
UserId = null,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "RejectionReason",
Width = 200,
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.Expense + ".Create",
R = AppCodes.Hr.Expense,
U = AppCodes.Hr.Expense + ".Update",
E = true,
I = true,
Deny = false
}),
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
{
IsPivot = true
})
},
]);
#endregion
}
#endregion
#endregion
}
}

View file

@ -122,5 +122,6 @@ public enum TableNameEnum
Reservation,
ShuttleRoute,
Announcement,
Visitor
Visitor,
Expense
}

View file

@ -533,6 +533,7 @@ public static class PlatformConsts
public const string ShuttleRoute = "list-shuttleroute";
public const string Announcement = "list-announcement";
public const string Visitor = "list-visitor";
public const string Expense = "list-expense";
}
}

View file

@ -130,6 +130,7 @@ public static class TableNameResolver
{ nameof(TableNameEnum.PayrollItem), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) },
{ nameof(TableNameEnum.Template360), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) },
{ nameof(TableNameEnum.Performance360), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) },
{ nameof(TableNameEnum.Expense), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Hr) },
// Intranet
{ nameof(TableNameEnum.EventCategory), (PlatformConsts.TablePrefix.TenantByName, MenuPrefix.Intranet) },

View file

@ -472,6 +472,7 @@ public static class SeedConsts
public const string CostCenter = Default + ".CostCenter";
public const string Leave = Default + ".Leave";
public const string Overtime = Default + ".Overtime";
public const string Expense = Default + ".Expense";
public const string Payroll = Default + ".Payroll";
public const string Template360 = Default + ".Template360";
public const string Performance360 = Default + ".Performance360";

View file

@ -72,4 +72,5 @@ public class Employee : FullAuditedEntity<Guid>, IMultiTenant
public ICollection<Visitor> Visitors { get; set; }
public ICollection<Reservation> Reservations { get; set; }
public ICollection<Certificate> Certificates { get; set; }
public ICollection<Expense> ExpenseRequests { get; set; }
}

View file

@ -0,0 +1,28 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Kurs.Platform.Entities;
public class Expense : FullAuditedEntity<Guid>, IMultiTenant
{
public Guid? TenantId { get; set; }
public Guid? EmployeeId { get; set; }
public Employee Employee { get; set; }
public string Category { get; set; }
public decimal Amount { get; set; }
public Guid? CurrencyId { get; set; }
public Currency Currency { get; set; }
public DateTime RequestDate { get; set; }
public string Description { get; set; }
public string Project { get; set; }
public string Status { get; set; }
public Guid? ApproverId { get; set; }
public Employee Approver { get; set; }
public DateTime? ApprovalDate { get; set; }
public string RejectionReason { get; set; }
public string Notes { get; set; }
}

View file

@ -65,17 +65,48 @@ public class QueryHelper
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();
// 🔹 Kabul edilen olası tarih formatları (tüm dillerde yaygın)
var possibleFormats = new[]
{
"yyyy-MM-dd",
"dd.MM.yyyy",
"dd/MM/yyyy",
"MM/dd/yyyy",
"yyyy/MM/dd",
"yyyy-MM-ddTHH:mm:ss",
"yyyy-MM-ddTHH:mm:ss.fff",
"yyyy-MM-ddTHH:mm:ssZ",
"yyyy-MM-dd HH:mm:ss",
"dd.MM.yyyy HH:mm:ss",
"dd/MM/yyyy HH:mm:ss",
"MM/dd/yyyy HH:mm:ss"
};
// Genel parse denemesi
if (DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out dto))
// 🔹 1. Önce ISO / Invariant formatları dene
if (DateTimeOffset.TryParseExact(s, possibleFormats,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
out var dto))
{
return dto.ToUniversalTime();
}
// Başarısızsa null dön
// 🔹 2. Eğer olmadıysa kültür bağımlı genel parse denemesi
if (DateTimeOffset.TryParse(s, CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out dto))
{
return dto.ToUniversalTime();
}
// 🔹 3. Son çare: system culture veya ISO fallback
if (DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dto))
{
return dto.ToUniversalTime();
}
// 🔹 Parse edilemezse null
return (DateTimeOffset?)null;
}).ToArray();
value = isArray ? dateTimeValues : dateTimeValues[0];
break;
case DbType.Int16:

View file

@ -183,6 +183,7 @@ public class PlatformDbContext :
public DbSet<ShuttleRoute> ShuttleRoutes { get; set; }
public DbSet<Announcement> Announcements { get; set; }
public DbSet<Visitor> Visitors { get; set; }
public DbSet<Expense> ExpenseRequests { get; set; }
#endregion
@ -2000,5 +2001,27 @@ public class PlatformDbContext :
.HasPrincipalKey(e => e.Id)
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<Expense>(b =>
{
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.Expense)), Prefix.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.EmployeeId).IsRequired();
b.Property(x => x.Category).IsRequired().HasMaxLength(50);
b.Property(x => x.Amount).IsRequired().HasPrecision(18, 2);
b.Property(x => x.RequestDate).IsRequired();
b.Property(x => x.Description).HasMaxLength(1000);
b.Property(x => x.Project).HasMaxLength(200);
b.Property(x => x.Status).IsRequired().HasMaxLength(20);
b.Property(x => x.RejectionReason).HasMaxLength(300);
b.Property(x => x.Notes).HasMaxLength(1000);
b.HasOne(x => x.Employee)
.WithMany(e => e.ExpenseRequests)
.HasForeignKey(x => x.EmployeeId)
.HasPrincipalKey(e => e.Id)
.OnDelete(DeleteBehavior.Restrict);
});
}
}

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Kurs.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20251025204259_Initial")]
[Migration("20251026200120_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -4009,6 +4009,101 @@ namespace Kurs.Platform.Migrations
b.ToTable("T_Net_EventType", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.Expense", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<DateTime?>("ApprovalDate")
.HasColumnType("datetime2");
b.Property<Guid?>("ApproverId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Category")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("CurrencyId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<Guid>("EmployeeId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Notes")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("Project")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("RejectionReason")
.HasMaxLength(300)
.HasColumnType("nvarchar(300)");
b.Property<DateTime>("RequestDate")
.HasColumnType("datetime2");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("ApproverId");
b.HasIndex("CurrencyId");
b.HasIndex("EmployeeId");
b.ToTable("T_Hr_Expense", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.GlobalSearch", b =>
{
b.Property<int>("Id")
@ -10969,6 +11064,29 @@ namespace Kurs.Platform.Migrations
b.Navigation("Event");
});
modelBuilder.Entity("Kurs.Platform.Entities.Expense", b =>
{
b.HasOne("Kurs.Platform.Entities.Employee", "Approver")
.WithMany()
.HasForeignKey("ApproverId");
b.HasOne("Kurs.Platform.Entities.Currency", "Currency")
.WithMany()
.HasForeignKey("CurrencyId");
b.HasOne("Kurs.Platform.Entities.Employee", "Employee")
.WithMany("ExpenseRequests")
.HasForeignKey("EmployeeId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Approver");
b.Navigation("Currency");
b.Navigation("Employee");
});
modelBuilder.Entity("Kurs.Platform.Entities.JobPosition", b =>
{
b.HasOne("Kurs.Platform.Entities.Currency", "Currency")
@ -11470,6 +11588,8 @@ namespace Kurs.Platform.Migrations
b.Navigation("Certificates");
b.Navigation("ExpenseRequests");
b.Navigation("Leaves");
b.Navigation("Overtimes");

View file

@ -4119,6 +4119,53 @@ namespace Kurs.Platform.Migrations
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "T_Hr_Expense",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
EmployeeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Category = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
Amount = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
CurrencyId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
RequestDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
Project = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Status = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
ApproverId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
ApprovalDate = table.Column<DateTime>(type: "datetime2", nullable: true),
RejectionReason = table.Column<string>(type: "nvarchar(300)", maxLength: 300, nullable: true),
Notes = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, 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),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_T_Hr_Expense", x => x.Id);
table.ForeignKey(
name: "FK_T_Hr_Expense_P_Sas_Currency_CurrencyId",
column: x => x.CurrencyId,
principalTable: "P_Sas_Currency",
principalColumn: "Id");
table.ForeignKey(
name: "FK_T_Hr_Expense_T_Hr_Employee_ApproverId",
column: x => x.ApproverId,
principalTable: "T_Hr_Employee",
principalColumn: "Id");
table.ForeignKey(
name: "FK_T_Hr_Expense_T_Hr_Employee_EmployeeId",
column: x => x.EmployeeId,
principalTable: "T_Hr_Employee",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "T_Hr_Leave",
columns: table => new
@ -4946,6 +4993,21 @@ namespace Kurs.Platform.Migrations
table: "T_Hr_Employee",
column: "ManagerId");
migrationBuilder.CreateIndex(
name: "IX_T_Hr_Expense_ApproverId",
table: "T_Hr_Expense",
column: "ApproverId");
migrationBuilder.CreateIndex(
name: "IX_T_Hr_Expense_CurrencyId",
table: "T_Hr_Expense",
column: "CurrencyId");
migrationBuilder.CreateIndex(
name: "IX_T_Hr_Expense_EmployeeId",
table: "T_Hr_Expense",
column: "EmployeeId");
migrationBuilder.CreateIndex(
name: "IX_T_Hr_JobPosition_CurrencyId",
table: "T_Hr_JobPosition",
@ -5338,6 +5400,9 @@ namespace Kurs.Platform.Migrations
migrationBuilder.DropTable(
name: "T_Crd_QuestionTag");
migrationBuilder.DropTable(
name: "T_Hr_Expense");
migrationBuilder.DropTable(
name: "T_Hr_Leave");

View file

@ -4006,6 +4006,101 @@ namespace Kurs.Platform.Migrations
b.ToTable("T_Net_EventType", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.Expense", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<DateTime?>("ApprovalDate")
.HasColumnType("datetime2");
b.Property<Guid?>("ApproverId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Category")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("CurrencyId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<Guid>("EmployeeId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Notes")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("Project")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("RejectionReason")
.HasMaxLength(300)
.HasColumnType("nvarchar(300)");
b.Property<DateTime>("RequestDate")
.HasColumnType("datetime2");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("ApproverId");
b.HasIndex("CurrencyId");
b.HasIndex("EmployeeId");
b.ToTable("T_Hr_Expense", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.GlobalSearch", b =>
{
b.Property<int>("Id")
@ -10966,6 +11061,29 @@ namespace Kurs.Platform.Migrations
b.Navigation("Event");
});
modelBuilder.Entity("Kurs.Platform.Entities.Expense", b =>
{
b.HasOne("Kurs.Platform.Entities.Employee", "Approver")
.WithMany()
.HasForeignKey("ApproverId");
b.HasOne("Kurs.Platform.Entities.Currency", "Currency")
.WithMany()
.HasForeignKey("CurrencyId");
b.HasOne("Kurs.Platform.Entities.Employee", "Employee")
.WithMany("ExpenseRequests")
.HasForeignKey("EmployeeId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Approver");
b.Navigation("Currency");
b.Navigation("Employee");
});
modelBuilder.Entity("Kurs.Platform.Entities.JobPosition", b =>
{
b.HasOne("Kurs.Platform.Entities.Currency", "Currency")
@ -11467,6 +11585,8 @@ namespace Kurs.Platform.Migrations
b.Navigation("Certificates");
b.Navigation("ExpenseRequests");
b.Navigation("Leaves");
b.Navigation("Overtimes");

View file

@ -3671,5 +3671,43 @@
"purpose": "Teknik Sunum",
"status": "checked-out"
}
],
"ExpenseRequests": [
{
"employeeCode": "EMP-001",
"category": "travel",
"amount": 850,
"currencyCode": "TRY",
"requestDate": "08-10-2024",
"description": "Ankara ofis ziyareti - uçak bileti",
"project": "Intranet v2",
"status": "approved",
"approverCode": "EMP-004",
"approvalDate": "10-10-2024"
},
{
"employeeCode": "EMP-002",
"category": "meal",
"amount": 320,
"currencyCode": "TRY",
"requestDate": "07-10-2024",
"description": "Müşteri toplantısı - öğle yemeği",
"project": null,
"status": "pending",
"approverCode": null,
"approvalDate": null
},
{
"employeeCode": "EMP-003",
"category": "accommodation",
"amount": 1200,
"currencyCode": "TRY",
"requestDate": "04-10-2024",
"description": "İzmir workshop - otel konaklaması (2 gece)",
"project": "UX Workshop",
"status": "approved",
"approverCode": "EMP-005",
"approvalDate": "05-10-2024"
}
]
}

View file

@ -13,6 +13,7 @@ using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
using Volo.Abp.Identity;
using Azure.Core;
namespace Kurs.Platform.Data.Seeds;
@ -78,6 +79,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
private readonly IRepository<ShuttleRoute, Guid> _shuttleRouteRepository;
private readonly IRepository<Announcement, Guid> _announcementRepository;
private readonly IRepository<Visitor, Guid> _visitorRepository;
private readonly IRepository<Expense, Guid> _expenseRepository;
public TenantDataSeeder(
IRepository<IdentityUser, Guid> repositoryUser,
@ -139,7 +141,8 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
IRepository<Reservation, Guid> reservationRepository,
IRepository<ShuttleRoute, Guid> shuttleRouteRepository,
IRepository<Announcement, Guid> announcementRepository,
IRepository<Visitor, Guid> visitorRepository
IRepository<Visitor, Guid> visitorRepository,
IRepository<Expense, Guid> expenseRepository
)
{
_repositoryUser = repositoryUser;
@ -202,6 +205,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
_shuttleRouteRepository = shuttleRouteRepository;
_announcementRepository = announcementRepository;
_visitorRepository = visitorRepository;
_expenseRepository = expenseRepository;
}
private static IConfigurationRoot BuildConfiguration()
@ -1190,7 +1194,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
Status = item.Status,
DepartmentId = department != null ? department.Id : null,
TargetEmployees = string.Join("|", targetEmployees.Select(e => e.Id))
}, autoSave: true);
});
}
foreach (var item in items.Trainings)
@ -1213,7 +1217,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
Status = item.Status,
Location = item.Location,
Thumbnail = item.Thumbnail
}, autoSave: true);
});
}
foreach (var item in items.Reservations)
@ -1234,7 +1238,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
Participants = item.Participants,
Notes = item.Notes,
Status = item.Status
}, autoSave: true);
});
}
foreach (var item in items.ShuttleRoutes)
@ -1252,7 +1256,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
Capacity = item.Capacity,
Available = item.Available,
Type = item.Type
}, autoSave: true);
});
}
foreach (var item in items.Announcements)
@ -1283,7 +1287,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
IsPinned = item.IsPinned,
ViewCount = item.ViewCount,
Departments = string.Join("|", targetDepartments.Select(d => d.Id)),
}, autoSave: true);
});
}
@ -1306,7 +1310,31 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
CheckOut = item.CheckOut,
EmployeeId = employee != null ? employee.Id : null,
Status = item.Status
}, autoSave: true);
});
}
foreach (var item in items.ExpenseRequests)
{
var employee = await _employeeRepository.FirstOrDefaultAsync(x => x.Code == item.EmployeeCode);
var exists = await _expenseRepository.AnyAsync(x => x.EmployeeId == employee.Id && x.RequestDate == item.RequestDate);
if (exists)
continue;
var approver = await _employeeRepository.FirstOrDefaultAsync(x => x.Code == item.ApproverCode);
var currency = await _currencyRepository.FirstOrDefaultAsync(x => x.Code == item.CurrencyCode);
await _expenseRepository.InsertAsync(new Expense
{
EmployeeId = employee != null ? employee.Id : null,
Category = item.Category,
Amount = item.Amount,
CurrencyId = currency != null ? currency.Id : null,
RequestDate = item.RequestDate,
Description = item.Description,
Project = item.Project,
Status = item.Status,
ApproverId = approver != null ? approver.Id : null,
ApprovalDate = item.ApprovalDate
});
}
}
}

View file

@ -67,6 +67,21 @@ public class TenantSeederDto
public List<ShuttleRouteSeedDto> ShuttleRoutes { get; set; }
public List<AnnouncementSeedDto> Announcements { get; set; }
public List<VisitorSeedDto> Visitors { get; set; }
public List<ExpenseRequestSeedDto> ExpenseRequests { get; set; }
}
public class ExpenseRequestSeedDto
{
public string EmployeeCode { get; set; }
public string Category { get; set; }
public decimal Amount { get; set; }
public string CurrencyCode { get; set; }
public DateTime RequestDate { get; set; }
public string Description { get; set; }
public string Project { get; set; }
public string Status { get; set; }
public string ApproverCode { get; set; }
public DateTime? ApprovalDate { get; set; }
}
public class VisitorSeedDto

View file

@ -1,5 +1,5 @@
.menu-item {
@apply cursor-pointer font-medium rounded-md flex items-center w-full whitespace-nowrap gap-x-1 px-1.5;
@apply cursor-pointer font-medium rounded-md flex items-center w-full whitespace-nowrap px-1.5;
&.menu-item-light {
@apply text-gray-600;

View file

@ -86,9 +86,9 @@ export const mockSurveys: Survey[] = [
2: 'Kötü',
3: 'Orta',
4: 'İyi',
5: 'Çok İyi'
}
}
5: 'Çok İyi',
},
},
},
{
id: 'q2',
@ -102,8 +102,8 @@ export const mockSurveys: Survey[] = [
{ id: 'opt2', text: 'İnsan Kaynakları', order: 2 },
{ id: 'opt3', text: 'Finans', order: 3 },
{ id: 'opt4', text: 'Satış', order: 4 },
{ id: 'opt5', text: 'Pazarlama', order: 5 }
]
{ id: 'opt5', text: 'Pazarlama', order: 5 },
],
},
{
id: 'q3',
@ -111,7 +111,7 @@ export const mockSurveys: Survey[] = [
questionText: 'Görüş ve önerileriniz',
type: 'textarea',
order: 3,
isRequired: false
isRequired: false,
},
{
id: 'q4',
@ -119,8 +119,8 @@ export const mockSurveys: Survey[] = [
questionText: 'Çalışma ortamından memnun musunuz?',
type: 'yes-no',
order: 4,
isRequired: true
}
isRequired: true,
},
],
responses: 45,
targetAudience: ['Tüm Çalışanlar'],
@ -147,8 +147,8 @@ export const mockSurveys: Survey[] = [
{ id: 'opt7', text: 'Node.js / Backend', order: 2 },
{ id: 'opt8', text: 'Database / SQL', order: 3 },
{ id: 'opt9', text: 'DevOps / Cloud', order: 4 },
{ id: 'opt10', text: 'Mobile Development', order: 5 }
]
{ id: 'opt10', text: 'Mobile Development', order: 5 },
],
},
{
id: 'q6',
@ -160,8 +160,8 @@ export const mockSurveys: Survey[] = [
options: [
{ id: 'opt11', text: 'Online Eğitim', order: 1 },
{ id: 'opt12', text: 'Yüz Yüze Eğitim', order: 2 },
{ id: 'opt13', text: 'Hibrit (Karma)', order: 3 }
]
{ id: 'opt13', text: 'Hibrit (Karma)', order: 3 },
],
},
{
id: 'q7',
@ -176,10 +176,10 @@ export const mockSurveys: Survey[] = [
labels: {
1: '1 saat',
5: '5 saat',
10: '10+ saat'
}
}
}
10: '10+ saat',
},
},
},
],
responses: 28,
targetAudience: ['Yazılım Geliştirme', 'Ürün Yönetimi'],
@ -209,9 +209,9 @@ export const mockSurveys: Survey[] = [
2: 'Kötü',
3: 'Orta',
4: 'İyi',
5: 'Mükemmel'
}
}
5: 'Mükemmel',
},
},
},
{
id: 'q9',
@ -219,7 +219,7 @@ export const mockSurveys: Survey[] = [
questionText: 'Hangi yemekleri daha sık görmek istiyorsunuz?',
type: 'textarea',
order: 2,
isRequired: false
isRequired: false,
},
{
id: 'q10',
@ -227,8 +227,8 @@ export const mockSurveys: Survey[] = [
questionText: 'Servis hızından memnun musunuz?',
type: 'yes-no',
order: 3,
isRequired: true
}
isRequired: true,
},
],
responses: 62,
targetAudience: ['Tüm Çalışanlar'],
@ -1065,4 +1065,4 @@ export const mockExpenseRequests: ExpenseRequest[] = [
approvalDate: new Date('2024-10-15T09:00:00'),
creationTime: new Date('2024-10-14T22:00:00'),
},
]
]

View file

@ -258,12 +258,12 @@ function RolesPermission({
onClose={onDialogClose}
onRequestClose={onDialogClose}
>
<h5 className="mb-4">
<h5 className="mb-1">
{translate('::Permission')} - {name}
</h5>
<hr className="mt-2 mb-2"></hr>
<hr className="mt-1 mb-1"></hr>
<div className="flex flex-col md:flex-row gap-4 mb-2">
<div className="flex flex-col md:flex-row gap-4 mb-1">
<div style={{ width: '30%' }}>
<Checkbox name="all" checked={isAllSelected} onChange={onSelectAll}>
{translate('AbpPermissionManagement::SelectAllInAllTabs')}

View file

@ -270,6 +270,7 @@ const Grid = (props: GridProps) => {
// Grid'den gelen columnFormat'ları kullanarak default değerleri set et
if (colFormat.defaultValue != null) {
console.log('Setting default value for', colFormat.fieldName, colFormat.defaultValue)
e.data[colFormat.fieldName] = colFormat.defaultValue
}