initial commit

This commit is contained in:
2026-07-21 13:38:38 +07:00
commit 5047288f04
777 changed files with 57255 additions and 0 deletions
@@ -0,0 +1,59 @@
using Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Infrastructure.Database;
using MediatR;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class CreateTodoRequest
{
public string? Name { get; set; }
public string? Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool IsCompleted { get; set; }
}
public class CreateTodoResponse
{
public string? Id { get; set; }
public string? Name { get; set; }
}
public record CreateTodoCommand(CreateTodoRequest Data) : IRequest<CreateTodoResponse>;
public class CreateTodoHandler : IRequestHandler<CreateTodoCommand, CreateTodoResponse>
{
private readonly AppDbContext _context;
public CreateTodoHandler(AppDbContext context) => _context = context;
public async Task<CreateTodoResponse> Handle(CreateTodoCommand request, CancellationToken cancellationToken)
{
var entityName = nameof(Data.Entities.Booking);
var autoNo = await _context.GenerateAutoNumberAsync(
entityName: entityName,
prefixTemplate: $"{entityName.ToShortNameConsonant(3)}/{{Year}}/",
ct: cancellationToken
);
var entity = new Data.Entities.Todo
{
AutoNumber = autoNo,
Name = request.Data.Name,
Description = request.Data.Description,
StartTime = request.Data.StartTime,
EndTime = request.Data.EndTime,
IsCompleted = request.Data.IsCompleted
};
_context.Todo.Add(entity);
await _context.SaveChangesAsync(cancellationToken);
return new CreateTodoResponse
{
Id = entity.Id,
Name = entity.Name
};
}
}
@@ -0,0 +1,51 @@
using Indotalent.Infrastructure.Database;
using MediatR;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class CreateTodoItemRequest
{
public string? TodoId { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool IsCompleted { get; set; }
}
public class CreateTodoItemResponse
{
public string? Id { get; set; }
public string? Name { get; set; }
}
public record CreateTodoItemCommand(CreateTodoItemRequest Data) : IRequest<CreateTodoItemResponse>;
public class CreateTodoItemHandler : IRequestHandler<CreateTodoItemCommand, CreateTodoItemResponse>
{
private readonly AppDbContext _context;
public CreateTodoItemHandler(AppDbContext context) => _context = context;
public async Task<CreateTodoItemResponse> Handle(CreateTodoItemCommand request, CancellationToken cancellationToken)
{
var entity = new Data.Entities.TodoItem
{
TodoId = request.Data.TodoId,
Name = request.Data.Name,
Description = request.Data.Description,
StartTime = request.Data.StartTime,
EndTime = request.Data.EndTime,
IsCompleted = request.Data.IsCompleted
};
_context.TodoItem.Add(entity);
await _context.SaveChangesAsync(cancellationToken);
return new CreateTodoItemResponse
{
Id = entity.Id,
Name = entity.Name
};
}
}
@@ -0,0 +1,14 @@
using FluentValidation;
using Indotalent.Shared.Consts;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class CreateTodoValidator : AbstractValidator<CreateTodoRequest>
{
public CreateTodoValidator()
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required")
.MaximumLength(GlobalConsts.StringLengthShort);
}
}
@@ -0,0 +1,36 @@
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class DeleteTodoByIdRequest
{
public DeleteTodoByIdRequest(string id) => Id = id;
public string Id { get; set; }
}
public record DeleteTodoByIdCommand(DeleteTodoByIdRequest Data) : IRequest<bool>;
public class DeleteTodoByIdHandler : IRequestHandler<DeleteTodoByIdCommand, bool>
{
private readonly AppDbContext _context;
public DeleteTodoByIdHandler(AppDbContext context) => _context = context;
public async Task<bool> Handle(DeleteTodoByIdCommand request, CancellationToken cancellationToken)
{
var entity = await _context.Todo
.FirstOrDefaultAsync(x => x.Id == request.Data.Id, cancellationToken);
if (entity == null)
{
return false;
}
_context.Todo.Remove(entity);
await _context.SaveChangesAsync(cancellationToken);
return true;
}
}
@@ -0,0 +1,30 @@
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public record DeleteTodoItemCommand(string Id) : IRequest<bool>;
public class DeleteTodoItemHandler : IRequestHandler<DeleteTodoItemCommand, bool>
{
private readonly AppDbContext _context;
public DeleteTodoItemHandler(AppDbContext context) => _context = context;
public async Task<bool> Handle(DeleteTodoItemCommand request, CancellationToken cancellationToken)
{
var entity = await _context.TodoItem
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken);
if (entity == null)
{
return false;
}
_context.TodoItem.Remove(entity);
await _context.SaveChangesAsync(cancellationToken);
return true;
}
}
@@ -0,0 +1,74 @@
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class TodoItemResponse
{
public string? Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool IsCompleted { get; set; }
}
public class GetTodoByIdResponse
{
public string? Id { get; set; }
public string? AutoNumber { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool IsCompleted { get; set; }
public DateTimeOffset? CreatedAt { get; set; }
public string? CreatedBy { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public string? UpdatedBy { get; set; }
public List<TodoItemResponse> TodoItems { get; set; } = new List<TodoItemResponse>();
}
public record GetTodoByIdQuery(string Id) : IRequest<GetTodoByIdResponse?>;
public class GetTodoByIdHandler : IRequestHandler<GetTodoByIdQuery, GetTodoByIdResponse?>
{
private readonly AppDbContext _context;
public GetTodoByIdHandler(AppDbContext context) => _context = context;
public async Task<GetTodoByIdResponse?> Handle(GetTodoByIdQuery request, CancellationToken cancellationToken)
{
return await _context.Todo
.AsNoTracking()
.Include(x => x.TodoItemList)
.Where(x => x.Id == request.Id)
.Select(x => new GetTodoByIdResponse
{
Id = x.Id,
AutoNumber = x.AutoNumber,
Name = x.Name,
Description = x.Description,
StartTime = x.StartTime,
EndTime = x.EndTime,
IsCompleted = x.IsCompleted,
CreatedAt = x.CreatedAt,
CreatedBy = x.CreatedBy,
UpdatedAt = x.UpdatedAt,
UpdatedBy = x.UpdatedBy,
TodoItems = x.TodoItemList
.OrderBy(i => i.StartTime)
.Select(i => new TodoItemResponse
{
Id = i.Id,
Name = i.Name,
Description = i.Description,
StartTime = i.StartTime,
EndTime = i.EndTime,
IsCompleted = i.IsCompleted
}).ToList()
})
.FirstOrDefaultAsync(cancellationToken);
}
}
@@ -0,0 +1,51 @@
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class GetTodoListResponse
{
public string? Id { get; set; }
public string? AutoNumber { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool IsCompleted { get; set; }
public DateTimeOffset? CreatedAt { get; set; }
public string? CreatedBy { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public string? UpdatedBy { get; set; }
}
public record GetTodoListQuery() : IRequest<List<GetTodoListResponse>>;
public class GetTodoListHandler : IRequestHandler<GetTodoListQuery, List<GetTodoListResponse>>
{
private readonly AppDbContext _context;
public GetTodoListHandler(AppDbContext context) => _context = context;
public async Task<List<GetTodoListResponse>> Handle(GetTodoListQuery request, CancellationToken cancellationToken)
{
return await _context.Todo
.AsNoTracking()
.OrderByDescending(x => x.CreatedAt)
.Select(x => new GetTodoListResponse
{
Id = x.Id,
AutoNumber = x.AutoNumber,
Name = x.Name,
Description = x.Description,
StartTime = x.StartTime,
EndTime = x.EndTime,
IsCompleted = x.IsCompleted,
CreatedAt = x.CreatedAt,
CreatedBy = x.CreatedBy,
UpdatedAt = x.UpdatedAt,
UpdatedBy = x.UpdatedBy,
})
.ToListAsync(cancellationToken);
}
}
@@ -0,0 +1,59 @@
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class UpdateTodoRequest
{
public string? Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool IsCompleted { get; set; }
public DateTimeOffset? CreatedAt { get; set; }
public string? CreatedBy { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public string? UpdatedBy { get; set; }
}
public class UpdateTodoResponse
{
public string? Id { get; set; }
public bool Success { get; set; }
}
public record UpdateTodoCommand(UpdateTodoRequest Data) : IRequest<UpdateTodoResponse>;
public class UpdateTodoHandler : IRequestHandler<UpdateTodoCommand, UpdateTodoResponse>
{
private readonly AppDbContext _context;
public UpdateTodoHandler(AppDbContext context) => _context = context;
public async Task<UpdateTodoResponse> Handle(UpdateTodoCommand request, CancellationToken cancellationToken)
{
var entity = await _context.Todo
.FirstOrDefaultAsync(x => x.Id == request.Data.Id, cancellationToken);
if (entity == null)
{
return new UpdateTodoResponse { Id = request.Data.Id, Success = false };
}
entity.Name = request.Data.Name;
entity.Description = request.Data.Description;
entity.StartTime = request.Data.StartTime;
entity.EndTime = request.Data.EndTime;
entity.IsCompleted = request.Data.IsCompleted;
await _context.SaveChangesAsync(cancellationToken);
return new UpdateTodoResponse
{
Id = entity.Id,
Success = true
};
}
}
@@ -0,0 +1,55 @@
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class UpdateTodoItemRequest
{
public string? Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool IsCompleted { get; set; }
}
public class UpdateTodoItemResponse
{
public string? Id { get; set; }
public bool Success { get; set; }
}
public record UpdateTodoItemCommand(UpdateTodoItemRequest Data) : IRequest<UpdateTodoItemResponse>;
public class UpdateTodoItemHandler : IRequestHandler<UpdateTodoItemCommand, UpdateTodoItemResponse>
{
private readonly AppDbContext _context;
public UpdateTodoItemHandler(AppDbContext context) => _context = context;
public async Task<UpdateTodoItemResponse> Handle(UpdateTodoItemCommand request, CancellationToken cancellationToken)
{
var entity = await _context.TodoItem
.FirstOrDefaultAsync(x => x.Id == request.Data.Id, cancellationToken);
if (entity == null)
{
return new UpdateTodoItemResponse { Id = request.Data.Id, Success = false };
}
entity.Name = request.Data.Name;
entity.Description = request.Data.Description;
entity.StartTime = request.Data.StartTime;
entity.EndTime = request.Data.EndTime;
entity.IsCompleted = request.Data.IsCompleted;
await _context.SaveChangesAsync(cancellationToken);
return new UpdateTodoItemResponse
{
Id = entity.Id,
Success = true
};
}
}
@@ -0,0 +1,17 @@
using FluentValidation;
using Indotalent.Shared.Consts;
namespace Indotalent.Features.Utilities.Todo.Cqrs;
public class UpdateTodoValidator : AbstractValidator<UpdateTodoRequest>
{
public UpdateTodoValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("ID is required");
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required")
.MaximumLength(GlobalConsts.StringLengthShort);
}
}