add version 0.2.3.1

fix cores error in authorize , fix update shift plan and activity errors
master
Amir Hossein Khademi 2023-12-13 12:05:04 +03:30
parent 48523274e2
commit e067a5fe73
25 changed files with 151 additions and 37 deletions

View File

@ -1 +1 @@
0.2.1.0
0.2.3.1

View File

@ -6,8 +6,8 @@
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<AssemblyVersion>0.2.1.0</AssemblyVersion>
<FileVersion>0.2.1.0</FileVersion>
<AssemblyVersion>0.2.3.1</AssemblyVersion>
<FileVersion>0.2.3.1</FileVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -39,8 +39,8 @@ public class RoutineController : ICarterModule
=> TypedResults.Ok(await sender.Send(new GetRoutineQuery(id), cancellationToken));
// GET:Get Shifts By Id
public async Task<IResult> GetShiftsAsync(Guid id, ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetRoutineShiftsQuery(id), cancellationToken));
public async Task<IResult> GetShiftsAsync(Guid id, [FromQuery]long? selectedDate, ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetRoutineShiftsQuery(id, selectedDate ?? 0), cancellationToken));
// POST:Create Entity
public async Task<IResult> Post([FromBody] CreateRoutineCommand ent, ISender mediator, CancellationToken cancellationToken)

View File

@ -49,8 +49,8 @@ public class ShiftPlanController : ICarterModule
=> TypedResults.Ok(await shiftPlanService.CreateAsync(ent, cancellationToken));
// PUT:Update Entity
public async Task<IResult> Put([FromBody] UpdateShiftPlanCommand ent, ISender mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(ent, cancellationToken));
public async Task<IResult> Put([FromBody] UpdateShiftPlanCommand ent, IShiftPlanService shiftPlanService, CancellationToken cancellationToken)
=> TypedResults.Ok(await shiftPlanService.UpdateAsync(ent, cancellationToken));
// DELETE:Delete Entity
public async Task<IResult> Delete(Guid id, ISender mediator, CancellationToken cancellationToken)

View File

@ -35,9 +35,10 @@ builder.Services.Configure<SiteSettings>(configuration.GetSection(nameof(SiteSet
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddCustomCores();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddCustomSwagger(siteSetting.BaseUrl);
builder.Services.AddCustomSwagger(siteSetting!.BaseUrl);
builder.Services.AddCustomApiVersioning();
builder.Services.AddCustomController();
builder.Services.AddControllers();
@ -101,16 +102,13 @@ if (app.Environment.IsDevelopment())
//app.UseSwagger();
//app.UseSwaggerUI();
}
app.UseCors("CorsPolicy");
app.UseCustomSwagger(siteSetting.BaseUrl);
app.UseAuthorization();
app.UseAuthentication();
app.UseCors(x => x
.SetIsOriginAllowed(origin => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseExceptionHandlerMiddleware();

View File

@ -4,7 +4,7 @@ namespace Brizco.Api.WebFramework.Configurations;
public class ConfigureJwtBearerOptions : IPostConfigureOptions<JwtBearerOptions>
{
public void PostConfigure(string name, JwtBearerOptions options)
public void PostConfigure(string? name, JwtBearerOptions options)
{
var originalOnMessageReceived = options.Events.OnMessageReceived;
options.Events.OnMessageReceived = async context =>

View File

@ -29,7 +29,7 @@ public class PersianIdentityErrorDescriber : IdentityErrorDescriber
{ Code = nameof(LoginAlreadyAssociated), Description = "یوزری با این مشخصات در حال حاضر لاگین کرده است" };
}
public override IdentityError InvalidUserName(string userName)
public override IdentityError InvalidUserName(string? userName)
{
return new IdentityError
{
@ -38,7 +38,7 @@ public class PersianIdentityErrorDescriber : IdentityErrorDescriber
};
}
public override IdentityError InvalidEmail(string email)
public override IdentityError InvalidEmail(string? email)
{
return new IdentityError { Code = nameof(InvalidEmail), Description = $"ایمیل '{email}' صحیح نمی باشد" };
}
@ -58,7 +58,7 @@ public class PersianIdentityErrorDescriber : IdentityErrorDescriber
{ Code = nameof(DuplicateEmail), Description = $"ایمیل '{email}' قبل استفاده شده است" };
}
public override IdentityError InvalidRoleName(string role)
public override IdentityError InvalidRoleName(string? role)
{
return new IdentityError { Code = nameof(InvalidRoleName), Description = $"نقش '{role}' موجود نمی باشد" };
}

View File

@ -95,6 +95,7 @@ public static class ServiceExtensions
.AllowAnyHeader()
.SetIsOriginAllowed(_ => true)
.AllowCredentials();
}));
}
@ -164,6 +165,16 @@ public static class ServiceExtensions
context.Token = accessToken.ToString();
return Task.CompletedTask;
},
OnForbidden = context =>
{
context.Response.StatusCode = StatusCodes.Status403Forbidden;
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
},
OnChallenge = async context =>
{
// Call this to skip the default logic and avoid using the default response

View File

@ -18,7 +18,6 @@
<TargetFramework>net5.0</TargetFramework>
<LangVersion>10</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>

View File

@ -14,10 +14,10 @@ namespace Brizco.Common.Extensions
var displayAttribute = attr as ClassDisplay;
if (displayAttribute == null)
continue;
return displayAttribute.GetName();
return displayAttribute.GetName() ?? string.Empty;
}
return null;
return string.Empty;
}
public static string GetDisplayAttributeDescription<T>()
@ -30,10 +30,10 @@ namespace Brizco.Common.Extensions
var displayAttribute = attr as ClassDisplay;
if (displayAttribute == null)
continue;
return displayAttribute.GetDescription();
return displayAttribute.GetDescription() ?? string.Empty;
}
return null;
return string.Empty;
}
}
}

