merge from programManager Move
This commit is contained in:
@@ -1,21 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<RootNamespace>_0_Framework</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="IPE.SmsIR" Version="1.0.5" />
|
||||
<PackageReference Include="EPPlus" Version="7.5.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.1.34" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.2" />
|
||||
<PackageReference Include="IPE.SmsIR" Version="1.2.7" />
|
||||
<PackageReference Include="EPPlus" Version="8.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.3" />
|
||||
<PackageReference Include="PersianTools.Core" Version="2.0.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
|
||||
<PackageReference Include="MD.PersianDateTime.Standard" Version="2.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.2.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="10.0.1" />
|
||||
<PackageReference Include="MD.PersianDateTime.Standard" Version="2.6.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="10.0.1" />
|
||||
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -198,7 +198,8 @@ public class AuthHelper : IAuthHelper
|
||||
new("workshopList",workshopBson),
|
||||
new("WorkshopSlug",slug),
|
||||
new("WorkshopId", account.WorkshopId.ToString()),
|
||||
new("WorkshopName",account.WorkshopName??"")
|
||||
new("WorkshopName",account.WorkshopName??""),
|
||||
new("pm.userId", account.PmUserId?.ToString() ?? "0"),
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -27,10 +27,12 @@ public class AuthViewModel
|
||||
#endregion
|
||||
|
||||
public long SubAccountId { get; set; }
|
||||
public long? PmUserId { get; set; }
|
||||
|
||||
|
||||
public AuthViewModel(long id, long roleId, string fullname, string username, string mobile,string profilePhoto,
|
||||
List<int> permissions, string roleName, string adminAreaPermission, string clientAriaPermission, int? positionValue, long subAccountId = 0)
|
||||
List<int> permissions, string roleName, string adminAreaPermission, string clientAriaPermission, int? positionValue,
|
||||
long subAccountId = 0,long? pmUserId = null)
|
||||
{
|
||||
Id = id;
|
||||
RoleId = roleId;
|
||||
@@ -44,6 +46,7 @@ public class AuthViewModel
|
||||
ClientAriaPermission = clientAriaPermission;
|
||||
PositionValue = positionValue;
|
||||
SubAccountId = subAccountId;
|
||||
PmUserId = pmUserId;
|
||||
}
|
||||
|
||||
public AuthViewModel()
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
|
||||
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\0_Framework\0_Framework.csproj" />
|
||||
<ProjectReference Include="..\Shared.Contracts\Shared.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using _0_Framework.Application;
|
||||
using AccountManagement.Application.Contracts.ProgramManager;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Shared.Contracts.PmRole.Queries;
|
||||
|
||||
namespace AccountManagement.Application.Contracts.Role
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AccountManagement.Application.Contracts.ProgramManager;
|
||||
using Shared.Contracts.PmUser;
|
||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
|
||||
|
||||
//using AccountManagement.Domain.RoleAgg;
|
||||
@@ -58,9 +59,10 @@ public class AccountApplication : IAccountApplication
|
||||
private readonly ISubAccountPermissionSubtitle1Repository _accountPermissionSubtitle1Repository;
|
||||
private readonly IPmUserRepository _pmUserRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IPmUserQueryService _pmUserQueryService;
|
||||
|
||||
public AccountApplication(IAccountRepository accountRepository, IPasswordHasher passwordHasher,
|
||||
IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserRepository pmUserRepository)
|
||||
IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserRepository pmUserRepository, IPmUserQueryService pmUserQueryService)
|
||||
{
|
||||
_authHelper = authHelper;
|
||||
_roleRepository = roleRepository;
|
||||
@@ -75,6 +77,7 @@ public class AccountApplication : IAccountApplication
|
||||
_accountPermissionSubtitle1Repository = accountPermissionSubtitle1Repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_pmUserRepository = pmUserRepository;
|
||||
_pmUserQueryService = pmUserQueryService;
|
||||
_fileUploader = fileUploader;
|
||||
_passwordHasher = passwordHasher;
|
||||
_accountRepository = accountRepository;
|
||||
@@ -463,8 +466,11 @@ public class AccountApplication : IAccountApplication
|
||||
{
|
||||
positionValue = null;
|
||||
}
|
||||
var pmUserId = _pmUserQueryService.GetCurrentPmUserIdFromAccountId(account.id).GetAwaiter().GetResult();
|
||||
var authViewModel = new AuthViewModel(account.id, account.RoleId, account.Fullname
|
||||
, account.Username, account.Mobile, account.ProfilePhoto, permissions, account.RoleName, account.AdminAreaPermission, account.ClientAriaPermission, positionValue);
|
||||
, account.Username, account.Mobile, account.ProfilePhoto,
|
||||
permissions, account.RoleName, account.AdminAreaPermission,
|
||||
account.ClientAriaPermission, positionValue,0,pmUserId);
|
||||
|
||||
if (account.ClientAriaPermission == "true" && account.AdminAreaPermission == "false" &&
|
||||
account.IsActiveString == "true")
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AccountManagement.Application.Contracts\AccountManagement.Application.Contracts.csproj" />
|
||||
<ProjectReference Include="..\AccountManagement.Domain\AccountManagement.Domain.csproj" />
|
||||
<ProjectReference Include="..\Company.Domain\Company.Domain.csproj" />
|
||||
<ProjectReference Include="..\Shared.Contracts\Shared.Contracts.csproj" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ using AccountManagement.Domain.RoleAgg;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AccountManagement.Application.Contracts.ProgramManager;
|
||||
using AccountManagement.Application.Contracts.ProgramManagerApiResult;
|
||||
using AccountManagement.Domain.InternalApiCaller;
|
||||
using Company.Domain._common;
|
||||
@@ -13,7 +12,10 @@ using AccountManagement.Domain.PmDomains.PmPermissionAgg;
|
||||
using AccountManagement.Domain.PmDomains.PmRoleAgg;
|
||||
using AccountManagement.Domain.PmDomains.PmUserAgg;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Shared.Contracts.PmRole.Commands;
|
||||
using GetPmRolesDto = Shared.Contracts.PmRole.Queries.GetPmRolesDto;
|
||||
using Role = AccountManagement.Domain.RoleAgg.Role;
|
||||
using Shared.Contracts.PmRole.Queries;
|
||||
|
||||
namespace AccountManagement.Application;
|
||||
|
||||
@@ -22,14 +24,18 @@ public class RoleApplication : IRoleApplication
|
||||
private readonly IRoleRepository _roleRepository;
|
||||
private readonly IPmRoleRepository _pmRoleRepository;
|
||||
private readonly IPmUserRepository _pmUserRepository;
|
||||
private readonly IPmRoleQueryService _pmRoleQueryService;
|
||||
private readonly IPmRoleCommandService _pmRoleCommandService;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleRepository pmRoleRepository, IPmUserRepository pmUserRepository)
|
||||
public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleRepository pmRoleRepository, IPmUserRepository pmUserRepository, IPmRoleQueryService pmRoleQueryService, IPmRoleCommandService pmRoleCommandService)
|
||||
{
|
||||
_roleRepository = roleRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_pmRoleRepository = pmRoleRepository;
|
||||
_pmUserRepository = pmUserRepository;
|
||||
_pmRoleQueryService = pmRoleQueryService;
|
||||
_pmRoleCommandService = pmRoleCommandService;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Create(CreateRole command)
|
||||
@@ -47,19 +53,15 @@ public class RoleApplication : IRoleApplication
|
||||
var pmPermissions = command.PmPermissions.Where(x => x > 0).ToList();
|
||||
if (pmPermissions.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
var pmPermissionsData = pmPermissions.Where(x => x > 0).Select(x => new PmPermission(x)).ToList();
|
||||
var pmRole = new PmRole(command.Name, role.id, pmPermissionsData);
|
||||
await _pmRoleRepository.CreateAsync(pmRole);
|
||||
await _pmRoleRepository.SaveChangesAsync();
|
||||
|
||||
}
|
||||
catch (System.Exception)
|
||||
|
||||
var pmRole = new CreatePmRoleDto{ RoleName = command.Name, Permissions = pmPermissions, GozareshgirRoleId = role.id};
|
||||
var res =await _pmRoleCommandService.Create(pmRole);
|
||||
if (!res.Item1)
|
||||
{
|
||||
_unitOfWork.RollbackAccountContext();
|
||||
return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر");
|
||||
}
|
||||
|
||||
|
||||
//var parameters = new CreateProgramManagerRole
|
||||
//{
|
||||
@@ -136,24 +138,20 @@ public class RoleApplication : IRoleApplication
|
||||
//);
|
||||
|
||||
|
||||
var pmRoleResult = await _pmRoleRepository.GetPmRoleToEdit(command.Id);
|
||||
|
||||
var pmRoleListResult = await _pmRoleQueryService.GetPmRoleList(command.Id);
|
||||
var pmRoleResult = pmRoleListResult.FirstOrDefault();
|
||||
|
||||
//اگر این نقش در پروگرام منیجر وجود داشت ویرایش کن
|
||||
if (pmRoleResult != null)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var pmpermissionsData = pmPermissions.Where(x => x > 0).Select(x => new PmPermission(x)).ToList();
|
||||
pmRoleResult.Edit(command.Name, pmpermissionsData);
|
||||
await _pmRoleRepository.SaveChangesAsync();
|
||||
}
|
||||
catch (System.Exception)
|
||||
var edit = new CreatePmRoleDto { RoleName = command.Name, Permissions = pmPermissions, GozareshgirRoleId = role.id };
|
||||
var res = await _pmRoleCommandService.Edit(edit);
|
||||
if (!res.Item1)
|
||||
{
|
||||
_unitOfWork.RollbackAccountContext();
|
||||
return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//var parameters = new CreateProgramManagerRole
|
||||
@@ -254,7 +252,7 @@ public class RoleApplication : IRoleApplication
|
||||
|
||||
public async Task<SelectList> GetPmRoleList(long? gozareshgirRoleId)
|
||||
{
|
||||
var rolse = await _pmRoleRepository.GetPmRoleList(gozareshgirRoleId);
|
||||
var rolse = await _pmRoleQueryService.GetPmRoleList(gozareshgirRoleId);
|
||||
return new SelectList(rolse, "Id", "RoleName");
|
||||
|
||||
|
||||
@@ -262,7 +260,7 @@ public class RoleApplication : IRoleApplication
|
||||
|
||||
public async Task<List<GetPmRolesDto>> GetPmRoleListToEdit(long? gozareshgirRoleId)
|
||||
{
|
||||
return await _pmRoleRepository.GetPmRoleList(gozareshgirRoleId);
|
||||
return await _pmRoleQueryService.GetPmRoleList(gozareshgirRoleId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
|
||||
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\0_Framework\0_Framework.csproj" />
|
||||
<ProjectReference Include="..\AccountManagement.Application.Contracts\AccountManagement.Application.Contracts.csproj" />
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
|
||||
<PackageReference Include="Azure.Identity" Version="1.17.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -18,6 +20,10 @@
|
||||
<ProjectReference Include="..\Company.Domain\Company.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Services\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Mappings\BugReportMapping.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AccountMangement.Infrastructure.EFCore.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class addprogrammangerbooinaccount : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsProgramManagerUser",
|
||||
table: "Accounts",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsProgramManagerUser",
|
||||
table: "Accounts");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AccountMangement.Infrastructure.EFCore.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class romoveIsProgramManagerUserFromAccount : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsProgramManagerUser",
|
||||
table: "Accounts");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsProgramManagerUser",
|
||||
table: "Accounts",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.10")
|
||||
.HasAnnotation("ProductVersion", "10.0.1")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
@@ -377,6 +377,87 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations
|
||||
b.ToTable("Medias", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b =>
|
||||
{
|
||||
b.Property<long>("id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<long?>("GozareshgirRoleId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("RoleName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.HasKey("id");
|
||||
|
||||
b.ToTable("PmRoles", null, t =>
|
||||
{
|
||||
t.ExcludeFromMigrations();
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b =>
|
||||
{
|
||||
b.Property<long>("id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
|
||||
|
||||
b.Property<long?>("AccountId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(150)
|
||||
.HasColumnType("nvarchar(150)");
|
||||
|
||||
b.Property<string>("FullName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Mobile")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("nvarchar(1000)");
|
||||
|
||||
b.Property<string>("ProfilePhotoPath")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<string>("VerifyCode")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("nvarchar(10)");
|
||||
|
||||
b.HasKey("id");
|
||||
|
||||
b.ToTable("Users", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AccountManagement.Domain.PositionAgg.Position", b =>
|
||||
{
|
||||
b.Property<long>("id")
|
||||
@@ -1001,6 +1082,71 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations
|
||||
b.Navigation("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b =>
|
||||
{
|
||||
b.OwnsMany("AccountManagement.Domain.PmDomains.PmPermissionAgg.PmPermission", "PmPermission", b1 =>
|
||||
{
|
||||
b1.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<long>("Id"));
|
||||
|
||||
b1.Property<int>("Code")
|
||||
.HasColumnType("int");
|
||||
|
||||
b1.Property<long>("Roleid")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("Roleid");
|
||||
|
||||
b1.ToTable("PmRolePermissions", null, t =>
|
||||
{
|
||||
t.ExcludeFromMigrations();
|
||||
});
|
||||
|
||||
b1.WithOwner("Role")
|
||||
.HasForeignKey("Roleid");
|
||||
|
||||
b1.Navigation("Role");
|
||||
});
|
||||
|
||||
b.Navigation("PmPermission");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b =>
|
||||
{
|
||||
b.OwnsMany("AccountManagement.Domain.PmDomains.PmRoleUserAgg.PmRoleUser", "RoleUser", b1 =>
|
||||
{
|
||||
b1.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<long>("Id"));
|
||||
|
||||
b1.Property<long>("RoleId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.Property<long>("Userid")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("Userid");
|
||||
|
||||
b1.ToTable("RoleUsers", (string)null);
|
||||
|
||||
b1.WithOwner("User")
|
||||
.HasForeignKey("Userid");
|
||||
|
||||
b1.Navigation("User");
|
||||
});
|
||||
|
||||
b.Navigation("RoleUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b =>
|
||||
{
|
||||
b.OwnsMany("AccountManagement.Domain.RoleAgg.Permission", "Permissions", b1 =>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<AssemblyName>BackgroundInstitutionContract.Task</AssemblyName>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -20,7 +20,11 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MongoDB.Bson" Version="3.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
|
||||
<PackageReference Include="MongoDB.Bson" Version="3.5.2" />
|
||||
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EPPlus" Version="7.5.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
|
||||
<PackageReference Include="Azure.Identity" Version="1.17.1" />
|
||||
<PackageReference Include="EPPlus" Version="8.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AccountMangement.Infrastructure.EFCore\AccountMangement.Infrastructure.EFCore.csproj" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
@@ -11,7 +11,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MongoDB.Driver" Version="3.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="3.5.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
|
||||
<PackageReference Include="PersianTools.Core" Version="2.0.4" />
|
||||
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AndroidXml" Version="1.1.24" />
|
||||
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
|
||||
<PackageReference Include="Azure.Identity" Version="1.17.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
|
||||
<PackageReference Include="Azure.Identity" Version="1.17.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.QualityTools.Testing.Fakes" Version="16.11.230815" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="3.5.0" />
|
||||
<PackageReference Include="Microsoft.QualityTools.Testing.Fakes" Version="18.1.1" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="3.5.2" />
|
||||
<PackageReference Include="Parbad.Gateway.Sepehr" Version="1.7.0" />
|
||||
<PackageReference Include="PersianTools.Core" Version="2.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
14
CompanyManagment.EFCore/Services/HolidayQueryService.cs
Normal file
14
CompanyManagment.EFCore/Services/HolidayQueryService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Shared.Contracts.Holidays;
|
||||
|
||||
namespace CompanyManagment.EFCore.Services;
|
||||
|
||||
public class HolidayQueryService : IHolidayQueryService
|
||||
{
|
||||
public Task<List<HolidayDto>> GetHolidaysInDates(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,24 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompanyManagement.Infrastru
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundInstitutionContract.Task", "BackgroundInstitutionContract\BackgroundInstitutionContract.Task\BackgroundInstitutionContract.Task.csproj", "{F78FBB92-294B-88BA-168D-F0C578B0D7D6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ProgramManager", "ProgramManager", "{67AFF7B6-4C4F-464C-A90D-9BDB644D83A9}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{9D85672B-D48E-40B5-9804-0CE220E0E64C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{D74D1E3B-3BE3-47EE-9914-785A8AD536E5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{C0AE9368-D4E7-450B-9713-929D319DE690}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.Application", "ProgramManager\src\Application\GozareshgirProgramManager.Application\GozareshgirProgramManager.Application.csproj", "{B57EB542-C028-4A77-9386-9DFF1E60FDCB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.Domain", "ProgramManager\src\Domain\GozareshgirProgramManager.Domain\GozareshgirProgramManager.Domain.csproj", "{D2B4F1D7-6336-4B30-910C-219F4119303F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.Infrastructure", "ProgramManager\src\Infrastructure\GozareshgirProgramManager.Infrastructure\GozareshgirProgramManager.Infrastructure.csproj", "{408281FE-615F-4CBE-BD95-2E86F5ACC6C3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared.Contracts", "Shared.Contracts\Shared.Contracts.csproj", "{08B234B6-783B-44E9-9961-4F97EAD16308}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -198,6 +216,22 @@ Global
|
||||
{F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D2B4F1D7-6336-4B30-910C-219F4119303F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{08B234B6-783B-44E9-9961-4F97EAD16308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{08B234B6-783B-44E9-9961-4F97EAD16308}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{08B234B6-783B-44E9-9961-4F97EAD16308}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{08B234B6-783B-44E9-9961-4F97EAD16308}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -234,6 +268,13 @@ Global
|
||||
{BF98173C-42AF-4897-A7CB-4CACEB2B52A2} = {86921E1B-2AFA-4B8A-9403-EE16D58B5B26}
|
||||
{97E148FA-3C36-40DD-B121-D90C1C0F3B47} = {C10E256D-7E7D-4C77-B416-E577A34AF924}
|
||||
{F78FBB92-294B-88BA-168D-F0C578B0D7D6} = {C10E256D-7E7D-4C77-B416-E577A34AF924}
|
||||
{48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1} = {67AFF7B6-4C4F-464C-A90D-9BDB644D83A9}
|
||||
{9D85672B-D48E-40B5-9804-0CE220E0E64C} = {48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1}
|
||||
{D74D1E3B-3BE3-47EE-9914-785A8AD536E5} = {48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1}
|
||||
{C0AE9368-D4E7-450B-9713-929D319DE690} = {48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1}
|
||||
{B57EB542-C028-4A77-9386-9DFF1E60FDCB} = {9D85672B-D48E-40B5-9804-0CE220E0E64C}
|
||||
{D2B4F1D7-6336-4B30-910C-219F4119303F} = {D74D1E3B-3BE3-47EE-9914-785A8AD536E5}
|
||||
{408281FE-615F-4CBE-BD95-2E86F5ACC6C3} = {C0AE9368-D4E7-450B-9713-929D319DE690}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E6CFB3A7-A7C8-4E82-8F06-F750408F0BA9}
|
||||
|
||||
@@ -1,18 +1,44 @@
|
||||
using System;
|
||||
using _0_Framework.Application.FaceEmbedding;
|
||||
using _0_Framework.Application.UID;
|
||||
using _0_Framework.Infrastructure;
|
||||
using _0_Framework.InfraStructure;
|
||||
using Company.Application.Contracts.AuthorizedBankDetails;
|
||||
using Company.Domain._common;
|
||||
using Company.Domain.AdminMonthlyOverviewAgg;
|
||||
using Company.Domain.AndroidApkVersionAgg;
|
||||
using Company.Domain.AuthorizedBankDetailsAgg;
|
||||
using Company.Domain.AuthorizedPersonAgg;
|
||||
using Company.Domain.BankAgg;
|
||||
using Company.Domain.BillAgg;
|
||||
using Company.Domain.Board;
|
||||
using Company.Domain.ChapterAgg;
|
||||
using Company.Domain.CheckoutAgg;
|
||||
using Company.Domain.ClassifiedSalaryAgg;
|
||||
using Company.Domain.Contact2Agg;
|
||||
using Company.Domain.CrossJobAgg;
|
||||
using Company.Domain.CrossJobGuildAgg;
|
||||
using Company.Domain.ContactUsAgg;
|
||||
using Company.Domain.ContarctingPartyAgg;
|
||||
using Company.Domain.ContractAgg;
|
||||
using Company.Domain.ContractingPartyBankAccountsAgg;
|
||||
using Company.Domain.CrossJobAgg;
|
||||
using Company.Domain.CrossJobGuildAgg;
|
||||
using Company.Domain.CrossJobItemsAgg;
|
||||
using Company.Domain.CustomizeCheckoutAgg;
|
||||
using Company.Domain.CustomizeCheckoutTempAgg;
|
||||
using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg;
|
||||
using Company.Domain.CustomizeWorkshopGroupSettingsAgg;
|
||||
using Company.Domain.CustomizeWorkshopSettingsAgg;
|
||||
using Company.Domain.DateSalaryAgg;
|
||||
using Company.Domain.DateSalaryItemAgg;
|
||||
using Company.Domain.EmployeeAgg;
|
||||
using Company.Domain.EmployeeAuthorizeTempAgg;
|
||||
using Company.Domain.EmployeeBankInformationAgg;
|
||||
using Company.Domain.EmployeeChildrenAgg;
|
||||
using Company.Domain.EmployeeClientTempAgg;
|
||||
using Company.Domain.EmployeeComputeOptionsAgg;
|
||||
using Company.Domain.EmployeeDocumentItemAgg;
|
||||
using Company.Domain.EmployeeDocumentsAdminSelectionAgg;
|
||||
using Company.Domain.EmployeeDocumentsAgg;
|
||||
using Company.Domain.EmployeeFaceEmbeddingAgg;
|
||||
using Company.Domain.empolyerAgg;
|
||||
using Company.Domain.Evidence;
|
||||
using Company.Domain.EvidenceDetail;
|
||||
@@ -23,38 +49,108 @@ using Company.Domain.FileEmployerAgg;
|
||||
using Company.Domain.FileState;
|
||||
using Company.Domain.FileTiming;
|
||||
using Company.Domain.FileTitle;
|
||||
using Company.Domain.FinancialInvoiceAgg;
|
||||
using Company.Domain.FinancialStatmentAgg;
|
||||
using Company.Domain.FinancialTransactionAgg;
|
||||
using Company.Domain.FineAgg;
|
||||
using Company.Domain.FineSubjectAgg;
|
||||
using Company.Domain.GroupPlanAgg;
|
||||
using Company.Domain.GroupPlanJobItemAgg;
|
||||
using Company.Domain.HolidayAgg;
|
||||
using Company.Domain.HolidayItemAgg;
|
||||
using Company.Domain.InstitutionContractAgg;
|
||||
using Company.Domain.InstitutionContractContactInfoAgg;
|
||||
using Company.Domain.InstitutionContractExtensionTempAgg;
|
||||
using Company.Domain.InstitutionPlanAgg;
|
||||
using Company.Domain.InsuranceAgg;
|
||||
using Company.Domain.InsuranceEmployeeInfoAgg;
|
||||
using Company.Domain.InsuranceJobItemAgg;
|
||||
using Company.Domain.InsuranceListAgg;
|
||||
using Company.Domain.InsuranceYearlySalaryAgg;
|
||||
using Company.Domain.InsurancJobAgg;
|
||||
using Company.Domain.InsurancWorkshopInfoAgg;
|
||||
using Company.Domain.JobAgg;
|
||||
using Company.Domain.LawAgg;
|
||||
using Company.Domain.LeaveAgg;
|
||||
using Company.Domain.LeftWorkAgg;
|
||||
using Company.Domain.LeftWorkInsuranceAgg;
|
||||
using Company.Domain.LeftWorkTempAgg;
|
||||
using Company.Domain.LoanAgg;
|
||||
using Company.Domain.MandatoryHoursAgg;
|
||||
using Company.Domain.MasterPenaltyTitle;
|
||||
using Company.Domain.MasterPetition;
|
||||
using Company.Domain.MasterWorkHistory;
|
||||
using Company.Domain.ModuleAgg;
|
||||
using Company.Domain.OriginalTitleAgg;
|
||||
using Company.Domain.PaymentInstrumentAgg;
|
||||
using Company.Domain.PaymentToEmployeeAgg;
|
||||
using Company.Domain.PaymentToEmployeeItemAgg;
|
||||
using Company.Domain.PaymentTransactionAgg;
|
||||
using Company.Domain.PenaltyTitle;
|
||||
using Company.Domain.PercentageAgg;
|
||||
using Company.Domain.PersonnelCodeAgg;
|
||||
using Company.Domain.Petition;
|
||||
using Company.Domain.ProceedingSession;
|
||||
using Company.Domain.ReportAgg;
|
||||
using Company.Domain.ReportClientAgg;
|
||||
using Company.Domain.RepresentativeAgg;
|
||||
using Company.Domain.RewardAgg;
|
||||
using Company.Domain.RollCallAgg;
|
||||
using Company.Domain.RollCallAgg.DomainService;
|
||||
using Company.Domain.RollCallEmployeeAgg;
|
||||
using Company.Domain.RollCallEmployeeStatusAgg;
|
||||
using Company.Domain.RollCallPlanAgg;
|
||||
using Company.Domain.RollCallServiceAgg;
|
||||
using Company.Domain.SalaryAidAgg;
|
||||
using Company.Domain.SmsResultAgg;
|
||||
using Company.Domain.SubtitleAgg;
|
||||
using Company.Domain.TaxJobCategoryAgg;
|
||||
using Company.Domain.TemporaryClientRegistrationAgg;
|
||||
using Company.Domain.WorkHistory;
|
||||
using Company.Domain.WorkingHoursAgg;
|
||||
using Company.Domain.WorkingHoursItemsAgg;
|
||||
using Company.Domain.WorkingHoursTempAgg;
|
||||
using Company.Domain.WorkingHoursTempItemAgg;
|
||||
using Company.Domain.WorkshopAccountAgg;
|
||||
using Company.Domain.WorkshopAgg;
|
||||
using Company.Domain.WorkshopPlanAgg;
|
||||
using Company.Domain.WorkshopPlanEmployeeAgg;
|
||||
using Company.Domain.WorkshopSubAccountAgg;
|
||||
using Company.Domain.YearlySalaryAgg;
|
||||
using Company.Domain.YearlySalaryItemsAgg;
|
||||
using Company.Domain.YearlysSalaryTitleAgg;
|
||||
using Company.Domain.ZoneAgg;
|
||||
using CompanyManagement.Infrastructure.Excel.SalaryAid;
|
||||
using CompanyManagement.Infrastructure.Mongo.EmployeeFaceEmbeddingRepo;
|
||||
using CompanyManagement.Infrastructure.Mongo.InstitutionContractInsertTempRepo;
|
||||
using CompanyManagment.App.Contracts.AdminMonthlyOverview;
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
using CompanyManagment.App.Contracts.AuthorizedPerson;
|
||||
using CompanyManagment.App.Contracts.Bank;
|
||||
using CompanyManagment.App.Contracts.Board;
|
||||
using CompanyManagment.App.Contracts.Chapter;
|
||||
using CompanyManagment.App.Contracts.Checkout;
|
||||
using CompanyManagment.App.Contracts.ClassifiedSalary;
|
||||
using CompanyManagment.App.Contracts.Contact2;
|
||||
using CompanyManagment.App.Contracts.ContactUs;
|
||||
using CompanyManagment.App.Contracts.Contract;
|
||||
using CompanyManagment.App.Contracts.ContractingPartyBankAccounts;
|
||||
using CompanyManagment.App.Contracts.CrossJob;
|
||||
using CompanyManagment.App.Contracts.CrossJobGuild;
|
||||
using CompanyManagment.App.Contracts.CrossJobItems;
|
||||
using CompanyManagment.App.Contracts.CustomizeCheckout;
|
||||
using CompanyManagment.App.Contracts.CustomizeWorkshopSettings;
|
||||
using CompanyManagment.App.Contracts.DateSalary;
|
||||
using CompanyManagment.App.Contracts.DateSalaryItem;
|
||||
using CompanyManagment.App.Contracts.Employee;
|
||||
using CompanyManagment.App.Contracts.EmployeeBankInformation;
|
||||
using CompanyManagment.App.Contracts.EmployeeChildren;
|
||||
using CompanyManagment.App.Contracts.EmployeeClientTemp;
|
||||
using CompanyManagment.App.Contracts.EmployeeComputeOptions;
|
||||
using CompanyManagment.App.Contracts.EmployeeDocuments;
|
||||
using CompanyManagment.App.Contracts.EmployeeDocumentsAdminSelection;
|
||||
using CompanyManagment.App.Contracts.EmployeeFaceEmbedding;
|
||||
using CompanyManagment.App.Contracts.EmployeeInsurancListData;
|
||||
using CompanyManagment.App.Contracts.Employer;
|
||||
using CompanyManagment.App.Contracts.Evidence;
|
||||
using CompanyManagment.App.Contracts.EvidenceDetail;
|
||||
@@ -65,33 +161,74 @@ using CompanyManagment.App.Contracts.FileEmployer;
|
||||
using CompanyManagment.App.Contracts.FileState;
|
||||
using CompanyManagment.App.Contracts.FileTiming;
|
||||
using CompanyManagment.App.Contracts.FileTitle;
|
||||
using CompanyManagment.App.Contracts.FinancialInvoice;
|
||||
using CompanyManagment.App.Contracts.FinancialStatment;
|
||||
using CompanyManagment.App.Contracts.FinancilTransaction;
|
||||
using CompanyManagment.App.Contracts.Fine;
|
||||
using CompanyManagment.App.Contracts.FineSubject;
|
||||
using CompanyManagment.App.Contracts.Holiday;
|
||||
using CompanyManagment.App.Contracts.HolidayItem;
|
||||
using CompanyManagment.App.Contracts.InstitutionContract;
|
||||
using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
|
||||
using CompanyManagment.App.Contracts.InstitutionPlan;
|
||||
using CompanyManagment.App.Contracts.Insurance;
|
||||
using CompanyManagment.App.Contracts.InsuranceEmployeeInfo;
|
||||
using CompanyManagment.App.Contracts.InsuranceJob;
|
||||
using CompanyManagment.App.Contracts.InsuranceList;
|
||||
using CompanyManagment.App.Contracts.InsuranceWorkshopInfo;
|
||||
using CompanyManagment.App.Contracts.InsuranceYearlySalary;
|
||||
using CompanyManagment.App.Contracts.Job;
|
||||
using CompanyManagment.App.Contracts.Law;
|
||||
using CompanyManagment.App.Contracts.Leave;
|
||||
using CompanyManagment.App.Contracts.LeftWork;
|
||||
using CompanyManagment.App.Contracts.LeftWorkInsurance;
|
||||
using CompanyManagment.App.Contracts.LeftWorkTemp;
|
||||
using CompanyManagment.App.Contracts.Loan;
|
||||
using CompanyManagment.App.Contracts.MandantoryHours;
|
||||
using CompanyManagment.App.Contracts.MasterPenaltyTitle;
|
||||
using CompanyManagment.App.Contracts.MasterPetition;
|
||||
using CompanyManagment.App.Contracts.MasterWorkHistory;
|
||||
using CompanyManagment.App.Contracts.Module;
|
||||
using CompanyManagment.App.Contracts.OriginalTitle;
|
||||
using CompanyManagment.App.Contracts.PaymentInstrument;
|
||||
using CompanyManagment.App.Contracts.PaymentToEmployee;
|
||||
using CompanyManagment.App.Contracts.PaymentTransaction;
|
||||
using CompanyManagment.App.Contracts.PenaltyTitle;
|
||||
using CompanyManagment.App.Contracts.Percentage;
|
||||
using CompanyManagment.App.Contracts.PersonalContractingParty;
|
||||
using CompanyManagment.App.Contracts.PersonnleCode;
|
||||
using CompanyManagment.App.Contracts.Petition;
|
||||
using CompanyManagment.App.Contracts.ProceedingSession;
|
||||
using CompanyManagment.App.Contracts.Report;
|
||||
using CompanyManagment.App.Contracts.ReportClient;
|
||||
using CompanyManagment.App.Contracts.Representative;
|
||||
using CompanyManagment.App.Contracts.Reward;
|
||||
using CompanyManagment.App.Contracts.RollCall;
|
||||
using CompanyManagment.App.Contracts.RollCallEmployee;
|
||||
using CompanyManagment.App.Contracts.RollCallEmployeeStatus;
|
||||
using CompanyManagment.App.Contracts.RollCallPlan;
|
||||
using CompanyManagment.App.Contracts.RollCallService;
|
||||
using CompanyManagment.App.Contracts.SalaryAid;
|
||||
using CompanyManagment.App.Contracts.SmsResult;
|
||||
using CompanyManagment.App.Contracts.Subtitle;
|
||||
using CompanyManagment.App.Contracts.TaxJobCategory;
|
||||
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
|
||||
using CompanyManagment.App.Contracts.TextManager;
|
||||
using CompanyManagment.App.Contracts.WorkHistory;
|
||||
using CompanyManagment.App.Contracts.WorkingHours;
|
||||
using CompanyManagment.App.Contracts.WorkingHoursItems;
|
||||
using CompanyManagment.App.Contracts.WorkingHoursTemp;
|
||||
using CompanyManagment.App.Contracts.WorkingHoursTempItem;
|
||||
using CompanyManagment.App.Contracts.Workshop;
|
||||
using CompanyManagment.App.Contracts.WorkshopPlan;
|
||||
using CompanyManagment.App.Contracts.YearlySalary;
|
||||
using CompanyManagment.App.Contracts.YearlySalaryItems;
|
||||
using CompanyManagment.App.Contracts.YearlySalaryTitles;
|
||||
using CompanyManagment.App.Contracts.Zone;
|
||||
using CompanyManagment.Application;
|
||||
using CompanyManagment.EFCore;
|
||||
using CompanyManagment.EFCore._common;
|
||||
using CompanyManagment.EFCore.Repository;
|
||||
using CompanyManagment.EFCore.Repository;
|
||||
using File.EfCore.Repository;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -239,6 +376,8 @@ using CompanyManagement.Infrastructure.Mongo.CameraBugReportRepo;
|
||||
using CameraBugReportRepository = CompanyManagement.Infrastructure.Mongo.CameraBugReportRepo.CameraBugReportRepository;
|
||||
using Company.Domain._common;
|
||||
using CompanyManagment.EFCore._common;
|
||||
using CompanyManagment.EFCore.Services;
|
||||
using Shared.Contracts.Holidays;
|
||||
|
||||
namespace PersonalContractingParty.Config;
|
||||
|
||||
@@ -246,6 +385,12 @@ public class PersonalBootstrapper
|
||||
{
|
||||
public static void Configure(IServiceCollection services, string connectionString)
|
||||
{
|
||||
|
||||
#region Services
|
||||
|
||||
services.AddTransient<IHolidayQueryService, HolidayQueryService>();
|
||||
|
||||
#endregion
|
||||
//----Task-Manager-Project---------------------------------
|
||||
|
||||
//services.AddTransient<ITaskApplication, TaskApplication>();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using GozareshgirProgramManager.Domain.CustomerAgg.Events;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.DomainEventHandlers;
|
||||
|
||||
public class CustomerRegisteredHandler : INotificationHandler<DomainEventNotification<CustomerRegistered>>
|
||||
{
|
||||
private readonly ILogger<CustomerRegisteredHandler> _logger;
|
||||
|
||||
public CustomerRegisteredHandler(ILogger<CustomerRegisteredHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task Handle(DomainEventNotification<CustomerRegistered> notification, CancellationToken cancellationToken)
|
||||
{
|
||||
var domainEvent = notification.DomainEvent;
|
||||
|
||||
_logger.LogInformation(
|
||||
"Customer registered: {CustomerId}, Name: {Name}, Email: {Email}",
|
||||
domainEvent.CustomerId,
|
||||
domainEvent.Name,
|
||||
domainEvent.Email);
|
||||
|
||||
|
||||
// اینجا میتوانید email ارسال کنید یا کارهای دیگر انجام دهید
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Interfaces;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Events;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.DomainEventHandlers.ProjectSection;
|
||||
|
||||
public class ProjectSectionAddedHandler:INotificationHandler<DomainEventNotification<ProjectSectionAddedEvent>>
|
||||
{
|
||||
private readonly ILogger<CustomerRegisteredHandler> _logger;
|
||||
|
||||
public ProjectSectionAddedHandler(ILogger<CustomerRegisteredHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task Handle(DomainEventNotification<ProjectSectionAddedEvent> notification, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Events;
|
||||
using MediatR;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.DomainEventHandlers.ProjectSection;
|
||||
|
||||
public class ProjectSectionAssignedHandler:INotificationHandler<DomainEventNotification<ProjectSectionAssignedEvent>>
|
||||
{
|
||||
public Task Handle(DomainEventNotification<ProjectSectionAssignedEvent> notification, CancellationToken cancellationToken)
|
||||
{
|
||||
var domainEvent = notification.DomainEvent;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="12.1.1" />
|
||||
<PackageReference Include="MediatR" Version="14.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\Shared.Contracts\Shared.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\Domain\GozareshgirProgramManager.Domain\GozareshgirProgramManager.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace GozareshgirProgramManager.Application.Interfaces;
|
||||
|
||||
public interface IBoardNotificationService
|
||||
{
|
||||
Task SendProjectAssignedAsync();
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.CheckoutAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.CheckoutAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.CheckoutAgg.Repositories;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories;
|
||||
using GozareshgirProgramManager.Domain.UserAgg.Entities;
|
||||
using MediatR;
|
||||
using PersianTools.Core;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Shared.Contracts.Holidays;
|
||||
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Checkouts.Commands.CreateCheckout;
|
||||
|
||||
public class CreateOrEditCheckoutCommandHandler : IBaseCommandHandler<CreateOrEditCheckoutCommand>
|
||||
{
|
||||
private readonly ICheckoutRepository _checkoutRepository;
|
||||
private readonly ISalaryPaymentSettingRepository _salaryPaymentSettingRepository;
|
||||
private readonly ITaskSectionActivityRepository _taskSectionActivityRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IHolidayQueryService _holidayQueryService;
|
||||
|
||||
|
||||
public CreateOrEditCheckoutCommandHandler(ICheckoutRepository checkoutRepository, IUnitOfWork unitOfWork,
|
||||
ISalaryPaymentSettingRepository salaryPaymentSettingRepository,
|
||||
ITaskSectionActivityRepository taskSectionActivityRepository, IHolidayQueryService holidayQueryService)
|
||||
{
|
||||
_checkoutRepository = checkoutRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_salaryPaymentSettingRepository = salaryPaymentSettingRepository;
|
||||
_taskSectionActivityRepository = taskSectionActivityRepository;
|
||||
_holidayQueryService = holidayQueryService;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(CreateOrEditCheckoutCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
switch (request.TypeOfCheckoutHandler)
|
||||
{
|
||||
case TypeOfCheckoutHandler.CreateInGroup:
|
||||
return await Create(request.Year, request.Month, request.UserIdList);
|
||||
break;
|
||||
case TypeOfCheckoutHandler.SingleEdit:
|
||||
case TypeOfCheckoutHandler.GroupEditing:
|
||||
return await GroupOrSingleEditing(request.CheckoutIdList);
|
||||
break;
|
||||
|
||||
}
|
||||
return OperationResult.Failure("نوع متد انتخاب نشده است");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ایجاد گروهی فیش حقوقی
|
||||
/// </summary>
|
||||
/// <param name="Year"></param>
|
||||
/// <param name="Month"></param>
|
||||
/// <param name="UserIdList"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperationResult> Create(string? Year, string? Month, List<long>? UserIdList)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Month))
|
||||
return OperationResult.Failure("ماه خالی است");
|
||||
if (string.IsNullOrWhiteSpace(Year))
|
||||
return OperationResult.Failure("سال خالی است");
|
||||
if (UserIdList == null)
|
||||
return OperationResult.Failure("هیچ موردی برای ایجاد انتخاب نشده اشت");
|
||||
if (UserIdList.Count == 0)
|
||||
return OperationResult.Failure("هیچ موردی برای ایجاد انتخاب نشده اشت");
|
||||
|
||||
var startDateGr = new DateTime();
|
||||
var EndDateGr = new DateTime();
|
||||
var persianStart = new PersianDateTime();
|
||||
|
||||
int year = 0;
|
||||
int month = 0;
|
||||
try
|
||||
{
|
||||
year = Convert.ToInt32(Year);
|
||||
month = Convert.ToInt32(Month);
|
||||
persianStart = new PersianDateTime(year, month, 1);
|
||||
var startDateFa = $"{persianStart}";
|
||||
startDateGr = startDateFa.ToGeorgianDateTime();
|
||||
|
||||
var endDateFa = startDateFa.FindeEndOfMonth();
|
||||
|
||||
EndDateGr = endDateFa.ToGeorgianDateTime();
|
||||
|
||||
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
return OperationResult<GetUserToGroupCreatingResponse>.Failure(
|
||||
"خطا در ورود سال و ماه");
|
||||
}
|
||||
|
||||
var totalDays = Convert.ToInt32((EndDateGr - startDateGr).TotalDays + 1);
|
||||
|
||||
var getAllSettings = await _salaryPaymentSettingRepository.GetAllSettings(UserIdList);
|
||||
var get = await _taskSectionActivityRepository.GetTotalTimeSpentPerUserInRangeAsync(startDateGr, EndDateGr);
|
||||
|
||||
foreach (var user in getAllSettings)
|
||||
{
|
||||
var totalWorked = get.FirstOrDefault(x => x.UserId == user.UserId);
|
||||
var totalTimeTotalMinutes = (int)totalWorked.TotalTime.TotalMinutes;
|
||||
var res = await ComputeSalary(user.WorkingHoursListDto, totalTimeTotalMinutes, user.MonthlySalary, startDateGr, EndDateGr, user.HolidayWorking);
|
||||
var createCheckout = new Checkout(startDateGr, EndDateGr, year, month, user.FullName, user.UserId,
|
||||
res.MandatoryHours, totalTimeTotalMinutes,
|
||||
totalDays, res.RemainingHours, user.MonthlySalary, res.MonthlySalaryPay, res.DeductionFromSalary);
|
||||
await _checkoutRepository.CreateAsync(createCheckout);
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// متد ویراش گروهی و تکی
|
||||
/// </summary>
|
||||
/// <param name="CheckoutIdList"></param>
|
||||
/// <param name="CheckoutId"></param>
|
||||
/// <param name="TypeOfCheckoutHandler"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperationResult> GroupOrSingleEditing(List<Guid>? CheckoutIdList)
|
||||
{
|
||||
|
||||
if (CheckoutIdList == null)
|
||||
return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت");
|
||||
if (CheckoutIdList.Count == 0)
|
||||
return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت");
|
||||
|
||||
var checkouts = await _checkoutRepository.GetCheckoutListByIds(CheckoutIdList);
|
||||
if (!checkouts.Any())
|
||||
return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت");
|
||||
var UserIdList = checkouts.Select(x => x.UserId).ToList();
|
||||
var getAllSettings = await _salaryPaymentSettingRepository.GetAllSettings(UserIdList);
|
||||
if (!getAllSettings.Any())
|
||||
return OperationResult.Failure("تنظیمات ساعت و حقوق یافت نشد");
|
||||
foreach (var checkoutId in CheckoutIdList)
|
||||
{
|
||||
var checkout = checkouts.FirstOrDefault(x => x.Id == checkoutId);
|
||||
if (checkout == null)
|
||||
return OperationResult.Failure("فیش مورد نظر یافت نشد");
|
||||
|
||||
var userSetting = getAllSettings.FirstOrDefault(x => x.UserId == checkout.UserId);
|
||||
|
||||
var get = await _taskSectionActivityRepository.GetTotalTimeSpentByUserInRangeAsync(checkout.UserId, checkout.CheckoutStartDate, checkout.CheckoutEndDate);
|
||||
|
||||
var totalTimeTotalMinutes = (int)get.TotalMinutes;
|
||||
|
||||
var totalDays = Convert.ToInt32((checkout.CheckoutEndDate - checkout.CheckoutStartDate).TotalDays + 1);
|
||||
var res = await ComputeSalary(userSetting.WorkingHoursListDto, totalTimeTotalMinutes, userSetting.MonthlySalary, checkout.CheckoutStartDate, checkout.CheckoutEndDate, userSetting.HolidayWorking);
|
||||
checkout.Edit(res.MandatoryHours, totalTimeTotalMinutes, totalDays, res.RemainingHours, userSetting.MonthlySalary, res.MonthlySalaryPay, res.DeductionFromSalary);
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// محاسبه حقوق
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<ComputeResultDto> ComputeSalary(List<WorkingHoursListDto> workingHoursListDto, int totalHoursWorked, double monthlySalaryDefined, DateTime start, DateTime end, bool holidayWorking)
|
||||
{
|
||||
var startDate = start.ToFarsi();
|
||||
var startYear = Convert.ToInt32(startDate.Substring(0, 4));
|
||||
var startMonth = Convert.ToInt32(startDate.Substring(5, 2));
|
||||
var startDay = Convert.ToInt32(startDate.Substring(8, 2));
|
||||
var persianStart = new PersianDateTime(startYear, startMonth, startDay);
|
||||
var endDate = end.ToFarsi();
|
||||
var endYear = Convert.ToInt32(endDate.Substring(0, 4));
|
||||
var endMonth = Convert.ToInt32(endDate.Substring(5, 2));
|
||||
var endDay = Convert.ToInt32(endDate.Substring(8, 2));
|
||||
var persianEnd = new PersianDateTime(endYear, endMonth, endDay);
|
||||
var holidays = await _holidayQueryService.GetHolidaysInDates(start, end) ;
|
||||
int mandatoryHours = 0;
|
||||
for (var currentDay = persianStart; currentDay <= persianEnd; currentDay = currentDay.AddDays(1))
|
||||
{
|
||||
var currentDayOfWeek = new DNTPersianUtils.Core.PersianDateTime(currentDay.Year, currentDay.Month, currentDay.Day);
|
||||
var holidayDate = currentDay.ShamsiDate.ToGeorgianDateTime();
|
||||
var day = (PersianDayOfWeek)currentDayOfWeek.WeekDayNumber!;
|
||||
var getDaySetting = workingHoursListDto.FirstOrDefault(x => x.PersianDayOfWeek == day);
|
||||
if (getDaySetting != null)
|
||||
{
|
||||
if (!holidayWorking && holidays.Any(x => x.Holidaydate == holidayDate))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mandatoryHours += (int)getDaySetting.ShiftDuration.TotalMinutes;
|
||||
Console.WriteLine((int)getDaySetting.ShiftDuration.TotalMinutes + " " + currentDay + " - " + day);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
//حقوق نهایی
|
||||
var monthlySalaryPay = (totalHoursWorked * monthlySalaryDefined) / mandatoryHours;
|
||||
// اگر اضافه کار داشت حقوق تعین شده به عنوان حقوق نهایی در نظر گرفته میشود
|
||||
monthlySalaryPay = monthlySalaryPay > monthlySalaryDefined ? monthlySalaryDefined : monthlySalaryPay;
|
||||
|
||||
//حقوق کسر شده
|
||||
var deductionFromSalary = monthlySalaryDefined - monthlySalaryPay;
|
||||
|
||||
//زمان باقی مانده
|
||||
var remainingTime = totalHoursWorked - mandatoryHours;
|
||||
|
||||
var computeResult = new ComputeResultDto
|
||||
{
|
||||
MandatoryHours = mandatoryHours,
|
||||
MonthlySalaryPay = monthlySalaryPay,
|
||||
DeductionFromSalary = deductionFromSalary,
|
||||
RemainingHours = remainingTime
|
||||
};
|
||||
Console.WriteLine(mandatoryHours);
|
||||
return computeResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public record CreateOrEditCheckoutCommand(TypeOfCheckoutHandler TypeOfCheckoutHandler, string? Year, string? Month, List<long>? UserIdList, List<Guid>? CheckoutIdList) : IBaseCommand;
|
||||
|
||||
public record ComputeResultDto
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// ساعات باقی مانده
|
||||
/// کسر کار یا اضافه کار
|
||||
/// </summary>
|
||||
public int RemainingHours { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// حقوق نهایی که به پرسنل داده می شود
|
||||
/// </summary>
|
||||
public double MonthlySalaryPay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// کسر از حقوق
|
||||
/// </summary>
|
||||
public double DeductionFromSalary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ساعت موظفی
|
||||
/// </summary>
|
||||
public int MandatoryHours { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using GozareshgirProgramManager.Application._Common.Extensions;
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetCheckoutList;
|
||||
|
||||
public class GetCheckoutListQueryHandler : IBasePaginationQueryHandler<GetCheckoutListQuery, GetCheckoutListResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _programManagerDbContext;
|
||||
|
||||
public GetCheckoutListQueryHandler(IProgramManagerDbContext programManagerDbContext)
|
||||
{
|
||||
_programManagerDbContext = programManagerDbContext;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<PaginationResult<GetCheckoutListResponse>>> Handle(GetCheckoutListQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _programManagerDbContext.Checkouts.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.Year))
|
||||
{
|
||||
var year = Convert.ToInt32(request.Year);
|
||||
query = query.Where(x => x.Year == year);
|
||||
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.Month))
|
||||
{
|
||||
var month = Convert.ToInt32(request.Month);
|
||||
query = query.Where(x => x.Month == month);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.FullName))
|
||||
query = query.Where(x => x.FullName.Contains(request.FullName));
|
||||
|
||||
var res =await query.Select(x => new GetCheckoutListResponse()
|
||||
{
|
||||
CheckoutId = x.Id,
|
||||
Year = x.Year,
|
||||
Month = x.PersianMonthName,
|
||||
FullName = x.FullName,
|
||||
MandatoryHours = x.MandatoryHours,
|
||||
TotalHoursWorked = x.TotalHoursWorked,
|
||||
RemainingHours = x.RemainingHours,
|
||||
MonthlySalaryDefined = x.MonthlySalaryDefined.ToMoney(),
|
||||
DeductionFromSalary = x.DeductionFromSalary.ToMoney(),
|
||||
MonthlySalaryPay = x.MonthlySalaryPay.ToMoney()
|
||||
|
||||
|
||||
}).ApplyPagination(request.PageIndex,request.PageSize).ToListAsync(cancellationToken: cancellationToken);
|
||||
|
||||
var response = new PaginationResult<GetCheckoutListResponse>
|
||||
{
|
||||
List = res,
|
||||
TotalCount = query.Count(),
|
||||
};
|
||||
|
||||
return OperationResult<PaginationResult<GetCheckoutListResponse>>.Success(response);
|
||||
}
|
||||
}
|
||||
|
||||
public record GetCheckoutListQuery(string? Month, string? Year, string? FullName) : PaginationRequest, IBasePaginationQuery<GetCheckoutListResponse>;
|
||||
|
||||
public record GetCheckoutListResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// آی دی فیش حقوقی
|
||||
/// </summary>
|
||||
public Guid CheckoutId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// سال
|
||||
/// </summary>
|
||||
public int Year { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ماه
|
||||
/// </summary>
|
||||
public string Month { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نام کامل پرسنل
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ساعت موظفی
|
||||
/// </summary>
|
||||
public int MandatoryHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// مجموع ساعات کارکرد پرسنل
|
||||
/// </summary>
|
||||
public int TotalHoursWorked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ساعات باقی مانده
|
||||
/// کسر کار یا اضافه کار
|
||||
/// </summary>
|
||||
public int RemainingHours { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// حقوق ماهانه
|
||||
/// تعیین شده
|
||||
/// </summary>
|
||||
public string MonthlySalaryDefined { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// کسر از حقوق
|
||||
/// </summary>
|
||||
public string DeductionFromSalary { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// حقوق نهایی که به پرسنل داده می شود
|
||||
/// </summary>
|
||||
public string MonthlySalaryPay { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetUserListWhoHaveSettings;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.CheckoutAgg.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PersianTools.Core;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate;
|
||||
|
||||
/// <summary>
|
||||
/// دریافت کاربران برای ایجاد گروهی فیش حقوقی با سال و ماه
|
||||
/// </summary>
|
||||
public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler<GetUserToGroupCreatingQuery, GetUserToGroupCreatingResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetUserToGroupCreatingResponse>> Handle(GetUserToGroupCreatingQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
//سال و ماه انتخاب شده از فرانت
|
||||
var selectedDate = new DateTime();
|
||||
try
|
||||
{
|
||||
int year = Convert.ToInt32(request.Year);
|
||||
int month = Convert.ToInt32(request.Month);
|
||||
selectedDate = ($"{new PersianDateTime(year,month,1)}").ToGeorgianDateTime();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
return OperationResult<GetUserToGroupCreatingResponse>.Failure(
|
||||
"خطا در ورود سال و ماه");
|
||||
}
|
||||
|
||||
//آخرین تاریخ مجاز برای ایجاد فیش
|
||||
var lastMonth = ($"{DateTime.Now.ToFarsi().Substring(0, 8)}01").ToGeorgianDateTime().AddDays(-1);
|
||||
|
||||
if (selectedDate > lastMonth)
|
||||
return OperationResult<GetUserToGroupCreatingResponse>.Failure(
|
||||
"ایجاد فیش فقط برای ماه های گذشته امکان پذیر است");
|
||||
|
||||
|
||||
var lastMonthStart = lastMonth;
|
||||
var lastMonthEnd = lastMonth;
|
||||
|
||||
var query =
|
||||
await (from u in _context.Users
|
||||
|
||||
// LEFT JOIN
|
||||
// تنظیمات حقوق
|
||||
join s in _context.SalaryPaymentSettings
|
||||
on u.Id equals s.UserId into sJoin
|
||||
from s in sJoin.DefaultIfEmpty()
|
||||
|
||||
// LEFT JOIN
|
||||
//فیش
|
||||
join ch in _context.Checkouts
|
||||
.Where(x => x.CheckoutStartDate < lastMonthStart
|
||||
&& x.CheckoutEndDate >= lastMonthStart)
|
||||
on u.Id equals ch.UserId into chJoin
|
||||
from ch in chJoin.DefaultIfEmpty()
|
||||
|
||||
group new { s, ch } by new { u.Id, u.FullName } into g
|
||||
|
||||
select new GetUserWhoHaveSettingsAndCheckoutDto
|
||||
{
|
||||
UserId = g.Key.Id,
|
||||
FullName = g.Key.FullName,
|
||||
|
||||
HasSalarySettings = g.Any(x => x.s != null),
|
||||
HasCheckout = g.Any(x => x.ch != null)
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var responseList = query.Select(x =>
|
||||
{
|
||||
|
||||
bool validToCreate = x.HasSalarySettings && !x.HasCheckout;
|
||||
string message = "آماده تنظیم";
|
||||
CreateCheckoutStatus createCheckoutStatus = CreateCheckoutStatus.ReadyToCreate;
|
||||
if (x.HasCheckout)
|
||||
{
|
||||
message = "موجود است";
|
||||
createCheckoutStatus = CreateCheckoutStatus.AlreadyCreated;
|
||||
}
|
||||
|
||||
|
||||
if (!x.HasSalarySettings)
|
||||
{
|
||||
message = "فاقد تنظیمات";
|
||||
createCheckoutStatus = CreateCheckoutStatus.NotSetSalaryPaymentSettings;
|
||||
}
|
||||
|
||||
|
||||
return new GetUserToGroupCreatingDto
|
||||
{
|
||||
UserId = x.UserId,
|
||||
FullName = x.FullName,
|
||||
IsValidToCreate = validToCreate,
|
||||
StatusMessage = message,
|
||||
CreateCheckoutStatus = createCheckoutStatus
|
||||
|
||||
};
|
||||
|
||||
}).OrderByDescending(x=>x.IsValidToCreate).ToList();
|
||||
|
||||
var response = new GetUserToGroupCreatingResponse(responseList);
|
||||
|
||||
return OperationResult<GetUserToGroupCreatingResponse>.Success(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record GetUserToGroupCreatingQuery(string Year, string Month) : IBaseQuery<GetUserToGroupCreatingResponse>;
|
||||
|
||||
public record GetUserToGroupCreatingResponse(List<GetUserToGroupCreatingDto> GetUserToGroupCreatingDtoList);
|
||||
|
||||
public record GetUserToGroupCreatingDto
|
||||
{
|
||||
/// <summary>
|
||||
/// آی دی کاربر
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نام کامل پرسنل
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// پیام وضعیت ایجاد فیش
|
||||
/// </summary>
|
||||
public string StatusMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آیا مجاز به ایجاد فیش می باشد
|
||||
/// </summary>
|
||||
public bool IsValidToCreate { get; set; }
|
||||
|
||||
public CreateCheckoutStatus CreateCheckoutStatus { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public record GetUserWhoHaveSettingsAndCheckoutDto
|
||||
{
|
||||
/// <summary>
|
||||
/// آی دی کاربر
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نام کامل پرسنل
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// داشتن تنظیمات
|
||||
/// </summary>
|
||||
public bool HasSalarySettings { get; set; }
|
||||
|
||||
|
||||
public bool HasCheckout { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddPhaseToProject;
|
||||
|
||||
/// <summary>
|
||||
/// Command to add a phase to an existing project
|
||||
/// </summary>
|
||||
public record AddPhaseToProjectCommand(
|
||||
Guid ProjectId,
|
||||
string Name,
|
||||
string? Description = null,
|
||||
int OrderIndex = 0
|
||||
) : IBaseCommand;
|
||||
@@ -0,0 +1,47 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
using MediatR;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddPhaseToProject;
|
||||
|
||||
public class AddPhaseToProjectCommandHandler : IRequestHandler<AddPhaseToProjectCommand, OperationResult>
|
||||
{
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public AddPhaseToProjectCommandHandler(
|
||||
IProjectRepository projectRepository,
|
||||
IUnitOfWork unitOfWork)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(AddPhaseToProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get project
|
||||
var project = await _projectRepository.GetByIdAsync(request.ProjectId);
|
||||
if (project == null)
|
||||
{
|
||||
return OperationResult.NotFound("پروژه یافت نشد");
|
||||
}
|
||||
|
||||
// Add phase
|
||||
var phase = project.AddPhase(request.Name, request.Description);
|
||||
phase.SetOrderIndex(request.OrderIndex);
|
||||
|
||||
// Save changes
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return OperationResult.Failure($"خطا در افزودن فاز: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddTaskToPhase;
|
||||
|
||||
/// <summary>
|
||||
/// Command to add a task to an existing phase
|
||||
/// </summary>
|
||||
public record AddTaskToPhaseCommand(
|
||||
Guid PhaseId,
|
||||
string Name,
|
||||
string? Description = null,
|
||||
TaskPriority Priority = TaskPriority.Medium,
|
||||
int OrderIndex = 0,
|
||||
DateTime? DueDate = null
|
||||
) : IBaseCommand;
|
||||
@@ -0,0 +1,53 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
using MediatR;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddTaskToPhase;
|
||||
|
||||
public class AddTaskToPhaseCommandHandler : IRequestHandler<AddTaskToPhaseCommand, OperationResult>
|
||||
{
|
||||
private readonly IProjectPhaseRepository _phaseRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public AddTaskToPhaseCommandHandler(
|
||||
IProjectPhaseRepository phaseRepository,
|
||||
IUnitOfWork unitOfWork)
|
||||
{
|
||||
_phaseRepository = phaseRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(AddTaskToPhaseCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get phase
|
||||
var phase = await _phaseRepository.GetByIdAsync(request.PhaseId);
|
||||
if (phase == null)
|
||||
{
|
||||
return OperationResult.NotFound("فاز یافت نشد");
|
||||
}
|
||||
|
||||
// Add task
|
||||
var task = phase.AddTask(request.Name, request.Description);
|
||||
task.SetPriority(request.Priority);
|
||||
task.SetOrderIndex(request.OrderIndex);
|
||||
|
||||
if (request.DueDate.HasValue)
|
||||
{
|
||||
task.SetDates(dueDate: request.DueDate);
|
||||
}
|
||||
|
||||
// Save changes
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return OperationResult.Failure($"خطا در افزودن تسک: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject;
|
||||
|
||||
public class AssignProjectCommand:IBaseCommand
|
||||
{
|
||||
public List<AssignProjectCommandItem> Items { get; set; }
|
||||
public Guid Id { get; set; }
|
||||
public ProjectHierarchyLevel Level { get; set; }
|
||||
public bool CascadeToChildren { get; set; }
|
||||
}
|
||||
|
||||
public class AssignProjectCommandItem
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public Guid SkillId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
using GozareshgirProgramManager.Domain.SkillAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject;
|
||||
|
||||
public class AssignProjectCommandHandler:IBaseCommandHandler<AssignProjectCommand>
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IProjectPhaseRepository _projectPhaseRepository;
|
||||
private readonly IProjectTaskRepository _projectTaskRepository;
|
||||
private readonly ISkillRepository _skillRepository;
|
||||
private readonly IPhaseSectionRepository _phaseSectionRepository;
|
||||
private readonly IProjectSectionRepository _projectSectionRepository;
|
||||
private readonly ITaskSectionRepository _taskSectionRepository;
|
||||
|
||||
|
||||
public AssignProjectCommandHandler(
|
||||
IProjectRepository projectRepository,
|
||||
IProjectPhaseRepository projectPhaseRepository,
|
||||
IProjectTaskRepository projectTaskRepository,
|
||||
IUnitOfWork unitOfWork,
|
||||
ISkillRepository skillRepository,
|
||||
IPhaseSectionRepository phaseSectionRepository,
|
||||
IProjectSectionRepository projectSectionRepository,
|
||||
ITaskSectionRepository taskSectionRepository)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_projectPhaseRepository = projectPhaseRepository;
|
||||
_projectTaskRepository = projectTaskRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_skillRepository = skillRepository;
|
||||
_phaseSectionRepository = phaseSectionRepository;
|
||||
_projectSectionRepository = projectSectionRepository;
|
||||
_taskSectionRepository = taskSectionRepository;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(AssignProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
switch (request.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
return await AssignProject(request);
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
return await AssignProjectPhase(request);
|
||||
case ProjectHierarchyLevel.Task:
|
||||
return await AssignProjectTask(request);
|
||||
default:
|
||||
return OperationResult.Failure("سطح پروژه نامعتبر است");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperationResult> AssignProject(AssignProjectCommand request)
|
||||
{
|
||||
var project = await _projectRepository.GetWithFullHierarchyAsync(request.Id);
|
||||
if (project is null)
|
||||
{
|
||||
return OperationResult.NotFound("پروژه یافت نشد");
|
||||
}
|
||||
|
||||
// تخصیص در سطح پروژه
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var skill = await _skillRepository.GetByIdAsync(item.SkillId);
|
||||
if (skill is null)
|
||||
{
|
||||
return OperationResult.NotFound($"مهارت با شناسه {item.SkillId} یافت نشد");
|
||||
}
|
||||
|
||||
// بررسی و بهروزرسانی یا اضافه کردن ProjectSection
|
||||
var existingSection = project.ProjectSections.FirstOrDefault(s => s.SkillId == item.SkillId);
|
||||
if (existingSection != null)
|
||||
{
|
||||
// اگر وجود داشت، فقط userId را بهروزرسانی کن
|
||||
existingSection.UpdateUser(item.UserId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// اگر وجود نداشت، اضافه کن
|
||||
var newSection = new ProjectSection(project.Id, item.UserId, item.SkillId);
|
||||
await _projectSectionRepository.CreateAsync(newSection);
|
||||
}
|
||||
}
|
||||
|
||||
// حالا برای تمام فازها و تسکها cascade کن
|
||||
foreach (var phase in project.Phases)
|
||||
{
|
||||
// اگر CascadeToChildren true است یا فاز override ندارد
|
||||
if (request.CascadeToChildren || !phase.HasAssignmentOverride)
|
||||
{
|
||||
// برای phase هم باید sectionها را بهروزرسانی کنیم
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var existingSection = phase.PhaseSections.FirstOrDefault(s => s.SkillId == item.SkillId);
|
||||
if (existingSection != null)
|
||||
{
|
||||
existingSection.Update(item.UserId, item.SkillId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newPhaseSection = new PhaseSection(phase.Id, item.UserId, item.SkillId);
|
||||
await _phaseSectionRepository.CreateAsync(newPhaseSection);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var task in phase.Tasks)
|
||||
{
|
||||
// اگر CascadeToChildren true است یا تسک override ندارد
|
||||
if (request.CascadeToChildren || !task.HasAssignmentOverride)
|
||||
{
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var section = task.Sections.FirstOrDefault(s => s.SkillId == item.SkillId);
|
||||
if (section != null)
|
||||
{
|
||||
// استفاده از TransferToUser
|
||||
if (section.CurrentAssignedUserId != item.UserId)
|
||||
{
|
||||
if (section.CurrentAssignedUserId > 0)
|
||||
{
|
||||
section.TransferToUser(section.CurrentAssignedUserId, item.UserId);
|
||||
}
|
||||
else
|
||||
{
|
||||
section.AssignToUser(item.UserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var newTaskSection = new TaskSection(task.Id, item.SkillId, item.UserId);
|
||||
await _taskSectionRepository.CreateAsync(newTaskSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private async Task<OperationResult> AssignProjectPhase(AssignProjectCommand request)
|
||||
{
|
||||
var phase = await _projectPhaseRepository.GetWithTasksAsync(request.Id);
|
||||
if (phase is null)
|
||||
{
|
||||
return OperationResult.NotFound("فاز پروژه یافت نشد");
|
||||
}
|
||||
|
||||
// تخصیص در سطح فاز
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var skill = await _skillRepository.GetByIdAsync(item.SkillId);
|
||||
if (skill is null)
|
||||
{
|
||||
return OperationResult.NotFound($"مهارت با شناسه {item.SkillId} یافت نشد");
|
||||
}
|
||||
}
|
||||
|
||||
// علامتگذاری که این فاز نسبت به parent متمایز است
|
||||
phase.MarkAsOverridden();
|
||||
|
||||
// بهروزرسانی یا اضافه کردن PhaseSection
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var existingSection = phase.PhaseSections.FirstOrDefault(s => s.SkillId == item.SkillId);
|
||||
if (existingSection != null)
|
||||
{
|
||||
// اگر وجود داشت، فقط userId را بهروزرسانی کن
|
||||
existingSection.Update(item.UserId, item.SkillId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// اگر وجود نداشت، اضافه کن
|
||||
var newPhaseSection = new PhaseSection(phase.Id, item.UserId, item.SkillId);
|
||||
await _phaseSectionRepository.CreateAsync(newPhaseSection);
|
||||
}
|
||||
}
|
||||
|
||||
// cascade به تمام تسکها
|
||||
foreach (var task in phase.Tasks)
|
||||
{
|
||||
// اگر CascadeToChildren true است یا تسک override ندارد
|
||||
if (request.CascadeToChildren || !task.HasAssignmentOverride)
|
||||
{
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var section = task.Sections.FirstOrDefault(s => s.SkillId == item.SkillId);
|
||||
if (section != null)
|
||||
{
|
||||
// استفاده از TransferToUser
|
||||
if (section.CurrentAssignedUserId != item.UserId)
|
||||
{
|
||||
if (section.CurrentAssignedUserId > 0)
|
||||
{
|
||||
section.TransferToUser(section.CurrentAssignedUserId, item.UserId);
|
||||
}
|
||||
else
|
||||
{
|
||||
section.AssignToUser(item.UserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var newTaskSection = new TaskSection(task.Id, item.SkillId, item.UserId);
|
||||
await _taskSectionRepository.CreateAsync(newTaskSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private async Task<OperationResult> AssignProjectTask(AssignProjectCommand request)
|
||||
{
|
||||
var task = await _projectTaskRepository.GetWithSectionsAsync(request.Id);
|
||||
if (task is null)
|
||||
{
|
||||
return OperationResult.NotFound("تسک یافت نشد");
|
||||
}
|
||||
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var skill = await _skillRepository.GetByIdAsync(item.SkillId);
|
||||
if (skill is null)
|
||||
{
|
||||
return OperationResult.NotFound($"مهارت با شناسه {item.SkillId} یافت نشد");
|
||||
}
|
||||
}
|
||||
|
||||
// علامتگذاری که این تسک نسبت به parent متمایز است
|
||||
task.MarkAsOverridden();
|
||||
|
||||
// بهروزرسانی یا اضافه کردن TaskSection
|
||||
foreach (var item in request.Items)
|
||||
{
|
||||
var section = task.Sections.FirstOrDefault(s => s.SkillId == item.SkillId);
|
||||
if (section != null)
|
||||
{
|
||||
// اگر وجود داشت، از TransferToUser استفاده کن
|
||||
if (section.CurrentAssignedUserId != item.UserId)
|
||||
{
|
||||
if (section.CurrentAssignedUserId > 0)
|
||||
{
|
||||
section.TransferToUser(section.CurrentAssignedUserId, item.UserId);
|
||||
}
|
||||
else
|
||||
{
|
||||
section.AssignToUser(item.UserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// اگر وجود نداشت، اضافه کن
|
||||
var newTaskSection = new TaskSection(task.Id, item.SkillId, item.UserId);
|
||||
await _taskSectionRepository.CreateAsync(newTaskSection);
|
||||
}
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject;
|
||||
|
||||
public class AssignProjectCommandValidator : AbstractValidator<AssignProjectCommand>
|
||||
{
|
||||
public AssignProjectCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.Id)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("شناسه پروژه نمیتواند خالی باشد");
|
||||
|
||||
RuleFor(x => x.CascadeToChildren)
|
||||
.NotNull()
|
||||
.WithMessage("مقدار CascadeToChildren نمیتواند خالی باشد");
|
||||
|
||||
RuleForEach(x => x.Items)
|
||||
.SetValidator(new AssignProjectItemValidator());
|
||||
}
|
||||
}
|
||||
|
||||
public class AssignProjectItemValidator : AbstractValidator<AssignProjectCommandItem>
|
||||
{
|
||||
public AssignProjectItemValidator()
|
||||
{
|
||||
RuleFor(x => x.UserId)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه کاربر نمیتواند خالی باشد");
|
||||
|
||||
|
||||
RuleFor(x => x.SkillId)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("شناسه مهارت نمیتواند خالی باشد");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain._Common.Exceptions;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection;
|
||||
|
||||
public record ChangeStatusSectionCommand(Guid SectionId, TaskSectionStatus Status) : IBaseCommand;
|
||||
|
||||
public class ChangeStatusSectionCommandHandler : IBaseCommandHandler<ChangeStatusSectionCommand>
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly ITaskSectionRepository _taskSectionRepository;
|
||||
private readonly IAuthHelper _authHelper;
|
||||
|
||||
public ChangeStatusSectionCommandHandler(ITaskSectionRepository taskSectionRepository,
|
||||
IUnitOfWork unitOfWork, IAuthHelper authHelper)
|
||||
{
|
||||
_taskSectionRepository = taskSectionRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_authHelper = authHelper;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(ChangeStatusSectionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// استفاده از متد مخصوص که Activities رو load میکنه
|
||||
var section = await _taskSectionRepository.GetByIdWithActivitiesAsync(request.SectionId, cancellationToken);
|
||||
if (section == null)
|
||||
return OperationResult.NotFound("بخش مورد نظر یافت نشد");
|
||||
|
||||
if (section.Status == request.Status)
|
||||
return OperationResult.Success();
|
||||
|
||||
long currentUser = _authHelper.GetCurrentUserId()
|
||||
?? throw new UnAuthorizedException("کاربر احراز هویت نشده است");
|
||||
|
||||
// Validate state transitions
|
||||
var validationResult = ValidateStateTransition(section.Status, request.Status);
|
||||
if (!validationResult.IsSuccess)
|
||||
return validationResult;
|
||||
|
||||
// Handle state machine logic
|
||||
if (section.Status == TaskSectionStatus.InProgress)
|
||||
{
|
||||
// Coming FROM InProgress: Stop the active activity
|
||||
section.StopWork(currentUser, request.Status);
|
||||
}
|
||||
else if (request.Status == TaskSectionStatus.InProgress)
|
||||
{
|
||||
// Going TO InProgress: Start work and create activity
|
||||
section.StartWork(currentUser);
|
||||
}
|
||||
else
|
||||
{
|
||||
// All other transitions: Just update status
|
||||
section.UpdateStatus(request.Status);
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates state transitions based on business rules:
|
||||
/// - ReadyToStart: شروع نشده - Initial state only, cannot return to it once left
|
||||
/// - InProgress: درحال انجام - Can transition from ReadyToStart, can go to Incomplete or Completed
|
||||
/// - Incomplete: نیمه کاره - Can come from InProgress or other states
|
||||
/// - Completed: اتمام رسیده - Can come from InProgress or other states
|
||||
/// </summary>
|
||||
private OperationResult ValidateStateTransition(TaskSectionStatus currentStatus, TaskSectionStatus targetStatus)
|
||||
{
|
||||
// Cannot transition to ReadyToStart once the section has been started
|
||||
if (targetStatus == TaskSectionStatus.ReadyToStart)
|
||||
return OperationResult.ValidationError("بخش نمیتواند به وضعیت 'آماده برای شروع' تغییر کند");
|
||||
|
||||
// From ReadyToStart, can only go to InProgress
|
||||
if (currentStatus == TaskSectionStatus.ReadyToStart && targetStatus != TaskSectionStatus.InProgress)
|
||||
return OperationResult.ValidationError("از وضعیت 'آماده برای شروع' فقط میتوان به 'درحال انجام' رفت");
|
||||
|
||||
// Valid transitions matrix
|
||||
var validTransitions = new Dictionary<TaskSectionStatus, List<TaskSectionStatus>>
|
||||
{
|
||||
{ TaskSectionStatus.ReadyToStart, new List<TaskSectionStatus> { TaskSectionStatus.InProgress } },
|
||||
{ TaskSectionStatus.InProgress, new List<TaskSectionStatus> { TaskSectionStatus.Incomplete, TaskSectionStatus.Completed } },
|
||||
{ TaskSectionStatus.Incomplete, new List<TaskSectionStatus> { TaskSectionStatus.InProgress, TaskSectionStatus.Completed } },
|
||||
{ TaskSectionStatus.Completed, new List<TaskSectionStatus> { TaskSectionStatus.InProgress, TaskSectionStatus.Incomplete } }, // Can return to InProgress or Incomplete
|
||||
{ TaskSectionStatus.NotAssigned, new List<TaskSectionStatus> { TaskSectionStatus.InProgress, TaskSectionStatus.ReadyToStart } }
|
||||
};
|
||||
|
||||
if (!validTransitions.TryGetValue(currentStatus, out var allowedTargets))
|
||||
return OperationResult.ValidationError($"وضعیت فعلی '{currentStatus}' نامعتبر است");
|
||||
|
||||
if (!allowedTargets.Contains(targetStatus))
|
||||
return OperationResult.ValidationError(
|
||||
$"نمیتوان از وضعیت '{currentStatus}' به '{targetStatus}' رفت");
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection;
|
||||
|
||||
public class ChangeStatusSectionCommandValidator:AbstractValidator<ChangeStatusSectionCommand>
|
||||
{
|
||||
public ChangeStatusSectionCommandValidator()
|
||||
{
|
||||
RuleFor(c => c.SectionId)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("شناسه بخش نمیتواند خالی باشد");
|
||||
|
||||
RuleFor(c => c.Status)
|
||||
.IsInEnum()
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("وضعیت بخش نامعتبر است");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject;
|
||||
|
||||
public record CreateProjectCommand(string Name,ProjectHierarchyLevel Level,
|
||||
Guid? ParentId):IBaseCommand;
|
||||
@@ -0,0 +1,82 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain._Common.Exceptions;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject;
|
||||
|
||||
public class CreateProjectCommandHandler : IBaseCommandHandler<CreateProjectCommand>
|
||||
{
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IProjectPhaseRepository _projectPhaseRepository;
|
||||
private readonly IProjectTaskRepository _projectTaskRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
|
||||
public CreateProjectCommandHandler(IProjectRepository projectRepository, IUnitOfWork unitOfWork, IProjectTaskRepository projectTaskRepository, IProjectPhaseRepository projectPhaseRepository)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_projectTaskRepository = projectTaskRepository;
|
||||
_projectPhaseRepository = projectPhaseRepository;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(CreateProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
switch (request.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
await CreateProject(request);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
await CreateProjectPhase(request);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Task:
|
||||
await CreateProjectTask(request);
|
||||
break;
|
||||
default:
|
||||
return OperationResult.Failure("سطح پروژه نامعتبر است");
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private async Task CreateProject(CreateProjectCommand request)
|
||||
{
|
||||
var project = new Project(request.Name);
|
||||
await _projectRepository.CreateAsync(project);
|
||||
}
|
||||
|
||||
private async Task CreateProjectPhase(CreateProjectCommand request)
|
||||
{
|
||||
if (!request.ParentId.HasValue)
|
||||
throw new BadRequestException("برای ایجاد فاز، شناسه پروژه الزامی است");
|
||||
|
||||
if(!_projectRepository.Exists(x=>x.Id == request.ParentId.Value))
|
||||
{
|
||||
throw new BadRequestException("والد پروژه یافت نشد");
|
||||
}
|
||||
|
||||
var projectPhase = new ProjectPhase(request.Name, request.ParentId.Value);
|
||||
await _projectPhaseRepository.CreateAsync(projectPhase);
|
||||
}
|
||||
|
||||
private async Task CreateProjectTask(CreateProjectCommand request)
|
||||
{
|
||||
if (!request.ParentId.HasValue)
|
||||
throw new BadRequestException("برای ایجاد تسک، شناسه فاز الزامی است");
|
||||
|
||||
if(!_projectPhaseRepository.Exists(x=>x.Id == request.ParentId.Value))
|
||||
{
|
||||
throw new BadRequestException("والد پروژه یافت نشد");
|
||||
}
|
||||
|
||||
var projectTask = new ProjectTask(request.Name, request.ParentId.Value);
|
||||
await _projectTaskRepository.CreateAsync(projectTask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using FluentValidation;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject;
|
||||
|
||||
public class CreateProjectCommandValidator:AbstractValidator<CreateProjectCommand>
|
||||
{
|
||||
public CreateProjectCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.Name)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("نام نمیتواند خالی باشد");
|
||||
|
||||
RuleFor(y => y.Level)
|
||||
.NotNull()
|
||||
.IsInEnum();
|
||||
When(x=>x.Level>ProjectHierarchyLevel.Project,()=>
|
||||
{
|
||||
RuleFor(x => x.ParentId)
|
||||
.NotNull()
|
||||
.NotEmpty()
|
||||
.WithMessage("شناسه والد نمیتواند خالی باشد");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProjectWithHierarchy;
|
||||
|
||||
/// <summary>
|
||||
/// Command to create a new project with the new hierarchy structure
|
||||
/// </summary>
|
||||
public record CreateProjectWithHierarchyCommand(
|
||||
string Name,
|
||||
string? Description = null,
|
||||
DateTime? PlannedStartDate = null,
|
||||
DateTime? PlannedEndDate = null
|
||||
) : IBaseCommand;
|
||||
@@ -0,0 +1,49 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
using MediatR;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProjectWithHierarchy;
|
||||
|
||||
public class CreateProjectWithHierarchyCommandHandler : IRequestHandler<CreateProjectWithHierarchyCommand, OperationResult>
|
||||
{
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public CreateProjectWithHierarchyCommandHandler(
|
||||
IProjectRepository projectRepository,
|
||||
IUnitOfWork unitOfWork)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(CreateProjectWithHierarchyCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create new project
|
||||
var project = new Project(request.Name, request.Description);
|
||||
|
||||
// Set planned dates if provided
|
||||
if (request.PlannedStartDate.HasValue || request.PlannedEndDate.HasValue)
|
||||
{
|
||||
project.SetPlannedDates(request.PlannedStartDate, request.PlannedEndDate);
|
||||
}
|
||||
|
||||
// Add to repository
|
||||
await _projectRepository.CreateAsync(project);
|
||||
|
||||
// Save changes
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return OperationResult.Failure($"خطا در ایجاد پروژه: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProjectWithHierarchy;
|
||||
|
||||
public class CreateProjectWithHierarchyCommandValidator : AbstractValidator<CreateProjectWithHierarchyCommand>
|
||||
{
|
||||
public CreateProjectWithHierarchyCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.Name)
|
||||
.NotEmpty().WithMessage("نام پروژه نمیتواند خالی باشد")
|
||||
.MaximumLength(200).WithMessage("نام پروژه نمیتواند بیش از 200 کاراکتر باشد");
|
||||
|
||||
RuleFor(x => x.Description)
|
||||
.MaximumLength(1000).WithMessage("توضیحات نمیتواند بیش از 1000 کاراکتر باشد")
|
||||
.When(x => !string.IsNullOrEmpty(x.Description));
|
||||
|
||||
RuleFor(x => x)
|
||||
.Must(x => x.PlannedStartDate == null || x.PlannedEndDate == null || x.PlannedStartDate <= x.PlannedEndDate)
|
||||
.WithMessage("تاریخ شروع برنامهریزی شده نمیتواند بعد از تاریخ پایان برنامهریزی شده باشد");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain._Common.Exceptions;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject;
|
||||
|
||||
public record DeleteProjectCommand(Guid Id,ProjectHierarchyLevel Level) : IBaseCommand;
|
||||
|
||||
public class DeleteProjectCommandHandler : IBaseCommandHandler<DeleteProjectCommand>
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IProjectPhaseRepository _projectPhaseRepository;
|
||||
private readonly IProjectTaskRepository _projectTaskRepository;
|
||||
|
||||
public DeleteProjectCommandHandler(
|
||||
IUnitOfWork unitOfWork,
|
||||
IProjectRepository projectRepository,
|
||||
IProjectPhaseRepository projectPhaseRepository,
|
||||
IProjectTaskRepository projectTaskRepository)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_projectRepository = projectRepository;
|
||||
_projectPhaseRepository = projectPhaseRepository;
|
||||
_projectTaskRepository = projectTaskRepository;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(DeleteProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
switch (request.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
await DeleteProject(request.Id);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
await DeleteProjectPhase(request.Id);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Task:
|
||||
await DeleteProjectTask(request.Id);
|
||||
break;
|
||||
default:
|
||||
return OperationResult.Failure("سطح پروژه نامعتبر است");
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private async Task DeleteProject(Guid projectId)
|
||||
{
|
||||
var projectWithPhases = await _projectRepository.GetWithFullHierarchyAsync(projectId);
|
||||
|
||||
if (projectWithPhases == null)
|
||||
throw new NotFoundException("پروژه یافت نشد");
|
||||
|
||||
// بررسی اینکه پروژه فاز یا زیرمجموعه دارد یا نه
|
||||
if (projectWithPhases.Phases != null && projectWithPhases.Phases.Any())
|
||||
throw new BadRequestException("نمیتوان پروژهای را حذف کرد که دارای فاز است. ابتدا تمام فازها را حذف کنید.");
|
||||
|
||||
_projectRepository.Remove(projectWithPhases);
|
||||
}
|
||||
|
||||
private async Task DeleteProjectPhase(Guid phaseId)
|
||||
{
|
||||
var phase = await _projectPhaseRepository.GetByIdAsync(phaseId);
|
||||
|
||||
if (phase == null)
|
||||
throw new NotFoundException("فاز پروژه یافت نشد");
|
||||
|
||||
// بررسی اینکه فاز تسک یا زیرمجموعه دارد یا نه
|
||||
var phaseWithTasks = await _projectPhaseRepository.GetWithTasksAsync(phaseId);
|
||||
if (phaseWithTasks?.Tasks != null && phaseWithTasks.Tasks.Any())
|
||||
throw new InvalidOperationException("نمیتوان فازی را حذف کرد که دارای تسک است. ابتدا تمام تسکها را حذف کنید.");
|
||||
|
||||
_projectPhaseRepository.Remove(phase);
|
||||
}
|
||||
|
||||
private async Task DeleteProjectTask(Guid taskId)
|
||||
{
|
||||
var task = await _projectTaskRepository.GetByIdAsync(taskId);
|
||||
|
||||
if (task == null)
|
||||
throw new NotFoundException("تسک یافت نشد");
|
||||
|
||||
// حذف خود تسک
|
||||
_projectTaskRepository.Remove(task);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject;
|
||||
|
||||
public class DeleteProjectCommandValidator:AbstractValidator<DeleteProjectCommand>
|
||||
{
|
||||
public DeleteProjectCommandValidator()
|
||||
{
|
||||
RuleFor(x=>x.Id)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("شناسه پروژه نمیتواند خالی باشد.");
|
||||
RuleFor(x=>x.Level)
|
||||
.IsInEnum()
|
||||
.NotNull()
|
||||
.WithMessage("سطح حذف پروژه نامعتبر است.");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain._Common.Exceptions;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.EditProject;
|
||||
|
||||
public record EditProjectCommand(string Name, Guid Id, ProjectHierarchyLevel Level): IBaseCommand;
|
||||
public class EditProjectCommandHandler: IBaseCommandHandler<EditProjectCommand>
|
||||
{
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IProjectPhaseRepository _projectPhaseRepository;
|
||||
private readonly IProjectTaskRepository _projectTaskRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public EditProjectCommandHandler(
|
||||
IProjectRepository projectRepository,
|
||||
IProjectPhaseRepository projectPhaseRepository,
|
||||
IProjectTaskRepository projectTaskRepository,
|
||||
IUnitOfWork unitOfWork)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_projectPhaseRepository = projectPhaseRepository;
|
||||
_projectTaskRepository = projectTaskRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(EditProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
switch (request.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
await EditProject(request);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
await EditProjectPhase(request);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Task:
|
||||
await EditProjectTask(request);
|
||||
break;
|
||||
default:
|
||||
return OperationResult.Failure("سطح پروژه نامعتبر است");
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private async Task EditProject(EditProjectCommand request)
|
||||
{
|
||||
var project = await _projectRepository.GetByIdAsync(request.Id);
|
||||
|
||||
if (project == null)
|
||||
throw new NotFoundException("پروژه یافت نشد");
|
||||
|
||||
project.UpdateName(request.Name);
|
||||
}
|
||||
|
||||
private async Task EditProjectPhase(EditProjectCommand request)
|
||||
{
|
||||
var phase = await _projectPhaseRepository.GetByIdAsync(request.Id);
|
||||
|
||||
if (phase == null)
|
||||
throw new NotFoundException("فاز پروژه یافت نشد");
|
||||
|
||||
phase.UpdateName(request.Name);
|
||||
}
|
||||
|
||||
private async Task EditProjectTask(EditProjectCommand request)
|
||||
{
|
||||
var task = await _projectTaskRepository.GetByIdAsync(request.Id);
|
||||
|
||||
if (task == null)
|
||||
throw new NotFoundException("تسک یافت نشد");
|
||||
|
||||
task.UpdateName(request.Name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.EditProject;
|
||||
|
||||
public class EditProjectCommandValidator:AbstractValidator<EditProjectCommand>
|
||||
{
|
||||
public EditProjectCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.Name)
|
||||
.NotEmpty()
|
||||
.WithMessage("نام پروژه نمیتواند خالی باشد.");
|
||||
|
||||
RuleFor(x=>x.Id)
|
||||
.NotEmpty()
|
||||
.NotNull().WithMessage("شناسه پروژه نمیتواند خالی باشد.");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.DTOs;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject;
|
||||
|
||||
public record SetTimeProjectCommand(List<SetTimeProjectSectionItem> SectionItems, Guid Id, ProjectHierarchyLevel Level):IBaseCommand;
|
||||
|
||||
public class SetTimeSectionTime
|
||||
{
|
||||
public string Description { get; set; }
|
||||
public int Hours { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.DTOs;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject;
|
||||
|
||||
public class SetTimeProjectCommandHandler:IBaseCommandHandler<SetTimeProjectCommand>
|
||||
{
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IProjectPhaseRepository _projectPhaseRepository;
|
||||
private readonly IProjectTaskRepository _projectTaskRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IAuthHelper _authHelper;
|
||||
private long? _userId;
|
||||
|
||||
|
||||
public SetTimeProjectCommandHandler(
|
||||
IProjectRepository projectRepository,
|
||||
IProjectPhaseRepository projectPhaseRepository,
|
||||
IProjectTaskRepository projectTaskRepository,
|
||||
IUnitOfWork unitOfWork, IAuthHelper authHelper)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_projectPhaseRepository = projectPhaseRepository;
|
||||
_projectTaskRepository = projectTaskRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_authHelper = authHelper;
|
||||
_userId = authHelper.GetCurrentUserId();
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(SetTimeProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
switch (request.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Task:
|
||||
return await SetTimeForProjectTask(request, cancellationToken);
|
||||
default:
|
||||
return OperationResult.Failure("سطح پروژه نامعتبر است");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperationResult> SetTimeForProject(SetTimeProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var project = await _projectRepository.GetWithFullHierarchyAsync(request.Id);
|
||||
if (project == null)
|
||||
{
|
||||
return OperationResult.NotFound("پروژه یافت نشد");
|
||||
return OperationResult.NotFound("<22><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>");
|
||||
}
|
||||
|
||||
long? addedByUserId = _userId;
|
||||
|
||||
// تنظیم زمان برای تمام sections در تمام فازها و تسکهای پروژه
|
||||
foreach (var phase in project.Phases)
|
||||
{
|
||||
foreach (var task in phase.Tasks)
|
||||
{
|
||||
foreach (var section in task.Sections)
|
||||
{
|
||||
var sectionItem = request.SectionItems.FirstOrDefault(si => si.SectionId == section.Id);
|
||||
if (sectionItem != null)
|
||||
{
|
||||
SetSectionTime(section, sectionItem, addedByUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private async Task<OperationResult> SetTimeForProjectPhase(SetTimeProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var phase = await _projectPhaseRepository.GetWithTasksAsync(request.Id);
|
||||
if (phase == null)
|
||||
{
|
||||
return OperationResult.NotFound("فاز پروژه یافت نشد");
|
||||
return OperationResult.NotFound("<22><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>");
|
||||
}
|
||||
|
||||
long? addedByUserId = _userId;
|
||||
|
||||
// تنظیم زمان برای تمام sections در تمام تسکهای این فاز
|
||||
foreach (var task in phase.Tasks)
|
||||
{
|
||||
foreach (var section in task.Sections)
|
||||
{
|
||||
var sectionItem = request.SectionItems.FirstOrDefault(si => si.SectionId == section.Id);
|
||||
if (sectionItem != null)
|
||||
{
|
||||
SetSectionTime(section, sectionItem, addedByUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private async Task<OperationResult> SetTimeForProjectTask(SetTimeProjectCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var task = await _projectTaskRepository.GetWithSectionsAsync(request.Id);
|
||||
if (task == null)
|
||||
{
|
||||
return OperationResult.NotFound("تسک یافت نشد");
|
||||
return OperationResult.NotFound("<22>Ә <20><><EFBFBD><EFBFBD> <20><><EFBFBD>");
|
||||
}
|
||||
|
||||
long? addedByUserId = _userId;
|
||||
|
||||
// تنظیم زمان مستقیماً برای sections این تسک
|
||||
foreach (var section in task.Sections)
|
||||
{
|
||||
var sectionItem = request.SectionItems.FirstOrDefault(si => si.SectionId == section.Id);
|
||||
if (sectionItem != null)
|
||||
{
|
||||
SetSectionTime(section, sectionItem, addedByUserId);
|
||||
}
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
|
||||
private void SetSectionTime(TaskSection section, SetTimeProjectSectionItem sectionItem, long? addedByUserId)
|
||||
{
|
||||
var initData = sectionItem.InitData;
|
||||
var initialTime = TimeSpan.FromHours(initData.Hours);
|
||||
|
||||
// تنظیم زمان اولیه
|
||||
section.UpdateInitialEstimatedHours(initialTime, initData.Description);
|
||||
|
||||
section.ClearAdditionalTimes();
|
||||
// افزودن زمانهای اضافی
|
||||
foreach (var additionalTime in sectionItem.AdditionalTime)
|
||||
{
|
||||
var additionalTimeSpan = TimeSpan.FromHours(additionalTime.Hours);
|
||||
section.AddAdditionalTime(additionalTimeSpan, additionalTime.Description, addedByUserId);
|
||||
}
|
||||
}
|
||||
|
||||
// private void SetSectionTime(ProjectSection section, SetTimeProjectSectionItem sectionItem, long? addedByUserId)
|
||||
// {
|
||||
// var initData = sectionItem.InitData;
|
||||
// var initialTime = TimeSpan.FromHours(initData.Hours);
|
||||
//
|
||||
// // تنظیم زمان اولیه
|
||||
// section.UpdateInitialEstimatedHours(initialTime, initData.Description);
|
||||
//
|
||||
// section.ClearAdditionalTimes();
|
||||
// // افزودن زمانهای اضافی
|
||||
// foreach (var additionalTime in sectionItem.AdditionalTime)
|
||||
// {
|
||||
// var additionalTimeSpan = TimeSpan.FromHours(additionalTime.Hours);
|
||||
// section.AddAdditionalTime(additionalTimeSpan, additionalTime.Description, addedByUserId);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using FluentValidation;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.DTOs;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject;
|
||||
|
||||
public class SetTimeProjectCommandValidator:AbstractValidator<SetTimeProjectCommand>
|
||||
{
|
||||
public SetTimeProjectCommandValidator()
|
||||
{
|
||||
RuleFor(x=>x.Id)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("شناسه پروژه نمیتواند خالی باشد.");
|
||||
|
||||
RuleForEach(x => x.SectionItems)
|
||||
.SetValidator(command => new SetTimeProjectSectionItemValidator());
|
||||
|
||||
}
|
||||
}
|
||||
public class SetTimeProjectSectionItemValidator:AbstractValidator<SetTimeProjectSectionItem>
|
||||
{
|
||||
public SetTimeProjectSectionItemValidator()
|
||||
{
|
||||
RuleFor(x=>x.SectionId)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("شناسه بخش نمیتواند خالی باشد.");
|
||||
|
||||
RuleFor(x=>x.InitData)
|
||||
.SetValidator(new TimeDataValidator());
|
||||
|
||||
RuleForEach(x=>x.AdditionalTime)
|
||||
.SetValidator(new TimeDataValidator());
|
||||
}
|
||||
}
|
||||
|
||||
public class TimeDataValidator : AbstractValidator<SetTimeSectionTime>
|
||||
{
|
||||
public TimeDataValidator()
|
||||
{
|
||||
RuleFor(x => x.Hours)
|
||||
.GreaterThanOrEqualTo(0)
|
||||
.WithMessage("ساعت نمیتواند منفی باشد.");
|
||||
|
||||
RuleFor(x=>x.Description)
|
||||
.MaximumLength(500)
|
||||
.WithMessage("توضیحات نمیتواند بیشتر از 500 کاراکتر باشد.");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection;
|
||||
|
||||
public record TransferSectionCommand : IBaseCommand
|
||||
{
|
||||
public Guid SectionId { get; set; }
|
||||
public long FromUserId { get; set; }
|
||||
public long ToUserId { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
|
||||
using GozareshgirProgramManager.Domain.UserAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection;
|
||||
|
||||
public class TransferSectionCommandHandler : IBaseCommandHandler<TransferSectionCommand>
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly ITaskSectionRepository _taskSectionRepository;
|
||||
private readonly IUserRepository _userRepository;
|
||||
|
||||
public TransferSectionCommandHandler(
|
||||
ITaskSectionRepository taskSectionRepository,
|
||||
IUserRepository userRepository,
|
||||
IUnitOfWork unitOfWork)
|
||||
{
|
||||
_taskSectionRepository = taskSectionRepository;
|
||||
_userRepository = userRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(TransferSectionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// دریافت section با activities
|
||||
var section = await _taskSectionRepository.GetByIdWithActivitiesAsync(request.SectionId, cancellationToken);
|
||||
if (section == null)
|
||||
{
|
||||
return OperationResult.NotFound("بخش پروژه یافت نشد");
|
||||
}
|
||||
|
||||
// بررسی وجود کاربر مبدا
|
||||
var fromUser = await _userRepository.GetByIdAsync(request.FromUserId);
|
||||
if (fromUser == null)
|
||||
{
|
||||
return OperationResult.NotFound($"کاربر مبدا با شناسه {request.FromUserId} یافت نشد");
|
||||
}
|
||||
|
||||
// بررسی وجود کاربر مقصد
|
||||
var toUser = await _userRepository.GetByIdAsync(request.ToUserId);
|
||||
if (toUser == null)
|
||||
{
|
||||
return OperationResult.NotFound($"کاربر مقصد با شناسه {request.ToUserId} یافت نشد");
|
||||
}
|
||||
|
||||
// بررسی اینکه کاربر مبدا و مقصد یکسان نباشند
|
||||
if (request.FromUserId == request.ToUserId)
|
||||
{
|
||||
return OperationResult.Failure("کاربر مبدا و مقصد نمیتوانند یکسان باشند");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// انتقال به کاربر جدید
|
||||
section.TransferToUser(request.FromUserId, request.ToUserId);
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
return OperationResult.Failure(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection;
|
||||
|
||||
public class TransferSectionCommandValidator : AbstractValidator<TransferSectionCommand>
|
||||
{
|
||||
public TransferSectionCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.SectionId)
|
||||
.NotEmpty()
|
||||
.WithMessage("شناسه بخش نمیتواند خالی باشد");
|
||||
|
||||
RuleFor(x => x.FromUserId)
|
||||
.NotEmpty()
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه کاربر مبدا نمیتواند خالی یا صفر باشد");
|
||||
|
||||
RuleFor(x => x.ToUserId)
|
||||
.NotEmpty()
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه کاربر مقصد نمیتواند خالی یا صفر باشد");
|
||||
|
||||
RuleFor(x => x)
|
||||
.Must(x => x.FromUserId != x.ToUserId)
|
||||
.WithMessage("کاربر مبدا و مقصد نمیتوانند یکسان باشند");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.DTOs;
|
||||
|
||||
/// <summary>
|
||||
/// DTO for Project entity
|
||||
/// </summary>
|
||||
public class ProjectDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public DateTime CreationDate { get; set; }
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
public DateTime? PlannedStartDate { get; set; }
|
||||
public DateTime? PlannedEndDate { get; set; }
|
||||
public string Status { get; set; } = string.Empty;
|
||||
public TimeSpan? AllocatedTime { get; set; }
|
||||
public bool HasTimeOverride { get; set; }
|
||||
public bool HasAssignmentOverride { get; set; }
|
||||
public TimeSpan TotalTimeSpent { get; set; }
|
||||
public TimeSpan TotalEstimatedTime { get; set; }
|
||||
|
||||
public List<ProjectPhaseDto> Phases { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DTO for ProjectPhase entity
|
||||
/// </summary>
|
||||
public class ProjectPhaseDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public DateTime CreationDate { get; set; }
|
||||
public Guid ProjectId { get; set; }
|
||||
public string Status { get; set; } = string.Empty;
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
public int OrderIndex { get; set; }
|
||||
public TimeSpan? AllocatedTime { get; set; }
|
||||
public bool HasTimeOverride { get; set; }
|
||||
public bool HasAssignmentOverride { get; set; }
|
||||
public TimeSpan TotalTimeSpent { get; set; }
|
||||
public TimeSpan TotalEstimatedTime { get; set; }
|
||||
|
||||
public List<ProjectTaskDto> Tasks { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DTO for ProjectTask entity
|
||||
/// </summary>
|
||||
public class ProjectTaskDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public DateTime CreationDate { get; set; }
|
||||
public Guid PhaseId { get; set; }
|
||||
public string Status { get; set; } = string.Empty;
|
||||
public string Priority { get; set; } = string.Empty;
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
public DateTime? DueDate { get; set; }
|
||||
public int OrderIndex { get; set; }
|
||||
public TimeSpan? AllocatedTime { get; set; }
|
||||
public bool HasTimeOverride { get; set; }
|
||||
public bool HasAssignmentOverride { get; set; }
|
||||
public TimeSpan TotalTimeSpent { get; set; }
|
||||
public TimeSpan TotalEstimatedTime { get; set; }
|
||||
|
||||
public List<ProjectSectionDto> Sections { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DTO for TaskSection entity
|
||||
/// </summary>
|
||||
public class ProjectSectionDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TaskId { get; set; }
|
||||
public Guid SkillId { get; set; }
|
||||
public string SkillName { get; set; } = string.Empty;
|
||||
public TimeSpan InitialEstimatedHours { get; set; }
|
||||
public string? InitialDescription { get; set; }
|
||||
public string Status { get; set; } = string.Empty;
|
||||
public long CurrentAssignedUserId { get; set; }
|
||||
public string? CurrentAssignedUserName { get; set; }
|
||||
public DateTime CreationDate { get; set; }
|
||||
|
||||
public TimeSpan FinalEstimatedHours { get; set; }
|
||||
public TimeSpan TotalTimeSpent { get; set; }
|
||||
public bool IsCompleted { get; set; }
|
||||
public bool IsInProgress { get; set; }
|
||||
|
||||
public List<TaskSectionActivityDto> Activities { get; set; } = new();
|
||||
public List<TaskSectionAdditionalTimeDto> AdditionalTimes { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DTO for ProjectSectionActivity entity
|
||||
/// </summary>
|
||||
public class TaskSectionActivityDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid SectionId { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string? UserName { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public string? EndNotes { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public TimeSpan TimeSpent { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DTO for ProjectSectionAdditionalTime entity
|
||||
/// </summary>
|
||||
public class TaskSectionAdditionalTimeDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public TimeSpan Hours { get; set; }
|
||||
public string? Reason { get; set; }
|
||||
public long? AddedByUserId { get; set; }
|
||||
public string? AddedByUserName { get; set; }
|
||||
public DateTime AddedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.DTOs;
|
||||
|
||||
public class SetTimeProjectSectionItem
|
||||
{
|
||||
public Guid SectionId { get; set; }
|
||||
public SetTimeSectionTime InitData { get; set; }
|
||||
public List<SetTimeSectionTime> AdditionalTime { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.DTOs;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Mapping extensions for project hierarchy entities to DTOs
|
||||
/// </summary>
|
||||
public static class ProjectMappingExtensions
|
||||
{
|
||||
#region Project Mappings
|
||||
|
||||
public static ProjectDto ToDto(this Project project)
|
||||
{
|
||||
return new ProjectDto
|
||||
{
|
||||
Id = project.Id,
|
||||
Name = project.Name,
|
||||
Description = project.Description,
|
||||
CreationDate = project.CreationDate,
|
||||
StartDate = project.StartDate,
|
||||
EndDate = project.EndDate,
|
||||
PlannedStartDate = project.PlannedStartDate,
|
||||
PlannedEndDate = project.PlannedEndDate,
|
||||
Status = project.Status.ToString(),
|
||||
HasAssignmentOverride = project.HasAssignmentOverride,
|
||||
TotalTimeSpent = project.GetTotalTimeSpent(),
|
||||
TotalEstimatedTime = project.GetTotalEstimatedTime(),
|
||||
Phases = project.Phases.Select(p => p.ToDto()).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public static ProjectDto ToSummaryDto(this Project project)
|
||||
{
|
||||
return new ProjectDto
|
||||
{
|
||||
Id = project.Id,
|
||||
Name = project.Name,
|
||||
Description = project.Description,
|
||||
CreationDate = project.CreationDate,
|
||||
StartDate = project.StartDate,
|
||||
EndDate = project.EndDate,
|
||||
PlannedStartDate = project.PlannedStartDate,
|
||||
PlannedEndDate = project.PlannedEndDate,
|
||||
Status = project.Status.ToString(),
|
||||
HasAssignmentOverride = project.HasAssignmentOverride,
|
||||
TotalTimeSpent = project.GetTotalTimeSpent(),
|
||||
TotalEstimatedTime = project.GetTotalEstimatedTime()
|
||||
// No phases for summary
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Phase Mappings
|
||||
|
||||
public static ProjectPhaseDto ToDto(this ProjectPhase phase)
|
||||
{
|
||||
return new ProjectPhaseDto
|
||||
{
|
||||
Id = phase.Id,
|
||||
Name = phase.Name,
|
||||
Description = phase.Description,
|
||||
CreationDate = phase.CreationDate,
|
||||
ProjectId = phase.ProjectId,
|
||||
Status = phase.Status.ToString(),
|
||||
StartDate = phase.StartDate,
|
||||
EndDate = phase.EndDate,
|
||||
OrderIndex = phase.OrderIndex,
|
||||
HasAssignmentOverride = phase.HasAssignmentOverride,
|
||||
TotalTimeSpent = phase.GetTotalTimeSpent(),
|
||||
TotalEstimatedTime = phase.GetTotalEstimatedTime(),
|
||||
Tasks = phase.Tasks.Select(t => t.ToDto()).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public static ProjectPhaseDto ToSummaryDto(this ProjectPhase phase)
|
||||
{
|
||||
return new ProjectPhaseDto
|
||||
{
|
||||
Id = phase.Id,
|
||||
Name = phase.Name,
|
||||
Description = phase.Description,
|
||||
CreationDate = phase.CreationDate,
|
||||
ProjectId = phase.ProjectId,
|
||||
Status = phase.Status.ToString(),
|
||||
StartDate = phase.StartDate,
|
||||
EndDate = phase.EndDate,
|
||||
OrderIndex = phase.OrderIndex,
|
||||
HasAssignmentOverride = phase.HasAssignmentOverride,
|
||||
TotalTimeSpent = phase.GetTotalTimeSpent(),
|
||||
TotalEstimatedTime = phase.GetTotalEstimatedTime()
|
||||
// No tasks for summary
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Task Mappings
|
||||
|
||||
public static ProjectTaskDto ToDto(this ProjectTask task)
|
||||
{
|
||||
return new ProjectTaskDto
|
||||
{
|
||||
Id = task.Id,
|
||||
Name = task.Name,
|
||||
Description = task.Description,
|
||||
CreationDate = task.CreationDate,
|
||||
PhaseId = task.PhaseId,
|
||||
Status = task.Status.ToString(),
|
||||
Priority = task.Priority.ToString(),
|
||||
StartDate = task.StartDate,
|
||||
EndDate = task.EndDate,
|
||||
DueDate = task.DueDate,
|
||||
OrderIndex = task.OrderIndex,
|
||||
AllocatedTime = task.AllocatedTime,
|
||||
HasTimeOverride = task.HasTimeOverride,
|
||||
HasAssignmentOverride = task.HasAssignmentOverride,
|
||||
TotalTimeSpent = task.GetTotalTimeSpent(),
|
||||
TotalEstimatedTime = task.GetTotalEstimatedTime(),
|
||||
Sections = task.Sections.Select(s => s.ToDto()).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public static ProjectTaskDto ToSummaryDto(this ProjectTask task)
|
||||
{
|
||||
return new ProjectTaskDto
|
||||
{
|
||||
Id = task.Id,
|
||||
Name = task.Name,
|
||||
Description = task.Description,
|
||||
CreationDate = task.CreationDate,
|
||||
PhaseId = task.PhaseId,
|
||||
Status = task.Status.ToString(),
|
||||
Priority = task.Priority.ToString(),
|
||||
StartDate = task.StartDate,
|
||||
EndDate = task.EndDate,
|
||||
DueDate = task.DueDate,
|
||||
OrderIndex = task.OrderIndex,
|
||||
AllocatedTime = task.AllocatedTime,
|
||||
HasTimeOverride = task.HasTimeOverride,
|
||||
HasAssignmentOverride = task.HasAssignmentOverride,
|
||||
TotalTimeSpent = task.GetTotalTimeSpent(),
|
||||
TotalEstimatedTime = task.GetTotalEstimatedTime()
|
||||
// No sections for summary
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Section Mappings
|
||||
|
||||
public static ProjectSectionDto ToDto(this TaskSection section)
|
||||
{
|
||||
return new ProjectSectionDto
|
||||
{
|
||||
Id = section.Id,
|
||||
TaskId = section.TaskId,
|
||||
SkillId = section.SkillId,
|
||||
SkillName = section.Skill?.Name ?? string.Empty,
|
||||
InitialEstimatedHours = section.InitialEstimatedHours,
|
||||
InitialDescription = section.InitialDescription,
|
||||
Status = section.Status.ToString(),
|
||||
CurrentAssignedUserId = section.CurrentAssignedUserId,
|
||||
CreationDate = section.CreationDate,
|
||||
FinalEstimatedHours = section.FinalEstimatedHours,
|
||||
TotalTimeSpent = section.GetTotalTimeSpent(),
|
||||
IsCompleted = section.IsCompleted(),
|
||||
IsInProgress = section.IsInProgress(),
|
||||
Activities = section.Activities.Select(a => a.ToDto()).ToList(),
|
||||
AdditionalTimes = section.AdditionalTimes.Select(at => at.ToDto()).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public static ProjectSectionDto ToSummaryDto(this TaskSection section)
|
||||
{
|
||||
return new ProjectSectionDto
|
||||
{
|
||||
Id = section.Id,
|
||||
TaskId = section.TaskId,
|
||||
SkillId = section.SkillId,
|
||||
SkillName = section.Skill?.Name ?? string.Empty,
|
||||
InitialEstimatedHours = section.InitialEstimatedHours,
|
||||
InitialDescription = section.InitialDescription,
|
||||
Status = section.Status.ToString(),
|
||||
CurrentAssignedUserId = section.CurrentAssignedUserId,
|
||||
CreationDate = section.CreationDate,
|
||||
FinalEstimatedHours = section.FinalEstimatedHours,
|
||||
TotalTimeSpent = section.GetTotalTimeSpent(),
|
||||
IsCompleted = section.IsCompleted(),
|
||||
IsInProgress = section.IsInProgress()
|
||||
// No activities or additional times for summary
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Activity Mappings
|
||||
|
||||
public static TaskSectionActivityDto ToDto(this TaskSectionActivity activity)
|
||||
{
|
||||
return new TaskSectionActivityDto
|
||||
{
|
||||
Id = activity.Id,
|
||||
SectionId = activity.SectionId,
|
||||
UserId = activity.UserId,
|
||||
StartDate = activity.StartDate,
|
||||
EndDate = activity.EndDate,
|
||||
Notes = activity.Notes,
|
||||
EndNotes = activity.EndNotes,
|
||||
IsActive = activity.IsActive,
|
||||
TimeSpent = activity.GetTimeSpent()
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Additional Time Mappings
|
||||
|
||||
public static TaskSectionAdditionalTimeDto ToDto(this TaskSectionAdditionalTime additionalTime)
|
||||
{
|
||||
return new TaskSectionAdditionalTimeDto
|
||||
{
|
||||
Id = additionalTime.Id,
|
||||
Hours = additionalTime.Hours,
|
||||
Reason = additionalTime.Reason,
|
||||
AddedByUserId = additionalTime.AddedByUserId,
|
||||
AddedAt = additionalTime.AddedAt
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Collection Mappings
|
||||
|
||||
public static List<ProjectDto> ToSummaryDtos(this IEnumerable<Project> projects)
|
||||
{
|
||||
return projects.Select(p => p.ToSummaryDto()).ToList();
|
||||
}
|
||||
|
||||
public static List<ProjectPhaseDto> ToSummaryDtos(this IEnumerable<ProjectPhase> phases)
|
||||
{
|
||||
return phases.Select(p => p.ToSummaryDto()).ToList();
|
||||
}
|
||||
|
||||
public static List<ProjectTaskDto> ToSummaryDtos(this IEnumerable<ProjectTask> tasks)
|
||||
{
|
||||
return tasks.Select(t => t.ToSummaryDto()).ToList();
|
||||
}
|
||||
|
||||
public static List<ProjectSectionDto> ToSummaryDtos(this IEnumerable<TaskSection> sections)
|
||||
{
|
||||
return sections.Select(s => s.ToSummaryDto()).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectAssignDetails;
|
||||
|
||||
public record GetProjectAssignDetailsResponse(List<GetProjectAssignSectionDetails> Items);
|
||||
|
||||
public record GetProjectAssignSectionDetails(string Skill,Guid SkillId,Guid? SectionId,long UserId);
|
||||
|
||||
public record GetProjectAssignDetailsQuery(Guid Id,ProjectHierarchyLevel Level) : IBaseQuery<GetProjectAssignDetailsResponse>;
|
||||
|
||||
public class GetProjectAssignDetailsQueryHandler:IBaseQueryHandler<GetProjectAssignDetailsQuery,GetProjectAssignDetailsResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _dbContext;
|
||||
|
||||
public GetProjectAssignDetailsQueryHandler(IProgramManagerDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetProjectAssignDetailsResponse>> Handle(GetProjectAssignDetailsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
switch (request.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
return await GetProjectAssignDetails(request.Id, cancellationToken);
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
return await GetPhaseAssignDetails(request.Id, cancellationToken);
|
||||
case ProjectHierarchyLevel.Task:
|
||||
return await GetTaskAssignDetails(request.Id, cancellationToken);
|
||||
default:
|
||||
return OperationResult<GetProjectAssignDetailsResponse>.Failure("سطح پروژه نامعتبر است");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperationResult<GetProjectAssignDetailsResponse>> GetProjectAssignDetails(Guid projectId, CancellationToken cancellationToken)
|
||||
{
|
||||
// گرفتن تمام فازهای پروژه
|
||||
|
||||
var skills = _dbContext.Skills.ToList();
|
||||
var sectionsData =await _dbContext.ProjectSections
|
||||
.Where(p => p.ProjectId == projectId).ToListAsync(cancellationToken);
|
||||
|
||||
if (skills.Count == 0)
|
||||
{
|
||||
return OperationResult<GetProjectAssignDetailsResponse>.Success(new GetProjectAssignDetailsResponse(new List<GetProjectAssignSectionDetails>()));
|
||||
}
|
||||
var sections = skills.Select(x=>
|
||||
{
|
||||
var section = sectionsData.FirstOrDefault(s => s.SkillId == x.Id);
|
||||
|
||||
return new GetProjectAssignSectionDetails(
|
||||
x.Name,
|
||||
x.Id,
|
||||
section?.Id,
|
||||
section?.UserId ?? 0
|
||||
);
|
||||
|
||||
}).ToList();
|
||||
var response = new GetProjectAssignDetailsResponse(sections);
|
||||
return OperationResult<GetProjectAssignDetailsResponse>.Success(response);
|
||||
}
|
||||
|
||||
private async Task<OperationResult<GetProjectAssignDetailsResponse>> GetPhaseAssignDetails(Guid phaseId, CancellationToken cancellationToken)
|
||||
{
|
||||
var skills = _dbContext.Skills.ToList();
|
||||
|
||||
var sectionsData =await _dbContext.PhaseSections
|
||||
.Where(p => p.PhaseId == phaseId)
|
||||
.ToListAsync(cancellationToken: cancellationToken);
|
||||
|
||||
if (skills.Count == 0)
|
||||
{
|
||||
return OperationResult<GetProjectAssignDetailsResponse>.Success(new GetProjectAssignDetailsResponse(new List<GetProjectAssignSectionDetails>()));
|
||||
}
|
||||
|
||||
var sections = skills.Select(x=>
|
||||
{
|
||||
var section = sectionsData.FirstOrDefault(s => s.SkillId == x.Id);
|
||||
|
||||
return new GetProjectAssignSectionDetails(
|
||||
x.Name,
|
||||
x.Id,
|
||||
section?.Id,
|
||||
section?.UserId ?? 0
|
||||
);
|
||||
|
||||
}).ToList();
|
||||
|
||||
var response = new GetProjectAssignDetailsResponse(sections);
|
||||
return OperationResult<GetProjectAssignDetailsResponse>.Success(response);
|
||||
}
|
||||
|
||||
private async Task<OperationResult<GetProjectAssignDetailsResponse>> GetTaskAssignDetails(Guid taskId, CancellationToken cancellationToken)
|
||||
{
|
||||
var skills = _dbContext.Skills.ToList();
|
||||
var sectionsData =await _dbContext.TaskSections
|
||||
.Where(p => p.TaskId == taskId).ToListAsync(cancellationToken);
|
||||
|
||||
if (skills.Count == 0)
|
||||
{
|
||||
return OperationResult<GetProjectAssignDetailsResponse>.Success(new GetProjectAssignDetailsResponse(new List<GetProjectAssignSectionDetails>()));
|
||||
}
|
||||
var sections = skills.Select(x=>
|
||||
{
|
||||
var section = sectionsData.FirstOrDefault(s => s.SkillId == x.Id);
|
||||
|
||||
return new GetProjectAssignSectionDetails(
|
||||
x.Name,
|
||||
x.Id,
|
||||
section?.Id,
|
||||
section?.OriginalAssignedUserId ?? 0
|
||||
);
|
||||
|
||||
}).ToList();
|
||||
|
||||
var response = new GetProjectAssignDetailsResponse(sections);
|
||||
return OperationResult<GetProjectAssignDetailsResponse>.Success(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
|
||||
public record GetProjectListDto
|
||||
{
|
||||
public Guid Id { get; init; }
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public int Percentage { get; init; }
|
||||
public ProjectHierarchyLevel Level { get; init; }
|
||||
public Guid? ParentId { get; init; }
|
||||
public bool HasFront { get; set; }
|
||||
public bool HasBackend { get; set; }
|
||||
public bool HasDesign { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
|
||||
|
||||
public record GetProjectsListQuery(ProjectHierarchyLevel HierarchyLevel,
|
||||
Guid? ParentId) : IBaseQuery<GetProjectsListResponse>;
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
|
||||
|
||||
public class GetProjectsListQueryHandler : IBaseQueryHandler<GetProjectsListQuery, GetProjectsListResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetProjectsListQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetProjectsListResponse>> Handle(GetProjectsListQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
List<GetProjectListDto> projects;
|
||||
|
||||
switch (request.HierarchyLevel)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
projects = await GetProjects(request.ParentId, cancellationToken);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
projects = await GetPhases(request.ParentId, cancellationToken);
|
||||
break;
|
||||
case ProjectHierarchyLevel.Task:
|
||||
projects = await GetTasks(request.ParentId, cancellationToken);
|
||||
break;
|
||||
default:
|
||||
return OperationResult<GetProjectsListResponse>.Failure("سطح سلسله مراتب نامعتبر است");
|
||||
}
|
||||
await SetSkillFlags(projects, cancellationToken);
|
||||
|
||||
var response = new GetProjectsListResponse(projects);
|
||||
return OperationResult<GetProjectsListResponse>.Success(response);
|
||||
}
|
||||
|
||||
private async Task<List<GetProjectListDto>> GetProjects(Guid? parentId, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.Projects.AsQueryable();
|
||||
|
||||
// پروژهها سطح بالا هستند و parentId ندارند، فقط در صورت null بودن parentId نمایش داده میشوند
|
||||
if (parentId.HasValue)
|
||||
{
|
||||
return new List<GetProjectListDto>(); // پروژهها parent ندارند
|
||||
}
|
||||
|
||||
var projects = await query
|
||||
.OrderByDescending(p => p.CreationDate)
|
||||
.ToListAsync(cancellationToken);
|
||||
var result = new List<GetProjectListDto>();
|
||||
|
||||
foreach (var project in projects)
|
||||
{
|
||||
var percentage = await CalculateProjectPercentage(project, cancellationToken);
|
||||
result.Add(new GetProjectListDto
|
||||
{
|
||||
Id = project.Id,
|
||||
Name = project.Name,
|
||||
Level = ProjectHierarchyLevel.Project,
|
||||
ParentId = null,
|
||||
Percentage = percentage
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<List<GetProjectListDto>> GetPhases(Guid? parentId, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.ProjectPhases.AsQueryable();
|
||||
|
||||
if (parentId.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.ProjectId == parentId);
|
||||
}
|
||||
|
||||
var phases = await query
|
||||
.OrderByDescending(p => p.CreationDate)
|
||||
.ToListAsync(cancellationToken);
|
||||
var result = new List<GetProjectListDto>();
|
||||
|
||||
foreach (var phase in phases)
|
||||
{
|
||||
var percentage = await CalculatePhasePercentage(phase, cancellationToken);
|
||||
result.Add(new GetProjectListDto
|
||||
{
|
||||
Id = phase.Id,
|
||||
Name = phase.Name,
|
||||
Level = ProjectHierarchyLevel.Phase,
|
||||
ParentId = phase.ProjectId,
|
||||
Percentage = percentage
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<List<GetProjectListDto>> GetTasks(Guid? parentId, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.ProjectTasks.AsQueryable();
|
||||
|
||||
if (parentId.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.PhaseId == parentId);
|
||||
}
|
||||
|
||||
var tasks = await query
|
||||
.OrderByDescending(t => t.CreationDate)
|
||||
.ToListAsync(cancellationToken);
|
||||
var result = new List<GetProjectListDto>();
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
var percentage = await CalculateTaskPercentage(task, cancellationToken);
|
||||
result.Add(new GetProjectListDto
|
||||
{
|
||||
Id = task.Id,
|
||||
Name = task.Name,
|
||||
Level = ProjectHierarchyLevel.Task,
|
||||
ParentId = task.PhaseId,
|
||||
Percentage = percentage
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task SetSkillFlags(List<GetProjectListDto> projects, CancellationToken cancellationToken)
|
||||
{
|
||||
var projectIds = projects.Select(x => x.Id).ToList();
|
||||
|
||||
// تنها تسکها sections دارند، بنابراین برای سطوح مختلف باید متفاوت عمل کنیم
|
||||
List<Guid> taskIds;
|
||||
|
||||
switch (projects.FirstOrDefault()?.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
// برای پروژهها، باید تمام تسکهای زیرمجموعه را پیدا کنیم
|
||||
var phaseIds = await _context.ProjectPhases
|
||||
.Where(ph => projectIds.Contains(ph.ProjectId))
|
||||
.Select(ph => ph.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
taskIds = await _context.ProjectTasks
|
||||
.Where(t => phaseIds.Contains(t.PhaseId))
|
||||
.Select(t => t.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
break;
|
||||
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
// برای فازها، تمام تسکهای آن فازها را پیدا کنیم
|
||||
taskIds = await _context.ProjectTasks
|
||||
.Where(t => projectIds.Contains(t.PhaseId))
|
||||
.Select(t => t.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
break;
|
||||
|
||||
case ProjectHierarchyLevel.Task:
|
||||
// برای تسکها، خود آنها taskIds هستند
|
||||
taskIds = projectIds;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!taskIds.Any())
|
||||
return;
|
||||
|
||||
var sections = await _context.TaskSections
|
||||
.Include(x => x.Skill)
|
||||
.Where(x => taskIds.Contains(x.TaskId))
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
foreach (var project in projects)
|
||||
{
|
||||
List<Guid> relevantTaskIds;
|
||||
|
||||
switch (project.Level)
|
||||
{
|
||||
case ProjectHierarchyLevel.Project:
|
||||
// برای پروژه، تمام تسکهای زیرمجموعه
|
||||
var projectPhaseIds = await _context.ProjectPhases
|
||||
.Where(ph => ph.ProjectId == project.Id)
|
||||
.Select(ph => ph.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
relevantTaskIds = await _context.ProjectTasks
|
||||
.Where(t => projectPhaseIds.Contains(t.PhaseId))
|
||||
.Select(t => t.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
break;
|
||||
|
||||
case ProjectHierarchyLevel.Phase:
|
||||
// برای فاز، تمام تسکهای آن فاز
|
||||
relevantTaskIds = await _context.ProjectTasks
|
||||
.Where(t => t.PhaseId == project.Id)
|
||||
.Select(t => t.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
break;
|
||||
|
||||
case ProjectHierarchyLevel.Task:
|
||||
// برای تسک، خود آن
|
||||
relevantTaskIds = new List<Guid> { project.Id };
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
var projectSections = sections.Where(x => relevantTaskIds.Contains(x.TaskId)).ToList();
|
||||
project.HasBackend = projectSections.Any(x => x.Skill.Name == "Backend");
|
||||
project.HasFront = projectSections.Any(x => x.Skill.Name == "Frontend");
|
||||
project.HasDesign = projectSections.Any(x => x.Skill.Name == "UI/UX Design");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<int> CalculateProjectPercentage(Project project, CancellationToken cancellationToken)
|
||||
{
|
||||
// گرفتن تمام فازهای پروژه
|
||||
var phases = await _context.ProjectPhases
|
||||
.Where(ph => ph.ProjectId == project.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (!phases.Any())
|
||||
return 0;
|
||||
|
||||
// محاسبه درصد هر فاز و میانگینگیری
|
||||
var phasePercentages = new List<int>();
|
||||
foreach (var phase in phases)
|
||||
{
|
||||
var phasePercentage = await CalculatePhasePercentage(phase, cancellationToken);
|
||||
phasePercentages.Add(phasePercentage);
|
||||
}
|
||||
|
||||
return phasePercentages.Any() ? (int)phasePercentages.Average() : 0;
|
||||
}
|
||||
|
||||
private async Task<int> CalculatePhasePercentage(ProjectPhase phase, CancellationToken cancellationToken)
|
||||
{
|
||||
// گرفتن تمام تسکهای فاز
|
||||
var tasks = await _context.ProjectTasks
|
||||
.Where(t => t.PhaseId == phase.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (!tasks.Any())
|
||||
return 0;
|
||||
|
||||
// محاسبه درصد هر تسک و میانگینگیری
|
||||
var taskPercentages = new List<int>();
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
var taskPercentage = await CalculateTaskPercentage(task, cancellationToken);
|
||||
taskPercentages.Add(taskPercentage);
|
||||
}
|
||||
|
||||
return taskPercentages.Any() ? (int)taskPercentages.Average() : 0;
|
||||
}
|
||||
|
||||
private async Task<int> CalculateTaskPercentage(ProjectTask task, CancellationToken cancellationToken)
|
||||
{
|
||||
// گرفتن تمام سکشنهای تسک با activities
|
||||
var sections = await _context.TaskSections
|
||||
.Include(s => s.Activities)
|
||||
.Where(s => s.TaskId == task.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (!sections.Any())
|
||||
return 0;
|
||||
|
||||
// محاسبه درصد هر سکشن و میانگینگیری
|
||||
var sectionPercentages = new List<int>();
|
||||
foreach (var section in sections)
|
||||
{
|
||||
var sectionPercentage = CalculateSectionPercentage(section);
|
||||
sectionPercentages.Add(sectionPercentage);
|
||||
}
|
||||
|
||||
return sectionPercentages.Any() ? (int)sectionPercentages.Average() : 0;
|
||||
}
|
||||
|
||||
private static int CalculateSectionPercentage(TaskSection section)
|
||||
{
|
||||
// محاسبه کل زمان تخمین زده شده (اولیه + اضافی)
|
||||
var totalEstimatedHours = section.FinalEstimatedHours.TotalHours;
|
||||
|
||||
if (totalEstimatedHours <= 0)
|
||||
return 0;
|
||||
|
||||
// محاسبه کل زمان صرف شده از activities
|
||||
var totalSpentHours = section.Activities.Sum(a => a.GetTimeSpent().TotalHours);
|
||||
|
||||
// محاسبه درصد (حداکثر 100%)
|
||||
var percentage = (totalSpentHours / totalEstimatedHours) * 100;
|
||||
return Math.Min((int)Math.Round(percentage), 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
|
||||
|
||||
public class GetProjectsListQueryValidator : AbstractValidator<GetProjectsListQuery>
|
||||
{
|
||||
public GetProjectsListQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.HierarchyLevel)
|
||||
.IsInEnum().WithMessage("سطح ارسال شده معتبر نمیباشد.");
|
||||
|
||||
When(x => x.HierarchyLevel != Domain.ProjectAgg.Enums.ProjectHierarchyLevel.Project, () =>
|
||||
{
|
||||
RuleFor(x => x.ParentId)
|
||||
.NotNull().WithMessage("شناسه والد باید برای سطوح غیر از پروژه ارسال شود.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
|
||||
|
||||
public record GetProjectsListResponse(
|
||||
List<GetProjectListDto> Projects);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList;
|
||||
|
||||
public record ProjectBoardListQuery: IBaseQuery<List<ProjectBoardListResponse>>
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList;
|
||||
|
||||
public class ProjectBoardListQueryHandler : IBaseQueryHandler<ProjectBoardListQuery, List<ProjectBoardListResponse>>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _programManagerDbContext;
|
||||
private readonly IAuthHelper _authHelper;
|
||||
|
||||
public ProjectBoardListQueryHandler(IProgramManagerDbContext programManagerDbContext, IAuthHelper authHelper)
|
||||
{
|
||||
_programManagerDbContext = programManagerDbContext;
|
||||
_authHelper = authHelper;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<List<ProjectBoardListResponse>>> Handle(ProjectBoardListQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var currentUserId = _authHelper.GetCurrentUserId();
|
||||
var data = await _programManagerDbContext.TaskSections.AsNoTracking()
|
||||
.Where(x => x.CurrentAssignedUserId == currentUserId)
|
||||
.Where(x => x.InitialEstimatedHours > TimeSpan.Zero)
|
||||
.Include(x => x.Task)
|
||||
.ThenInclude(x => x.Phase)
|
||||
.ThenInclude(x => x.Project)
|
||||
.Include(x => x.Activities)
|
||||
.Include(x => x.AdditionalTimes)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var activityUserIds = data.SelectMany(x => x.Activities).Select(a => a.UserId).Distinct().ToList();
|
||||
var users = await _programManagerDbContext.Users.AsNoTracking()
|
||||
.Where(x => activityUserIds.Contains(x.Id))
|
||||
.Select(x => new { x.Id, x.FullName })
|
||||
.ToDictionaryAsync(x => x.Id, x => x.FullName, cancellationToken);
|
||||
|
||||
var result = data.Select(x =>
|
||||
{
|
||||
// محاسبه یکبار برای هر Activity و Cache کردن نتیجه
|
||||
var activityTimeData = x.Activities.Select(a =>
|
||||
{
|
||||
var timeSpent = a.GetTimeSpent();
|
||||
return new
|
||||
{
|
||||
Activity = a,
|
||||
TimeSpent = timeSpent,
|
||||
TotalSeconds = timeSpent.TotalSeconds,
|
||||
FormattedTime = timeSpent.ToString(@"hh\:mm")
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
// ادغام پشت سر هم فعالیتهای یک کاربر
|
||||
var mergedHistories = new List<ProjectProgressHistoryDto>();
|
||||
foreach (var activityData in activityTimeData)
|
||||
{
|
||||
var lastHistory = mergedHistories.LastOrDefault();
|
||||
|
||||
// اگر آخرین history برای همین کاربر باشد، زمانها را جمع میکنیم
|
||||
if (lastHistory != null && lastHistory.UserId == activityData.Activity.UserId)
|
||||
{
|
||||
var totalTimeSpan = lastHistory.WorkedTimeSpan + activityData.TimeSpent;
|
||||
lastHistory.WorkedTimeSpan = totalTimeSpan;
|
||||
lastHistory.WorkedTime = totalTimeSpan.ToString(@"hh\:mm");
|
||||
}
|
||||
else
|
||||
{
|
||||
// در غیر این صورت، یک history جدید اضافه میکنیم
|
||||
mergedHistories.Add(new ProjectProgressHistoryDto()
|
||||
{
|
||||
UserId = activityData.Activity.UserId,
|
||||
IsCurrentUser = activityData.Activity.UserId == currentUserId,
|
||||
Name = users.GetValueOrDefault(activityData.Activity.UserId, "ناشناس"),
|
||||
WorkedTime = activityData.FormattedTime,
|
||||
WorkedTimeSpan = activityData.TimeSpent,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return new ProjectBoardListResponse()
|
||||
{
|
||||
Id = x.Id,
|
||||
PhaseName = x.Task.Phase.Name,
|
||||
ProjectName = x.Task.Phase.Project.Name,
|
||||
TaskName = x.Task.Name,
|
||||
SectionStatus = x.Status,
|
||||
Progress = new ProjectProgressDto()
|
||||
{
|
||||
CompleteSecond = x.FinalEstimatedHours.TotalSeconds,
|
||||
CurrentSecond = activityTimeData.Sum(a => a.TotalSeconds),
|
||||
Histories = mergedHistories
|
||||
}
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
return OperationResult<List<ProjectBoardListResponse>>.Success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList;
|
||||
|
||||
public class ProjectBoardListResponse
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string ProjectName { get; set; }
|
||||
public string PhaseName { get; set; }
|
||||
public string TaskName { get; set; }
|
||||
public ProjectProgressDto Progress { get; set; }
|
||||
public TaskSectionStatus SectionStatus { get; set; }
|
||||
}
|
||||
public class ProjectProgressDto
|
||||
{
|
||||
public double CurrentSecond { get; set; }
|
||||
public double CompleteSecond { get; set; }
|
||||
public List<ProjectProgressHistoryDto> Histories { get; set; }
|
||||
}
|
||||
|
||||
public class ProjectProgressHistoryDto
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string WorkedTime { get; set; }
|
||||
public TimeSpan WorkedTimeSpan { get; set; }
|
||||
public bool IsCurrentUser { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails;
|
||||
|
||||
public record ProjectSetTimeDetailsQuery(Guid TaskId)
|
||||
: IBaseQuery<ProjectSetTimeResponse>;
|
||||
public record ProjectSetTimeResponse(
|
||||
List<ProjectSetTimeResponseSections> SectionItems,
|
||||
Guid Id,
|
||||
ProjectHierarchyLevel Level);
|
||||
|
||||
public record ProjectSetTimeResponseSections
|
||||
{
|
||||
public string SkillName { get; init; }
|
||||
public string UserName { get; init; }
|
||||
public int InitialTime { get; set; }
|
||||
public string InitialDescription { get; set; }
|
||||
public int TotalEstimateTime { get; init; }
|
||||
public int TotalAdditionalTime { get; init; }
|
||||
public string InitCreationTime { get; init; }
|
||||
public List<ProjectSetTimeResponseSectionAdditionalTime> AdditionalTimes { get; init; }
|
||||
public Guid SectionId { get; set; }
|
||||
}
|
||||
|
||||
public class ProjectSetTimeResponseSectionAdditionalTime
|
||||
{
|
||||
public int Time { get; init; }
|
||||
public string Description { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using DNTPersianUtils.Core;
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject;
|
||||
using GozareshgirProgramManager.Application.Modules.Projects.DTOs;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails;
|
||||
|
||||
|
||||
public class ProjectSetTimeDetailsQueryHandler
|
||||
: IBaseQueryHandler<ProjectSetTimeDetailsQuery, ProjectSetTimeResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public ProjectSetTimeDetailsQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<ProjectSetTimeResponse>> Handle(ProjectSetTimeDetailsQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var task = await _context.ProjectTasks
|
||||
.Where(p => p.Id == request.TaskId)
|
||||
.Include(x => x.Sections)
|
||||
.ThenInclude(x => x.AdditionalTimes).AsNoTracking()
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (task == null)
|
||||
{
|
||||
return OperationResult<ProjectSetTimeResponse>.NotFound("Project not found");
|
||||
}
|
||||
var userIds = task.Sections.Select(x => x.OriginalAssignedUserId)
|
||||
.Distinct().ToList();
|
||||
|
||||
var users = await _context.Users
|
||||
.Where(x => userIds.Contains(x.Id))
|
||||
.AsNoTracking()
|
||||
.ToListAsync(cancellationToken);
|
||||
var skillIds = task.Sections.Select(x => x.SkillId)
|
||||
.Distinct().ToList();
|
||||
|
||||
var skills = await _context.Skills
|
||||
.Where(x => skillIds.Contains(x.Id))
|
||||
.AsNoTracking()
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var res = new ProjectSetTimeResponse(
|
||||
task.Sections.Select(ts =>
|
||||
{
|
||||
var user = users.FirstOrDefault(x => x.Id == ts.OriginalAssignedUserId);
|
||||
var skill = skills.FirstOrDefault(x => x.Id == ts.SkillId);
|
||||
return new ProjectSetTimeResponseSections
|
||||
{
|
||||
AdditionalTimes = ts.AdditionalTimes
|
||||
.Select(x => new ProjectSetTimeResponseSectionAdditionalTime
|
||||
{
|
||||
Description = x.Reason ?? "",
|
||||
Time = (int)x.Hours.TotalHours
|
||||
}).ToList(),
|
||||
InitCreationTime = ts.CreationDate.ToFarsi(),
|
||||
SkillName = skill?.Name ?? "",
|
||||
TotalAdditionalTime = (int)ts.GetTotalAdditionalTime().TotalHours,
|
||||
TotalEstimateTime = (int)ts.FinalEstimatedHours.TotalHours,
|
||||
UserName = user?.UserName ?? "",
|
||||
SectionId = ts.Id,
|
||||
InitialDescription = ts.InitialDescription ?? "",
|
||||
InitialTime = (int)ts.InitialEstimatedHours.TotalHours
|
||||
};
|
||||
}).ToList(),
|
||||
task.Id,
|
||||
ProjectHierarchyLevel.Task);
|
||||
|
||||
|
||||
return OperationResult<ProjectSetTimeResponse>.Success(res);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails;
|
||||
|
||||
public class ProjectSetTimeDetailsQueryValidator:AbstractValidator<ProjectSetTimeDetailsQuery>
|
||||
{
|
||||
public ProjectSetTimeDetailsQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.TaskId)
|
||||
.NotEmpty()
|
||||
.WithMessage("شناسه پروژه نمیتواند خالی باشد.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.PermissionAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.RoleAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.RoleAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Roles.Commands.CreateRole;
|
||||
|
||||
public class CreateRoleCommandHandler : IBaseCommandHandler<CreateRoleCommand>
|
||||
{
|
||||
private readonly IRoleRepository _roleRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public CreateRoleCommandHandler(IRoleRepository roleRepository, IUnitOfWork unitOfWork)
|
||||
{
|
||||
_roleRepository = roleRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
if(string.IsNullOrWhiteSpace(request.RoleName))
|
||||
return OperationResult.Failure("نام نقش خالی است");
|
||||
if(!request.Permissions.Any())
|
||||
return OperationResult.Failure("هیچ دسترسی داده نشده است");
|
||||
var permissions = request.Permissions.Where(x => x > 0).Select(x => new Permission(x)).ToList();
|
||||
|
||||
var role = new Role(request.RoleName, request.GozareshgirRoleId, permissions);
|
||||
await _roleRepository.CreateAsync(role);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record CreateRoleCommand : IBaseCommand
|
||||
{
|
||||
public string RoleName { get; set; }
|
||||
public List<int> Permissions { get; set; }
|
||||
|
||||
public long? GozareshgirRoleId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.PermissionAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.RoleAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Roles.Commands.EditRole;
|
||||
|
||||
public class EditRoleCommandHandler : IBaseCommandHandler<EditRoleCommand>
|
||||
{
|
||||
private readonly IRoleRepository _roleRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public EditRoleCommandHandler(IRoleRepository roleRepository, IUnitOfWork unitOfWork)
|
||||
{
|
||||
_roleRepository = roleRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(EditRoleCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_roleRepository.Exists(x => x.RoleName == request.RoleName && x.GozareshgirRoleId != request.GozareshgirRoleId))
|
||||
return OperationResult.Failure("نام نقش تکراری است");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.RoleName))
|
||||
return OperationResult.Failure("نام نقش خالی است");
|
||||
|
||||
if(request.GozareshgirRoleId == null || request.GozareshgirRoleId == 0)
|
||||
return OperationResult.Failure("آی دی نقش از سمت گزارشگیر خالی است");
|
||||
|
||||
var permissions = request.Permissions.Where(x => x > 0).Select(x => new Permission(x)).ToList();
|
||||
|
||||
|
||||
var role =await _roleRepository.GetByGozareshgirRoleIdAsync(request.GozareshgirRoleId);
|
||||
|
||||
if (role != null)
|
||||
{
|
||||
role?.Edit(request.RoleName, permissions);
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
}
|
||||
|
||||
return OperationResult.Success();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public record EditRoleCommand : IBaseCommand
|
||||
{
|
||||
public string RoleName { get; set; }
|
||||
public List<int> Permissions { get; set; }
|
||||
|
||||
public long? GozareshgirRoleId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Roles.Queries.GetRoles;
|
||||
|
||||
public class GetRolesQueryHandler : IBaseQueryHandler<GetRolesQuery, GetRolesResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetRolesQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetRolesResponse>> Handle(GetRolesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.Roles.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.RoleName))
|
||||
query = query.Where(x => x.RoleName.Contains(request.RoleName));
|
||||
if (request.GozareshgirRoleId > 0)
|
||||
query = query.Where(x => x.GozareshgirRoleId == request.GozareshgirRoleId);
|
||||
|
||||
var roles = await query
|
||||
.Select(p => new GetRolesDto()
|
||||
{
|
||||
Id = p.Id,
|
||||
RoleName = p.RoleName,
|
||||
GozareshgirRoleId = p.GozareshgirRoleId,
|
||||
Permissions = p.Permissions.Select(x=>x.Code).ToList()
|
||||
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
if(!roles.Any())
|
||||
return OperationResult<GetRolesResponse>.NotFound("یافت نشد");
|
||||
|
||||
var response = new GetRolesResponse(
|
||||
roles
|
||||
);
|
||||
|
||||
return OperationResult<GetRolesResponse>.Success(response);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record GetRolesQuery(string? RoleName, long? GozareshgirRoleId) : IBaseQuery<GetRolesResponse>;
|
||||
|
||||
public record GetRolesResponse(List<GetRolesDto> Role);
|
||||
|
||||
public record GetRolesDto
|
||||
{
|
||||
/// <summary>
|
||||
/// آی دی نقش
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نام نقش
|
||||
/// </summary>
|
||||
public string RoleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آی دی نقش در گزارشگیر
|
||||
/// </summary>
|
||||
public long? GozareshgirRoleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// لیست کدهای دسترسی
|
||||
/// </summary>
|
||||
public List<int> Permissions { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings;
|
||||
|
||||
public class CreateSalarySettingsCommandHandler : IBaseCommandHandler<CreateSalarySettingsCommand>
|
||||
{
|
||||
readonly ISalaryPaymentSettingRepository _salaryPaymentSettingRepository;
|
||||
readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public CreateSalarySettingsCommandHandler(ISalaryPaymentSettingRepository salaryPaymentSettingRepository, IUnitOfWork unitOfWork)
|
||||
{
|
||||
_salaryPaymentSettingRepository = salaryPaymentSettingRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(CreateSalarySettingsCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
if(_salaryPaymentSettingRepository.Exists(x=>x.UserId == request.UserId))
|
||||
return OperationResult.Failure(" برای این پرسنل قبلا تنظیمات ایجاد شده است");
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.MonthlySalary))
|
||||
return OperationResult.Failure("حقوق ماهانه وارد نشده اشت");
|
||||
double monthlySalary = 0;
|
||||
try
|
||||
{
|
||||
monthlySalary = request.MonthlySalary.MoneyToDouble();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است");
|
||||
}
|
||||
|
||||
|
||||
if (monthlySalary == 0)
|
||||
return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است");
|
||||
|
||||
var workingHoursList = new List<WorkingHours>();
|
||||
foreach (var workingHours in request.WorkingHoursList)
|
||||
{
|
||||
var startShiftOne = new TimeSpan();
|
||||
var endShiftOne = new TimeSpan();
|
||||
var startShiftTwo = new TimeSpan();
|
||||
var endShiftTwo = new TimeSpan();
|
||||
var restTime = new TimeSpan();
|
||||
workingHours.HasShiftOne = false;
|
||||
workingHours.HasRestTime = false;
|
||||
workingHours.HasShiftTow = false;
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(workingHours.StartShiftOne) && !string.IsNullOrWhiteSpace(workingHours.EndShiftOne))
|
||||
{
|
||||
startShiftOne = TimeSpan.ParseExact(workingHours.StartShiftOne, @"hh\:mm", null);
|
||||
endShiftOne = TimeSpan.ParseExact(workingHours.EndShiftOne, @"hh\:mm", null);
|
||||
|
||||
workingHours.HasShiftOne = true;
|
||||
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(workingHours.RestTime))
|
||||
{
|
||||
try
|
||||
{
|
||||
restTime = TimeSpan.ParseExact(workingHours.RestTime, @"hh\:mm", null);
|
||||
workingHours.HasRestTime = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return OperationResult.Failure("فرمت ساعت استراحت اشتباه وارد شده است");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(workingHours.StartShiftTwo) &&
|
||||
!string.IsNullOrWhiteSpace(workingHours.EndShiftTwo))
|
||||
{
|
||||
workingHours.HasRestTime = false;
|
||||
workingHours.HasShiftTow = true;
|
||||
|
||||
startShiftTwo = TimeSpan.ParseExact(workingHours.StartShiftTwo, @"hh\:mm", null);
|
||||
endShiftTwo = TimeSpan.ParseExact(workingHours.EndShiftTwo, @"hh\:mm", null);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return OperationResult.Failure("فرمت ساعت اشتباه وارد شده است");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
workingHoursList.Add(new WorkingHours(startShiftOne,endShiftOne,startShiftTwo, endShiftTwo,restTime,workingHours.HasShiftOne,workingHours.HasShiftTow,workingHours.HasRestTime, workingHours.PersianDayOfWeek, workingHours.IsActiveDay));
|
||||
|
||||
}
|
||||
|
||||
if(workingHoursList.Count < 7)
|
||||
return OperationResult.Failure("خطا در تعداد روز های ارسال شده");
|
||||
var salarySetting = new SalaryPaymentSetting(request.HolidayWorking, request.UserId,monthlySalary, workingHoursList);
|
||||
await _salaryPaymentSettingRepository.CreateAsync(salarySetting);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
return OperationResult.Success();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record CreateSalarySettingsCommand(bool HolidayWorking, long UserId, string? MonthlySalary, List<WorkingHoursListDto> WorkingHoursList) : IBaseCommand;
|
||||
|
||||
|
||||
public record WorkingHoursListDto
|
||||
{
|
||||
/// <summary>
|
||||
/// ساعت شروع شیفت کاری
|
||||
/// </summary>
|
||||
public string? StartShiftOne { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ساعت پایان شیفت کاری
|
||||
/// </summary>
|
||||
public string? EndShiftOne { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ساعت شروع شیفت دوم کاری
|
||||
/// </summary>
|
||||
public string? StartShiftTwo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ساعت پایان شیفت دوم کاری
|
||||
/// </summary>
|
||||
public string? EndShiftTwo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// مدت استراحت
|
||||
/// </summary>
|
||||
public string? RestTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// آیا مقطع مار اول دارد
|
||||
/// </summary>
|
||||
public bool HasShiftOne { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آیا مقطع کار دوم دارد
|
||||
/// </summary>
|
||||
public bool HasShiftTow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آیا ساعت استراحت دارد
|
||||
/// </summary>
|
||||
public bool HasRestTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// عدد روز از ماه
|
||||
/// </summary>
|
||||
public PersianDayOfWeek PersianDayOfWeek { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// آیا این روز هفته
|
||||
/// فعال است
|
||||
/// </summary>
|
||||
public bool IsActiveDay { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.EditSalarySettings;
|
||||
|
||||
public class EditSalarySettingsCommandHandler : IBaseCommandHandler<EditSalarySettingsCommand>
|
||||
{
|
||||
private readonly ISalaryPaymentSettingRepository _salaryPaymentSettingRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public EditSalarySettingsCommandHandler(ISalaryPaymentSettingRepository salaryPaymentSettingRepository, IUnitOfWork unitOfWork)
|
||||
{
|
||||
_salaryPaymentSettingRepository = salaryPaymentSettingRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(EditSalarySettingsCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var getSettings =await _salaryPaymentSettingRepository.GetSalarySettingByUserId(request.UserId);
|
||||
if(getSettings == null)
|
||||
return OperationResult.NotFound("یافت نشد");
|
||||
|
||||
if(string.IsNullOrWhiteSpace(request.MonthlySalary))
|
||||
return OperationResult.Failure("حقوق ماهانه وارد نشده اشت");
|
||||
double monthlySalary = 0;
|
||||
try
|
||||
{
|
||||
monthlySalary = request.MonthlySalary.MoneyToDouble();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است");
|
||||
}
|
||||
|
||||
if (monthlySalary == 0)
|
||||
return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است");
|
||||
|
||||
|
||||
var workingHoursList = new List<WorkingHours>();
|
||||
foreach (var workingHours in request.WorkingHoursList)
|
||||
{
|
||||
var startShiftOne = new TimeSpan();
|
||||
var endShiftOne = new TimeSpan();
|
||||
var startShiftTwo = new TimeSpan();
|
||||
var endShiftTwo = new TimeSpan();
|
||||
var restTime = new TimeSpan();
|
||||
workingHours.HasShiftOne = false;
|
||||
workingHours.HasRestTime = false;
|
||||
workingHours.HasShiftTow = false;
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(workingHours.StartShiftOne) && !string.IsNullOrWhiteSpace(workingHours.EndShiftOne))
|
||||
{
|
||||
startShiftOne = TimeSpan.ParseExact(workingHours.StartShiftOne, @"hh\:mm", null);
|
||||
endShiftOne = TimeSpan.ParseExact(workingHours.EndShiftOne, @"hh\:mm", null);
|
||||
|
||||
workingHours.HasShiftOne = true;
|
||||
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(workingHours.RestTime))
|
||||
{
|
||||
try
|
||||
{
|
||||
restTime = TimeSpan.ParseExact(workingHours.RestTime, @"hh\:mm", null);
|
||||
workingHours.HasRestTime = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return OperationResult.Failure("فرمت ساعت استراحت اشتباه وارد شده است");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(workingHours.StartShiftTwo) &&
|
||||
!string.IsNullOrWhiteSpace(workingHours.EndShiftTwo))
|
||||
{
|
||||
workingHours.HasRestTime = false;
|
||||
workingHours.HasShiftTow = true;
|
||||
|
||||
startShiftTwo = TimeSpan.ParseExact(workingHours.StartShiftTwo, @"hh\:mm", null);
|
||||
endShiftTwo = TimeSpan.ParseExact(workingHours.EndShiftTwo, @"hh\:mm", null);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return OperationResult.Failure("فرمت ساعت اشتباه وارد شده است");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
workingHoursList.Add(new WorkingHours(startShiftOne, endShiftOne, startShiftTwo, endShiftTwo, restTime, workingHours.HasShiftOne, workingHours.HasShiftTow, workingHours.HasRestTime, workingHours.PersianDayOfWeek, workingHours.IsActiveDay));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
getSettings.Edit(request.HolidayWorking,monthlySalary, workingHoursList);
|
||||
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record EditSalarySettingsCommand(long UserId, bool HolidayWorking,string? MonthlySalary, List<WorkingHoursListDto> WorkingHoursList) : IBaseCommand;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit;
|
||||
|
||||
public class GetSalarySettingToEditQueryHandler : IBaseQueryHandler<GetSalarySettingToEditQuery, GetSalarySettingToEditResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetSalarySettingToEditQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetSalarySettingToEditResponse>> Handle(GetSalarySettingToEditQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var user =await _context.Users.FirstOrDefaultAsync(x => x.Id == request.UserId);
|
||||
if(user == null)
|
||||
return OperationResult<GetSalarySettingToEditResponse>.NotFound("کاربر یافت نشد");
|
||||
|
||||
var editSalarySettingsList = await _context.SalaryPaymentSettings
|
||||
.Select(x => new GetSalarySettingToEdit()
|
||||
{
|
||||
Id = x.Id,
|
||||
HolidayWorking = x.HolidayWorking,
|
||||
UserId = x.UserId,
|
||||
MonthlySalary = x.MonthlySalary.ToMoney(),
|
||||
|
||||
WorkingHoursList = x.WorkingHoursList.Select(wh => new WorkingHoursListDto
|
||||
{
|
||||
StartShiftOne =wh.HasShiftOne ? wh.StartShiftOne.ToString(@"hh\:mm") : null,
|
||||
EndShiftOne = wh.HasShiftOne ? wh.EndShiftOne.ToString(@"hh\:mm") : null,
|
||||
StartShiftTwo = wh.HasShiftTow ? wh.StartShiftTwo.ToString(@"hh\:mm") : null,
|
||||
EndShiftTwo = wh.HasShiftTow ? wh.EndShiftTwo.ToString(@"hh\:mm") :null,
|
||||
RestTime = wh.HasRestTime ? wh.RestTime.ToString(@"hh\:mm") : null,
|
||||
HasRestTime = wh.HasRestTime,
|
||||
HasShiftOne = wh.HasShiftOne,
|
||||
HasShiftTow = wh.HasShiftTow,
|
||||
PersianDayOfWeek = wh.PersianDayOfWeek,
|
||||
IsActiveDay = wh.IsActiveDay
|
||||
}).OrderBy(wh=>wh.PersianDayOfWeek).ToList(),
|
||||
|
||||
}).FirstOrDefaultAsync(x => x.UserId == request.UserId);
|
||||
|
||||
var response = new GetSalarySettingToEditResponse(request.UserId,user.FullName,editSalarySettingsList);
|
||||
|
||||
return OperationResult<GetSalarySettingToEditResponse>.Success(response);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public record GetSalarySettingToEditResponse(long UserId, string FullName, GetSalarySettingToEdit EditSalarySettingsList);
|
||||
|
||||
public record GetSalarySettingToEditQuery(long UserId) :IBaseQuery<GetSalarySettingToEditResponse>;
|
||||
|
||||
|
||||
public record GetSalarySettingToEdit
|
||||
{
|
||||
/// <summary>
|
||||
/// ای دی کاربر
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
/// <summary>
|
||||
/// آی دی کاربر
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// کار در تعطیلات رسمی
|
||||
/// </summary>
|
||||
public bool HolidayWorking { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// حقوق ماهانه
|
||||
/// </summary>
|
||||
public string MonthlySalary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// لیست روزهای هفته و ساعات کاری
|
||||
/// </summary>
|
||||
public List<WorkingHoursListDto> WorkingHoursList { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetUserListWhoHaveSettings;
|
||||
|
||||
public class GetUserListWhoHaveSettingsQueryHandler : IBaseQueryHandler<GetUserListWhoHaveSettingsQuery, GetUserListWhoHaveSettingsResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetUserListWhoHaveSettingsQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetUserListWhoHaveSettingsResponse>> Handle(GetUserListWhoHaveSettingsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = await (
|
||||
from u in _context.Users
|
||||
join s in _context.SalaryPaymentSettings
|
||||
on u.Id equals s.UserId into settingsGroup
|
||||
select new GetUserWhoHaveSettingsDto
|
||||
{
|
||||
UserId = u.Id,
|
||||
FullName = u.FullName,
|
||||
HasSalarySettings = settingsGroup.Any(),
|
||||
MontlySalary = settingsGroup.Any() ? settingsGroup.FirstOrDefault().MonthlySalary.ToMoney() : "",
|
||||
WeeklyWorkingTimeAvrageInt = settingsGroup
|
||||
.SelectMany(x => x.WorkingHoursList)
|
||||
.Sum(w => (int?)w.ShiftDurationInMinutes) ?? 0
|
||||
}
|
||||
).ToListAsync(cancellationToken);
|
||||
|
||||
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.FullName))
|
||||
query = query.Where(x => x.FullName.Contains(request.FullName)).ToList();
|
||||
|
||||
if (request.HasSalarySettings != HasSalarySettings.Default)
|
||||
{
|
||||
bool hasSettings = request.HasSalarySettings == HasSalarySettings.HasSettings;
|
||||
|
||||
query = query.Where(x => x.HasSalarySettings == hasSettings).ToList();
|
||||
}
|
||||
|
||||
var operationQuery = query.Select(user =>
|
||||
{
|
||||
var weeklyWorkingTimeAvrage = user.WeeklyWorkingTimeAvrageInt.ConvertIntDurationToHoursAndMinutes();
|
||||
|
||||
return new GetUserWhoHaveSettingsDto
|
||||
{
|
||||
UserId = user.UserId,
|
||||
FullName = user.FullName,
|
||||
HasSalarySettings = user.HasSalarySettings,
|
||||
MontlySalary = user.MontlySalary,
|
||||
WeeklyWorkingTimeAvrageInt = user.WeeklyWorkingTimeAvrageInt,
|
||||
WeeklyWorkingTimeAvrage = weeklyWorkingTimeAvrage
|
||||
};
|
||||
}).ToList();
|
||||
var response = new GetUserListWhoHaveSettingsResponse(operationQuery);
|
||||
|
||||
return OperationResult<GetUserListWhoHaveSettingsResponse>.Success(response);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record GetUserListWhoHaveSettingsQuery(string? FullName, HasSalarySettings HasSalarySettings) : IBaseQuery<GetUserListWhoHaveSettingsResponse>;
|
||||
|
||||
public record GetUserListWhoHaveSettingsResponse(List<GetUserWhoHaveSettingsDto> UserList);
|
||||
|
||||
public record GetUserWhoHaveSettingsDto
|
||||
{
|
||||
/// <summary>
|
||||
/// نام و نام خانوادگی
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آی دی کاربر
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آیا کاربر دارای تنظیمات حقوق است؟
|
||||
/// </summary>
|
||||
public bool HasSalarySettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// میانگین ساعت کار
|
||||
/// عددی مجموع دقایق
|
||||
/// </summary>
|
||||
public int WeeklyWorkingTimeAvrageInt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// میانگین ساعت کار در هفته
|
||||
/// رشته ساعت و دقیقه
|
||||
/// </summary>
|
||||
public string WeeklyWorkingTimeAvrage { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// حقوق ماهانه
|
||||
/// </summary>
|
||||
public string MontlySalary { get; set; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace GozareshgirProgramManager.Application.Modules.Skills.DTOs;
|
||||
|
||||
public class SkillDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Skills.DTOs;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Skills.Queries.GetSkillList;
|
||||
|
||||
public record GetSkillListQuery() : IBaseQuery<GetSkillListResponse>;
|
||||
public record GetSkillListResponse(List<SkillDto> Skills);
|
||||
|
||||
public class GetSkillListCommandHandler:IBaseQueryHandler<GetSkillListQuery,GetSkillListResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _dbContext;
|
||||
|
||||
public GetSkillListCommandHandler(IProgramManagerDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetSkillListResponse>> Handle(GetSkillListQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var skills =await _dbContext.Skills
|
||||
.Select(s => new SkillDto
|
||||
{
|
||||
Id = s.Id,
|
||||
Name = s.Name
|
||||
})
|
||||
.ToListAsync(cancellationToken: cancellationToken);
|
||||
|
||||
var response = new GetSkillListResponse(skills);
|
||||
return OperationResult<GetSkillListResponse>.Success(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser;
|
||||
|
||||
public record CreateUserCommand(string FullName, string UserName, string Password, string Mobile, string? Email, long? AccountId, List<long> Roles) : IBaseCommand;
|
||||
@@ -0,0 +1,43 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.RoleUserAgg;
|
||||
using GozareshgirProgramManager.Domain.UserAgg.Entities;
|
||||
using GozareshgirProgramManager.Domain.UserAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser;
|
||||
|
||||
public class CreateUserCommandHandler : IBaseCommandHandler<CreateUserCommand>
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public CreateUserCommandHandler(IUnitOfWork unitOfWork, IUserRepository userRepository)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_userRepository = userRepository;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(CreateUserCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
#region CustomValidation
|
||||
if (_userRepository.Exists(x => x.FullName == request.FullName))
|
||||
return OperationResult.Failure("نام و خانوادگی تکراری است");
|
||||
if (_userRepository.Exists(x => x.UserName == request.UserName))
|
||||
return OperationResult.Failure("نام کاربری تکراری است");
|
||||
if (_userRepository.Exists(x=> !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == request.Mobile))
|
||||
return OperationResult.ValidationError("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است");
|
||||
if(request.AccountId == 0)
|
||||
return OperationResult.Failure("آی دی اکانت، از سمت گزارشگیر صفر است");
|
||||
#endregion
|
||||
|
||||
var userRoles = request.Roles.Where(x => x > 0).Select(x => new RoleUser(x)).ToList() ;
|
||||
var create = new User(request.FullName, request.UserName, request.Password, request.Mobile,
|
||||
request.Email, request?.AccountId, userRoles);
|
||||
|
||||
await _userRepository.CreateAsync(create);
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser;
|
||||
|
||||
public class CreateUserCommandValidators : AbstractValidator<CreateUserCommand>
|
||||
{
|
||||
public CreateUserCommandValidators()
|
||||
{
|
||||
RuleFor(x => x.FullName)
|
||||
.NotEmpty()
|
||||
.NotNull()
|
||||
.WithMessage("نام و نام خانوادگی نمی تواند خالی باشد");
|
||||
|
||||
RuleFor(x => x.Mobile)
|
||||
.NotNull().NotEmpty().WithMessage("شماره همراه نمی تواند خالی باشد");
|
||||
RuleFor(x=>x.Mobile)
|
||||
.Length(11).WithMessage("طول شماره همراه می بایست 11 رقم باشد");
|
||||
RuleFor(x => x.UserName)
|
||||
.NotEmpty().NotNull().WithMessage("نام کاربری نمیتوان خالی باشد");
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Domain._Common;
|
||||
using GozareshgirProgramManager.Domain.RoleUserAgg;
|
||||
using GozareshgirProgramManager.Domain.UserAgg.Repositories;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Commands.EditUser;
|
||||
|
||||
public class EditUserCommandHandler :IBaseCommandHandler<EditUserCommand>
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public EditUserCommandHandler(IUserRepository userRepository, IUnitOfWork unitOfWork)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> Handle(EditUserCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = await _userRepository.GetByGozareshgirAccountId(request.AccountId);
|
||||
if (user != null)
|
||||
{
|
||||
var userRoles = request.Roles.Where(x => x > 0).Select(x => new RoleUser(x)).ToList();
|
||||
user.Edit(request.FullName, request.UserName, request.Mobile, userRoles, request.IsActive);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
}
|
||||
|
||||
return OperationResult.Success();
|
||||
}
|
||||
}
|
||||
|
||||
public record EditUserCommand(string FullName, string UserName, string Mobile,long AccountId, List<long> Roles, bool IsActive) : IBaseCommand;
|
||||
@@ -0,0 +1,126 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetSingleUser;
|
||||
|
||||
public class GetSingleUserQueryHandler : IBaseQueryHandler<GetSingleUserQuery, GetSingleUserResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetSingleUserQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetSingleUserResponse>> Handle(GetSingleUserQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.accountId))
|
||||
{
|
||||
long accountId = 0;
|
||||
try
|
||||
{
|
||||
accountId = Convert.ToInt64(request.accountId);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return (OperationResult<GetSingleUserResponse>)OperationResult.Failure("فقط عدد وارد کنید");
|
||||
}
|
||||
|
||||
|
||||
if (accountId > 0)
|
||||
{
|
||||
var user = await _context.Users
|
||||
.FirstOrDefaultAsync(x => x.AccountId == accountId);
|
||||
|
||||
|
||||
if(user != null)
|
||||
{
|
||||
List<long> roles = user.RoleUser.Select(x => x.RoleId).ToList();
|
||||
var response = new GetSingleUserResponse
|
||||
{
|
||||
Id = user.Id,
|
||||
FullName = user.FullName,
|
||||
UserName = user.UserName,
|
||||
ProfilePhotoPath = user.ProfilePhotoPath,
|
||||
Mobile = user.Mobile,
|
||||
IsActive = user.IsActive,
|
||||
AccountId = user.AccountId,
|
||||
Roles = roles,
|
||||
RoleListDto = await _context.Roles.Where(x => roles.Contains(x.Id)).Select(x=> new RoleListDto()
|
||||
{
|
||||
RoleName = x.RoleName,
|
||||
RoleId = x.Id,
|
||||
Permissions = x.Permissions.Select(x=>x.Code).ToList()
|
||||
}).ToListAsync(),
|
||||
};
|
||||
|
||||
return OperationResult<GetSingleUserResponse>.Success(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
return OperationResult<GetSingleUserResponse>.NotFound("کاربر یافت نشد");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OperationResult<GetSingleUserResponse>.Failure("آی دی اکانت گزارشگیر پر نشده است");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record GetSingleUserResponse
|
||||
{
|
||||
public long Id { get; set; }
|
||||
/// <summary>
|
||||
/// نام و نام خانوادگی
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نام کاربری
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// مسیر عکس پروفایل
|
||||
/// </summary>
|
||||
public string ProfilePhotoPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// شماره موبایل
|
||||
/// </summary>
|
||||
public string Mobile { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// فعال/غیر فعال بودن یوزر
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آی دی کاربر در گزارشگیر
|
||||
/// </summary>
|
||||
public long? AccountId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نقش ها
|
||||
/// </summary>
|
||||
public List<long> Roles { get; set; }
|
||||
|
||||
public List<RoleListDto> RoleListDto { get; set; }
|
||||
};
|
||||
|
||||
|
||||
public record RoleListDto
|
||||
{
|
||||
public string RoleName { get; set; }
|
||||
public long RoleId { get; set; }
|
||||
public List<int> Permissions { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public record GetSingleUserQuery(string? accountId) : IBaseQuery<GetSingleUserResponse>;
|
||||
@@ -0,0 +1,48 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using GozareshgirProgramManager.Application.Modules.Users.Queries.GetSingleUser;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUserSelectList;
|
||||
|
||||
public class GetUserSelectListQueryHandler : IBaseQueryHandler<GetUserSelectListQuery, GetUserSelectListResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetUserSelectListQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetUserSelectListResponse>> Handle(GetUserSelectListQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var query = await _context.Users.Select(x => new GetUserSelectListDto()
|
||||
{
|
||||
FullName = x.FullName,
|
||||
Id = x.Id
|
||||
}).ToListAsync();
|
||||
|
||||
var response = new GetUserSelectListResponse(query);
|
||||
|
||||
|
||||
return OperationResult<GetUserSelectListResponse>.Success(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public record GetUserSelectListResponse(List<GetUserSelectListDto>? GetUserSelectListDto);
|
||||
|
||||
public record GetUserSelectListDto
|
||||
{
|
||||
/// <summary>
|
||||
/// نام و نام خانوادگی
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آی دی کاربر
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
}
|
||||
public record GetUserSelectListQuery() : IBaseQuery<GetUserSelectListResponse>;
|
||||
@@ -0,0 +1,5 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUsers;
|
||||
|
||||
public record GetUsersQuery(string? FullName, string? UserName, string? Mobile) : IBaseQuery<GetUsersResponse>;
|
||||
@@ -0,0 +1,49 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using GozareshgirProgramManager.Application._Common.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUsers;
|
||||
|
||||
public class GetUsersQueryHandler :IBaseQueryHandler<GetUsersQuery, GetUsersResponse>
|
||||
{
|
||||
private readonly IProgramManagerDbContext _context;
|
||||
|
||||
public GetUsersQueryHandler(IProgramManagerDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<OperationResult<GetUsersResponse>> Handle(GetUsersQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.Users.AsQueryable();
|
||||
|
||||
//if (request.ParentId != null)
|
||||
//{
|
||||
// query = query.Where(x => x.ParentId == request.ParentId);
|
||||
//}
|
||||
|
||||
var users = await query
|
||||
.Select(p => new GetUserDto()
|
||||
{
|
||||
|
||||
FullName = p.FullName,
|
||||
Mobile = p.Mobile,
|
||||
UserName = p.UserName,
|
||||
AccountId = p.AccountId,
|
||||
IsActive = p.IsActive,
|
||||
ProfilePhotoPath = p.ProfilePhotoPath,
|
||||
|
||||
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var response = new GetUsersResponse(
|
||||
users
|
||||
);
|
||||
|
||||
return OperationResult<GetUsersResponse>.Success(response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
namespace GozareshgirProgramManager.Application.Modules.Users.Queries.GetUsers;
|
||||
|
||||
public record GetUsersResponse(List<GetUserDto> User);
|
||||
|
||||
public record GetUserDto
|
||||
{
|
||||
/// <summary>
|
||||
/// نام و نام خانوادگی
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نام کاربری
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// مسیر عکس پروفایل
|
||||
/// </summary>
|
||||
public string ProfilePhotoPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// شماره موبایل
|
||||
/// </summary>
|
||||
public string Mobile { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// فعال/غیر فعال بودن یوزر
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آی دی کاربر در گزارشگیر
|
||||
/// </summary>
|
||||
public long? AccountId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نقش ها
|
||||
/// </summary>
|
||||
public List<long> Roles { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Reflection;
|
||||
using GozareshgirProgramManager.Application.Interfaces;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace GozareshgirProgramManager.Application._Bootstrapper;
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddProgramManagerApplication(this IServiceCollection services)
|
||||
{
|
||||
services.AddMediatR(cfg =>
|
||||
{
|
||||
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
|
||||
cfg.LicenseKey =
|
||||
"eyJhbGciOiJSUzI1NiIsImtpZCI6Ikx1Y2t5UGVubnlTb2Z0d2FyZUxpY2Vuc2VLZXkvYmJiMTNhY2I1OTkwNGQ4OWI0Y2IxYzg1ZjA4OGNjZjkiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2x1Y2t5cGVubnlzb2Z0d2FyZS5jb20iLCJhdWQiOiJMdWNreVBlbm55U29mdHdhcmUiLCJleHAiOiIxNzk2MDgzMjAwIiwiaWF0IjoiMTc2NDU5NTE2OSIsImFjY291bnRfaWQiOiIwMTlhZGExMDA0MzA3M2Y5ODhhNWY0MmJmZDdlYTE3OCIsImN1c3RvbWVyX2lkIjoiY3RtXzAxa2JkMTJ4eXNnMHB6MjR0YnhqeXA0a2p3Iiwic3ViX2lkIjoiLSIsImVkaXRpb24iOiIwIiwidHlwZSI6IjIifQ.Gl0FB9XoQMJQgzdCh9gplRirYvmkDJYXD8tfLiWkRAeQJ2zlFdoHw7btxGrUVisI_ZfSxK2kkUB_LLty2eArbeZb5Ja1_xexgzTv3CJ4TnacT0FoVOc8eLeGCbJmmXtSt6CW89XwzvV_taiSSkcdsnATNTH0MEBLqCkKw4FMpSXqrPxCgakXB-pcyeqeTO9a0DD5XjBVITGaslUUFgnBGirsLdHRgL9AYVty3EzWTBH9WBcc4dHyZ5YUDMzsIab5elc-pmOLCXAJviamG9Afsaq4N88IMjsYvq6ihw_EAsmQH1K8WNunFMN8VjwO5csHmgKJ6wajONH7kUaMWNxRrQ";
|
||||
});
|
||||
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GozareshgirProgramManager.Application._Common.Behaviors;
|
||||
|
||||
public class TransactionBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IBaseCommand
|
||||
{
|
||||
private readonly IProgramManagerDbContext _dbContext;
|
||||
|
||||
public TransactionBehavior(IProgramManagerDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(
|
||||
TRequest request,
|
||||
RequestHandlerDelegate<TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// اگر تراکنش فعال است، ادامه بده
|
||||
if (_dbContext is not DbContext efContext)
|
||||
return await next();
|
||||
if (efContext.Database.CurrentTransaction != null)
|
||||
return await next();
|
||||
|
||||
await using var transaction = await efContext.Database.BeginTransactionAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
var response = await next();
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
return response;
|
||||
}
|
||||
catch
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using FluentValidation;
|
||||
using GozareshgirProgramManager.Application._Common.Interfaces;
|
||||
using MediatR;
|
||||
|
||||
namespace GozareshgirProgramManager.Application._Common.Behaviors;
|
||||
|
||||
public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IBaseCommand
|
||||
{
|
||||
private readonly IEnumerable<IValidator<TRequest>> _validators;
|
||||
|
||||
public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
|
||||
{
|
||||
_validators = validators;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(
|
||||
TRequest request,
|
||||
RequestHandlerDelegate<TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_validators.Any())
|
||||
return await next();
|
||||
|
||||
var context = new ValidationContext<TRequest>(request);
|
||||
|
||||
var validationResults = await Task.WhenAll(
|
||||
_validators.Select(v => v.ValidateAsync(context, cancellationToken)));
|
||||
|
||||
var failures = validationResults
|
||||
.SelectMany(r => r.Errors)
|
||||
.Where(f => f != null)
|
||||
.ToList();
|
||||
|
||||
if (failures.Count != 0)
|
||||
throw new ValidationException(failures);
|
||||
|
||||
return await next();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user