Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Application/Abstractions/Data/IApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Domain.AuditLogs;
using Domain.Businesses;
using Domain.BusinessMembers;
using Domain.Countries;
using Domain.Customers;
using Domain.EmailVerification;
using Domain.MfaLogs;
Expand Down Expand Up @@ -43,6 +44,7 @@ public interface IApplicationDbContext
DbSet<MfaSetting> MfaSettings { get; }
DbSet<Otp> Otp { get; }
DbSet<SmtpConfig> SmtpConfig { get; }
DbSet<Country> Countries { get; }
EntityEntry Entry(object entity);
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
13 changes: 13 additions & 0 deletions src/Application/Countries/Create/CreateCountryCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Application.Abstractions.Messaging;
using SharedKernel;

namespace Application.Countries.Create;

public sealed class CreateCountryCommand : ICommand<Guid>
{
public string Name { get; set; } = null!;
public string Capital { get; set; } = null!;
public string PhoneCode { get; set; } = null!;
public bool IsActive { get; set; }
}

35 changes: 35 additions & 0 deletions src/Application/Countries/Create/CreateCountryCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.Countries;
using SharedKernel;

namespace Application.Countries.Create;

internal sealed class CreateCountryCommandHandler
: ICommandHandler<CreateCountryCommand, Guid>
{
private readonly IApplicationDbContext _context;

public CreateCountryCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task<Result<Guid>> Handle(
CreateCountryCommand request,
CancellationToken cancellationToken)
{
var country = new Country
{
Id = Guid.NewGuid(),
Name = request.Name,
Capital = request.Capital,
PhoneCode = request.PhoneCode,
IsActive = request.IsActive
};

await _context.Countries.AddAsync(country, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
return Result.Success(country.Id);
}
}
20 changes: 20 additions & 0 deletions src/Application/Countries/Create/CreateCountryValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using FluentValidation;

namespace Application.Countries.Create;

public sealed class CreateCountryValidator : AbstractValidator<CreateCountryCommand>
{
public CreateCountryValidator()
{
RuleFor(x => x.Name)
.NotEmpty()
.MaximumLength(150);

RuleFor(x => x.Capital)
.MaximumLength(150);

RuleFor(x => x.PhoneCode)
.NotEmpty()
.MaximumLength(20);
}
}
6 changes: 6 additions & 0 deletions src/Application/Countries/Delete/DeleteCountryCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Application.Abstractions.Messaging;

namespace Application.Countries.Delete;

public sealed record DeleteCountryCommand(Guid Id) : ICommand;

37 changes: 37 additions & 0 deletions src/Application/Countries/Delete/DeleteCountryCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.Countries;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.Countries.Delete;

internal sealed class DeleteCountryCommandHandler : ICommandHandler<DeleteCountryCommand>
{
private readonly IApplicationDbContext _context;

public DeleteCountryCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task<Result> Handle(DeleteCountryCommand command, CancellationToken cancellationToken)
{
Country? country = await _context.Countries
.SingleOrDefaultAsync(c => c.Id == command.Id, cancellationToken);

if (country is null)
{
return Result.Failure(
Error.NotFound(
"Country.NotFound",
$"Country with Id {command.Id} not found."
)
);
}

_context.Countries.Remove(country);
await _context.SaveChangesAsync(cancellationToken);
return Result.Success();
}
}
12 changes: 12 additions & 0 deletions src/Application/Countries/Delete/DeleteCountryCommandValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using FluentValidation;

namespace Application.Countries.Delete;

public sealed class DeleteCountryCommandValidator : AbstractValidator<DeleteCountryCommand>
{
public DeleteCountryCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Country Id is required.");
}
}
5 changes: 5 additions & 0 deletions src/Application/Countries/Get/GetCountriesQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Application.Abstractions.Messaging;

namespace Application.Countries.Get;

public sealed record GetCountriesQuery() : IQuery<List<GetCountryResponse>>;
35 changes: 35 additions & 0 deletions src/Application/Countries/Get/GetCountriesQueryHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.Countries.Get;

internal sealed class GetCountriesQueryHandler
: IQueryHandler<GetCountriesQuery, List<GetCountryResponse>>
{
private readonly IApplicationDbContext _context;

public GetCountriesQueryHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task<Result<List<GetCountryResponse>>> Handle(
GetCountriesQuery request,
CancellationToken cancellationToken)
{
List<GetCountryResponse> countries = await _context.Countries
.AsNoTracking()
.Select(b => new GetCountryResponse
{
Id = b.Id,
Name = b.Name,
Capital = b.Capital,
PhoneCode = b.PhoneCode,
IsActive = b.IsActive
})
.ToListAsync(cancellationToken);
return Result.Success(countries);
}
}
10 changes: 10 additions & 0 deletions src/Application/Countries/Get/GetCountryResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Application.Countries.Get;

public sealed class GetCountryResponse
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Capital { get; set; }
public string PhoneCode { get; set; } = null!;
public bool IsActive { get; set; }
}
5 changes: 5 additions & 0 deletions src/Application/Countries/GetById/GetCountryByIdQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Application.Abstractions.Messaging;

namespace Application.Countries.GetById;