View File

@ -29,7 +29,7 @@ namespace Brizco.Common.Extensions
throw new NotSupportedException();
foreach (var value in Enum.GetValues(input.GetType()))
if ((input as Enum).HasFlag(value as Enum))
if (value is Enum valueEnum && ((input as Enum)!).HasFlag(valueEnum))
yield return (T)value;
}
@ -37,7 +37,7 @@ namespace Brizco.Common.Extensions
{
AssertExtensions.NotNull(value, nameof(value));
var attribute = value.GetType().GetField(value.ToString())
var attribute = (value.GetType().GetField(value.ToString()))
.GetCustomAttributes<DisplayAttribute>(false).FirstOrDefault();
if (attribute == null)

View File

@ -27,14 +27,14 @@ public abstract class ApiEntity : IApiEntity , IEquatable<ApiEntity>
public bool Equals(ApiEntity? other)
public bool Equals(ApiEntity other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Id.Equals(other.Id);
}
public override bool Equals(object? obj)
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;

View File

@ -174,6 +174,7 @@ public class AccountService : IAccountService
jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser, ComplexUserRoleSDto>(user, complexUser!.ComplexId, complexUserRole!.RoleId);
jwt.User.SelectedComplexName = complexUser.ComplexName;
jwt.User.SelectedRoleName = complexUserRole.RoleName;
jwt.User.SelectedRoleId = complexUserRole!.Id;
jwt.Roles = userComplexRoles;
}
else
@ -204,6 +205,7 @@ public class AccountService : IAccountService
jwt = (await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user, complexUser.ComplexId, complexUserRole.RoleId)).Adapt<AccessToken<ApplicationUserSDto, ComplexUserRoleSDto>>();
jwt.User.SelectedComplexName = complexUser.ComplexName;
jwt.User.SelectedRoleName = complexUserRole.RoleName;
jwt.User.SelectedRoleId = complexUserRole!.Id;
jwt.Roles = new List<ComplexUserRoleSDto> { complexUserRole };
}
else

View File

