From 7420a5fee104d11e561329d0e765ca6696666cd3 Mon Sep 17 00:00:00 2001 From: Mstaheri Date: Tue, 9 Jul 2024 12:01:33 +0330 Subject: [PATCH] create loanRepository and service and api --- Application/Application.csproj | 1 - .../UpdateBankSafeCommandValidator.cs | 2 +- .../Loan/Commands/AddLoan/AddLoanCommand.cs | 15 +++- .../Commands/AddLoan/AddLoanCommandHandler.cs | 48 +++++++++++- .../AddLoan/AddLoanCommandValidator.cs | 36 +++++++++ .../Commands/DeleteLoan/DeleteLoanCommand.cs | 15 ++++ .../DeleteLoan/DeleteLoanCommandHandler.cs | 48 ++++++++++++ .../DeleteLoan/DeleteLoanCommandValidator.cs | 19 +++++ .../Queries/GetAllLoan/GetAllLoanQuery.cs | 16 ++++ .../GetAllLoan/GetAllLoanQueryHandler.cs | 45 +++++++++++ .../GetByCodeLoan/GetByCodeLoanQuery.cs | 16 ++++ .../GetByCodeLoanQueryHandler.cs | 43 ++++++++++ Domain/Entity/Loan.cs | 5 +- Domain/Exceptions/ConstMessages.cs | 3 + Domain/Exceptions/OperationResult.cs | 2 +- Domain/IRepositories/ILoanRepositorie.cs | 10 ++- Domain/ValueObjects/AccountNumber.cs | 1 - Domain/ValueObjects/Name.cs | 19 ++--- Domain/ValueObjects/NationalIDNumber.cs | 1 - Domain/ValueObjects/Number.cs | 12 +-- Domain/ValueObjects/Password.cs | 1 - Domain/ValueObjects/Percent.cs | 45 +++++++++++ Domain/ValueObjects/PersianDate.cs | 32 +++----- Domain/ValueObjects/PhoneNumber.cs | 1 - Domain/ValueObjects/UserName.cs | 1 - .../Repositories/LoanRepositorie.cs | 60 +++++++++++++- Persistence/Config/LoanConfig.cs | 1 + Persistence/Convertors/PercentConverter.cs | 20 +++++ WebSite/Controllers/LoanController.cs | 78 +++++++++++++++++++ WebSite/Program.cs | 1 + 30 files changed, 541 insertions(+), 56 deletions(-) create mode 100644 Application/Services/Loan/Commands/AddLoan/AddLoanCommandValidator.cs create mode 100644 Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommand.cs create mode 100644 Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandHandler.cs create mode 100644 Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandValidator.cs create mode 100644 Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQuery.cs create mode 100644 Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQueryHandler.cs create mode 100644 Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQuery.cs create mode 100644 Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQueryHandler.cs create mode 100644 Domain/ValueObjects/Percent.cs create mode 100644 Persistence/Convertors/PercentConverter.cs create mode 100644 WebSite/Controllers/LoanController.cs diff --git a/Application/Application.csproj b/Application/Application.csproj index 628e76e..7deab53 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -20,7 +20,6 @@ - diff --git a/Application/Services/BankSafes/Commands/UpdateBankSafe/UpdateBankSafeCommandValidator.cs b/Application/Services/BankSafes/Commands/UpdateBankSafe/UpdateBankSafeCommandValidator.cs index 253185f..aa9b81d 100644 --- a/Application/Services/BankSafes/Commands/UpdateBankSafe/UpdateBankSafeCommandValidator.cs +++ b/Application/Services/BankSafes/Commands/UpdateBankSafe/UpdateBankSafeCommandValidator.cs @@ -1,7 +1,6 @@ using Application.Services.BankAccounts.Commands.AddBankAccount; using Domain.Exceptions; using FluentValidation; -using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -19,6 +18,7 @@ public UpdateBankSafeCommandValidator() RuleFor(p => p.SharePrice) .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "SharePrice")); + } } } diff --git a/Application/Services/Loan/Commands/AddLoan/AddLoanCommand.cs b/Application/Services/Loan/Commands/AddLoan/AddLoanCommand.cs index f1a3bd5..fd779fe 100644 --- a/Application/Services/Loan/Commands/AddLoan/AddLoanCommand.cs +++ b/Application/Services/Loan/Commands/AddLoan/AddLoanCommand.cs @@ -1,12 +1,23 @@ -using System; +using Domain.Exceptions; +using Domain.ValueObjects; +using MediatR; +using System; using System.Collections.Generic; using System.Linq; +using System.Reflection.Metadata.Ecma335; using System.Text; using System.Threading.Tasks; namespace Application.Services.Loan.Commands.AddLoan { - internal class AddLoanCommand + public record AddLoanCommand : IRequest> { + public required string NameBankSafe { get; init; } + public required string FirstName { get; init; } + public required string LastName { get; init; } + public required int NumberOfInstallments { get; init; } + public required decimal Amount { get; init; } + public required int Wage { get; init; } } + } diff --git a/Application/Services/Loan/Commands/AddLoan/AddLoanCommandHandler.cs b/Application/Services/Loan/Commands/AddLoan/AddLoanCommandHandler.cs index ca47cfe..126d1ca 100644 --- a/Application/Services/Loan/Commands/AddLoan/AddLoanCommandHandler.cs +++ b/Application/Services/Loan/Commands/AddLoan/AddLoanCommandHandler.cs @@ -1,4 +1,11 @@ -using System; +using Application.Services.BankSafes.Commands.AddBankSafe; +using Application.UnitOfWork; +using Domain.Entity; +using Domain.Exceptions; +using Domain.IRepositories; +using MediatR; +using Microsoft.Extensions.Logging; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +13,44 @@ namespace Application.Services.Loan.Commands.AddLoan { - internal class AddLoanCommandHandler + public class AddLoanCommandHandler + : IRequestHandler> { + private readonly ILoanRepositorie _loanRepositorie; + private readonly IUnitOfWork _unitOfWork; + private readonly ILogger _logger; + public AddLoanCommandHandler(ILoanRepositorie loanRepositorie, + IUnitOfWork unitOfWork + , ILogger logger) + { + _loanRepositorie = loanRepositorie; + _unitOfWork = unitOfWork; + _logger = logger; + } + public async Task> Handle(AddLoanCommand request, CancellationToken cancellationToken) + { + try + { + var loan = new Domain.Entity.Loan( + request.NameBankSafe, + request.FirstName, + request.LastName, + request.NumberOfInstallments, + request.Amount, + request.Wage); + await _loanRepositorie.AddAsync(loan, cancellationToken); + await _unitOfWork.SaveChangesAsync(cancellationToken); + string message = string.Format(ConstMessages.Successfully + , loan.FirstName.Value + " " + loan.LastName.Value + , nameof(AddLoanCommandHandler)); + _logger.LogInformation(message); + return new OperationResult(true, null , loan.Code); + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + return new OperationResult(false, ex.Message , Guid.Empty); + } + } } } diff --git a/Application/Services/Loan/Commands/AddLoan/AddLoanCommandValidator.cs b/Application/Services/Loan/Commands/AddLoan/AddLoanCommandValidator.cs new file mode 100644 index 0000000..f8ca2bf --- /dev/null +++ b/Application/Services/Loan/Commands/AddLoan/AddLoanCommandValidator.cs @@ -0,0 +1,36 @@ +using Domain.Exceptions; +using FluentValidation; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Commands.AddLoan +{ + public class AddLoanCommandValidator:AbstractValidator + { + public AddLoanCommandValidator() + { + RuleFor(p => p.NameBankSafe) + .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "NameBankSafe")) + .MaximumLength(50).WithMessage(string.Format(ConstMessages.MaximumLength, "NameBankSafe", "50")); + + RuleFor(p => p.FirstName) + .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "FirstName")) + .MaximumLength(50).WithMessage(string.Format(ConstMessages.MaximumLength, "FirstName", "50")); + + RuleFor(p => p.LastName) + .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "LastName")) + .MaximumLength(50).WithMessage(string.Format(ConstMessages.MaximumLength, "LastName", "50")); + + RuleFor(p => p.NumberOfInstallments) + .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "NumberOfInstallments")); + + RuleFor(p => p.Amount) + .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "Amount")); + + RuleFor(p => p.Wage) + .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "Wage")); + + } + } +} diff --git a/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommand.cs b/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommand.cs new file mode 100644 index 0000000..84c39d0 --- /dev/null +++ b/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommand.cs @@ -0,0 +1,15 @@ +using Domain.Exceptions; +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Commands.DeleteLoan +{ + public record DeleteLoanCommand : IRequest + { + public required Guid Code { get; init; } + } +} diff --git a/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandHandler.cs b/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandHandler.cs new file mode 100644 index 0000000..14df7a7 --- /dev/null +++ b/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandHandler.cs @@ -0,0 +1,48 @@ +using Application.Services.BankSafes.Commands.DeleteBankSafe; +using Application.UnitOfWork; +using Domain.Exceptions; +using Domain.IRepositories; +using MediatR; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Commands.DeleteLoan +{ + public class DeleteLoanCommandHandler : + IRequestHandler + { + private readonly ILoanRepositorie _loanRepositorie; + private readonly IUnitOfWork _unitOfWork; + private readonly ILogger _logger; + public DeleteLoanCommandHandler(ILoanRepositorie loanRepositorie, + IUnitOfWork unitOfWork + , ILogger logger) + { + _loanRepositorie = loanRepositorie; + _unitOfWork = unitOfWork; + _logger = logger; + } + public async Task Handle(DeleteLoanCommand request, CancellationToken cancellationToken) + { + try + { + await _loanRepositorie.DeleteAsync(request.Code, cancellationToken); + await _unitOfWork.SaveChangesAsync(cancellationToken); + string message = string.Format(ConstMessages.Successfully + , request.Code + , nameof(DeleteLoanCommandHandler)); + _logger.LogInformation(message); + return new OperationResult(true, null); + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + return new OperationResult(false, ex.Message); + } + } + } +} diff --git a/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandValidator.cs b/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandValidator.cs new file mode 100644 index 0000000..3316632 --- /dev/null +++ b/Application/Services/Loan/Commands/DeleteLoan/DeleteLoanCommandValidator.cs @@ -0,0 +1,19 @@ +using Domain.Exceptions; +using FluentValidation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Commands.DeleteLoan +{ + public class DeleteLoanCommandValidator : AbstractValidator + { + public DeleteLoanCommandValidator() + { + RuleFor(p => p.Code) + .NotNull().WithMessage(string.Format(ConstMessages.IsNull, "Code")); + } + } +} diff --git a/Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQuery.cs b/Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQuery.cs new file mode 100644 index 0000000..4b37aaa --- /dev/null +++ b/Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQuery.cs @@ -0,0 +1,16 @@ +using Domain.Exceptions; +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Queries.GetAllLoan +{ + public record GetAllLoanQuery + : IRequest>> + { + + } +} diff --git a/Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQueryHandler.cs b/Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQueryHandler.cs new file mode 100644 index 0000000..6b2393a --- /dev/null +++ b/Application/Services/Loan/Queries/GetAllLoan/GetAllLoanQueryHandler.cs @@ -0,0 +1,45 @@ +using Application.Services.BankSafes.Queries.GetAllBankSafe; +using Domain.Entity; +using Domain.Exceptions; +using Domain.IRepositories; +using MediatR; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Queries.GetAllLoan +{ + public class GetAllLoanQueryHandler : + IRequestHandler>> + { + private readonly ILoanRepositorie _loanRepositorie; + private readonly ILogger _logger; + public GetAllLoanQueryHandler(ILoanRepositorie loanRepositorie + , ILogger logger) + { + _loanRepositorie = loanRepositorie; + _logger = logger; + } + + public async Task>> Handle(GetAllLoanQuery request, CancellationToken cancellationToken) + { + try + { + var result = await _loanRepositorie.GetAllAsync(cancellationToken); + string message = string.Format(ConstMessages.Successfully + , nameof(GetAllLoanQueryHandler) + , ""); + _logger.LogInformation(message); + return new OperationResult>(true, null, result); + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + return new OperationResult>(false, ex.Message, null); + } + } + } +} diff --git a/Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQuery.cs b/Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQuery.cs new file mode 100644 index 0000000..e2cbff1 --- /dev/null +++ b/Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQuery.cs @@ -0,0 +1,16 @@ +using Domain.Exceptions; +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Queries.GetByCodeLoan +{ + public record GetByCodeLoanQuery + : IRequest> + { + public required Guid Code { get; init; } + } +} diff --git a/Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQueryHandler.cs b/Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQueryHandler.cs new file mode 100644 index 0000000..da98ba3 --- /dev/null +++ b/Application/Services/Loan/Queries/GetByCodeLoan/GetByCodeLoanQueryHandler.cs @@ -0,0 +1,43 @@ +using Application.Services.Loan.Queries.GetAllLoan; +using Domain.Exceptions; +using Domain.IRepositories; +using MediatR; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Services.Loan.Queries.GetByCodeLoan +{ + public class GetByCodeLoanQueryHandler : + IRequestHandler> + { + private readonly ILoanRepositorie _loanRepositorie; + private readonly ILogger _logger; + public GetByCodeLoanQueryHandler(ILoanRepositorie loanRepositorie + , ILogger logger) + { + _loanRepositorie = loanRepositorie; + _logger = logger; + } + public async Task> Handle(GetByCodeLoanQuery request, CancellationToken cancellationToken) + { + try + { + var result = await _loanRepositorie.GetByCodeAsync(request.Code, cancellationToken); + string message = string.Format(ConstMessages.Successfully + , nameof(GetAllLoanQueryHandler) + , ""); + _logger.LogInformation(message); + return new OperationResult(true, null, result); + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + return new OperationResult(false, ex.Message, null); + } + } + } +} diff --git a/Domain/Entity/Loan.cs b/Domain/Entity/Loan.cs index 228f2eb..6349f58 100644 --- a/Domain/Entity/Loan.cs +++ b/Domain/Entity/Loan.cs @@ -12,7 +12,7 @@ namespace Domain.Entity [AudiTable] public class Loan : IEntity { - public Loan(Name nameBankSafe, Name firstName, Name lastName, Number numberOfInstallments, Money amount) + public Loan(Name nameBankSafe, Name firstName, Name lastName, Number numberOfInstallments, Money amount , Percent wage) { Code = Guid.NewGuid(); NameBankSafe = nameBankSafe; @@ -20,6 +20,7 @@ public Loan(Name nameBankSafe, Name firstName, Name lastName, Number numberOfIns LastName = lastName; NumberOfInstallments = numberOfInstallments; Amount = amount; + Wage = wage; } public Guid Code { get; private set; } public Name NameBankSafe { get; private set; } @@ -27,7 +28,7 @@ public Loan(Name nameBankSafe, Name firstName, Name lastName, Number numberOfIns public Name LastName { get; private set; } public Number NumberOfInstallments { get; private set; } public Money Amount { get; private set; } - public int Wage { get; private set; } + public Percent Wage { get; private set; } public BankSafe BankSafe { get; private set; } public ICollection LoanTransactions { get; private set; } public ICollection LoanDocuments { get; private set; } diff --git a/Domain/Exceptions/ConstMessages.cs b/Domain/Exceptions/ConstMessages.cs index dd45137..11ebd85 100644 --- a/Domain/Exceptions/ConstMessages.cs +++ b/Domain/Exceptions/ConstMessages.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace Domain.Exceptions { @@ -19,6 +20,8 @@ public class ConstMessages public const string NotNegative = "The {0} must not be negative"; public const string NotInventory = "The balance of {0} account in Bank {1} is {2}"; public const string MaximumLength = "{0} cannot be more than {1} characters"; + public const string NotBetweenNumber = "The {0} number must be between {1} and {2}"; + } } diff --git a/Domain/Exceptions/OperationResult.cs b/Domain/Exceptions/OperationResult.cs index 49b1627..c84378e 100644 --- a/Domain/Exceptions/OperationResult.cs +++ b/Domain/Exceptions/OperationResult.cs @@ -23,7 +23,7 @@ public static OperationResult Failure(string message) => new(message); public static OperationResult Success(T data) - => new(data); + => new(data); } public class OperationResult : OperationResult { diff --git a/Domain/IRepositories/ILoanRepositorie.cs b/Domain/IRepositories/ILoanRepositorie.cs index 3ed3185..e005880 100644 --- a/Domain/IRepositories/ILoanRepositorie.cs +++ b/Domain/IRepositories/ILoanRepositorie.cs @@ -1,4 +1,6 @@ -using System; +using Domain.Entity; +using Domain.ValueObjects; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +8,11 @@ namespace Domain.IRepositories { - internal class ILoanRepositorie + public interface ILoanRepositorie { + ValueTask AddAsync(Loan loan, CancellationToken cancellationToken); + Task DeleteAsync(Guid code, CancellationToken cancellationToken); + Task GetByCodeAsync(Guid code , CancellationToken cancellationToken); + Task> GetAllAsync(CancellationToken cancellationToken); } } diff --git a/Domain/ValueObjects/AccountNumber.cs b/Domain/ValueObjects/AccountNumber.cs index 03a4e77..8f9e804 100644 --- a/Domain/ValueObjects/AccountNumber.cs +++ b/Domain/ValueObjects/AccountNumber.cs @@ -27,7 +27,6 @@ public AccountNumber(string value) private OperationResult CheckAccountNumber(string value) { var result = OperationResult.CreateValidator(value) - .Validate(x => string.IsNullOrWhiteSpace(x) , string.Format(ConstMessages.IsNull, nameof(AccountNumber))) .Validate(x => x.Length != 16 , string.Format(ConstMessages.IncorrectFormat, nameof(AccountNumber))) .Validate(x => !Validation.CheckNumberFormat(x) , string.Format(ConstMessages.IncorrectFormat, nameof(AccountNumber))); return result; diff --git a/Domain/ValueObjects/Name.cs b/Domain/ValueObjects/Name.cs index 8f51e9d..6d18f01 100644 --- a/Domain/ValueObjects/Name.cs +++ b/Domain/ValueObjects/Name.cs @@ -29,15 +29,16 @@ public Name(string value) } private OperationResult CheckValueName(string value) { - if (string.IsNullOrWhiteSpace(value)) - { - string message = string.Format(ConstMessages.IsNull, nameof(Name)); - return new OperationResult(false, message); - } - else - { - return new OperationResult(true, null); - } + //if (string.IsNullOrWhiteSpace(value)) + //{ + // string message = string.Format(ConstMessages.IsNull, nameof(Name)); + // return new OperationResult(false, message); + //} + //else + //{ + // return new OperationResult(true, null); + //} + return new OperationResult(true, null); } protected override IEnumerable GetEqualityComponents() diff --git a/Domain/ValueObjects/NationalIDNumber.cs b/Domain/ValueObjects/NationalIDNumber.cs index d1f6d3a..166b4cd 100644 --- a/Domain/ValueObjects/NationalIDNumber.cs +++ b/Domain/ValueObjects/NationalIDNumber.cs @@ -27,7 +27,6 @@ public NationalIDNumber(string value) private OperationResult CheckNationalIDNumber(string value) { var result = OperationResult.CreateValidator(value) - .Validate(x => string.IsNullOrWhiteSpace(x), string.Format(ConstMessages.IsNull, nameof(NationalIDNumber))) .Validate(x => x.Length != 10, string.Format(ConstMessages.IncorrectFormat, nameof(NationalIDNumber))) .Validate(x => !Validation.CheckNumberFormat(x), string.Format(ConstMessages.IncorrectFormat, nameof(NationalIDNumber))); diff --git a/Domain/ValueObjects/Number.cs b/Domain/ValueObjects/Number.cs index d546967..fa057ec 100644 --- a/Domain/ValueObjects/Number.cs +++ b/Domain/ValueObjects/Number.cs @@ -26,15 +26,9 @@ public Number(int value) } private OperationResult CheckNumber(int value) { - if (value <= 0) - { - string message = string.Format(ConstMessages.NotNegativeOrZero, nameof(Number)); - return new OperationResult(false, message); - } - else - { - return new OperationResult(true, null); - } + var result = OperationResult.CreateValidator(value) + .Validate(x => x <= 0, string.Format(ConstMessages.NotNegativeOrZero, nameof(Number))); + return result; } protected override IEnumerable GetEqualityComponents() diff --git a/Domain/ValueObjects/Password.cs b/Domain/ValueObjects/Password.cs index fbd8f6e..b590519 100644 --- a/Domain/ValueObjects/Password.cs +++ b/Domain/ValueObjects/Password.cs @@ -27,7 +27,6 @@ public Password(string value) private OperationResult CheckPassword(string value) { var result = OperationResult.CreateValidator(value) - .Validate(x => string.IsNullOrWhiteSpace(x), string.Format(ConstMessages.IsNull, nameof(Password))) .Validate(x => !Validation.CheckFormatcharacter(value), string.Format(ConstMessages.IncorrectFormatCharacters, nameof(Password))); return result; } diff --git a/Domain/ValueObjects/Percent.cs b/Domain/ValueObjects/Percent.cs new file mode 100644 index 0000000..1beba92 --- /dev/null +++ b/Domain/ValueObjects/Percent.cs @@ -0,0 +1,45 @@ +using Domain.Common; +using Domain.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Domain.ValueObjects +{ + public sealed class Percent : ValueObject + { + public int Value { get; private set; } + public Percent(int value) + { + var result = CheckPercent(value); + if (result.IsSuccess == true) + { + Value = value; + } + else + { + throw new Exception(result.Message); + } + } + + private OperationResult CheckPercent(int value) + { + var result = OperationResult.CreateValidator(value) + .Validate(p => !(p >= 1 && p <= 100), string.Format(ConstMessages.NotBetweenNumber, nameof(Percent), "1", "100")); + return result; + } + + protected override IEnumerable GetEqualityComponents() + { + yield return Value; + } + + public static implicit operator Percent(int value) + => new Percent(value); + + public static implicit operator int(Percent percent) + => percent.Value; + } +} diff --git a/Domain/ValueObjects/PersianDate.cs b/Domain/ValueObjects/PersianDate.cs index 9ef73d1..8c59bbb 100644 --- a/Domain/ValueObjects/PersianDate.cs +++ b/Domain/ValueObjects/PersianDate.cs @@ -27,31 +27,23 @@ public PersianDate(string value) } private OperationResult CheckPersianDate(string value) { - if (string.IsNullOrWhiteSpace(value)) + PersianCalendar persianCalendar = new PersianCalendar(); + string message = string.Format(ConstMessages.IncorrectFormatCharacters, nameof(PersianDate)); + ReadOnlySpan dataSpan = value; + bool y = int.TryParse(dataSpan.Slice(0, 4), out int year); + bool m = int.TryParse(dataSpan.Slice(5, 2), out int month); + bool d = int.TryParse(dataSpan.Slice(8, 2), out int day); + if (y == false || m == false || d == false) { - string message = string.Format(ConstMessages.IsNull, nameof(CheckPersianDate)); return new OperationResult(false, message); } else { - PersianCalendar persianCalendar = new PersianCalendar(); - string message = string.Format(ConstMessages.IncorrectFormatCharacters, nameof(CheckPersianDate)); - ReadOnlySpan dataSpan = value; - bool y = int.TryParse(dataSpan.Slice(0 , 4) , out int year); - bool m = int.TryParse(dataSpan.Slice(5 , 2) , out int month); - bool d = int.TryParse(dataSpan.Slice(8 , 2) , out int day); - if (y == false || m == false || d == false) - { - return new OperationResult(false, message); - } - else - { - var result = OperationResult.CreateValidator(month) - .Validate(x => year < 1 || year > 1600, message) - .Validate(x => month < 1 || month > 12, message) - .Validate(x => day < 1 || day > persianCalendar.GetDaysInMonth(year, month), message); - return result; - } + var result = OperationResult.CreateValidator(month) + .Validate(x => year < 1 || year > 1600, message) + .Validate(x => month < 1 || month > 12, message) + .Validate(x => day < 1 || day > persianCalendar.GetDaysInMonth(year, month), message); + return result; } } diff --git a/Domain/ValueObjects/PhoneNumber.cs b/Domain/ValueObjects/PhoneNumber.cs index 1673de4..1ca5d8e 100644 --- a/Domain/ValueObjects/PhoneNumber.cs +++ b/Domain/ValueObjects/PhoneNumber.cs @@ -27,7 +27,6 @@ public PhoneNumber(string value) private OperationResult CheckPhoneNumber(string value) { var result = OperationResult.CreateValidator(value) - .Validate(x => string.IsNullOrWhiteSpace(x), string.Format(ConstMessages.IsNull, nameof(PhoneNumber))) .Validate(x => x.Length != 11, string.Format(ConstMessages.IncorrectFormat, nameof(PhoneNumber))) .Validate(x => !x.StartsWith("09"), string.Format(ConstMessages.IncorrectFormat, nameof(PhoneNumber))) .Validate(x => !Validation.CheckNumberFormat(value), string.Format(ConstMessages.IncorrectFormat, nameof(PhoneNumber))); diff --git a/Domain/ValueObjects/UserName.cs b/Domain/ValueObjects/UserName.cs index 8ce8aa6..b6f9f4b 100644 --- a/Domain/ValueObjects/UserName.cs +++ b/Domain/ValueObjects/UserName.cs @@ -27,7 +27,6 @@ public UserName(string value) private OperationResult CheckUserName(string value) { var result = OperationResult.CreateValidator(value) - .Validate(x => string.IsNullOrWhiteSpace(x), string.Format(ConstMessages.IsNull, nameof(UserName))) .Validate(x => !Validation.CheckFormatcharacter(x), string.Format(ConstMessages.IncorrectFormatCharacters, nameof(UserName))); return result; } diff --git a/Infrastructure/Repositories/LoanRepositorie.cs b/Infrastructure/Repositories/LoanRepositorie.cs index 7fa6e7d..5e6cc8e 100644 --- a/Infrastructure/Repositories/LoanRepositorie.cs +++ b/Infrastructure/Repositories/LoanRepositorie.cs @@ -1,4 +1,10 @@ -using System; +using Application.UnitOfWork; +using Domain.Entity; +using Domain.Exceptions; +using Domain.IRepositories; +using Domain.ValueObjects; +using Microsoft.EntityFrameworkCore; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +12,57 @@ namespace Infrastructure.Repositories { - internal class LoanRepositorie + public class LoanRepositorie : ILoanRepositorie { + private readonly DbSet _loan; + private readonly IBankSafeRepositorie _bankSafeRepositorie; + public LoanRepositorie(IUnitOfWork unitOfWork + , IBankSafeRepositorie bankSafeRepositorie) + { + _loan = unitOfWork.Set(); + _bankSafeRepositorie= bankSafeRepositorie; + + } + public async ValueTask AddAsync(Loan loan, CancellationToken cancellationToken) + { + var result = await _bankSafeRepositorie + .GetAsync(loan.NameBankSafe , cancellationToken); + if (result != null) + { + _loan.Add(loan); + } + else + { + string message = string.Format(ConstMessages.NotFound, loan.NameBankSafe.Value); + throw new Exception(message); + } + } + + public async Task DeleteAsync(Guid code, CancellationToken cancellationToken) + { + var result = await _loan.FirstOrDefaultAsync(loan => loan.Code == code , cancellationToken); + if (result != null) + { + _loan.Remove(result); + } + else + { + string message = string.Format(ConstMessages.NotFound, code); + throw new Exception(message); + } + } + + public async Task> GetAllAsync(CancellationToken cancellationToken) + { + var result = await _loan.ToListAsync(cancellationToken); + return result; + } + + public async Task GetByCodeAsync(Guid code, CancellationToken cancellationToken) + { + var result = await _loan + .FirstOrDefaultAsync(p => p.Code== code, cancellationToken); + return result; + } } } diff --git a/Persistence/Config/LoanConfig.cs b/Persistence/Config/LoanConfig.cs index 4c98761..0824c31 100644 --- a/Persistence/Config/LoanConfig.cs +++ b/Persistence/Config/LoanConfig.cs @@ -58,6 +58,7 @@ public void Configure(EntityTypeBuilder builder) .IsRequired(true); builder.Property(p => p.Wage) + .HasConversion() .HasMaxLength(2) .IsRequired(true); } diff --git a/Persistence/Convertors/PercentConverter.cs b/Persistence/Convertors/PercentConverter.cs new file mode 100644 index 0000000..1682d01 --- /dev/null +++ b/Persistence/Convertors/PercentConverter.cs @@ -0,0 +1,20 @@ +using Domain.ValueObjects; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Persistence.Convertors +{ + public class PercentConverter : ValueConverter + { + public PercentConverter() : + base(ClrToDb => ClrToDb.Value, + DbToClr => new Percent(DbToClr)) + { + + } + } +} diff --git a/WebSite/Controllers/LoanController.cs b/WebSite/Controllers/LoanController.cs new file mode 100644 index 0000000..d46e0bd --- /dev/null +++ b/WebSite/Controllers/LoanController.cs @@ -0,0 +1,78 @@ +using Application.Services.Loan.Commands.AddLoan; +using Application.Services.Loan.Commands.DeleteLoan; +using Application.Services.Loan.Queries.GetAllLoan; +using Application.Services.Loan.Queries.GetByCodeLoan; +using Application.Services.UserAndNumberOfShares.Commands.AddUserAndNumberOfShare; +using Microsoft.AspNetCore.Mvc; + +namespace WebSite.Controllers +{ + [Route("api/Loan")] + [ApiController] + public class LoanController : BaseController + { + [HttpGet] + public async Task GetAll(CancellationToken cancellationToken) + { + var getAllLoanQuery = new GetAllLoanQuery(); + var result = await Mediator.Send(getAllLoanQuery, cancellationToken); + if (result.IsSuccess == true) + { + return Ok(result.Data); + } + else + { + return BadRequest(result.Message); + } + } + [HttpGet("{Code}")] + public async Task GetByCode([FromRoute] GetByCodeLoanQuery getByCodeLoanQuery + , CancellationToken cancellationToken) + { + var result = await Mediator.Send(getByCodeLoanQuery, cancellationToken); + if (result.IsSuccess) + { + return Ok(result.Data); + } + else + { + return BadRequest(result.Message); + } + } + [HttpDelete("{UserName}")] + public async Task Delete([FromRoute]DeleteLoanCommand deleteLoanCommand + ,CancellationToken cancellationToken) + { + var result = await Mediator.Send(deleteLoanCommand , cancellationToken); + if (result.IsSuccess == true) + { + return Ok(result.IsSuccess); + } + else + { + return BadRequest(result.Message); + } + } + [HttpPost] + public async Task Insert([FromBody] AddLoanCommand addLoanCommand , + CancellationToken cancellationToken) + { + var result = await Mediator.Send(addLoanCommand , cancellationToken); + if (result.IsSuccess == true) + { + string url = Url.Action(nameof(GetByCode), "loan", + new + { + Code = result.Data, + }, + Request.Scheme); + return Created(url, result.IsSuccess); + } + else + { + return BadRequest(result.Message); + } + } + + } +} diff --git a/WebSite/Program.cs b/WebSite/Program.cs index 4bd6a3f..3240442 100644 --- a/WebSite/Program.cs +++ b/WebSite/Program.cs @@ -82,6 +82,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.RegisterApplication();