public sealed record GetCountryByIdQuery(Guid Id) : IQuery<GetCountryByIdResponse>;
44 changes: 44 additions & 0 deletions src/Application/Countries/GetById/GetCountryByIdQueryHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.Countries.GetById;

internal sealed class GetCountryByIdQueryHandler : IQueryHandler<GetCountryByIdQuery, GetCountryByIdResponse>
{
private readonly IApplicationDbContext _context;

public GetCountryByIdQueryHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task<Result<GetCountryByIdResponse>> Handle(GetCountryByIdQuery request, CancellationToken cancellationToken)
{
GetCountryByIdResponse country = await _context.Countries
.AsNoTracking()
.Where(b => b.Id == request.Id)
.Select(b => new GetCountryByIdResponse
{
Id = b.Id,
Name = b.Name,
Capital = b.Capital,
PhoneCode = b.PhoneCode,
IsActive = b.IsActive
})
.SingleOrDefaultAsync(cancellationToken);

if (country is null)
{
return Result.Failure<GetCountryByIdResponse>(
Error.NotFound(
"Country.NotFound",
$"Country with Id {request.Id} not found."
)
);
}

return Result.Success(country);
}
}
10 changes: 10 additions & 0 deletions src/Application/Countries/GetById/GetCountryByIdResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Application.Countries.GetById;

public sealed class GetCountryByIdResponse
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Capital { get; set; } = string.Empty;
public string PhoneCode { get; set; } = string.Empty;
public bool IsActive { get; set; }
}
12 changes: 12 additions & 0 deletions src/Application/Countries/Update/UpdateCountryCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Application.Abstractions.Messaging;

namespace Application.Countries.Update;

public sealed class UpdateCountryCommand() : ICommand
{
public Guid Id { get; set; }
public string Name { get; set; } = null!;
public string Capital { get; set; } = null!;
public string PhoneCode { get; set; } = null!;
public bool IsActive { get; set; }
}
41 changes: 41 additions & 0 deletions src/Application/Countries/Update/UpdateCountryCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.Countries;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.Countries.Update;

internal sealed class UpdateCountryCommandHandler : ICommandHandler<UpdateCountryCommand>
{
private readonly IApplicationDbContext _context;

public UpdateCountryCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task<Result> Handle(UpdateCountryCommand command, CancellationToken cancellationToken)
{
Country? country = await _context.Countries
.FirstOrDefaultAsync(c => c.Id == command.Id, cancellationToken);

if (country is null)
{
return Result.Failure(
Error.NotFound(
"Country.NotFound",
$"Country with Id {command.Id} not found."
)
);
}

country.Name = command.Name;
country.Capital = command.Capital;
country.PhoneCode = command.PhoneCode;
country.IsActive = command.IsActive;

await _context.SaveChangesAsync(cancellationToken);
return Result.Success();
}
}
24 changes: 24 additions & 0 deletions src/Application/Countries/Update/UpdateCountryCommandValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using FluentValidation;

namespace Application.Countries.Update;


public sealed class UpdateCountryCommandValidator : AbstractValidator<UpdateCountryCommand>
{
public UpdateCountryCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Country Id is required.");

RuleFor(x => x.Name)
.NotEmpty().WithMessage("Country name is required.")
.MaximumLength(150);

RuleFor(x => x.Capital)
.MaximumLength(150);

RuleFor(x => x.PhoneCode)
.NotEmpty()
.MaximumLength(20);
}
}
34 changes: 16 additions & 18 deletions src/Application/SmtpConfigs/OtpMail/SendOtpCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,27 @@ public async Task<Result<Guid>> Handle(SendOtpCommand command, CancellationToken

try
{
using (var client = new SmtpClient())
{
SecureSocketOptions sslOption = smtpConfig.EnableSsl
? SecureSocketOptions.StartTls
: SecureSocketOptions.None;
using var client = new SmtpClient();
SecureSocketOptions sslOption = smtpConfig.EnableSsl
? SecureSocketOptions.StartTls
: SecureSocketOptions.None;

await client.ConnectAsync(
smtpConfig.Host,
smtpConfig.Port,
sslOption,
cancellationToken);
await client.ConnectAsync(
smtpConfig.Host,
smtpConfig.Port,
sslOption,
cancellationToken);

await client.AuthenticateAsync(
smtpConfig.Username,
smtpConfig.Password,
cancellationToken);
await client.AuthenticateAsync(
smtpConfig.Username,
smtpConfig.Password,
cancellationToken);

await client.SendAsync(message, cancellationToken);
await client.SendAsync(message, cancellationToken);

await client.DisconnectAsync(true, cancellationToken);
await client.DisconnectAsync(true, cancellationToken);

return Result.Success(otpId);
}
return Result.Success(otpId);
}
catch (Exception)
{
Expand Down
13 changes: 13 additions & 0 deletions src/Domain/Countries/Country.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using SharedKernel;

namespace Domain.Countries;

public sealed class Country : Entity
{
public Guid Id { get; set; }
public string Name { get; set; } = null!;
public string Capital { get; set; } = null!;
public string PhoneCode { get; set; } = null!;
public bool IsActive { get; set; }
}

Loading