@ -2,6 +2,7 @@
public interface IActivityService : IScopedDependency
{
Task<bool> UpdateActivitiesByShiftPlan(Guid shiftPlanId, CancellationToken cancellationToken);
Task<bool> CreateActivitiesByShiftPlan(Guid shiftPlanId, CancellationToken cancellationToken);
Task<bool> DoneActivityAsync(Guid activityId, CancellationToken cancellationToken);
Task<bool> CompleteActivitiesAsync(List<CompleteActivityRequestDto> requestDtos, CancellationToken cancellationToken);

View File

@ -4,5 +4,6 @@ public interface IShiftPlanService : IScopedDependency
{
Task ChangeShiftPlanTaskStatusAsync(Guid shiftPlanId,bool isChangeToShift , bool isDisable);
Task<bool> CreateAsync(CreateShiftPlanCommand createShiftPlanCommand,CancellationToken cancellationToken);
Task<bool> UpdateAsync(UpdateShiftPlanCommand createShiftPlanCommand,CancellationToken cancellationToken);
Task<bool> CompleteShiftPlanAsync(Guid id,CompleteShiftPlanRequestDto requestDtos, CancellationToken cancellationToken);
}

View File

@ -1,6 +1,8 @@
using Brizco.Domain.CommandQueries.Queries;
using Brizco.Domain.Entities.Shift;
using Brizco.Domain.Entities.Task;
using System.Threading.Tasks;
using Brizco.Domain.Mappers;
namespace Brizco.Core.EntityServices;
@ -62,6 +64,66 @@ public class ActivityService : IActivityService
return true;
}
public async Task<bool> UpdateActivitiesByShiftPlan(Guid shiftPlanId, CancellationToken cancellationToken)
{
var shiftPlan = await _mediator.Send(new GetShiftPlanQuery(shiftPlanId), cancellationToken);
if (shiftPlan.Id == Guid.Empty)
return false;
var tasks = await _repositoryWrapper.SetRepository<Brizco.Domain.Entities.Task.Task>()
.ExecuteCommand(
$@"SELECT t.""Id"", t.""Amount"", t.""AmountType"", t.""ComplexId"",
t.""CreatedAt"", t.""CreatedBy"", t.""Description"", t.""Discriminator"", t.""HasDisposed"", t.""IsDisposable"", t.""IsRemoved"", t.""ModifiedAt"",
t.""ModifiedBy"", t.""RemovedAt"", t.""RemovedBy"", t.""ScheduleType"", t.""SetFor"", t.""Title"", t.""Type"", t.""DoneAt"", t.""IsDone"",
t.""PerformanceDescription"", t.""ShiftId"", t.""Status"", t.""UserId"" , t.""IsActivity"" , t.""UnDoneReason""
FROM public.""Tasks"" t
INNER JOIN public.""TaskShifts"" t1 ON t.""Id"" = t1.""TaskId""
INNER JOIN public.""TaskDays"" t2 ON t.""Id"" = t1.""TaskId""
INNER JOIN public.""TaskRoutines"" t3 ON t.""Id"" = t1.""TaskId""
AND {shiftPlan.ShiftId} = t1.""ShiftId""
AND {shiftPlan.RoutineId} = t3.""RoutineId""
AND {shiftPlan.PlanFor.DayOfWeek} = t2.""DayOfWeek""
GROUP BY t.""Id""").AsNoTracking().ToListAsync(cancellationToken);
var shiftPlanPositions = await _repositoryWrapper.SetRepository<ShiftPlanUser>()
.TableNoTracking
.Where(spu => spu.ShiftPlanId == shiftPlan.Id)
.ToListAsync(cancellationToken);
var activities = await _repositoryWrapper.SetRepository<Activity>()
.TableNoTracking
.Where(a => a.ShiftId == shiftPlan.ShiftId && a.SetFor.Date == shiftPlan.PlanFor.Date)
.Select(ActivityMapper.ProjectToLDto)
.ToListAsync(cancellationToken);
foreach (var activity in activities)
{
var foundedTask = tasks.FirstOrDefault(t => t.Title == activity.Title);
if (foundedTask == null)
continue;
var taskPositions = await _repositoryWrapper.SetRepository<TaskPosition>()
.TableNoTracking
.Where(tp => tp.TaskId == foundedTask.Id)
.ToListAsync(cancellationToken);
foreach (var taskPosition in taskPositions)
{
var foundedUser = shiftPlanPositions.FirstOrDefault(spu => spu.PositionId == taskPosition.PositionId);
if(foundedUser == null)
continue;
if (activity.UserId != foundedUser.UserId)
{
await _mediator.Send(new UpdateActivityCommand(activity.Id,activity.Status,activity.DoneAt,activity.PerformanceDescription,
activity.Type,activity.Title,activity.Description,activity.IsDisposable,activity.SetFor,activity.HasDisposed,activity.Amount
,activity.AmountType,activity.ScheduleType,shiftPlan.ShiftId,foundedUser.UserId), cancellationToken);
}
}
}
return true;
}
public async Task<bool> CreateActivitiesByShiftPlan(Guid shiftPlanId,CancellationToken cancellationToken)
{
var shiftPlan = await _mediator.Send(new GetShiftPlanQuery(shiftPlanId), cancellationToken);
@ -81,7 +143,7 @@ INNER JOIN public.""TaskRoutines"" t3 ON t.""Id"" = t1.""TaskId""
AND {shiftPlan.ShiftId} = t1.""ShiftId""
AND {shiftPlan.RoutineId} = t3.""RoutineId""
AND {shiftPlan.PlanFor.DayOfWeek} = t2.""DayOfWeek""
GROUP BY t.""Id""").ToListAsync(cancellationToken);
GROUP BY t.""Id""").AsNoTracking().ToListAsync(cancellationToken);
var shiftPlanPositions = await _repositoryWrapper.SetRepository<ShiftPlanUser>()
.TableNoTracking
@ -102,7 +164,7 @@ GROUP BY t.""Id""").ToListAsync(cancellationToken);
{
await _mediator.Send(new CreateActivityCommand(task.Type, task.Title, task.Description, task.IsDisposable,
shiftPlan.PlanFor, task.HasDisposed, task.Amount, task.AmountType,
task.ScheduleType, shiftPlan.ShiftId, new List<Guid> { fundedUser.UserId }),cancellationToken);
task.ScheduleType, shiftPlan.ShiftId, fundedUser.UserId),cancellationToken);
}
}
}

View File

@ -1,4 +1,5 @@
using Brizco.Domain.CommandQueries.Queries;
using Brizco.Domain.CommandQueries.Commands;
using Brizco.Domain.CommandQueries.Queries;
using Brizco.Domain.Entities.Shift;
namespace Brizco.Core.EntityServices;
@ -28,6 +29,13 @@ public class ShiftPlanService : IShiftPlanService
return true;
}
public async Task<bool> UpdateAsync(UpdateShiftPlanCommand updateShiftPlanCommand, CancellationToken cancellationToken)
{
await _sender.Send(updateShiftPlanCommand, cancellationToken);
await _activityService.UpdateActivitiesByShiftPlan(updateShiftPlanCommand.Id, cancellationToken);
return true;
}
public async Task<bool> CompleteShiftPlanAsync(Guid id, CompleteShiftPlanRequestDto requestDtos, CancellationToken cancellationToken)
{
var shiftPlan = await _repositoryWrapper.SetRepository<ShiftPlan>()

View File

@ -11,7 +11,7 @@ public sealed record CreateActivityCommand(
PurchaseAmountType AmountType,
TaskScheduleType ScheduleType,
Guid ShiftId,
List<Guid> UserIds) : IRequest<ActivityLDto>;
Guid UserId) : IRequest<ActivityLDto>;
public sealed record UpdateActivityCommand(Guid Id,
ActivityStatus Status,
@ -26,7 +26,8 @@ public sealed record UpdateActivityCommand(Guid Id,
int Amount,
PurchaseAmountType AmountType,
TaskScheduleType ScheduleType,
List<Guid> UserIds) : IRequest<bool>;
Guid ShiftId,
Guid UserId) : IRequest<bool>;
public sealed record DeleteActivityCommand(Guid Id)

View File

@ -6,5 +6,5 @@ public sealed record GetRoutinesQuery(int Page = 0) :
public sealed record GetRoutineQuery(Guid Id) :
IRequest<RoutineSDto>;
public sealed record GetRoutineShiftsQuery(Guid Id):
public sealed record GetRoutineShiftsQuery(Guid Id,long SelectedDate):
IRequest<List<RoutineShiftResponseDto>>;

View File

@ -11,9 +11,11 @@ public class ActivityLDto : BaseDto<ActivityLDto , Activity>
public DateTime SetFor { get; set; }
public bool HasDisposed { get; set; }
public ActivityStatus Status { get; set; }
public TaskScheduleType ScheduleType { get; set; }
public DateTime DoneAt { get; set; }
public bool IsDone { get; set; }
public string PerformanceDescription { get; set; } = string.Empty;
public Guid UserId { get; internal set; }
public int Amount { get; set; }

View File

@ -186,12 +186,14 @@ namespace Brizco.Domain.Mappers
DoneAt = p13.DoneAt,
IsDone = p13.IsDone,
PerformanceDescription = p13.PerformanceDescription,
UserId = p13.UserId,
Type = p13.Type,
Title = p13.Title,
Description = p13.Description,
IsDisposable = p13.IsDisposable,
SetFor = p13.SetFor,
HasDisposed = p13.HasDisposed,
ScheduleType = p13.ScheduleType,
Amount = p13.Amount,
AmountType = p13.AmountType,
Id = p13.Id
@ -209,12 +211,14 @@ namespace Brizco.Domain.Mappers
result.DoneAt = p14.DoneAt;
result.IsDone = p14.IsDone;
result.PerformanceDescription = p14.PerformanceDescription;
result.UserId = p14.UserId;
result.Type = p14.Type;
result.Title = p14.Title;
result.Description = p14.Description;
result.IsDisposable = p14.IsDisposable;
result.SetFor = p14.SetFor;
result.HasDisposed = p14.HasDisposed;
result.ScheduleType = p14.ScheduleType;
result.Amount = p14.Amount;
result.AmountType = p14.AmountType;
result.Id = p14.Id;
@ -232,9 +236,11 @@ namespace Brizco.Domain.Mappers
SetFor = p16.SetFor,
HasDisposed = p16.HasDisposed,
Status = p16.Status,
ScheduleType = p16.ScheduleType,
DoneAt = p16.DoneAt,
IsDone = p16.IsDone,
PerformanceDescription = p16.PerformanceDescription,
UserId = p16.UserId,
Amount = p16.Amount,
AmountType = p16.AmountType,
Id = p16.Id
@ -255,9 +261,11 @@ namespace Brizco.Domain.Mappers
result.SetFor = p17.SetFor;
result.HasDisposed = p17.HasDisposed;
result.Status = p17.Status;
result.ScheduleType = p17.ScheduleType;
result.DoneAt = p17.DoneAt;
result.IsDone = p17.IsDone;
result.PerformanceDescription = p17.PerformanceDescription;
result.UserId = p17.UserId;
result.Amount = p17.Amount;
result.AmountType = p17.AmountType;
result.Id = p17.Id;
@ -273,9 +281,11 @@ namespace Brizco.Domain.Mappers
SetFor = p19.SetFor,
HasDisposed = p19.HasDisposed,
Status = p19.Status,
ScheduleType = p19.ScheduleType,
DoneAt = p19.DoneAt,
IsDone = p19.IsDone,
PerformanceDescription = p19.PerformanceDescription,
UserId = p19.UserId,
Amount = p19.Amount,
AmountType = p19.AmountType,
Id = p19.Id

View File

@ -5,7 +5,7 @@ public class CreateActivityCommandHandler : IRequestHandler<CreateActivityComman
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
public CreateActivityCommandHandler(IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService)
public CreateActivityCommandHandler(IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService)
{
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
@ -23,7 +23,7 @@ public class CreateActivityCommandHandler : IRequestHandler<CreateActivityComman
var activity = Domain.Entities.Task.Activity
.Create(
ActivityStatus.Created,
DateTime.MinValue,
DateTime.MinValue,
string.Empty,
request.Title,
request.Description,
@ -35,8 +35,7 @@ public class CreateActivityCommandHandler : IRequestHandler<CreateActivityComman
request.AmountType,
complexId,
request.ScheduleType);
foreach (var requestUserId in request.UserIds)
activity.SetUser(requestUserId);
activity.SetUser(request.UserId);
activity.SetShift(request.ShiftId);

View File

@ -42,6 +42,9 @@ public class UpdateActivityCommandHandler : IRequestHandler<UpdateActivityComman
newTask.Id = request.Id;
newTask.SetUser(request.UserId);
newTask.SetShift(request.ShiftId);
_repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
.Update(newTask);
await _repositoryWrapper.SaveChangesAsync(cancellationToken);

View File

@ -26,7 +26,9 @@ public class GetRoutineShiftsQueryHandler : IRequestHandler<GetRoutineShiftsQuer
.Where(s => s.Id == shiftRoutine.ShiftId)
.Select(ShiftMapper.ProjectToSDto)
.FirstOrDefaultAsync(cancellationToken);
shift?.Days.ForEach(d =>
if (shift == null)
continue;
shift.Days.ForEach(d =>
{
var routineShiftRes = routineShiftResponse.FirstOrDefault(s => s.Day == d);
if (routineShiftRes != null)
@ -42,6 +44,18 @@ public class GetRoutineShiftsQueryHandler : IRequestHandler<GetRoutineShiftsQuer
});
}
});
if (request.SelectedDate > 0)
{
var selectedDate = DateTimeExtensions.UnixTimeStampToDateTime(request.SelectedDate);
var existedShiftPlan = await _repositoryWrapper.SetRepository<Domain.Entities.Shift.ShiftPlan>()
.TableNoTracking
.FirstOrDefaultAsync(s => s.ShiftId == shift.Id && s.PlanFor.Date == selectedDate.Date, cancellationToken);
shift.IsCompleted = existedShiftPlan?.IsCompleted ?? false;
shift.CurrentShiftPlanId = existedShiftPlan?.Id ?? default;
shift.HasCurrentShiftPlan = existedShiftPlan != null;
}
}
return routineShiftResponse;

View File

@ -38,8 +38,11 @@ public class UpdateShiftPlanCommandHandler : IRequestHandler<UpdateShiftPlanComm
if (request.UserAndPositionIds.Contains(new KeyValuePair<Guid, Guid>(shiftPlanUser.PositionId,shiftPlanUser.UserId)))
request.UserAndPositionIds.Remove(new KeyValuePair<Guid, Guid>(shiftPlanUser.PositionId, shiftPlanUser.UserId));
else
{
_repositoryWrapper.SetRepository<Domain.Entities.Shift.ShiftPlanUser>()
.Delete(shiftPlanUser);
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
}
}
foreach (var userId in request.UserAndPositionIds)