initial commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.BudgetManager.Commands;
|
||||
|
||||
public class CreateBudgetResult
|
||||
{
|
||||
public Budget? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateBudgetRequest : IRequest<CreateBudgetResult>
|
||||
{
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? BudgetDate { get; init; }
|
||||
public string? Status { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateBudgetValidator : AbstractValidator<CreateBudgetRequest>
|
||||
{
|
||||
public CreateBudgetValidator()
|
||||
{
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.BudgetDate).NotNull();
|
||||
RuleFor(x => x.Amount).NotNull();
|
||||
RuleFor(x => x.CampaignId).NotEmpty();
|
||||
RuleFor(x => x.Status).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateBudgetHandler : IRequestHandler<CreateBudgetRequest, CreateBudgetResult>
|
||||
{
|
||||
private readonly ICommandRepository<Budget> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateBudgetHandler(
|
||||
ICommandRepository<Budget> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateBudgetResult> Handle(CreateBudgetRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new Budget
|
||||
{
|
||||
CreatedById = request.CreatedById,
|
||||
Number = _numberSequenceService.GenerateNumber(nameof(Budget), "", "BUD"),
|
||||
Title = request.Title,
|
||||
Description = request.Description,
|
||||
BudgetDate = request.BudgetDate,
|
||||
Status = (BudgetStatus)int.Parse(request.Status!),
|
||||
Amount = request.Amount,
|
||||
CampaignId = request.CampaignId
|
||||
};
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateBudgetResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.BudgetManager.Commands;
|
||||
|
||||
public class DeleteBudgetResult
|
||||
{
|
||||
public Budget? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteBudgetRequest : IRequest<DeleteBudgetResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteBudgetValidator : AbstractValidator<DeleteBudgetRequest>
|
||||
{
|
||||
public DeleteBudgetValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteBudgetHandler : IRequestHandler<DeleteBudgetRequest, DeleteBudgetResult>
|
||||
{
|
||||
private readonly ICommandRepository<Budget> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteBudgetHandler(
|
||||
ICommandRepository<Budget> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteBudgetResult> Handle(DeleteBudgetRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteBudgetResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.BudgetManager.Commands;
|
||||
|
||||
public class UpdateBudgetResult
|
||||
{
|
||||
public Budget? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateBudgetRequest : IRequest<UpdateBudgetResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? BudgetDate { get; init; }
|
||||
public string? Status { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateBudgetValidator : AbstractValidator<UpdateBudgetRequest>
|
||||
{
|
||||
public UpdateBudgetValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.BudgetDate).NotNull();
|
||||
RuleFor(x => x.Amount).NotNull();
|
||||
RuleFor(x => x.CampaignId).NotEmpty();
|
||||
RuleFor(x => x.Status).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateBudgetHandler : IRequestHandler<UpdateBudgetRequest, UpdateBudgetResult>
|
||||
{
|
||||
private readonly ICommandRepository<Budget> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateBudgetHandler(
|
||||
ICommandRepository<Budget> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateBudgetResult> Handle(UpdateBudgetRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
entity.Title = request.Title;
|
||||
entity.Description = request.Description;
|
||||
entity.BudgetDate = request.BudgetDate;
|
||||
entity.Status = (BudgetStatus)int.Parse(request.Status!);
|
||||
entity.Amount = request.Amount;
|
||||
entity.CampaignId = request.CampaignId;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateBudgetResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.BudgetManager.Queries;
|
||||
|
||||
public record GetBudgetByCampaignIdListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? BudgetDate { get; init; }
|
||||
public BudgetStatus? Status { get; init; }
|
||||
public string? StatusName { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? CampaignName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetByCampaignIdListProfile : Profile
|
||||
{
|
||||
public GetBudgetByCampaignIdListProfile()
|
||||
{
|
||||
CreateMap<Budget, GetBudgetByCampaignIdListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CampaignName,
|
||||
opt => opt.MapFrom(src => src.Campaign != null ? src.Campaign.Title : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.StatusName,
|
||||
opt => opt.MapFrom(src => src.Status.HasValue ? src.Status.Value.ToFriendlyName() : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetBudgetByCampaignIdListResult
|
||||
{
|
||||
public List<GetBudgetByCampaignIdListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetByCampaignIdListRequest : IRequest<GetBudgetByCampaignIdListResult>
|
||||
{
|
||||
public string? CampaignId { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetByCampaignIdListHandler : IRequestHandler<GetBudgetByCampaignIdListRequest, GetBudgetByCampaignIdListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetBudgetByCampaignIdListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetBudgetByCampaignIdListResult> Handle(GetBudgetByCampaignIdListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Budget
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.Campaign)
|
||||
.Where(x => x.CampaignId == request.CampaignId)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetBudgetByCampaignIdListDto>>(entities);
|
||||
|
||||
return new GetBudgetByCampaignIdListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.BudgetManager.Queries;
|
||||
|
||||
public record GetBudgetListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? BudgetDate { get; init; }
|
||||
public BudgetStatus? Status { get; init; }
|
||||
public string? StatusName { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? CampaignName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetListProfile : Profile
|
||||
{
|
||||
public GetBudgetListProfile()
|
||||
{
|
||||
CreateMap<Budget, GetBudgetListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CampaignName,
|
||||
opt => opt.MapFrom(src => src.Campaign != null ? src.Campaign.Title : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.StatusName,
|
||||
opt => opt.MapFrom(src => src.Status.HasValue ? src.Status.Value.ToFriendlyName() : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetBudgetListResult
|
||||
{
|
||||
public List<GetBudgetListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetListRequest : IRequest<GetBudgetListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
public class GetBudgetListHandler : IRequestHandler<GetBudgetListRequest, GetBudgetListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetBudgetListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetBudgetListResult> Handle(GetBudgetListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Budget
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.Campaign)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetBudgetListDto>>(entities);
|
||||
|
||||
return new GetBudgetListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.BudgetManager.Queries;
|
||||
|
||||
public class GetBudgetSingleProfile : Profile
|
||||
{
|
||||
public GetBudgetSingleProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetBudgetSingleResult
|
||||
{
|
||||
public Budget? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetSingleRequest : IRequest<GetBudgetSingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetSingleValidator : AbstractValidator<GetBudgetSingleRequest>
|
||||
{
|
||||
public GetBudgetSingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetBudgetSingleHandler : IRequestHandler<GetBudgetSingleRequest, GetBudgetSingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetBudgetSingleHandler(
|
||||
IQueryContext context
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetBudgetSingleResult> Handle(GetBudgetSingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Budget
|
||||
.AsNoTracking()
|
||||
.Include(x => x.Campaign)
|
||||
.Where(x => x.Id == request.Id)
|
||||
.AsQueryable();
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return new GetBudgetSingleResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.BudgetManager.Queries;
|
||||
|
||||
public record GetBudgetStatusListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetStatusListProfile : Profile
|
||||
{
|
||||
public GetBudgetStatusListProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetBudgetStatusListResult
|
||||
{
|
||||
public List<GetBudgetStatusListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetBudgetStatusListRequest : IRequest<GetBudgetStatusListResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetBudgetStatusListHandler : IRequestHandler<GetBudgetStatusListRequest, GetBudgetStatusListResult>
|
||||
{
|
||||
|
||||
public GetBudgetStatusListHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<GetBudgetStatusListResult> Handle(GetBudgetStatusListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var statuses = Enum.GetValues(typeof(BudgetStatus))
|
||||
.Cast<BudgetStatus>()
|
||||
.Select(status => new GetBudgetStatusListDto
|
||||
{
|
||||
Id = ((int)status).ToString(),
|
||||
Name = status.ToFriendlyName()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new GetBudgetStatusListResult
|
||||
{
|
||||
Data = statuses
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CampaignManager.Commands;
|
||||
|
||||
public class CreateCampaignResult
|
||||
{
|
||||
public Campaign? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateCampaignRequest : IRequest<CreateCampaignResult>
|
||||
{
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public double? TargetRevenueAmount { get; init; }
|
||||
public DateTime? CampaignDateStart { get; init; }
|
||||
public DateTime? CampaignDateFinish { get; init; }
|
||||
public string? SalesTeamId { get; init; }
|
||||
public string? Status { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateCampaignValidator : AbstractValidator<CreateCampaignRequest>
|
||||
{
|
||||
public CreateCampaignValidator()
|
||||
{
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.SalesTeamId).NotEmpty();
|
||||
RuleFor(x => x.CampaignDateStart).NotEmpty();
|
||||
RuleFor(x => x.CampaignDateFinish).NotEmpty();
|
||||
RuleFor(x => x.TargetRevenueAmount).NotEmpty();
|
||||
RuleFor(x => x.Status).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateCampaignHandler : IRequestHandler<CreateCampaignRequest, CreateCampaignResult>
|
||||
{
|
||||
private readonly ICommandRepository<Campaign> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateCampaignHandler(
|
||||
ICommandRepository<Campaign> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateCampaignResult> Handle(CreateCampaignRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new Campaign();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Number = _numberSequenceService.GenerateNumber(nameof(Campaign), "", "CAM");
|
||||
entity.Title = request.Title;
|
||||
entity.SalesTeamId = request.SalesTeamId;
|
||||
entity.Description = request.Description;
|
||||
entity.TargetRevenueAmount = request.TargetRevenueAmount;
|
||||
entity.CampaignDateStart = request.CampaignDateStart;
|
||||
entity.CampaignDateFinish = request.CampaignDateFinish;
|
||||
entity.Status = (CampaignStatus)int.Parse(request.Status!);
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateCampaignResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CampaignManager.Commands;
|
||||
|
||||
public class DeleteCampaignResult
|
||||
{
|
||||
public Campaign? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteCampaignRequest : IRequest<DeleteCampaignResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteCampaignValidator : AbstractValidator<DeleteCampaignRequest>
|
||||
{
|
||||
public DeleteCampaignValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteCampaignHandler : IRequestHandler<DeleteCampaignRequest, DeleteCampaignResult>
|
||||
{
|
||||
private readonly ICommandRepository<Campaign> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteCampaignHandler(
|
||||
ICommandRepository<Campaign> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteCampaignResult> Handle(DeleteCampaignRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteCampaignResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CampaignManager.Commands;
|
||||
|
||||
public class UpdateCampaignResult
|
||||
{
|
||||
public Campaign? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateCampaignRequest : IRequest<UpdateCampaignResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public double? TargetRevenueAmount { get; init; }
|
||||
public DateTime? CampaignDateStart { get; init; }
|
||||
public DateTime? CampaignDateFinish { get; init; }
|
||||
public string? SalesTeamId { get; init; }
|
||||
public string? Status { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateCampaignValidator : AbstractValidator<UpdateCampaignRequest>
|
||||
{
|
||||
public UpdateCampaignValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.SalesTeamId).NotEmpty();
|
||||
RuleFor(x => x.CampaignDateStart).NotEmpty();
|
||||
RuleFor(x => x.CampaignDateFinish).NotEmpty();
|
||||
RuleFor(x => x.Status).NotEmpty();
|
||||
RuleFor(x => x.Status).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateCampaignHandler : IRequestHandler<UpdateCampaignRequest, UpdateCampaignResult>
|
||||
{
|
||||
private readonly ICommandRepository<Campaign> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateCampaignHandler(
|
||||
ICommandRepository<Campaign> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateCampaignResult> Handle(UpdateCampaignRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Title = request.Title;
|
||||
entity.SalesTeamId = request.SalesTeamId;
|
||||
entity.Description = request.Description;
|
||||
entity.TargetRevenueAmount = request.TargetRevenueAmount;
|
||||
entity.CampaignDateStart = request.CampaignDateStart;
|
||||
entity.CampaignDateFinish = request.CampaignDateFinish;
|
||||
entity.Status = (CampaignStatus)int.Parse(request.Status!);
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateCampaignResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CampaignManager.Queries;
|
||||
|
||||
public record GetCampaignListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public double? TargetRevenueAmount { get; init; }
|
||||
public DateTime? CampaignDateStart { get; init; }
|
||||
public DateTime? CampaignDateFinish { get; init; }
|
||||
public CampaignStatus? Status { get; init; }
|
||||
public string? StatusName { get; init; }
|
||||
public string? SalesTeamId { get; init; }
|
||||
public string? SalesTeamName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignListProfile : Profile
|
||||
{
|
||||
public GetCampaignListProfile()
|
||||
{
|
||||
CreateMap<Campaign, GetCampaignListDto>()
|
||||
.ForMember(
|
||||
dest => dest.StatusName,
|
||||
opt => opt.MapFrom(src => src.Status.HasValue ? src.Status.Value.ToFriendlyName() : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.SalesTeamName,
|
||||
opt => opt.MapFrom(src => src.SalesTeam != null ? src.SalesTeam.Name : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCampaignListResult
|
||||
{
|
||||
public List<GetCampaignListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignListRequest : IRequest<GetCampaignListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
public class GetCampaignListHandler : IRequestHandler<GetCampaignListRequest, GetCampaignListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCampaignListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCampaignListResult> Handle(GetCampaignListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Campaign
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.SalesTeam)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetCampaignListDto>>(entities);
|
||||
|
||||
return new GetCampaignListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CampaignManager.Queries;
|
||||
|
||||
public class GetCampaignSingleProfile : Profile
|
||||
{
|
||||
public GetCampaignSingleProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCampaignSingleResult
|
||||
{
|
||||
public Campaign? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignSingleRequest : IRequest<GetCampaignSingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignSingleValidator : AbstractValidator<GetCampaignSingleRequest>
|
||||
{
|
||||
public GetCampaignSingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCampaignSingleHandler : IRequestHandler<GetCampaignSingleRequest, GetCampaignSingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCampaignSingleHandler(
|
||||
IQueryContext context
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCampaignSingleResult> Handle(GetCampaignSingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Campaign
|
||||
.AsNoTracking()
|
||||
.Include(x => x.CampaignBudgetList.Where(budget => !budget.IsDeleted))
|
||||
.Include(x => x.CampaignExpenseList.Where(expense => !expense.IsDeleted))
|
||||
.Include(x => x.CampaignLeadList.Where(lead => !lead.IsDeleted))
|
||||
.Where(x => x.Id == request.Id)
|
||||
.AsQueryable();
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return new GetCampaignSingleResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CampaignManager.Queries;
|
||||
|
||||
public record GetCampaignStatusListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignStatusListProfile : Profile
|
||||
{
|
||||
public GetCampaignStatusListProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCampaignStatusListResult
|
||||
{
|
||||
public List<GetCampaignStatusListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignStatusListRequest : IRequest<GetCampaignStatusListResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetCampaignStatusListHandler : IRequestHandler<GetCampaignStatusListRequest, GetCampaignStatusListResult>
|
||||
{
|
||||
public GetCampaignStatusListHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<GetCampaignStatusListResult> Handle(GetCampaignStatusListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var statuses = Enum.GetValues(typeof(CampaignStatus))
|
||||
.Cast<CampaignStatus>()
|
||||
.Select(status => new GetCampaignStatusListDto
|
||||
{
|
||||
Id = ((int)status).ToString(),
|
||||
Name = status.ToFriendlyName()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new GetCampaignStatusListResult
|
||||
{
|
||||
Data = statuses
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CompanyManager.Commands;
|
||||
|
||||
public class UpdateCompanyResult
|
||||
{
|
||||
public Company? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateCompanyRequest : IRequest<UpdateCompanyResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? Currency { get; init; }
|
||||
public string? Street { get; init; }
|
||||
public string? City { get; init; }
|
||||
public string? State { get; init; }
|
||||
public string? ZipCode { get; init; }
|
||||
public string? Country { get; init; }
|
||||
public string? PhoneNumber { get; init; }
|
||||
public string? FaxNumber { get; init; }
|
||||
public string? EmailAddress { get; init; }
|
||||
public string? Website { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateCompanyValidator : AbstractValidator<UpdateCompanyRequest>
|
||||
{
|
||||
public UpdateCompanyValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
RuleFor(x => x.Currency).NotEmpty();
|
||||
RuleFor(x => x.Street).NotEmpty();
|
||||
RuleFor(x => x.City).NotEmpty();
|
||||
RuleFor(x => x.State).NotEmpty();
|
||||
RuleFor(x => x.ZipCode).NotEmpty();
|
||||
RuleFor(x => x.PhoneNumber).NotEmpty();
|
||||
RuleFor(x => x.EmailAddress).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateCompanyHandler : IRequestHandler<UpdateCompanyRequest, UpdateCompanyResult>
|
||||
{
|
||||
private readonly ICommandRepository<Company> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateCompanyHandler(
|
||||
ICommandRepository<Company> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateCompanyResult> Handle(UpdateCompanyRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
entity.Currency = request.Currency;
|
||||
entity.Street = request.Street;
|
||||
entity.City = request.City;
|
||||
entity.State = request.State;
|
||||
entity.ZipCode = request.ZipCode;
|
||||
entity.Country = request.Country;
|
||||
entity.PhoneNumber = request.PhoneNumber;
|
||||
entity.FaxNumber = request.FaxNumber;
|
||||
entity.EmailAddress = request.EmailAddress;
|
||||
entity.Website = request.Website;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateCompanyResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CompanyManager.Queries;
|
||||
|
||||
public record GetCompanyListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? Currency { get; init; }
|
||||
public string? Street { get; init; }
|
||||
public string? City { get; init; }
|
||||
public string? State { get; init; }
|
||||
public string? ZipCode { get; init; }
|
||||
public string? Country { get; init; }
|
||||
public string? PhoneNumber { get; init; }
|
||||
public string? FaxNumber { get; init; }
|
||||
public string? EmailAddress { get; init; }
|
||||
public string? Website { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetCompanyListProfile : Profile
|
||||
{
|
||||
public GetCompanyListProfile()
|
||||
{
|
||||
CreateMap<Company, GetCompanyListDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCompanyListResult
|
||||
{
|
||||
public List<GetCompanyListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCompanyListRequest : IRequest<GetCompanyListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetCompanyListHandler : IRequestHandler<GetCompanyListRequest, GetCompanyListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCompanyListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCompanyListResult> Handle(GetCompanyListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Company
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetCompanyListDto>>(entities);
|
||||
|
||||
return new GetCompanyListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CompanyManager.Queries;
|
||||
|
||||
public record GetCompanySingleDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? Currency { get; init; }
|
||||
public string? Street { get; init; }
|
||||
public string? City { get; init; }
|
||||
public string? State { get; init; }
|
||||
public string? ZipCode { get; init; }
|
||||
public string? Country { get; init; }
|
||||
public string? PhoneNumber { get; init; }
|
||||
public string? FaxNumber { get; init; }
|
||||
public string? EmailAddress { get; init; }
|
||||
public string? Website { get; init; }
|
||||
}
|
||||
|
||||
public class GetCompanySingleProfile : Profile
|
||||
{
|
||||
public GetCompanySingleProfile()
|
||||
{
|
||||
CreateMap<Company, GetCompanySingleDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCompanySingleResult
|
||||
{
|
||||
public GetCompanySingleDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCompanySingleRequest : IRequest<GetCompanySingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetCompanySingleValidator : AbstractValidator<GetCompanySingleRequest>
|
||||
{
|
||||
public GetCompanySingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCompanySingleHandler : IRequestHandler<GetCompanySingleRequest, GetCompanySingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public GetCompanySingleHandler(
|
||||
IQueryContext context,
|
||||
IMapper mapper
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<GetCompanySingleResult> Handle(GetCompanySingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Company
|
||||
.AsNoTracking()
|
||||
.AsQueryable();
|
||||
|
||||
query = query
|
||||
.Where(x => x.Id == request.Id);
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
var dto = _mapper.Map<GetCompanySingleDto>(entity);
|
||||
|
||||
return new GetCompanySingleResult
|
||||
{
|
||||
Data = dto
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerCategoryManager.Commands;
|
||||
|
||||
public class CreateCustomerCategoryResult
|
||||
{
|
||||
public CustomerCategory? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateCustomerCategoryRequest : IRequest<CreateCustomerCategoryResult>
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateCustomerCategoryValidator : AbstractValidator<CreateCustomerCategoryRequest>
|
||||
{
|
||||
public CreateCustomerCategoryValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateCustomerCategoryHandler : IRequestHandler<CreateCustomerCategoryRequest, CreateCustomerCategoryResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerCategory> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public CreateCustomerCategoryHandler(
|
||||
ICommandRepository<CustomerCategory> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<CreateCustomerCategoryResult> Handle(CreateCustomerCategoryRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new CustomerCategory();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateCustomerCategoryResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerCategoryManager.Commands;
|
||||
|
||||
public class DeleteCustomerCategoryResult
|
||||
{
|
||||
public CustomerCategory? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerCategoryRequest : IRequest<DeleteCustomerCategoryResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerCategoryValidator : AbstractValidator<DeleteCustomerCategoryRequest>
|
||||
{
|
||||
public DeleteCustomerCategoryValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteCustomerCategoryHandler : IRequestHandler<DeleteCustomerCategoryRequest, DeleteCustomerCategoryResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerCategory> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteCustomerCategoryHandler(
|
||||
ICommandRepository<CustomerCategory> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteCustomerCategoryResult> Handle(DeleteCustomerCategoryRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteCustomerCategoryResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerCategoryManager.Commands;
|
||||
|
||||
public class UpdateCustomerCategoryResult
|
||||
{
|
||||
public CustomerCategory? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerCategoryRequest : IRequest<UpdateCustomerCategoryResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerCategoryValidator : AbstractValidator<UpdateCustomerCategoryRequest>
|
||||
{
|
||||
public UpdateCustomerCategoryValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateCustomerCategoryHandler : IRequestHandler<UpdateCustomerCategoryRequest, UpdateCustomerCategoryResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerCategory> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateCustomerCategoryHandler(
|
||||
ICommandRepository<CustomerCategory> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateCustomerCategoryResult> Handle(UpdateCustomerCategoryRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateCustomerCategoryResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CustomerCategoryManager.Queries;
|
||||
|
||||
public record GetCustomerCategoryListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerCategoryListProfile : Profile
|
||||
{
|
||||
public GetCustomerCategoryListProfile()
|
||||
{
|
||||
CreateMap<CustomerCategory, GetCustomerCategoryListDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCustomerCategoryListResult
|
||||
{
|
||||
public List<GetCustomerCategoryListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerCategoryListRequest : IRequest<GetCustomerCategoryListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetCustomerCategoryListHandler : IRequestHandler<GetCustomerCategoryListRequest, GetCustomerCategoryListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCustomerCategoryListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerCategoryListResult> Handle(GetCustomerCategoryListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.CustomerCategory
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetCustomerCategoryListDto>>(entities);
|
||||
|
||||
return new GetCustomerCategoryListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerContactManager.Commands;
|
||||
|
||||
public class CreateCustomerContactResult
|
||||
{
|
||||
public CustomerContact? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateCustomerContactRequest : IRequest<CreateCustomerContactResult>
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
public string? JobTitle { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? CustomerId { get; set; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateCustomerContactValidator : AbstractValidator<CreateCustomerContactRequest>
|
||||
{
|
||||
public CreateCustomerContactValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
RuleFor(x => x.JobTitle).NotEmpty();
|
||||
RuleFor(x => x.PhoneNumber).NotEmpty();
|
||||
RuleFor(x => x.EmailAddress).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateCustomerContactHandler : IRequestHandler<CreateCustomerContactRequest, CreateCustomerContactResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerContact> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateCustomerContactHandler(
|
||||
ICommandRepository<CustomerContact> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateCustomerContactResult> Handle(CreateCustomerContactRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new CustomerContact();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Number = _numberSequenceService.GenerateNumber(nameof(CustomerContact), "", "CC");
|
||||
entity.JobTitle = request.JobTitle;
|
||||
entity.PhoneNumber = request.PhoneNumber;
|
||||
entity.EmailAddress = request.EmailAddress;
|
||||
entity.Description = request.Description;
|
||||
entity.CustomerId = request.CustomerId;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateCustomerContactResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerContactManager.Commands;
|
||||
|
||||
public class DeleteCustomerContactResult
|
||||
{
|
||||
public CustomerContact? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerContactRequest : IRequest<DeleteCustomerContactResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerContactValidator : AbstractValidator<DeleteCustomerContactRequest>
|
||||
{
|
||||
public DeleteCustomerContactValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteCustomerContactHandler : IRequestHandler<DeleteCustomerContactRequest, DeleteCustomerContactResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerContact> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteCustomerContactHandler(
|
||||
ICommandRepository<CustomerContact> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteCustomerContactResult> Handle(DeleteCustomerContactRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteCustomerContactResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerContactManager.Commands;
|
||||
|
||||
public class UpdateCustomerContactResult
|
||||
{
|
||||
public CustomerContact? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerContactRequest : IRequest<UpdateCustomerContactResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? JobTitle { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? CustomerId { get; set; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerContactValidator : AbstractValidator<UpdateCustomerContactRequest>
|
||||
{
|
||||
public UpdateCustomerContactValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
RuleFor(x => x.JobTitle).NotEmpty();
|
||||
RuleFor(x => x.PhoneNumber).NotEmpty();
|
||||
RuleFor(x => x.EmailAddress).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateCustomerContactHandler : IRequestHandler<UpdateCustomerContactRequest, UpdateCustomerContactResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerContact> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateCustomerContactHandler(
|
||||
ICommandRepository<CustomerContact> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateCustomerContactResult> Handle(UpdateCustomerContactRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.JobTitle = request.JobTitle;
|
||||
entity.PhoneNumber = request.PhoneNumber;
|
||||
entity.EmailAddress = request.EmailAddress;
|
||||
entity.Description = request.Description;
|
||||
entity.CustomerId = request.CustomerId;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateCustomerContactResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CustomerContactManager.Queries;
|
||||
|
||||
public record GetCustomerContactByCustomerIdListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; set; }
|
||||
public string? Number { get; set; }
|
||||
public string? JobTitle { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? CustomerId { get; set; }
|
||||
public string? CustomerName { get; set; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerContactByCustomerIdListProfile : Profile
|
||||
{
|
||||
public GetCustomerContactByCustomerIdListProfile()
|
||||
{
|
||||
CreateMap<CustomerContact, GetCustomerContactByCustomerIdListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CustomerName,
|
||||
opt => opt.MapFrom(src => src.Customer != null ? src.Customer.Name : string.Empty)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCustomerContactByCustomerIdListResult
|
||||
{
|
||||
public List<GetCustomerContactByCustomerIdListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerContactByCustomerIdListRequest : IRequest<GetCustomerContactByCustomerIdListResult>
|
||||
{
|
||||
public string? CustomerId { get; init; }
|
||||
}
|
||||
|
||||
|
||||
public class GetCustomerContactByCustomerIdListHandler : IRequestHandler<GetCustomerContactByCustomerIdListRequest, GetCustomerContactByCustomerIdListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCustomerContactByCustomerIdListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerContactByCustomerIdListResult> Handle(GetCustomerContactByCustomerIdListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.CustomerContact
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.Customer)
|
||||
.Where(x => x.CustomerId == request.CustomerId)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetCustomerContactByCustomerIdListDto>>(entities);
|
||||
|
||||
return new GetCustomerContactByCustomerIdListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CustomerContactManager.Queries;
|
||||
|
||||
public record GetCustomerContactListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; set; }
|
||||
public string? Number { get; set; }
|
||||
public string? JobTitle { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? CustomerId { get; set; }
|
||||
public string? CustomerName { get; set; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerContactListProfile : Profile
|
||||
{
|
||||
public GetCustomerContactListProfile()
|
||||
{
|
||||
CreateMap<CustomerContact, GetCustomerContactListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CustomerName,
|
||||
opt => opt.MapFrom(src => src.Customer != null ? src.Customer.Name : string.Empty)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCustomerContactListResult
|
||||
{
|
||||
public List<GetCustomerContactListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerContactListRequest : IRequest<GetCustomerContactListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetCustomerContactListHandler : IRequestHandler<GetCustomerContactListRequest, GetCustomerContactListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCustomerContactListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerContactListResult> Handle(GetCustomerContactListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.CustomerContact
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.Customer)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetCustomerContactListDto>>(entities);
|
||||
|
||||
return new GetCustomerContactListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerGroupManager.Commands;
|
||||
|
||||
public class CreateCustomerGroupResult
|
||||
{
|
||||
public CustomerGroup? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateCustomerGroupRequest : IRequest<CreateCustomerGroupResult>
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateCustomerGroupValidator : AbstractValidator<CreateCustomerGroupRequest>
|
||||
{
|
||||
public CreateCustomerGroupValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateCustomerGroupHandler : IRequestHandler<CreateCustomerGroupRequest, CreateCustomerGroupResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerGroup> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public CreateCustomerGroupHandler(
|
||||
ICommandRepository<CustomerGroup> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<CreateCustomerGroupResult> Handle(CreateCustomerGroupRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new CustomerGroup();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateCustomerGroupResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerGroupManager.Commands;
|
||||
|
||||
public class DeleteCustomerGroupResult
|
||||
{
|
||||
public CustomerGroup? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerGroupRequest : IRequest<DeleteCustomerGroupResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerGroupValidator : AbstractValidator<DeleteCustomerGroupRequest>
|
||||
{
|
||||
public DeleteCustomerGroupValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteCustomerGroupHandler : IRequestHandler<DeleteCustomerGroupRequest, DeleteCustomerGroupResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerGroup> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteCustomerGroupHandler(
|
||||
ICommandRepository<CustomerGroup> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteCustomerGroupResult> Handle(DeleteCustomerGroupRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteCustomerGroupResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerGroupManager.Commands;
|
||||
|
||||
public class UpdateCustomerGroupResult
|
||||
{
|
||||
public CustomerGroup? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerGroupRequest : IRequest<UpdateCustomerGroupResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerGroupValidator : AbstractValidator<UpdateCustomerGroupRequest>
|
||||
{
|
||||
public UpdateCustomerGroupValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateCustomerGroupHandler : IRequestHandler<UpdateCustomerGroupRequest, UpdateCustomerGroupResult>
|
||||
{
|
||||
private readonly ICommandRepository<CustomerGroup> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateCustomerGroupHandler(
|
||||
ICommandRepository<CustomerGroup> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateCustomerGroupResult> Handle(UpdateCustomerGroupRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateCustomerGroupResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CustomerGroupManager.Queries;
|
||||
|
||||
public record GetCustomerGroupListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerGroupListProfile : Profile
|
||||
{
|
||||
public GetCustomerGroupListProfile()
|
||||
{
|
||||
CreateMap<CustomerGroup, GetCustomerGroupListDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCustomerGroupListResult
|
||||
{
|
||||
public List<GetCustomerGroupListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerGroupListRequest : IRequest<GetCustomerGroupListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetCustomerGroupListHandler : IRequestHandler<GetCustomerGroupListRequest, GetCustomerGroupListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCustomerGroupListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerGroupListResult> Handle(GetCustomerGroupListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.CustomerGroup
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetCustomerGroupListDto>>(entities);
|
||||
|
||||
return new GetCustomerGroupListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerManager.Commands;
|
||||
|
||||
public class CreateCustomerResult
|
||||
{
|
||||
public Customer? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateCustomerRequest : IRequest<CreateCustomerResult>
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Street { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? State { get; set; }
|
||||
public string? ZipCode { get; set; }
|
||||
public string? Country { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? FaxNumber { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public string? Website { get; set; }
|
||||
public string? WhatsApp { get; set; }
|
||||
public string? LinkedIn { get; set; }
|
||||
public string? Facebook { get; set; }
|
||||
public string? Instagram { get; set; }
|
||||
public string? TwitterX { get; set; }
|
||||
public string? TikTok { get; set; }
|
||||
public string? CustomerGroupId { get; set; }
|
||||
public string? CustomerCategoryId { get; set; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateCustomerValidator : AbstractValidator<CreateCustomerRequest>
|
||||
{
|
||||
public CreateCustomerValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
RuleFor(x => x.Street).NotEmpty();
|
||||
RuleFor(x => x.City).NotEmpty();
|
||||
RuleFor(x => x.State).NotEmpty();
|
||||
RuleFor(x => x.ZipCode).NotEmpty();
|
||||
RuleFor(x => x.PhoneNumber).NotEmpty();
|
||||
RuleFor(x => x.EmailAddress).NotEmpty();
|
||||
RuleFor(x => x.CustomerGroupId).NotEmpty();
|
||||
RuleFor(x => x.CustomerCategoryId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateCustomerHandler : IRequestHandler<CreateCustomerRequest, CreateCustomerResult>
|
||||
{
|
||||
private readonly ICommandRepository<Customer> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateCustomerHandler(
|
||||
ICommandRepository<Customer> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateCustomerResult> Handle(CreateCustomerRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new Customer();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Number = _numberSequenceService.GenerateNumber(nameof(Customer), "", "CST");
|
||||
entity.Description = request.Description;
|
||||
entity.Street = request.Street;
|
||||
entity.City = request.City;
|
||||
entity.State = request.State;
|
||||
entity.ZipCode = request.ZipCode;
|
||||
entity.Country = request.Country;
|
||||
entity.PhoneNumber = request.PhoneNumber;
|
||||
entity.FaxNumber = request.FaxNumber;
|
||||
entity.EmailAddress = request.EmailAddress;
|
||||
entity.Website = request.Website;
|
||||
entity.WhatsApp = request.WhatsApp;
|
||||
entity.LinkedIn = request.LinkedIn;
|
||||
entity.Facebook = request.Facebook;
|
||||
entity.Instagram = request.Instagram;
|
||||
entity.TwitterX = request.TwitterX;
|
||||
entity.TikTok = request.TikTok;
|
||||
entity.CustomerGroupId = request.CustomerGroupId;
|
||||
entity.CustomerCategoryId = request.CustomerCategoryId;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateCustomerResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerManager.Commands;
|
||||
|
||||
public class DeleteCustomerResult
|
||||
{
|
||||
public Customer? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerRequest : IRequest<DeleteCustomerResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteCustomerValidator : AbstractValidator<DeleteCustomerRequest>
|
||||
{
|
||||
public DeleteCustomerValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteCustomerHandler : IRequestHandler<DeleteCustomerRequest, DeleteCustomerResult>
|
||||
{
|
||||
private readonly ICommandRepository<Customer> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteCustomerHandler(
|
||||
ICommandRepository<Customer> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteCustomerResult> Handle(DeleteCustomerRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteCustomerResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CustomerManager.Commands;
|
||||
|
||||
public class UpdateCustomerResult
|
||||
{
|
||||
public Customer? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerRequest : IRequest<UpdateCustomerResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Street { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? State { get; set; }
|
||||
public string? ZipCode { get; set; }
|
||||
public string? Country { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? FaxNumber { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public string? Website { get; set; }
|
||||
public string? WhatsApp { get; set; }
|
||||
public string? LinkedIn { get; set; }
|
||||
public string? Facebook { get; set; }
|
||||
public string? Instagram { get; set; }
|
||||
public string? TwitterX { get; set; }
|
||||
public string? TikTok { get; set; }
|
||||
public string? CustomerGroupId { get; set; }
|
||||
public string? CustomerCategoryId { get; set; }
|
||||
public string? CreatedById { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateCustomerValidator : AbstractValidator<UpdateCustomerRequest>
|
||||
{
|
||||
public UpdateCustomerValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
RuleFor(x => x.Street).NotEmpty();
|
||||
RuleFor(x => x.City).NotEmpty();
|
||||
RuleFor(x => x.State).NotEmpty();
|
||||
RuleFor(x => x.ZipCode).NotEmpty();
|
||||
RuleFor(x => x.PhoneNumber).NotEmpty();
|
||||
RuleFor(x => x.EmailAddress).NotEmpty();
|
||||
RuleFor(x => x.CustomerGroupId).NotEmpty();
|
||||
RuleFor(x => x.CustomerCategoryId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateCustomerHandler : IRequestHandler<UpdateCustomerRequest, UpdateCustomerResult>
|
||||
{
|
||||
private readonly ICommandRepository<Customer> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateCustomerHandler(
|
||||
ICommandRepository<Customer> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateCustomerResult> Handle(UpdateCustomerRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
entity.Street = request.Street;
|
||||
entity.City = request.City;
|
||||
entity.State = request.State;
|
||||
entity.ZipCode = request.ZipCode;
|
||||
entity.Country = request.Country;
|
||||
entity.PhoneNumber = request.PhoneNumber;
|
||||
entity.FaxNumber = request.FaxNumber;
|
||||
entity.EmailAddress = request.EmailAddress;
|
||||
entity.Website = request.Website;
|
||||
entity.WhatsApp = request.WhatsApp;
|
||||
entity.LinkedIn = request.LinkedIn;
|
||||
entity.Facebook = request.Facebook;
|
||||
entity.Instagram = request.Instagram;
|
||||
entity.TwitterX = request.TwitterX;
|
||||
entity.TikTok = request.TikTok;
|
||||
entity.CustomerGroupId = request.CustomerGroupId;
|
||||
entity.CustomerCategoryId = request.CustomerCategoryId;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateCustomerResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.CustomerManager.Queries;
|
||||
|
||||
public record GetCustomerListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; set; }
|
||||
public string? Number { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Street { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? State { get; set; }
|
||||
public string? ZipCode { get; set; }
|
||||
public string? Country { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? FaxNumber { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public string? Website { get; set; }
|
||||
public string? WhatsApp { get; set; }
|
||||
public string? LinkedIn { get; set; }
|
||||
public string? Facebook { get; set; }
|
||||
public string? Instagram { get; set; }
|
||||
public string? TwitterX { get; set; }
|
||||
public string? TikTok { get; set; }
|
||||
public string? CustomerGroupId { get; set; }
|
||||
public string? CustomerGroupName { get; set; }
|
||||
public string? CustomerCategoryId { get; set; }
|
||||
public string? CustomerCategoryName { get; set; }
|
||||
public string? CreatedById { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerListProfile : Profile
|
||||
{
|
||||
public GetCustomerListProfile()
|
||||
{
|
||||
CreateMap<Customer, GetCustomerListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CustomerGroupName,
|
||||
opt => opt.MapFrom(src => src.CustomerGroup != null ? src.CustomerGroup.Name : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.CustomerCategoryName,
|
||||
opt => opt.MapFrom(src => src.CustomerCategory != null ? src.CustomerCategory.Name : string.Empty)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class GetCustomerListResult
|
||||
{
|
||||
public List<GetCustomerListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCustomerListRequest : IRequest<GetCustomerListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetCustomerListHandler : IRequestHandler<GetCustomerListRequest, GetCustomerListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCustomerListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerListResult> Handle(GetCustomerListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Customer
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.CustomerGroup)
|
||||
.Include(x => x.CustomerCategory)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetCustomerListDto>>(entities);
|
||||
|
||||
return new GetCustomerListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class AccummulationChartItem
|
||||
{
|
||||
public string X { get; init; } = string.Empty;
|
||||
public double Y { get; init; } = 0.0;
|
||||
public string Text { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class BarDataItem
|
||||
{
|
||||
public string X { get; set; } = string.Empty;
|
||||
public int Y { get; set; }
|
||||
public string TooltipMappingName { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class BarSeries
|
||||
{
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public string XName { get; set; } = string.Empty;
|
||||
public int Width { get; set; }
|
||||
public string YName { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public double ColumnSpacing { get; set; }
|
||||
public string TooltipMappingName { get; set; } = string.Empty;
|
||||
public List<BarDataItem> DataSource { get; set; } = new List<BarDataItem>();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class CRMItem
|
||||
{
|
||||
public double? CampaignTotalAmount { get; init; }
|
||||
public double? LeadTotalAmount { get; init; }
|
||||
public double? BudgetTotalAmount { get; init; }
|
||||
public double? ExpenseTotalAmount { get; init; }
|
||||
public double? ClosedTotalAmount { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class CardsItem
|
||||
{
|
||||
public double? SalesTotal { get; init; }
|
||||
public double? SalesReturnTotal { get; init; }
|
||||
public double? PurchaseTotal { get; init; }
|
||||
public double? PurchaseReturnTotal { get; init; }
|
||||
public double? DeliveryOrderTotal { get; init; }
|
||||
public double? GoodsReceiveTotal { get; init; }
|
||||
public double? TransferOutTotal { get; init; }
|
||||
public double? TransferInTotal { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetCRMDashboardDto
|
||||
{
|
||||
public CRMItem? CRMDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetCRMDashboardResult
|
||||
{
|
||||
public GetCRMDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCRMDashboardRequest : IRequest<GetCRMDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetCRMDashboardHandler : IRequestHandler<GetCRMDashboardRequest, GetCRMDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCRMDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCRMDashboardResult> Handle(GetCRMDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var campaignTotalAmount = await _context.Campaign
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.TargetRevenueAmount, cancellationToken);
|
||||
|
||||
var closedTotalAmount = await _context.Lead
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Where(x => x.ClosingStatus == ClosingStatus.ClosedWon)
|
||||
.SumAsync(x => (double?)x.AmountClosed, cancellationToken);
|
||||
|
||||
var leadTotalAmount = await _context.Lead
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.AmountTargeted, cancellationToken);
|
||||
|
||||
var budgetTotalAmount = await _context.Budget
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Amount, cancellationToken);
|
||||
|
||||
var expenseTotalAmount = await _context.Expense
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Amount, cancellationToken);
|
||||
|
||||
|
||||
var cardsDashboardData = new CRMItem
|
||||
{
|
||||
CampaignTotalAmount = campaignTotalAmount,
|
||||
LeadTotalAmount = leadTotalAmount,
|
||||
BudgetTotalAmount = budgetTotalAmount,
|
||||
ExpenseTotalAmount = expenseTotalAmount,
|
||||
ClosedTotalAmount = closedTotalAmount
|
||||
};
|
||||
|
||||
|
||||
|
||||
var result = new GetCRMDashboardResult
|
||||
{
|
||||
Data = new GetCRMDashboardDto
|
||||
{
|
||||
CRMDashboard = cardsDashboardData
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetCampaignByStatusResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignByStatusRequest : IRequest<GetCampaignByStatusResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetCampaignByStatusHandler : IRequestHandler<GetCampaignByStatusRequest, GetCampaignByStatusResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCampaignByStatusHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCampaignByStatusResult> Handle(GetCampaignByStatusRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedCampaigns = await _context.Set<Campaign>()
|
||||
.GroupBy(c => c.Status)
|
||||
.Select(g => new { Status = g.Key, Count = g.Count() })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var result = groupedCampaigns.Select(g => new AccummulationChartItem
|
||||
{
|
||||
X = g.Status.HasValue ? ((CampaignStatus)g.Status).ToFriendlyName() : string.Empty,
|
||||
Y = (double)g.Count,
|
||||
Text = g.Status.HasValue
|
||||
? $"{((CampaignStatus)g.Status).ToFriendlyName()} ({g.Count})"
|
||||
: $"Unknown ({g.Count})"
|
||||
}).ToList();
|
||||
|
||||
return new GetCampaignByStatusResult { Data = result };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetCardsDashboardDto
|
||||
{
|
||||
public CardsItem? CardsDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetCardsDashboardResult
|
||||
{
|
||||
public GetCardsDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCardsDashboardRequest : IRequest<GetCardsDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetCardsDashboardHandler : IRequestHandler<GetCardsDashboardRequest, GetCardsDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCardsDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCardsDashboardResult> Handle(GetCardsDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var salesTotal = await _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Quantity, cancellationToken);
|
||||
|
||||
var purchaseTotal = await _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Quantity, cancellationToken);
|
||||
|
||||
var cardsDashboardData = new CardsItem
|
||||
{
|
||||
SalesTotal = salesTotal,
|
||||
PurchaseTotal = purchaseTotal,
|
||||
};
|
||||
|
||||
|
||||
|
||||
var result = new GetCardsDashboardResult
|
||||
{
|
||||
Data = new GetCardsDashboardDto
|
||||
{
|
||||
CardsDashboard = cardsDashboardData
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetLeadActivityByTypeResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityByTypeRequest : IRequest<GetLeadActivityByTypeResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetLeadActivityByTypeHandler : IRequestHandler<GetLeadActivityByTypeRequest, GetLeadActivityByTypeResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadActivityByTypeHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadActivityByTypeResult> Handle(GetLeadActivityByTypeRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedActivities = await _context.Set<LeadActivity>()
|
||||
.GroupBy(a => a.Type)
|
||||
.Select(g => new { Type = g.Key, Count = g.Count() })
|
||||
.OrderBy(g => g.Count)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var result = groupedActivities.Select(g => new AccummulationChartItem
|
||||
{
|
||||
X = g.Type.HasValue ? ((LeadActivityType)g.Type).ToFriendlyName() : string.Empty,
|
||||
Y = (double)g.Count,
|
||||
Text = g.Type.HasValue
|
||||
? $"{((LeadActivityType)g.Type).ToFriendlyName()} ({g.Count})"
|
||||
: $"Unknown ({g.Count})"
|
||||
}).ToList();
|
||||
|
||||
return new GetLeadActivityByTypeResult { Data = result };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetLeadPipelineFunnelResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadPipelineFunnelRequest : IRequest<GetLeadPipelineFunnelResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetLeadPipelineFunnelHandler : IRequestHandler<GetLeadPipelineFunnelRequest, GetLeadPipelineFunnelResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadPipelineFunnelHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadPipelineFunnelResult> Handle(GetLeadPipelineFunnelRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedLeads = await _context.Set<Lead>()
|
||||
.GroupBy(l => l.PipelineStage)
|
||||
.Select(g => new { Stage = g.Key, Count = g.Count() })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var result = groupedLeads.Select(g => new
|
||||
{
|
||||
Item = new AccummulationChartItem
|
||||
{
|
||||
X = g.Stage.HasValue ? ((PipelineStage)g.Stage).ToFriendlyName() : string.Empty,
|
||||
Y = g.Count,
|
||||
Text = g.Stage.HasValue
|
||||
? $"{((PipelineStage)g.Stage).ToFriendlyName()} ({g.Count})"
|
||||
: $"Unknown ({g.Count})"
|
||||
},
|
||||
OrderKey = g.Stage.HasValue ? ((PipelineStage)g.Stage).ToFriendlyName() : string.Empty
|
||||
})
|
||||
.OrderByDescending(i => i.OrderKey)
|
||||
.Select(i => i.Item)
|
||||
.ToList();
|
||||
|
||||
return new GetLeadPipelineFunnelResult { Data = result };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetPurchaseDashboardDto
|
||||
{
|
||||
public List<PurchaseOrderItem>? PurchaseOrderDashboard { get; init; }
|
||||
public List<BarSeries>? PurchaseByVendorGroupDashboard { get; init; }
|
||||
public List<BarSeries>? PurchaseByVendorCategoryDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseDashboardResult
|
||||
{
|
||||
public GetPurchaseDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseDashboardRequest : IRequest<GetPurchaseDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetPurchaseDashboardHandler : IRequestHandler<GetPurchaseDashboardRequest, GetPurchaseDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetPurchaseDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetPurchaseDashboardResult> Handle(GetPurchaseDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var purchaseOrderItemData = await _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.PurchaseOrder!.OrderStatus == PurchaseOrderStatus.Confirmed)
|
||||
.OrderByDescending(x => x.PurchaseOrder!.OrderDate)
|
||||
.Take(30)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var purchaseByVendorGroupData = _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.ThenInclude(x => x!.Vendor)
|
||||
.ThenInclude(x => x!.VendorGroup)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.PurchaseOrder!.OrderStatus,
|
||||
VendorGroupName = x.PurchaseOrder!.Vendor!.VendorGroup!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.VendorGroupName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
VendorGroupName = g.Key.VendorGroupName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var purchaseByVendorCategoryDate = _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.ThenInclude(x => x!.Vendor)
|
||||
.ThenInclude(x => x!.VendorCategory)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.PurchaseOrder!.OrderStatus,
|
||||
VendorCategoryName = x.PurchaseOrder!.Vendor!.VendorCategory!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.VendorCategoryName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
VendorCategoryName = g.Key.VendorCategoryName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
var result = new GetPurchaseDashboardResult
|
||||
{
|
||||
Data = new GetPurchaseDashboardDto
|
||||
{
|
||||
PurchaseOrderDashboard = purchaseOrderItemData,
|
||||
PurchaseByVendorGroupDashboard =
|
||||
Enum.GetValues(typeof(PurchaseOrderStatus))
|
||||
.Cast<PurchaseOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Bar",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(PurchaseOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = purchaseByVendorGroupData
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.VendorGroupName ?? "",
|
||||
TooltipMappingName = x.VendorGroupName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList(),
|
||||
PurchaseByVendorCategoryDashboard =
|
||||
Enum.GetValues(typeof(PurchaseOrderStatus))
|
||||
.Cast<PurchaseOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Column",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(PurchaseOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = purchaseByVendorCategoryDate
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.VendorCategoryName ?? "",
|
||||
TooltipMappingName = x.VendorCategoryName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList(),
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetSalesDashboardDto
|
||||
{
|
||||
public List<SalesOrderItem>? SalesOrderDashboard { get; init; }
|
||||
public List<BarSeries>? SalesByCustomerGroupDashboard { get; init; }
|
||||
public List<BarSeries>? SalesByCustomerCategoryDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetSalesDashboardResult
|
||||
{
|
||||
public GetSalesDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetSalesDashboardRequest : IRequest<GetSalesDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetSalesDashboardHandler : IRequestHandler<GetSalesDashboardRequest, GetSalesDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetSalesDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetSalesDashboardResult> Handle(GetSalesDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var salesOrderItemData = await _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.SalesOrder)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.SalesOrder!.OrderStatus == SalesOrderStatus.Confirmed)
|
||||
.OrderByDescending(x => x.SalesOrder!.OrderDate)
|
||||
.Take(30)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var salesByCustomerGroupData = _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.SalesOrder)
|
||||
.ThenInclude(x => x!.Customer)
|
||||
.ThenInclude(x => x!.CustomerGroup)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.SalesOrder!.OrderStatus,
|
||||
CustomerGroupName = x.SalesOrder!.Customer!.CustomerGroup!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.CustomerGroupName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
CustomerGroupName = g.Key.CustomerGroupName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var salesByCustomerCategoryData = _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.SalesOrder)
|
||||
.ThenInclude(x => x!.Customer)
|
||||
.ThenInclude(x => x!.CustomerCategory)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.SalesOrder!.OrderStatus,
|
||||
CustomerCategoryName = x.SalesOrder!.Customer!.CustomerCategory!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.CustomerCategoryName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
CustomerCategoryName = g.Key.CustomerCategoryName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
var result = new GetSalesDashboardResult
|
||||
{
|
||||
Data = new GetSalesDashboardDto
|
||||
{
|
||||
SalesOrderDashboard = salesOrderItemData,
|
||||
SalesByCustomerGroupDashboard =
|
||||
Enum.GetValues(typeof(SalesOrderStatus))
|
||||
.Cast<SalesOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Column",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(SalesOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = salesByCustomerGroupData
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.CustomerGroupName ?? "",
|
||||
TooltipMappingName = x.CustomerGroupName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList(),
|
||||
SalesByCustomerCategoryDashboard =
|
||||
Enum.GetValues(typeof(SalesOrderStatus))
|
||||
.Cast<SalesOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Bar",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(SalesOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = salesByCustomerCategoryData
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.CustomerCategoryName ?? "",
|
||||
TooltipMappingName = x.CustomerCategoryName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList()
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetSalesTeamLeadClosingResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetSalesTeamLeadClosingRequest : IRequest<GetSalesTeamLeadClosingResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetSalesTeamLeadClosingHandler : IRequestHandler<GetSalesTeamLeadClosingRequest, GetSalesTeamLeadClosingResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetSalesTeamLeadClosingHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetSalesTeamLeadClosingResult> Handle(GetSalesTeamLeadClosingRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedLeads = await _context.Set<Lead>()
|
||||
.Include(l => l.SalesTeam)
|
||||
.Where(l => l.SalesTeam != null && l.AmountClosed.HasValue)
|
||||
.GroupBy(l => l.SalesTeam!.Name)
|
||||
.Select(g => new
|
||||
{
|
||||
Name = g.Key,
|
||||
TotalClosed = g.Sum(l => l.AmountClosed ?? 0)
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var totalAmountClosed = groupedLeads.Sum(g => g.TotalClosed);
|
||||
|
||||
var result = groupedLeads.Select(g =>
|
||||
{
|
||||
double percentageValue = totalAmountClosed > 0
|
||||
? (double)g.TotalClosed / totalAmountClosed * 100
|
||||
: 0;
|
||||
var percentage = percentageValue.ToString("F2");
|
||||
|
||||
return new AccummulationChartItem
|
||||
{
|
||||
X = g.Name ?? "Unknown",
|
||||
Y = Math.Round(percentageValue, 2),
|
||||
Text = $"{g.Name ?? "Unknown"} ({Math.Round(percentageValue, 2)}%)"
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
return new GetSalesTeamLeadClosingResult { Data = result };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ExpenseManager.Commands;
|
||||
|
||||
public class CreateExpenseResult
|
||||
{
|
||||
public Expense? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateExpenseRequest : IRequest<CreateExpenseResult>
|
||||
{
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? ExpenseDate { get; init; }
|
||||
public string? Status { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateExpenseValidator : AbstractValidator<CreateExpenseRequest>
|
||||
{
|
||||
public CreateExpenseValidator()
|
||||
{
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.ExpenseDate).NotNull();
|
||||
RuleFor(x => x.Amount).NotNull();
|
||||
RuleFor(x => x.CampaignId).NotEmpty();
|
||||
RuleFor(x => x.Status).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateExpenseHandler : IRequestHandler<CreateExpenseRequest, CreateExpenseResult>
|
||||
{
|
||||
private readonly ICommandRepository<Expense> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateExpenseHandler(
|
||||
ICommandRepository<Expense> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateExpenseResult> Handle(CreateExpenseRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new Expense
|
||||
{
|
||||
CreatedById = request.CreatedById,
|
||||
Number = _numberSequenceService.GenerateNumber(nameof(Expense), "", "EXP"),
|
||||
Title = request.Title,
|
||||
Description = request.Description,
|
||||
ExpenseDate = request.ExpenseDate,
|
||||
Status = (ExpenseStatus)int.Parse(request.Status!),
|
||||
Amount = request.Amount,
|
||||
CampaignId = request.CampaignId
|
||||
};
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateExpenseResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ExpenseManager.Commands;
|
||||
|
||||
public class DeleteExpenseResult
|
||||
{
|
||||
public Expense? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteExpenseRequest : IRequest<DeleteExpenseResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteExpenseValidator : AbstractValidator<DeleteExpenseRequest>
|
||||
{
|
||||
public DeleteExpenseValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteExpenseHandler : IRequestHandler<DeleteExpenseRequest, DeleteExpenseResult>
|
||||
{
|
||||
private readonly ICommandRepository<Expense> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteExpenseHandler(
|
||||
ICommandRepository<Expense> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteExpenseResult> Handle(DeleteExpenseRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteExpenseResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ExpenseManager.Commands;
|
||||
|
||||
public class UpdateExpenseResult
|
||||
{
|
||||
public Expense? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateExpenseRequest : IRequest<UpdateExpenseResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? ExpenseDate { get; init; }
|
||||
public string? Status { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateExpenseValidator : AbstractValidator<UpdateExpenseRequest>
|
||||
{
|
||||
public UpdateExpenseValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.ExpenseDate).NotNull();
|
||||
RuleFor(x => x.Amount).NotNull();
|
||||
RuleFor(x => x.CampaignId).NotEmpty();
|
||||
RuleFor(x => x.Status).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateExpenseHandler : IRequestHandler<UpdateExpenseRequest, UpdateExpenseResult>
|
||||
{
|
||||
private readonly ICommandRepository<Expense> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateExpenseHandler(
|
||||
ICommandRepository<Expense> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateExpenseResult> Handle(UpdateExpenseRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
entity.Title = request.Title;
|
||||
entity.Description = request.Description;
|
||||
entity.ExpenseDate = request.ExpenseDate;
|
||||
entity.Status = (ExpenseStatus)int.Parse(request.Status!);
|
||||
entity.Amount = request.Amount;
|
||||
entity.CampaignId = request.CampaignId;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateExpenseResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.ExpenseManager.Queries;
|
||||
|
||||
public record GetExpenseByCampaignIdListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? ExpenseDate { get; init; }
|
||||
public ExpenseStatus? Status { get; init; }
|
||||
public string? StatusName { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? CampaignName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseByCampaignIdListProfile : Profile
|
||||
{
|
||||
public GetExpenseByCampaignIdListProfile()
|
||||
{
|
||||
CreateMap<Expense, GetExpenseByCampaignIdListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CampaignName,
|
||||
opt => opt.MapFrom(src => src.Campaign != null ? src.Campaign.Title : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.StatusName,
|
||||
opt => opt.MapFrom(src => src.Status.HasValue ? src.Status.Value.ToFriendlyName() : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetExpenseByCampaignIdListResult
|
||||
{
|
||||
public List<GetExpenseByCampaignIdListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseByCampaignIdListRequest : IRequest<GetExpenseByCampaignIdListResult>
|
||||
{
|
||||
public string? CampaignId { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseByCampaignIdListHandler : IRequestHandler<GetExpenseByCampaignIdListRequest, GetExpenseByCampaignIdListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetExpenseByCampaignIdListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetExpenseByCampaignIdListResult> Handle(GetExpenseByCampaignIdListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Expense
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.Campaign)
|
||||
.Where(x => x.CampaignId == request.CampaignId)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetExpenseByCampaignIdListDto>>(entities);
|
||||
|
||||
return new GetExpenseByCampaignIdListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.ExpenseManager.Queries;
|
||||
|
||||
public record GetExpenseListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? ExpenseDate { get; init; }
|
||||
public ExpenseStatus? Status { get; init; }
|
||||
public string? StatusName { get; init; }
|
||||
public double? Amount { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? CampaignName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseListProfile : Profile
|
||||
{
|
||||
public GetExpenseListProfile()
|
||||
{
|
||||
CreateMap<Expense, GetExpenseListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CampaignName,
|
||||
opt => opt.MapFrom(src => src.Campaign != null ? src.Campaign.Title : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.StatusName,
|
||||
opt => opt.MapFrom(src => src.Status.HasValue ? src.Status.Value.ToFriendlyName() : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetExpenseListResult
|
||||
{
|
||||
public List<GetExpenseListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseListRequest : IRequest<GetExpenseListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
public class GetExpenseListHandler : IRequestHandler<GetExpenseListRequest, GetExpenseListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetExpenseListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetExpenseListResult> Handle(GetExpenseListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Expense
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.Campaign)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetExpenseListDto>>(entities);
|
||||
|
||||
return new GetExpenseListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.ExpenseManager.Queries;
|
||||
|
||||
public class GetExpenseSingleProfile : Profile
|
||||
{
|
||||
public GetExpenseSingleProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetExpenseSingleResult
|
||||
{
|
||||
public Expense? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseSingleRequest : IRequest<GetExpenseSingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseSingleValidator : AbstractValidator<GetExpenseSingleRequest>
|
||||
{
|
||||
public GetExpenseSingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetExpenseSingleHandler : IRequestHandler<GetExpenseSingleRequest, GetExpenseSingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetExpenseSingleHandler(
|
||||
IQueryContext context
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetExpenseSingleResult> Handle(GetExpenseSingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Expense
|
||||
.AsNoTracking()
|
||||
.Include(x => x.Campaign)
|
||||
.Where(x => x.Id == request.Id)
|
||||
.AsQueryable();
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return new GetExpenseSingleResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ExpenseManager.Queries;
|
||||
|
||||
public record GetExpenseStatusListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseStatusListProfile : Profile
|
||||
{
|
||||
public GetExpenseStatusListProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetExpenseStatusListResult
|
||||
{
|
||||
public List<GetExpenseStatusListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetExpenseStatusListRequest : IRequest<GetExpenseStatusListResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetExpenseStatusListHandler : IRequestHandler<GetExpenseStatusListRequest, GetExpenseStatusListResult>
|
||||
{
|
||||
public GetExpenseStatusListHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<GetExpenseStatusListResult> Handle(GetExpenseStatusListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var statuses = Enum.GetValues(typeof(ExpenseStatus))
|
||||
.Cast<ExpenseStatus>()
|
||||
.Select(status => new GetExpenseStatusListDto
|
||||
{
|
||||
Id = ((int)status).ToString(),
|
||||
Name = status.ToFriendlyName()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new GetExpenseStatusListResult
|
||||
{
|
||||
Data = statuses
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using Application.Common.Services.FileDocumentManager;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.FileDocumentManager.Commands;
|
||||
|
||||
public class CreateDocumentResult
|
||||
{
|
||||
public string? DocumentName { get; init; }
|
||||
}
|
||||
|
||||
public class CreateDocumentRequest : IRequest<CreateDocumentResult>
|
||||
{
|
||||
public string? OriginalFileName { get; init; }
|
||||
public string? Extension { get; init; }
|
||||
public byte[]? Data { get; init; }
|
||||
public long? Size { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
|
||||
public class CreateDocumentValidator : AbstractValidator<CreateDocumentRequest>
|
||||
{
|
||||
public CreateDocumentValidator()
|
||||
{
|
||||
RuleFor(x => x.OriginalFileName)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(x => x.Extension)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(x => x.Data)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(x => x.Size)
|
||||
.NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateDocumentHandler : IRequestHandler<CreateDocumentRequest, CreateDocumentResult>
|
||||
{
|
||||
private readonly IFileDocumentService _uploadDocument;
|
||||
|
||||
public CreateDocumentHandler(IFileDocumentService uploadDocument)
|
||||
{
|
||||
_uploadDocument = uploadDocument;
|
||||
}
|
||||
|
||||
public async Task<CreateDocumentResult> Handle(CreateDocumentRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await _uploadDocument.UploadAsync(
|
||||
request.OriginalFileName,
|
||||
request.Extension,
|
||||
request.Data,
|
||||
request.Size,
|
||||
request.Description,
|
||||
request.CreatedById,
|
||||
cancellationToken);
|
||||
|
||||
return new CreateDocumentResult { DocumentName = result };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using Application.Common.Services.FileDocumentManager;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.FileDocumentManager.Queries;
|
||||
|
||||
|
||||
public class GetDocumentResult
|
||||
{
|
||||
public byte[]? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetDocumentRequest : IRequest<GetDocumentResult>
|
||||
{
|
||||
public string? DocumentName { get; init; }
|
||||
}
|
||||
|
||||
public class GetDocumentValidator : AbstractValidator<GetDocumentRequest>
|
||||
{
|
||||
public GetDocumentValidator()
|
||||
{
|
||||
RuleFor(x => x.DocumentName)
|
||||
.NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetDocumentHandler : IRequestHandler<GetDocumentRequest, GetDocumentResult>
|
||||
{
|
||||
private readonly IFileDocumentService _documentService;
|
||||
|
||||
public GetDocumentHandler(IFileDocumentService documentService)
|
||||
{
|
||||
_documentService = documentService;
|
||||
}
|
||||
|
||||
public async Task<GetDocumentResult> Handle(GetDocumentRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await _documentService.GetFileAsync(request.DocumentName ?? "", cancellationToken);
|
||||
|
||||
return new GetDocumentResult { Data = result };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using Application.Common.Services.FileImageManager;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.FileImageManager.Commands;
|
||||
|
||||
public class CreateImageResult
|
||||
{
|
||||
public string? ImageName { get; init; }
|
||||
}
|
||||
|
||||
public class CreateImageRequest : IRequest<CreateImageResult>
|
||||
{
|
||||
public string? OriginalFileName { get; init; }
|
||||
public string? Extension { get; init; }
|
||||
public byte[]? Data { get; init; }
|
||||
public long? Size { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
|
||||
public class CreateImageValidator : AbstractValidator<CreateImageRequest>
|
||||
{
|
||||
public CreateImageValidator()
|
||||
{
|
||||
RuleFor(x => x.OriginalFileName)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(x => x.Extension)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(x => x.Data)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(x => x.Size)
|
||||
.NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateImageHandler : IRequestHandler<CreateImageRequest, CreateImageResult>
|
||||
{
|
||||
private readonly IFileImageService _uploadImage;
|
||||
|
||||
public CreateImageHandler(IFileImageService uploadImage)
|
||||
{
|
||||
_uploadImage = uploadImage;
|
||||
}
|
||||
|
||||
public async Task<CreateImageResult> Handle(CreateImageRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await _uploadImage.UploadAsync(
|
||||
request.OriginalFileName,
|
||||
request.Extension,
|
||||
request.Data,
|
||||
request.Size,
|
||||
request.Description,
|
||||
request.CreatedById,
|
||||
cancellationToken);
|
||||
|
||||
return new CreateImageResult { ImageName = result };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using Application.Common.Services.FileImageManager;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.FileImageManager.Queries;
|
||||
|
||||
|
||||
public class GetImageResult
|
||||
{
|
||||
public byte[]? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetImageRequest : IRequest<GetImageResult>
|
||||
{
|
||||
public string? ImageName { get; init; }
|
||||
}
|
||||
|
||||
public class GetImageValidator : AbstractValidator<GetImageRequest>
|
||||
{
|
||||
public GetImageValidator()
|
||||
{
|
||||
RuleFor(x => x.ImageName)
|
||||
.NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetImageHandler : IRequestHandler<GetImageRequest, GetImageResult>
|
||||
{
|
||||
private readonly IFileImageService _imageService;
|
||||
|
||||
public GetImageHandler(IFileImageService imageService)
|
||||
{
|
||||
_imageService = imageService;
|
||||
}
|
||||
|
||||
public async Task<GetImageResult> Handle(GetImageRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await _imageService.GetFileAsync(request.ImageName ?? "", cancellationToken);
|
||||
|
||||
return new GetImageResult { Data = result };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadActivityManager.Commands;
|
||||
|
||||
public class CreateLeadActivityResult
|
||||
{
|
||||
public LeadActivity? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateLeadActivityRequest : IRequest<CreateLeadActivityResult>
|
||||
{
|
||||
public string? LeadId { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? FromDate { get; init; }
|
||||
public DateTime? ToDate { get; init; }
|
||||
public string? Type { get; init; }
|
||||
public string? AttachmentName { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateLeadActivityValidator : AbstractValidator<CreateLeadActivityRequest>
|
||||
{
|
||||
public CreateLeadActivityValidator()
|
||||
{
|
||||
RuleFor(x => x.LeadId).NotEmpty();
|
||||
RuleFor(x => x.Summary).NotEmpty();
|
||||
RuleFor(x => x.FromDate).NotNull();
|
||||
RuleFor(x => x.ToDate).NotNull();
|
||||
RuleFor(x => x.Type).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateLeadActivityHandler : IRequestHandler<CreateLeadActivityRequest, CreateLeadActivityResult>
|
||||
{
|
||||
private readonly ICommandRepository<LeadActivity> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateLeadActivityHandler(
|
||||
ICommandRepository<LeadActivity> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateLeadActivityResult> Handle(CreateLeadActivityRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new LeadActivity
|
||||
{
|
||||
CreatedById = request.CreatedById,
|
||||
LeadId = request.LeadId,
|
||||
Number = _numberSequenceService.GenerateNumber(nameof(LeadActivity), "", "LA"),
|
||||
Summary = request.Summary,
|
||||
Description = request.Description,
|
||||
FromDate = request.FromDate,
|
||||
ToDate = request.ToDate,
|
||||
Type = (LeadActivityType)int.Parse(request.Type!),
|
||||
AttachmentName = request.AttachmentName
|
||||
};
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateLeadActivityResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadActivityManager.Commands;
|
||||
|
||||
public class DeleteLeadActivityResult
|
||||
{
|
||||
public LeadActivity? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteLeadActivityRequest : IRequest<DeleteLeadActivityResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteLeadActivityValidator : AbstractValidator<DeleteLeadActivityRequest>
|
||||
{
|
||||
public DeleteLeadActivityValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteLeadActivityHandler : IRequestHandler<DeleteLeadActivityRequest, DeleteLeadActivityResult>
|
||||
{
|
||||
private readonly ICommandRepository<LeadActivity> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteLeadActivityHandler(
|
||||
ICommandRepository<LeadActivity> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteLeadActivityResult> Handle(DeleteLeadActivityRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteLeadActivityResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadActivityManager.Commands;
|
||||
|
||||
public class UpdateLeadActivityResult
|
||||
{
|
||||
public LeadActivity? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateLeadActivityRequest : IRequest<UpdateLeadActivityResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? LeadId { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? FromDate { get; init; }
|
||||
public DateTime? ToDate { get; init; }
|
||||
public string? Type { get; init; }
|
||||
public string? AttachmentName { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateLeadActivityValidator : AbstractValidator<UpdateLeadActivityRequest>
|
||||
{
|
||||
public UpdateLeadActivityValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Summary).NotEmpty();
|
||||
RuleFor(x => x.FromDate).NotNull();
|
||||
RuleFor(x => x.ToDate).NotNull();
|
||||
RuleFor(x => x.Type).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateLeadActivityHandler : IRequestHandler<UpdateLeadActivityRequest, UpdateLeadActivityResult>
|
||||
{
|
||||
private readonly ICommandRepository<LeadActivity> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateLeadActivityHandler(
|
||||
ICommandRepository<LeadActivity> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateLeadActivityResult> Handle(UpdateLeadActivityRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
entity.LeadId = request.LeadId;
|
||||
entity.Summary = request.Summary;
|
||||
entity.Description = request.Description;
|
||||
entity.FromDate = request.FromDate;
|
||||
entity.ToDate = request.ToDate;
|
||||
entity.Type = (LeadActivityType)int.Parse(request.Type!);
|
||||
entity.AttachmentName = request.AttachmentName;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateLeadActivityResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadActivityManager.Queries;
|
||||
|
||||
public record GetLeadActivityByLeadIdListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? FromDate { get; init; }
|
||||
public DateTime? ToDate { get; init; }
|
||||
public LeadActivityType? Type { get; init; }
|
||||
public string? TypeName { get; init; }
|
||||
public string? AttachmentName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityByLeadIdListProfile : Profile
|
||||
{
|
||||
public GetLeadActivityByLeadIdListProfile()
|
||||
{
|
||||
CreateMap<LeadActivity, GetLeadActivityByLeadIdListDto>()
|
||||
.ForMember(
|
||||
dest => dest.TypeName,
|
||||
opt => opt.MapFrom(src => src.Type.HasValue ? src.Type.Value.ToFriendlyName() : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadActivityByLeadIdListResult
|
||||
{
|
||||
public List<GetLeadActivityByLeadIdListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityByLeadIdListRequest : IRequest<GetLeadActivityByLeadIdListResult>
|
||||
{
|
||||
public string? LeadId { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityByLeadIdListHandler : IRequestHandler<GetLeadActivityByLeadIdListRequest, GetLeadActivityByLeadIdListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadActivityByLeadIdListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadActivityByLeadIdListResult> Handle(GetLeadActivityByLeadIdListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.LeadActivity
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Where(x => x.LeadId == request.LeadId)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetLeadActivityByLeadIdListDto>>(entities);
|
||||
|
||||
return new GetLeadActivityByLeadIdListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadActivityManager.Queries;
|
||||
|
||||
public record GetLeadActivityListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? FromDate { get; init; }
|
||||
public DateTime? ToDate { get; init; }
|
||||
public LeadActivityType? Type { get; init; }
|
||||
public string? TypeName { get; init; }
|
||||
public string? AttachmentName { get; init; }
|
||||
public string? LeadId { get; init; }
|
||||
public string? LeadTitle { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityListProfile : Profile
|
||||
{
|
||||
public GetLeadActivityListProfile()
|
||||
{
|
||||
CreateMap<LeadActivity, GetLeadActivityListDto>()
|
||||
.ForMember(
|
||||
dest => dest.TypeName,
|
||||
opt => opt.MapFrom(src => src.Type.HasValue ? src.Type.Value.ToFriendlyName() : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.LeadTitle,
|
||||
opt => opt.MapFrom(src => src.Lead != null ? src.Lead.Title : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadActivityListResult
|
||||
{
|
||||
public List<GetLeadActivityListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityListRequest : IRequest<GetLeadActivityListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
public class GetLeadActivityListHandler : IRequestHandler<GetLeadActivityListRequest, GetLeadActivityListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadActivityListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadActivityListResult> Handle(GetLeadActivityListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.LeadActivity
|
||||
.Include(x => x.Lead)
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetLeadActivityListDto>>(entities);
|
||||
|
||||
return new GetLeadActivityListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadActivityManager.Queries;
|
||||
|
||||
public class GetLeadActivitySingleProfile : Profile
|
||||
{
|
||||
public GetLeadActivitySingleProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadActivitySingleResult
|
||||
{
|
||||
public LeadActivity? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivitySingleRequest : IRequest<GetLeadActivitySingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivitySingleValidator : AbstractValidator<GetLeadActivitySingleRequest>
|
||||
{
|
||||
public GetLeadActivitySingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadActivitySingleHandler : IRequestHandler<GetLeadActivitySingleRequest, GetLeadActivitySingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadActivitySingleHandler(
|
||||
IQueryContext context
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadActivitySingleResult> Handle(GetLeadActivitySingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.LeadActivity
|
||||
.AsNoTracking()
|
||||
.Where(x => x.Id == request.Id)
|
||||
.AsQueryable();
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return new GetLeadActivitySingleResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.DeliveryOrderManager.Queries;
|
||||
|
||||
public record GetLeadActivityTypeListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityTypeListProfile : Profile
|
||||
{
|
||||
public GetLeadActivityTypeListProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadActivityTypeListResult
|
||||
{
|
||||
public List<GetLeadActivityTypeListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityTypeListRequest : IRequest<GetLeadActivityTypeListResult>
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public class GetLeadActivityTypeListHandler : IRequestHandler<GetLeadActivityTypeListRequest, GetLeadActivityTypeListResult>
|
||||
{
|
||||
|
||||
public GetLeadActivityTypeListHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<GetLeadActivityTypeListResult> Handle(GetLeadActivityTypeListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var statuses = Enum.GetValues(typeof(LeadActivityType))
|
||||
.Cast<LeadActivityType>()
|
||||
.Select(status => new GetLeadActivityTypeListDto
|
||||
{
|
||||
Id = ((int)status).ToString(),
|
||||
Name = status.ToFriendlyName()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new GetLeadActivityTypeListResult
|
||||
{
|
||||
Data = statuses
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadContactManager.Commands;
|
||||
|
||||
public class CreateLeadContactResult
|
||||
{
|
||||
public LeadContact? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateLeadContactRequest : IRequest<CreateLeadContactResult>
|
||||
{
|
||||
public string? LeadId { get; init; }
|
||||
public string? FullName { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? AddressStreet { get; init; }
|
||||
public string? AddressCity { get; init; }
|
||||
public string? AddressState { get; init; }
|
||||
public string? MobileNumber { get; init; }
|
||||
public string? Email { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateLeadContactValidator : AbstractValidator<CreateLeadContactRequest>
|
||||
{
|
||||
public CreateLeadContactValidator()
|
||||
{
|
||||
RuleFor(x => x.LeadId).NotEmpty();
|
||||
RuleFor(x => x.FullName).NotEmpty();
|
||||
RuleFor(x => x.AddressStreet).NotEmpty();
|
||||
RuleFor(x => x.AddressCity).NotEmpty();
|
||||
RuleFor(x => x.AddressState).NotEmpty();
|
||||
RuleFor(x => x.MobileNumber).NotEmpty();
|
||||
RuleFor(x => x.Email).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateLeadContactHandler : IRequestHandler<CreateLeadContactRequest, CreateLeadContactResult>
|
||||
{
|
||||
private readonly ICommandRepository<LeadContact> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateLeadContactHandler(
|
||||
ICommandRepository<LeadContact> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateLeadContactResult> Handle(CreateLeadContactRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new LeadContact
|
||||
{
|
||||
CreatedById = request.CreatedById,
|
||||
LeadId = request.LeadId,
|
||||
Number = _numberSequenceService.GenerateNumber(nameof(LeadContact), "", "LC"),
|
||||
FullName = request.FullName,
|
||||
Description = request.Description,
|
||||
AddressStreet = request.AddressStreet,
|
||||
AddressCity = request.AddressCity,
|
||||
AddressState = request.AddressState,
|
||||
MobileNumber = request.MobileNumber,
|
||||
Email = request.Email
|
||||
};
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateLeadContactResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadContactManager.Commands;
|
||||
|
||||
public class DeleteLeadContactResult
|
||||
{
|
||||
public LeadContact? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteLeadContactRequest : IRequest<DeleteLeadContactResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteLeadContactValidator : AbstractValidator<DeleteLeadContactRequest>
|
||||
{
|
||||
public DeleteLeadContactValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteLeadContactHandler : IRequestHandler<DeleteLeadContactRequest, DeleteLeadContactResult>
|
||||
{
|
||||
private readonly ICommandRepository<LeadContact> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteLeadContactHandler(
|
||||
ICommandRepository<LeadContact> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteLeadContactResult> Handle(DeleteLeadContactRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteLeadContactResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadContactManager.Commands;
|
||||
|
||||
public class UpdateLeadContactResult
|
||||
{
|
||||
public LeadContact? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateLeadContactRequest : IRequest<UpdateLeadContactResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? LeadId { get; init; }
|
||||
public string? FullName { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? AddressStreet { get; init; }
|
||||
public string? AddressCity { get; init; }
|
||||
public string? AddressState { get; init; }
|
||||
public string? AddressZipCode { get; init; }
|
||||
public string? AddressCountry { get; init; }
|
||||
public string? PhoneNumber { get; init; }
|
||||
public string? FaxNumber { get; init; }
|
||||
public string? MobileNumber { get; init; }
|
||||
public string? Email { get; init; }
|
||||
public string? Website { get; init; }
|
||||
public string? WhatsApp { get; init; }
|
||||
public string? LinkedIn { get; init; }
|
||||
public string? Facebook { get; init; }
|
||||
public string? Twitter { get; init; }
|
||||
public string? Instagram { get; init; }
|
||||
public string? AvatarName { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateLeadContactValidator : AbstractValidator<UpdateLeadContactRequest>
|
||||
{
|
||||
public UpdateLeadContactValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.FullName).NotEmpty();
|
||||
RuleFor(x => x.AddressStreet).NotEmpty();
|
||||
RuleFor(x => x.AddressCity).NotEmpty();
|
||||
RuleFor(x => x.AddressState).NotEmpty();
|
||||
RuleFor(x => x.MobileNumber).NotEmpty();
|
||||
RuleFor(x => x.Email).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateLeadContactHandler : IRequestHandler<UpdateLeadContactRequest, UpdateLeadContactResult>
|
||||
{
|
||||
private readonly ICommandRepository<LeadContact> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateLeadContactHandler(
|
||||
ICommandRepository<LeadContact> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateLeadContactResult> Handle(UpdateLeadContactRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
entity.LeadId = request.LeadId;
|
||||
entity.FullName = request.FullName;
|
||||
entity.Description = request.Description;
|
||||
entity.AddressStreet = request.AddressStreet;
|
||||
entity.AddressCity = request.AddressCity;
|
||||
entity.AddressState = request.AddressState;
|
||||
entity.AddressZipCode = request.AddressZipCode;
|
||||
entity.AddressCountry = request.AddressCountry;
|
||||
entity.PhoneNumber = request.PhoneNumber;
|
||||
entity.FaxNumber = request.FaxNumber;
|
||||
entity.MobileNumber = request.MobileNumber;
|
||||
entity.Email = request.Email;
|
||||
entity.Website = request.Website;
|
||||
entity.WhatsApp = request.WhatsApp;
|
||||
entity.LinkedIn = request.LinkedIn;
|
||||
entity.Facebook = request.Facebook;
|
||||
entity.Twitter = request.Twitter;
|
||||
entity.Instagram = request.Instagram;
|
||||
entity.AvatarName = request.AvatarName;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateLeadContactResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadContactManager.Queries;
|
||||
|
||||
public record GetLeadContactByLeadIdListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? FullName { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? AddressStreet { get; init; }
|
||||
public string? AddressCity { get; init; }
|
||||
public string? AddressState { get; init; }
|
||||
public string? AddressZipCode { get; init; }
|
||||
public string? AddressCountry { get; init; }
|
||||
public string? PhoneNumber { get; init; }
|
||||
public string? FaxNumber { get; init; }
|
||||
public string? MobileNumber { get; init; }
|
||||
public string? Email { get; init; }
|
||||
public string? Website { get; init; }
|
||||
public string? WhatsApp { get; init; }
|
||||
public string? LinkedIn { get; init; }
|
||||
public string? Facebook { get; init; }
|
||||
public string? Twitter { get; init; }
|
||||
public string? Instagram { get; init; }
|
||||
public string? AvatarName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadContactByLeadIdListProfile : Profile
|
||||
{
|
||||
public GetLeadContactByLeadIdListProfile()
|
||||
{
|
||||
CreateMap<LeadContact, GetLeadContactByLeadIdListDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadContactByLeadIdListResult
|
||||
{
|
||||
public List<GetLeadContactByLeadIdListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadContactByLeadIdListRequest : IRequest<GetLeadContactByLeadIdListResult>
|
||||
{
|
||||
public string? LeadId { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadContactByLeadIdListHandler : IRequestHandler<GetLeadContactByLeadIdListRequest, GetLeadContactByLeadIdListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadContactByLeadIdListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadContactByLeadIdListResult> Handle(GetLeadContactByLeadIdListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.LeadContact
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false) // Assuming contacts aren't soft-deleted or this method filters out deleted contacts
|
||||
.Where(x => x.LeadId == request.LeadId)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetLeadContactByLeadIdListDto>>(entities);
|
||||
|
||||
return new GetLeadContactByLeadIdListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadContactManager.Queries;
|
||||
|
||||
public record GetLeadContactListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? FullName { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? AddressStreet { get; init; }
|
||||
public string? AddressCity { get; init; }
|
||||
public string? AddressState { get; init; }
|
||||
public string? AddressZipCode { get; init; }
|
||||
public string? AddressCountry { get; init; }
|
||||
public string? PhoneNumber { get; init; }
|
||||
public string? FaxNumber { get; init; }
|
||||
public string? MobileNumber { get; init; }
|
||||
public string? Email { get; init; }
|
||||
public string? Website { get; init; }
|
||||
public string? WhatsApp { get; init; }
|
||||
public string? LinkedIn { get; init; }
|
||||
public string? Facebook { get; init; }
|
||||
public string? Twitter { get; init; }
|
||||
public string? Instagram { get; init; }
|
||||
public string? AvatarName { get; init; }
|
||||
public string? LeadId { get; init; }
|
||||
public string? LeadTitle { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadContactListProfile : Profile
|
||||
{
|
||||
public GetLeadContactListProfile()
|
||||
{
|
||||
CreateMap<LeadContact, GetLeadContactListDto>()
|
||||
.ForMember(
|
||||
dest => dest.LeadTitle,
|
||||
opt => opt.MapFrom(src => src.Lead != null ? src.Lead.Title : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadContactListResult
|
||||
{
|
||||
public List<GetLeadContactListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadContactListRequest : IRequest<GetLeadContactListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
public class GetLeadContactListHandler : IRequestHandler<GetLeadContactListRequest, GetLeadContactListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadContactListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadContactListResult> Handle(GetLeadContactListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.LeadContact
|
||||
.Include(x => x.Lead)
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetLeadContactListDto>>(entities);
|
||||
|
||||
return new GetLeadContactListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadContactManager.Queries;
|
||||
|
||||
public class GetLeadContactSingleProfile : Profile
|
||||
{
|
||||
public GetLeadContactSingleProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadContactSingleResult
|
||||
{
|
||||
public LeadContact? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadContactSingleRequest : IRequest<GetLeadContactSingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadContactSingleValidator : AbstractValidator<GetLeadContactSingleRequest>
|
||||
{
|
||||
public GetLeadContactSingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadContactSingleHandler : IRequestHandler<GetLeadContactSingleRequest, GetLeadContactSingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadContactSingleHandler(
|
||||
IQueryContext context
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadContactSingleResult> Handle(GetLeadContactSingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.LeadContact
|
||||
.AsNoTracking()
|
||||
.Where(x => x.Id == request.Id)
|
||||
.AsQueryable();
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return new GetLeadContactSingleResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadManager.Commands;
|
||||
|
||||
public class CreateLeadResult
|
||||
{
|
||||
public Lead? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateLeadRequest : IRequest<CreateLeadResult>
|
||||
{
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? CompanyName { get; init; }
|
||||
public string? CompanyAddressStreet { get; init; }
|
||||
public string? CompanyAddressCity { get; init; }
|
||||
public string? CompanyAddressState { get; init; }
|
||||
public string? CompanyPhoneNumber { get; init; }
|
||||
public string? CompanyEmail { get; init; }
|
||||
public DateTime? DateProspecting { get; init; }
|
||||
public DateTime? DateClosingEstimation { get; init; }
|
||||
public DateTime? DateClosingActual { get; init; }
|
||||
public double? AmountTargeted { get; init; }
|
||||
public double? AmountClosed { get; init; }
|
||||
public double? BudgetScore { get; init; }
|
||||
public double? AuthorityScore { get; init; }
|
||||
public double? NeedScore { get; init; }
|
||||
public double? TimelineScore { get; init; }
|
||||
public string? PipelineStage { get; init; }
|
||||
public string? ClosingStatus { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? SalesTeamId { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateLeadValidator : AbstractValidator<CreateLeadRequest>
|
||||
{
|
||||
public CreateLeadValidator()
|
||||
{
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.SalesTeamId).NotEmpty();
|
||||
RuleFor(x => x.CompanyName).NotEmpty();
|
||||
RuleFor(x => x.CompanyAddressStreet).NotEmpty();
|
||||
RuleFor(x => x.CompanyAddressCity).NotEmpty();
|
||||
RuleFor(x => x.CompanyAddressState).NotEmpty();
|
||||
RuleFor(x => x.CompanyPhoneNumber).NotEmpty();
|
||||
RuleFor(x => x.CompanyEmail).NotEmpty();
|
||||
RuleFor(x => x.DateProspecting).NotNull();
|
||||
RuleFor(x => x.DateClosingEstimation).NotNull();
|
||||
RuleFor(x => x.AmountTargeted).NotNull();
|
||||
RuleFor(x => x.AmountClosed).NotNull();
|
||||
RuleFor(x => x.BudgetScore).NotNull();
|
||||
RuleFor(x => x.AuthorityScore).NotNull();
|
||||
RuleFor(x => x.NeedScore).NotNull();
|
||||
RuleFor(x => x.TimelineScore).NotNull();
|
||||
RuleFor(x => x.PipelineStage).NotEmpty();
|
||||
RuleFor(x => x.CampaignId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateLeadHandler : IRequestHandler<CreateLeadRequest, CreateLeadResult>
|
||||
{
|
||||
private readonly ICommandRepository<Lead> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateLeadHandler(
|
||||
ICommandRepository<Lead> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateLeadResult> Handle(CreateLeadRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new Lead
|
||||
{
|
||||
CreatedById = request.CreatedById,
|
||||
Number = _numberSequenceService.GenerateNumber(nameof(Lead), "", "LEA"),
|
||||
Title = request.Title,
|
||||
SalesTeamId = request.SalesTeamId,
|
||||
Description = request.Description,
|
||||
CompanyName = request.CompanyName,
|
||||
CompanyAddressStreet = request.CompanyAddressStreet,
|
||||
CompanyAddressCity = request.CompanyAddressCity,
|
||||
CompanyAddressState = request.CompanyAddressState,
|
||||
CompanyPhoneNumber = request.CompanyPhoneNumber,
|
||||
CompanyEmail = request.CompanyEmail,
|
||||
DateProspecting = request.DateProspecting,
|
||||
DateClosingEstimation = request.DateClosingEstimation,
|
||||
DateClosingActual = request.DateClosingActual,
|
||||
AmountTargeted = request.AmountTargeted,
|
||||
AmountClosed = request.AmountClosed,
|
||||
BudgetScore = request.BudgetScore,
|
||||
AuthorityScore = request.AuthorityScore,
|
||||
NeedScore = request.NeedScore,
|
||||
TimelineScore = request.TimelineScore,
|
||||
PipelineStage = (PipelineStage)int.Parse(request.PipelineStage!),
|
||||
CampaignId = request.CampaignId
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(request.ClosingStatus))
|
||||
{
|
||||
entity.ClosingStatus = (ClosingStatus)int.Parse(request.ClosingStatus!);
|
||||
}
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateLeadResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadManager.Commands;
|
||||
|
||||
public class DeleteLeadResult
|
||||
{
|
||||
public Lead? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteLeadRequest : IRequest<DeleteLeadResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteLeadValidator : AbstractValidator<DeleteLeadRequest>
|
||||
{
|
||||
public DeleteLeadValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteLeadHandler : IRequestHandler<DeleteLeadRequest, DeleteLeadResult>
|
||||
{
|
||||
private readonly ICommandRepository<Lead> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteLeadHandler(
|
||||
ICommandRepository<Lead> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteLeadResult> Handle(DeleteLeadRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteLeadResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.LeadManager.Commands;
|
||||
|
||||
public class UpdateLeadResult
|
||||
{
|
||||
public Lead? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateLeadRequest : IRequest<UpdateLeadResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? CompanyName { get; init; }
|
||||
public string? CompanyAddressStreet { get; init; }
|
||||
public string? CompanyAddressCity { get; init; }
|
||||
public string? CompanyAddressState { get; init; }
|
||||
public string? CompanyPhoneNumber { get; init; }
|
||||
public string? CompanyEmail { get; init; }
|
||||
public DateTime? DateProspecting { get; init; }
|
||||
public DateTime? DateClosingEstimation { get; init; }
|
||||
public DateTime? DateClosingActual { get; init; }
|
||||
public double? AmountTargeted { get; init; }
|
||||
public double? AmountClosed { get; init; }
|
||||
public double? BudgetScore { get; init; }
|
||||
public double? AuthorityScore { get; init; }
|
||||
public double? NeedScore { get; init; }
|
||||
public double? TimelineScore { get; init; }
|
||||
public string? PipelineStage { get; init; }
|
||||
public string? ClosingStatus { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? SalesTeamId { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateLeadValidator : AbstractValidator<UpdateLeadRequest>
|
||||
{
|
||||
public UpdateLeadValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.SalesTeamId).NotEmpty();
|
||||
RuleFor(x => x.CompanyName).NotEmpty();
|
||||
RuleFor(x => x.CompanyAddressStreet).NotEmpty();
|
||||
RuleFor(x => x.CompanyAddressCity).NotEmpty();
|
||||
RuleFor(x => x.CompanyAddressState).NotEmpty();
|
||||
RuleFor(x => x.CompanyPhoneNumber).NotEmpty();
|
||||
RuleFor(x => x.CompanyEmail).NotEmpty();
|
||||
RuleFor(x => x.DateProspecting).NotNull();
|
||||
RuleFor(x => x.DateClosingEstimation).NotNull();
|
||||
RuleFor(x => x.AmountTargeted).NotNull();
|
||||
RuleFor(x => x.AmountClosed).NotNull();
|
||||
RuleFor(x => x.BudgetScore).NotNull();
|
||||
RuleFor(x => x.AuthorityScore).NotNull();
|
||||
RuleFor(x => x.NeedScore).NotNull();
|
||||
RuleFor(x => x.TimelineScore).NotNull();
|
||||
RuleFor(x => x.PipelineStage).NotEmpty();
|
||||
RuleFor(x => x.CampaignId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateLeadHandler : IRequestHandler<UpdateLeadRequest, UpdateLeadResult>
|
||||
{
|
||||
private readonly ICommandRepository<Lead> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateLeadHandler(
|
||||
ICommandRepository<Lead> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateLeadResult> Handle(UpdateLeadRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
entity.Title = request.Title;
|
||||
entity.SalesTeamId = request.SalesTeamId;
|
||||
entity.Description = request.Description;
|
||||
entity.CompanyName = request.CompanyName;
|
||||
entity.CompanyAddressStreet = request.CompanyAddressStreet;
|
||||
entity.CompanyAddressCity = request.CompanyAddressCity;
|
||||
entity.CompanyAddressState = request.CompanyAddressState;
|
||||
entity.CompanyPhoneNumber = request.CompanyPhoneNumber;
|
||||
entity.CompanyEmail = request.CompanyEmail;
|
||||
entity.DateProspecting = request.DateProspecting;
|
||||
entity.DateClosingEstimation = request.DateClosingEstimation;
|
||||
entity.DateClosingActual = request.DateClosingActual;
|
||||
entity.AmountTargeted = request.AmountTargeted;
|
||||
entity.AmountClosed = request.AmountClosed;
|
||||
entity.BudgetScore = request.BudgetScore;
|
||||
entity.AuthorityScore = request.AuthorityScore;
|
||||
entity.NeedScore = request.NeedScore;
|
||||
entity.TimelineScore = request.TimelineScore;
|
||||
entity.PipelineStage = (PipelineStage)int.Parse(request.PipelineStage!);
|
||||
entity.CampaignId = request.CampaignId;
|
||||
|
||||
if (!string.IsNullOrEmpty(request.ClosingStatus))
|
||||
{
|
||||
entity.ClosingStatus = (ClosingStatus)int.Parse(request.ClosingStatus!);
|
||||
}
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateLeadResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CampaignManager.Queries;
|
||||
|
||||
public record GetClosingStatusListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
|
||||
public class GetClosingStatusListProfile : Profile
|
||||
{
|
||||
public GetClosingStatusListProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetClosingStatusListResult
|
||||
{
|
||||
public List<GetClosingStatusListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetClosingStatusListRequest : IRequest<GetClosingStatusListResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetClosingStatusListHandler : IRequestHandler<GetClosingStatusListRequest, GetClosingStatusListResult>
|
||||
{
|
||||
public GetClosingStatusListHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<GetClosingStatusListResult> Handle(GetClosingStatusListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var statuses = Enum.GetValues(typeof(ClosingStatus))
|
||||
.Cast<ClosingStatus>()
|
||||
.Select(status => new GetClosingStatusListDto
|
||||
{
|
||||
Id = ((int)status).ToString(),
|
||||
Name = status.ToFriendlyName()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new GetClosingStatusListResult
|
||||
{
|
||||
Data = statuses
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadManager.Queries;
|
||||
|
||||
public record GetLeadByCampaignIdListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? CompanyName { get; init; }
|
||||
public string? CompanyAddressStreet { get; init; }
|
||||
public string? CompanyAddressCity { get; init; }
|
||||
public string? CompanyAddressState { get; init; }
|
||||
public string? CompanyPhoneNumber { get; init; }
|
||||
public string? CompanyEmail { get; init; }
|
||||
public DateTime? DateProspecting { get; init; }
|
||||
public DateTime? DateClosingEstimation { get; init; }
|
||||
public double? AmountTargeted { get; init; }
|
||||
public double? AmountClosed { get; init; }
|
||||
public double? BudgetScore { get; init; }
|
||||
public double? AuthorityScore { get; init; }
|
||||
public double? NeedScore { get; init; }
|
||||
public double? TimelineScore { get; init; }
|
||||
public string? PipelineStage { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public string? CampaignName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadByCampaignIdListProfile : Profile
|
||||
{
|
||||
public GetLeadByCampaignIdListProfile()
|
||||
{
|
||||
CreateMap<Lead, GetLeadByCampaignIdListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CampaignName,
|
||||
opt => opt.MapFrom(src => src.Campaign != null ? src.Campaign.Title : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.PipelineStage,
|
||||
opt => opt.MapFrom(src => src.PipelineStage.HasValue ? src.PipelineStage.Value.ToFriendlyName() : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadByCampaignIdListResult
|
||||
{
|
||||
public List<GetLeadByCampaignIdListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadByCampaignIdListRequest : IRequest<GetLeadByCampaignIdListResult>
|
||||
{
|
||||
public string? CampaignId { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadByCampaignIdListHandler : IRequestHandler<GetLeadByCampaignIdListRequest, GetLeadByCampaignIdListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadByCampaignIdListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadByCampaignIdListResult> Handle(GetLeadByCampaignIdListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Lead
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.Campaign)
|
||||
.Where(x => x.CampaignId == request.CampaignId)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetLeadByCampaignIdListDto>>(entities);
|
||||
|
||||
return new GetLeadByCampaignIdListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadManager.Queries;
|
||||
|
||||
public record GetLeadListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? CompanyName { get; init; }
|
||||
public string? CompanyDescription { get; init; }
|
||||
public string? CompanyAddressStreet { get; init; }
|
||||
public string? CompanyAddressCity { get; init; }
|
||||
public string? CompanyAddressState { get; init; }
|
||||
public string? CompanyAddressZipCode { get; init; }
|
||||
public string? CompanyAddressCountry { get; init; }
|
||||
public string? CompanyPhoneNumber { get; init; }
|
||||
public string? CompanyFaxNumber { get; init; }
|
||||
public string? CompanyEmail { get; init; }
|
||||
public string? CompanyWebsite { get; init; }
|
||||
public string? CompanyWhatsApp { get; init; }
|
||||
public string? CompanyLinkedIn { get; init; }
|
||||
public string? CompanyFacebook { get; init; }
|
||||
public string? CompanyInstagram { get; init; }
|
||||
public string? CompanyTwitter { get; init; }
|
||||
public DateTime? DateProspecting { get; init; }
|
||||
public DateTime? DateClosingEstimation { get; init; }
|
||||
public DateTime? DateClosingActual { get; init; }
|
||||
public double? AmountTargeted { get; init; }
|
||||
public double? AmountClosed { get; init; }
|
||||
public double? BudgetScore { get; init; }
|
||||
public double? AuthorityScore { get; init; }
|
||||
public double? NeedScore { get; init; }
|
||||
public double? TimelineScore { get; init; }
|
||||
public PipelineStage? PipelineStage { get; init; }
|
||||
public string? PipelineStageName { get; init; }
|
||||
public ClosingStatus? ClosingStatus { get; init; }
|
||||
public string? ClosingStatusName { get; init; }
|
||||
public string? ClosingNote { get; init; }
|
||||
public string? CampaignId { get; init; }
|
||||
public Campaign? Campaign { get; init; }
|
||||
public string? CampaignName { get; init; }
|
||||
public string? SalesTeamId { get; init; }
|
||||
public string? SalesTeamName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadListProfile : Profile
|
||||
{
|
||||
public GetLeadListProfile()
|
||||
{
|
||||
CreateMap<Lead, GetLeadListDto>()
|
||||
.ForMember(
|
||||
dest => dest.CampaignName,
|
||||
opt => opt.MapFrom(src => src.Campaign != null ? src.Campaign.Title : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.PipelineStageName,
|
||||
opt => opt.MapFrom(src => src.PipelineStage.HasValue ? src.PipelineStage.Value.ToFriendlyName() : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.ClosingStatusName,
|
||||
opt => opt.MapFrom(src => src.ClosingStatus.HasValue ? src.ClosingStatus.Value.ToFriendlyName() : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.SalesTeamName,
|
||||
opt => opt.MapFrom(src => src.SalesTeam != null ? src.SalesTeam.Name : string.Empty)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadListResult
|
||||
{
|
||||
public List<GetLeadListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadListRequest : IRequest<GetLeadListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
public class GetLeadListHandler : IRequestHandler<GetLeadListRequest, GetLeadListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadListResult> Handle(GetLeadListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Lead
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.Campaign)
|
||||
.Include(x => x.SalesTeam)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetLeadListDto>>(entities);
|
||||
|
||||
return new GetLeadListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.LeadManager.Queries;
|
||||
|
||||
public class GetLeadSingleProfile : Profile
|
||||
{
|
||||
public GetLeadSingleProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadSingleResult
|
||||
{
|
||||
public Lead? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadSingleRequest : IRequest<GetLeadSingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadSingleValidator : AbstractValidator<GetLeadSingleRequest>
|
||||
{
|
||||
public GetLeadSingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLeadSingleHandler : IRequestHandler<GetLeadSingleRequest, GetLeadSingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadSingleHandler(
|
||||
IQueryContext context
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadSingleResult> Handle(GetLeadSingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Lead
|
||||
.AsNoTracking()
|
||||
.Include(x => x.Campaign)
|
||||
.Include(x => x.LeadContacts)
|
||||
.Include(x => x.LeadActivities)
|
||||
.Where(x => x.Id == request.Id)
|
||||
.AsQueryable();
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return new GetLeadSingleResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.CampaignManager.Queries;
|
||||
|
||||
public record GetPipelineStageListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
|
||||
public class GetPipelineStageListProfile : Profile
|
||||
{
|
||||
public GetPipelineStageListProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetPipelineStageListResult
|
||||
{
|
||||
public List<GetPipelineStageListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPipelineStageListRequest : IRequest<GetPipelineStageListResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetPipelineStageListHandler : IRequestHandler<GetPipelineStageListRequest, GetPipelineStageListResult>
|
||||
{
|
||||
public GetPipelineStageListHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<GetPipelineStageListResult> Handle(GetPipelineStageListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var statuses = Enum.GetValues(typeof(PipelineStage))
|
||||
.Cast<PipelineStage>()
|
||||
.Select(status => new GetPipelineStageListDto
|
||||
{
|
||||
Id = ((int)status).ToString(),
|
||||
Name = status.ToFriendlyName()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new GetPipelineStageListResult
|
||||
{
|
||||
Data = statuses
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Features.NumberSequenceManager;
|
||||
|
||||
public class NumberSequenceService
|
||||
{
|
||||
|
||||
private readonly object lockObject = new object();
|
||||
private readonly ICommandRepository<NumberSequence> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public NumberSequenceService(
|
||||
ICommandRepository<NumberSequence> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
private NumberSequence? GetNumberSequence(string entityName, string prefix, string suffix)
|
||||
{
|
||||
return _repository.GetQuery()
|
||||
.FirstOrDefault(ns => ns.EntityName == entityName && ns.Prefix == prefix && ns.Suffix == suffix);
|
||||
}
|
||||
|
||||
private void UpdateNumberSequence(NumberSequence sequence)
|
||||
{
|
||||
sequence.LastUsedCount++;
|
||||
_unitOfWork.Save();
|
||||
}
|
||||
|
||||
private NumberSequence InsertNumberSequence(string entityName, string prefix, string suffix)
|
||||
{
|
||||
NumberSequence newSequence = new NumberSequence
|
||||
{
|
||||
EntityName = entityName,
|
||||
Prefix = prefix,
|
||||
Suffix = suffix,
|
||||
LastUsedCount = 1
|
||||
};
|
||||
|
||||
_repository.Create(newSequence);
|
||||
_unitOfWork.Save();
|
||||
|
||||
return newSequence;
|
||||
}
|
||||
|
||||
public string GenerateNumber(string entityName, string prefix, string suffix, bool useDate = true, int padding = 4)
|
||||
{
|
||||
var result = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(entityName))
|
||||
{
|
||||
throw new Exception("Parameter entityName must not be null");
|
||||
}
|
||||
|
||||
lock (lockObject)
|
||||
{
|
||||
NumberSequence? sequence = GetNumberSequence(entityName, prefix, suffix);
|
||||
|
||||
if (sequence != null)
|
||||
{
|
||||
UpdateNumberSequence(sequence);
|
||||
}
|
||||
else
|
||||
{
|
||||
sequence = InsertNumberSequence(entityName, prefix, suffix);
|
||||
}
|
||||
|
||||
string formattedNumber = $"{prefix}{sequence?.LastUsedCount?.ToString().PadLeft(padding, '0')}{(useDate ? DateTime.Now.ToString("yyyyMMdd") : "")}{suffix}";
|
||||
result = formattedNumber;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.NumberSequenceManager.Queries;
|
||||
|
||||
public record GetNumberSequenceListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? EntityName { get; init; }
|
||||
public string? Prefix { get; init; }
|
||||
public string? Suffix { get; init; }
|
||||
public string? LastUsedCount { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetNumberSequenceListProfile : Profile
|
||||
{
|
||||
public GetNumberSequenceListProfile()
|
||||
{
|
||||
CreateMap<NumberSequence, GetNumberSequenceListDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetNumberSequenceListResult
|
||||
{
|
||||
public List<GetNumberSequenceListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetNumberSequenceListRequest : IRequest<GetNumberSequenceListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetNumberSequenceListHandler : IRequestHandler<GetNumberSequenceListRequest, GetNumberSequenceListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetNumberSequenceListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetNumberSequenceListResult> Handle(GetNumberSequenceListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.NumberSequence
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetNumberSequenceListDto>>(entities);
|
||||
|
||||
return new GetNumberSequenceListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ProductGroupManager.Commands;
|
||||
|
||||
public class CreateProductGroupResult
|
||||
{
|
||||
public ProductGroup? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateProductGroupRequest : IRequest<CreateProductGroupResult>
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateProductGroupValidator : AbstractValidator<CreateProductGroupRequest>
|
||||
{
|
||||
public CreateProductGroupValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateProductGroupHandler : IRequestHandler<CreateProductGroupRequest, CreateProductGroupResult>
|
||||
{
|
||||
private readonly ICommandRepository<ProductGroup> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public CreateProductGroupHandler(
|
||||
ICommandRepository<ProductGroup> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<CreateProductGroupResult> Handle(CreateProductGroupRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new ProductGroup();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateProductGroupResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ProductGroupManager.Commands;
|
||||
|
||||
public class DeleteProductGroupResult
|
||||
{
|
||||
public ProductGroup? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteProductGroupRequest : IRequest<DeleteProductGroupResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteProductGroupValidator : AbstractValidator<DeleteProductGroupRequest>
|
||||
{
|
||||
public DeleteProductGroupValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteProductGroupHandler : IRequestHandler<DeleteProductGroupRequest, DeleteProductGroupResult>
|
||||
{
|
||||
private readonly ICommandRepository<ProductGroup> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteProductGroupHandler(
|
||||
ICommandRepository<ProductGroup> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteProductGroupResult> Handle(DeleteProductGroupRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteProductGroupResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ProductGroupManager.Commands;
|
||||
|
||||
public class UpdateProductGroupResult
|
||||
{
|
||||
public ProductGroup? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateProductGroupRequest : IRequest<UpdateProductGroupResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateProductGroupValidator : AbstractValidator<UpdateProductGroupRequest>
|
||||
{
|
||||
public UpdateProductGroupValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateProductGroupHandler : IRequestHandler<UpdateProductGroupRequest, UpdateProductGroupResult>
|
||||
{
|
||||
private readonly ICommandRepository<ProductGroup> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateProductGroupHandler(
|
||||
ICommandRepository<ProductGroup> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateProductGroupResult> Handle(UpdateProductGroupRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.Description = request.Description;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateProductGroupResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.ProductGroupManager.Queries;
|
||||
|
||||
public record GetProductGroupListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetProductGroupListProfile : Profile
|
||||
{
|
||||
public GetProductGroupListProfile()
|
||||
{
|
||||
CreateMap<ProductGroup, GetProductGroupListDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetProductGroupListResult
|
||||
{
|
||||
public List<GetProductGroupListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetProductGroupListRequest : IRequest<GetProductGroupListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetProductGroupListHandler : IRequestHandler<GetProductGroupListRequest, GetProductGroupListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetProductGroupListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetProductGroupListResult> Handle(GetProductGroupListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.ProductGroup
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetProductGroupListDto>>(entities);
|
||||
|
||||
return new GetProductGroupListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ProductManager.Commands;
|
||||
|
||||
public class CreateProductResult
|
||||
{
|
||||
public Product? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreateProductRequest : IRequest<CreateProductResult>
|
||||
{
|
||||
public string? Number { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public double? UnitPrice { get; init; }
|
||||
public bool? Physical { get; init; } = true;
|
||||
public string? UnitMeasureId { get; init; }
|
||||
public string? ProductGroupId { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreateProductValidator : AbstractValidator<CreateProductRequest>
|
||||
{
|
||||
public CreateProductValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
RuleFor(x => x.UnitPrice).NotEmpty();
|
||||
RuleFor(x => x.Physical).NotEmpty();
|
||||
RuleFor(x => x.UnitMeasureId).NotEmpty();
|
||||
RuleFor(x => x.ProductGroupId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateProductHandler : IRequestHandler<CreateProductRequest, CreateProductResult>
|
||||
{
|
||||
private readonly ICommandRepository<Product> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
|
||||
public CreateProductHandler(
|
||||
ICommandRepository<Product> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
}
|
||||
|
||||
public async Task<CreateProductResult> Handle(CreateProductRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new Product();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Number = _numberSequenceService.GenerateNumber(nameof(Product), "", "ART");
|
||||
entity.Name = request.Name;
|
||||
entity.UnitPrice = request.UnitPrice;
|
||||
entity.Physical = request.Physical;
|
||||
entity.Description = request.Description;
|
||||
entity.UnitMeasureId = request.UnitMeasureId;
|
||||
entity.ProductGroupId = request.ProductGroupId;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new CreateProductResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ProductManager.Commands;
|
||||
|
||||
public class DeleteProductResult
|
||||
{
|
||||
public Product? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteProductRequest : IRequest<DeleteProductResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeleteProductValidator : AbstractValidator<DeleteProductRequest>
|
||||
{
|
||||
public DeleteProductValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteProductHandler : IRequestHandler<DeleteProductRequest, DeleteProductResult>
|
||||
{
|
||||
private readonly ICommandRepository<Product> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteProductHandler(
|
||||
ICommandRepository<Product> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeleteProductResult> Handle(DeleteProductRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeleteProductResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.ProductManager.Commands;
|
||||
|
||||
public class UpdateProductResult
|
||||
{
|
||||
public Product? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateProductRequest : IRequest<UpdateProductResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public double? UnitPrice { get; init; }
|
||||
public bool? Physical { get; init; } = true;
|
||||
public string? UnitMeasureId { get; init; }
|
||||
public string? ProductGroupId { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdateProductValidator : AbstractValidator<UpdateProductRequest>
|
||||
{
|
||||
public UpdateProductValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.Name).NotEmpty();
|
||||
RuleFor(x => x.UnitPrice).NotEmpty();
|
||||
RuleFor(x => x.Physical).NotEmpty();
|
||||
RuleFor(x => x.UnitMeasureId).NotEmpty();
|
||||
RuleFor(x => x.ProductGroupId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateProductHandler : IRequestHandler<UpdateProductRequest, UpdateProductResult>
|
||||
{
|
||||
private readonly ICommandRepository<Product> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public UpdateProductHandler(
|
||||
ICommandRepository<Product> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<UpdateProductResult> Handle(UpdateProductRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.UnitPrice = request.UnitPrice;
|
||||
entity.Physical = request.Physical;
|
||||
entity.Description = request.Description;
|
||||
entity.UnitMeasureId = request.UnitMeasureId;
|
||||
entity.ProductGroupId = request.ProductGroupId;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new UpdateProductResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.ProductManager.Queries;
|
||||
|
||||
public record GetProductListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public double? UnitPrice { get; init; }
|
||||
public bool? Physical { get; init; }
|
||||
public string? UnitMeasureId { get; init; }
|
||||
public string? UnitMeasureName { get; init; }
|
||||
public string? ProductGroupId { get; init; }
|
||||
public string? ProductGroupName { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetProductListProfile : Profile
|
||||
{
|
||||
public GetProductListProfile()
|
||||
{
|
||||
CreateMap<Product, GetProductListDto>()
|
||||
.ForMember(
|
||||
dest => dest.UnitMeasureName,
|
||||
opt => opt.MapFrom(src => src.UnitMeasure != null ? src.UnitMeasure.Name : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.ProductGroupName,
|
||||
opt => opt.MapFrom(src => src.ProductGroup != null ? src.ProductGroup.Name : string.Empty)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class GetProductListResult
|
||||
{
|
||||
public List<GetProductListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetProductListRequest : IRequest<GetProductListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetProductListHandler : IRequestHandler<GetProductListRequest, GetProductListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetProductListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetProductListResult> Handle(GetProductListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.Product
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.UnitMeasure)
|
||||
.Include(x => x.ProductGroup)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetProductListDto>>(entities);
|
||||
|
||||
return new GetProductListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.PurchaseOrderManager;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.PurchaseOrderItemManager.Commands;
|
||||
|
||||
public class CreatePurchaseOrderItemResult
|
||||
{
|
||||
public PurchaseOrderItem? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreatePurchaseOrderItemRequest : IRequest<CreatePurchaseOrderItemResult>
|
||||
{
|
||||
public string? PurchaseOrderId { get; init; }
|
||||
public string? ProductId { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public double? UnitPrice { get; init; }
|
||||
public double? Quantity { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreatePurchaseOrderItemValidator : AbstractValidator<CreatePurchaseOrderItemRequest>
|
||||
{
|
||||
public CreatePurchaseOrderItemValidator()
|
||||
{
|
||||
RuleFor(x => x.PurchaseOrderId).NotEmpty();
|
||||
RuleFor(x => x.ProductId).NotEmpty();
|
||||
RuleFor(x => x.UnitPrice).NotEmpty();
|
||||
RuleFor(x => x.Quantity).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreatePurchaseOrderItemHandler : IRequestHandler<CreatePurchaseOrderItemRequest, CreatePurchaseOrderItemResult>
|
||||
{
|
||||
private readonly ICommandRepository<PurchaseOrderItem> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly PurchaseOrderService _purchaseOrderService;
|
||||
|
||||
public CreatePurchaseOrderItemHandler(
|
||||
ICommandRepository<PurchaseOrderItem> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
PurchaseOrderService purchaseOrderService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_purchaseOrderService = purchaseOrderService;
|
||||
}
|
||||
|
||||
public async Task<CreatePurchaseOrderItemResult> Handle(CreatePurchaseOrderItemRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new PurchaseOrderItem();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.PurchaseOrderId = request.PurchaseOrderId;
|
||||
entity.ProductId = request.ProductId;
|
||||
entity.Summary = request.Summary;
|
||||
entity.UnitPrice = request.UnitPrice;
|
||||
entity.Quantity = request.Quantity;
|
||||
|
||||
entity.Total = entity.Quantity * entity.UnitPrice;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
_purchaseOrderService.Recalculate(entity.PurchaseOrderId ?? "");
|
||||
|
||||
return new CreatePurchaseOrderItemResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.PurchaseOrderManager;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.PurchaseOrderItemManager.Commands;
|
||||
|
||||
public class DeletePurchaseOrderItemResult
|
||||
{
|
||||
public PurchaseOrderItem? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeletePurchaseOrderItemRequest : IRequest<DeletePurchaseOrderItemResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeletePurchaseOrderItemValidator : AbstractValidator<DeletePurchaseOrderItemRequest>
|
||||
{
|
||||
public DeletePurchaseOrderItemValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeletePurchaseOrderItemHandler : IRequestHandler<DeletePurchaseOrderItemRequest, DeletePurchaseOrderItemResult>
|
||||
{
|
||||
private readonly ICommandRepository<PurchaseOrderItem> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly PurchaseOrderService _purchaseOrderService;
|
||||
|
||||
public DeletePurchaseOrderItemHandler(
|
||||
ICommandRepository<PurchaseOrderItem> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
PurchaseOrderService purchaseOrderService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_purchaseOrderService = purchaseOrderService;
|
||||
}
|
||||
|
||||
public async Task<DeletePurchaseOrderItemResult> Handle(DeletePurchaseOrderItemRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
_purchaseOrderService.Recalculate(entity.PurchaseOrderId ?? "");
|
||||
|
||||
return new DeletePurchaseOrderItemResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.PurchaseOrderManager;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.PurchaseOrderItemManager.Commands;
|
||||
|
||||
public class UpdatePurchaseOrderItemResult
|
||||
{
|
||||
public PurchaseOrderItem? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdatePurchaseOrderItemRequest : IRequest<UpdatePurchaseOrderItemResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? PurchaseOrderId { get; init; }
|
||||
public string? ProductId { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public double? UnitPrice { get; init; }
|
||||
public double? Quantity { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdatePurchaseOrderItemValidator : AbstractValidator<UpdatePurchaseOrderItemRequest>
|
||||
{
|
||||
public UpdatePurchaseOrderItemValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.PurchaseOrderId).NotEmpty();
|
||||
RuleFor(x => x.ProductId).NotEmpty();
|
||||
RuleFor(x => x.UnitPrice).NotEmpty();
|
||||
RuleFor(x => x.Quantity).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdatePurchaseOrderItemHandler : IRequestHandler<UpdatePurchaseOrderItemRequest, UpdatePurchaseOrderItemResult>
|
||||
{
|
||||
private readonly ICommandRepository<PurchaseOrderItem> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly PurchaseOrderService _purchaseOrderService;
|
||||
|
||||
public UpdatePurchaseOrderItemHandler(
|
||||
ICommandRepository<PurchaseOrderItem> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
PurchaseOrderService purchaseOrderService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_purchaseOrderService = purchaseOrderService;
|
||||
}
|
||||
|
||||
public async Task<UpdatePurchaseOrderItemResult> Handle(UpdatePurchaseOrderItemRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.PurchaseOrderId = request.PurchaseOrderId;
|
||||
entity.ProductId = request.ProductId;
|
||||
entity.Summary = request.Summary;
|
||||
entity.UnitPrice = request.UnitPrice;
|
||||
entity.Quantity = request.Quantity;
|
||||
|
||||
entity.Total = entity.UnitPrice * entity.Quantity;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
_purchaseOrderService.Recalculate(entity.PurchaseOrderId ?? "");
|
||||
|
||||
return new UpdatePurchaseOrderItemResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.PurchaseOrderItemManager.Queries;
|
||||
|
||||
public record GetPurchaseOrderItemByPurchaseOrderIdListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? PurchaseOrderId { get; init; }
|
||||
public string? PurchaseOrderNumber { get; init; }
|
||||
public string? ProductId { get; init; }
|
||||
public string? ProductName { get; init; }
|
||||
public string? ProductNumber { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public double? UnitPrice { get; init; }
|
||||
public double? Quantity { get; init; }
|
||||
public double? Total { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderItemByPurchaseOrderIdListProfile : Profile
|
||||
{
|
||||
public GetPurchaseOrderItemByPurchaseOrderIdListProfile()
|
||||
{
|
||||
CreateMap<PurchaseOrderItem, GetPurchaseOrderItemByPurchaseOrderIdListDto>()
|
||||
.ForMember(
|
||||
dest => dest.PurchaseOrderNumber,
|
||||
opt => opt.MapFrom(src => src.PurchaseOrder != null ? src.PurchaseOrder.Number : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.ProductName,
|
||||
opt => opt.MapFrom(src => src.Product != null ? src.Product.Name : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.ProductNumber,
|
||||
opt => opt.MapFrom(src => src.Product != null ? src.Product.Number : string.Empty)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderItemByPurchaseOrderIdListResult
|
||||
{
|
||||
public List<GetPurchaseOrderItemByPurchaseOrderIdListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderItemByPurchaseOrderIdListRequest : IRequest<GetPurchaseOrderItemByPurchaseOrderIdListResult>
|
||||
{
|
||||
public string? PurchaseOrderId { get; init; }
|
||||
}
|
||||
|
||||
|
||||
public class GetPurchaseOrderItemByPurchaseOrderIdListHandler : IRequestHandler<GetPurchaseOrderItemByPurchaseOrderIdListRequest, GetPurchaseOrderItemByPurchaseOrderIdListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetPurchaseOrderItemByPurchaseOrderIdListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetPurchaseOrderItemByPurchaseOrderIdListResult> Handle(GetPurchaseOrderItemByPurchaseOrderIdListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.PurchaseOrderId == request.PurchaseOrderId)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetPurchaseOrderItemByPurchaseOrderIdListDto>>(entities);
|
||||
|
||||
return new GetPurchaseOrderItemByPurchaseOrderIdListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.PurchaseOrderItemManager.Queries;
|
||||
|
||||
public record GetPurchaseOrderItemListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? PurchaseOrderId { get; init; }
|
||||
public string? PurchaseOrderNumber { get; init; }
|
||||
public string? VendorName { get; init; }
|
||||
public string? ProductId { get; init; }
|
||||
public string? ProductName { get; init; }
|
||||
public string? ProductNumber { get; init; }
|
||||
public string? Summary { get; init; }
|
||||
public double? UnitPrice { get; init; }
|
||||
public double? Quantity { get; init; }
|
||||
public double? Total { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderItemListProfile : Profile
|
||||
{
|
||||
public GetPurchaseOrderItemListProfile()
|
||||
{
|
||||
CreateMap<PurchaseOrderItem, GetPurchaseOrderItemListDto>()
|
||||
.ForMember(
|
||||
dest => dest.PurchaseOrderNumber,
|
||||
opt => opt.MapFrom(src => src.PurchaseOrder != null ? src.PurchaseOrder.Number : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.VendorName,
|
||||
opt => opt.MapFrom(src => src.PurchaseOrder!.Vendor != null ? src.PurchaseOrder.Vendor.Name : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.ProductName,
|
||||
opt => opt.MapFrom(src => src.Product != null ? src.Product.Name : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.ProductNumber,
|
||||
opt => opt.MapFrom(src => src.Product != null ? src.Product.Number : string.Empty)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderItemListResult
|
||||
{
|
||||
public List<GetPurchaseOrderItemListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderItemListRequest : IRequest<GetPurchaseOrderItemListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetPurchaseOrderItemListHandler : IRequestHandler<GetPurchaseOrderItemListRequest, GetPurchaseOrderItemListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetPurchaseOrderItemListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetPurchaseOrderItemListResult> Handle(GetPurchaseOrderItemListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.ThenInclude(x => x!.Vendor)
|
||||
.Include(x => x.Product)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetPurchaseOrderItemListDto>>(entities);
|
||||
|
||||
return new GetPurchaseOrderItemListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using Application.Common.Repositories;
|
||||
using Application.Features.NumberSequenceManager;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.PurchaseOrderManager.Commands;
|
||||
|
||||
public class CreatePurchaseOrderResult
|
||||
{
|
||||
public PurchaseOrder? Data { get; set; }
|
||||
}
|
||||
|
||||
public class CreatePurchaseOrderRequest : IRequest<CreatePurchaseOrderResult>
|
||||
{
|
||||
public DateTime? OrderDate { get; init; }
|
||||
public string? OrderStatus { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? VendorId { get; init; }
|
||||
public string? TaxId { get; init; }
|
||||
public string? CreatedById { get; init; }
|
||||
}
|
||||
|
||||
public class CreatePurchaseOrderValidator : AbstractValidator<CreatePurchaseOrderRequest>
|
||||
{
|
||||
public CreatePurchaseOrderValidator()
|
||||
{
|
||||
RuleFor(x => x.OrderDate).NotEmpty();
|
||||
RuleFor(x => x.OrderStatus).NotEmpty();
|
||||
RuleFor(x => x.VendorId).NotEmpty();
|
||||
RuleFor(x => x.TaxId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreatePurchaseOrderHandler : IRequestHandler<CreatePurchaseOrderRequest, CreatePurchaseOrderResult>
|
||||
{
|
||||
private readonly ICommandRepository<PurchaseOrder> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly NumberSequenceService _numberSequenceService;
|
||||
private readonly PurchaseOrderService _purchaseOrderService;
|
||||
|
||||
public CreatePurchaseOrderHandler(
|
||||
ICommandRepository<PurchaseOrder> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
NumberSequenceService numberSequenceService,
|
||||
PurchaseOrderService purchaseOrderService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_numberSequenceService = numberSequenceService;
|
||||
_purchaseOrderService = purchaseOrderService;
|
||||
}
|
||||
|
||||
public async Task<CreatePurchaseOrderResult> Handle(CreatePurchaseOrderRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = new PurchaseOrder();
|
||||
entity.CreatedById = request.CreatedById;
|
||||
|
||||
entity.Number = _numberSequenceService.GenerateNumber(nameof(PurchaseOrder), "", "PO");
|
||||
entity.OrderDate = request.OrderDate;
|
||||
entity.OrderStatus = (PurchaseOrderStatus)int.Parse(request.OrderStatus!);
|
||||
entity.Description = request.Description;
|
||||
entity.VendorId = request.VendorId;
|
||||
entity.TaxId = request.TaxId;
|
||||
|
||||
await _repository.CreateAsync(entity, cancellationToken);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
_purchaseOrderService.Recalculate(entity.Id);
|
||||
|
||||
return new CreatePurchaseOrderResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.PurchaseOrderManager.Commands;
|
||||
|
||||
public class DeletePurchaseOrderResult
|
||||
{
|
||||
public PurchaseOrder? Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeletePurchaseOrderRequest : IRequest<DeletePurchaseOrderResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? DeletedById { get; init; }
|
||||
}
|
||||
|
||||
public class DeletePurchaseOrderValidator : AbstractValidator<DeletePurchaseOrderRequest>
|
||||
{
|
||||
public DeletePurchaseOrderValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeletePurchaseOrderHandler : IRequestHandler<DeletePurchaseOrderRequest, DeletePurchaseOrderResult>
|
||||
{
|
||||
private readonly ICommandRepository<PurchaseOrder> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeletePurchaseOrderHandler(
|
||||
ICommandRepository<PurchaseOrder> repository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeletePurchaseOrderResult> Handle(DeletePurchaseOrderRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.DeletedById;
|
||||
|
||||
_repository.Delete(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
return new DeletePurchaseOrderResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.PurchaseOrderManager.Commands;
|
||||
|
||||
public class UpdatePurchaseOrderResult
|
||||
{
|
||||
public PurchaseOrder? Data { get; set; }
|
||||
}
|
||||
|
||||
public class UpdatePurchaseOrderRequest : IRequest<UpdatePurchaseOrderResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public DateTime? OrderDate { get; init; }
|
||||
public string? OrderStatus { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? VendorId { get; init; }
|
||||
public string? TaxId { get; init; }
|
||||
public string? UpdatedById { get; init; }
|
||||
}
|
||||
|
||||
public class UpdatePurchaseOrderValidator : AbstractValidator<UpdatePurchaseOrderRequest>
|
||||
{
|
||||
public UpdatePurchaseOrderValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
RuleFor(x => x.OrderDate).NotEmpty();
|
||||
RuleFor(x => x.OrderStatus).NotEmpty();
|
||||
RuleFor(x => x.VendorId).NotEmpty();
|
||||
RuleFor(x => x.TaxId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdatePurchaseOrderHandler : IRequestHandler<UpdatePurchaseOrderRequest, UpdatePurchaseOrderResult>
|
||||
{
|
||||
private readonly ICommandRepository<PurchaseOrder> _repository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly PurchaseOrderService _purchaseOrderService;
|
||||
|
||||
public UpdatePurchaseOrderHandler(
|
||||
ICommandRepository<PurchaseOrder> repository,
|
||||
IUnitOfWork unitOfWork,
|
||||
PurchaseOrderService purchaseOrderService
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_purchaseOrderService = purchaseOrderService;
|
||||
}
|
||||
|
||||
public async Task<UpdatePurchaseOrderResult> Handle(UpdatePurchaseOrderRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var entity = await _repository.GetAsync(request.Id ?? string.Empty, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new Exception($"Entity not found: {request.Id}");
|
||||
}
|
||||
|
||||
entity.UpdatedById = request.UpdatedById;
|
||||
|
||||
entity.OrderDate = request.OrderDate;
|
||||
entity.OrderStatus = (PurchaseOrderStatus)int.Parse(request.OrderStatus!);
|
||||
entity.Description = request.Description;
|
||||
entity.VendorId = request.VendorId;
|
||||
entity.TaxId = request.TaxId;
|
||||
|
||||
_repository.Update(entity);
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
|
||||
_purchaseOrderService.Recalculate(entity.Id);
|
||||
|
||||
return new UpdatePurchaseOrderResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
using Application.Common.Extensions;
|
||||
using Application.Common.Repositories;
|
||||
using Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.PurchaseOrderManager;
|
||||
|
||||
public class PurchaseOrderService
|
||||
{
|
||||
private readonly ICommandRepository<PurchaseOrder> _purchaseOrderRepository;
|
||||
private readonly ICommandRepository<PurchaseOrderItem> _purchaseOrderItemRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public PurchaseOrderService(
|
||||
ICommandRepository<PurchaseOrder> purchaseOrderRepository,
|
||||
ICommandRepository<PurchaseOrderItem> purchaseOrderItemRepository,
|
||||
IUnitOfWork unitOfWork
|
||||
)
|
||||
{
|
||||
_purchaseOrderRepository = purchaseOrderRepository;
|
||||
_purchaseOrderItemRepository = purchaseOrderItemRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public void Recalculate(string purchaseOrderId)
|
||||
{
|
||||
var purchaseOrder = _purchaseOrderRepository
|
||||
.GetQuery()
|
||||
.IsDeletedEqualTo()
|
||||
.Where(x => x.Id == purchaseOrderId)
|
||||
.Include(x => x.Tax)
|
||||
.SingleOrDefault();
|
||||
|
||||
if (purchaseOrder == null)
|
||||
return;
|
||||
|
||||
var purchaseOrderItems = _purchaseOrderItemRepository
|
||||
.GetQuery()
|
||||
.IsDeletedEqualTo()
|
||||
.Where(x => x.PurchaseOrderId == purchaseOrderId)
|
||||
.ToList();
|
||||
|
||||
purchaseOrder.BeforeTaxAmount = purchaseOrderItems.Sum(x => x.Total ?? 0);
|
||||
|
||||
var taxPercentage = purchaseOrder.Tax?.Percentage ?? 0;
|
||||
purchaseOrder.TaxAmount = (purchaseOrder.BeforeTaxAmount ?? 0) * taxPercentage / 100;
|
||||
|
||||
purchaseOrder.AfterTaxAmount = (purchaseOrder.BeforeTaxAmount ?? 0) + (purchaseOrder.TaxAmount ?? 0);
|
||||
|
||||
_purchaseOrderRepository.Update(purchaseOrder);
|
||||
_unitOfWork.Save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.PurchaseOrderManager.Queries;
|
||||
|
||||
public record GetPurchaseOrderListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Number { get; init; }
|
||||
public DateTime? OrderDate { get; init; }
|
||||
public PurchaseOrderStatus? OrderStatus { get; init; }
|
||||
public string? OrderStatusName { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? VendorId { get; init; }
|
||||
public string? VendorName { get; init; }
|
||||
public string? TaxId { get; init; }
|
||||
public string? TaxName { get; init; }
|
||||
public double? BeforeTaxAmount { get; init; }
|
||||
public double? TaxAmount { get; init; }
|
||||
public double? AfterTaxAmount { get; init; }
|
||||
public DateTime? CreatedAtUtc { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderListProfile : Profile
|
||||
{
|
||||
public GetPurchaseOrderListProfile()
|
||||
{
|
||||
CreateMap<PurchaseOrder, GetPurchaseOrderListDto>()
|
||||
.ForMember(
|
||||
dest => dest.VendorName,
|
||||
opt => opt.MapFrom(src => src.Vendor != null ? src.Vendor.Name : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.TaxName,
|
||||
opt => opt.MapFrom(src => src.Tax != null ? src.Tax.Name : string.Empty)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.OrderStatusName,
|
||||
opt => opt.MapFrom(src => src.OrderStatus.HasValue ? src.OrderStatus.Value.ToFriendlyName() : string.Empty)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderListResult
|
||||
{
|
||||
public List<GetPurchaseOrderListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderListRequest : IRequest<GetPurchaseOrderListResult>
|
||||
{
|
||||
public bool IsDeleted { get; init; } = false;
|
||||
}
|
||||
|
||||
|
||||
public class GetPurchaseOrderListHandler : IRequestHandler<GetPurchaseOrderListRequest, GetPurchaseOrderListResult>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetPurchaseOrderListHandler(IMapper mapper, IQueryContext context)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetPurchaseOrderListResult> Handle(GetPurchaseOrderListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.PurchaseOrder
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(request.IsDeleted)
|
||||
.Include(x => x.Vendor)
|
||||
.Include(x => x.Tax)
|
||||
.AsQueryable();
|
||||
|
||||
var entities = await query.ToListAsync(cancellationToken);
|
||||
|
||||
var dtos = _mapper.Map<List<GetPurchaseOrderListDto>>(entities);
|
||||
|
||||
return new GetPurchaseOrderListResult
|
||||
{
|
||||
Data = dtos
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using AutoMapper;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.PurchaseOrderManager.Queries;
|
||||
|
||||
|
||||
public class GetPurchaseOrderSingleProfile : Profile
|
||||
{
|
||||
public GetPurchaseOrderSingleProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderSingleResult
|
||||
{
|
||||
public PurchaseOrder? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderSingleRequest : IRequest<GetPurchaseOrderSingleResult>
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderSingleValidator : AbstractValidator<GetPurchaseOrderSingleRequest>
|
||||
{
|
||||
public GetPurchaseOrderSingleValidator()
|
||||
{
|
||||
RuleFor(x => x.Id).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderSingleHandler : IRequestHandler<GetPurchaseOrderSingleRequest, GetPurchaseOrderSingleResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetPurchaseOrderSingleHandler(
|
||||
IQueryContext context
|
||||
)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetPurchaseOrderSingleResult> Handle(GetPurchaseOrderSingleRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context
|
||||
.PurchaseOrder
|
||||
.AsNoTracking()
|
||||
.Include(x => x.Vendor)
|
||||
.Include(x => x.Tax)
|
||||
.Include(x => x.PurchaseOrderItemList.Where(item => !item.IsDeleted))
|
||||
.ThenInclude(x => x.Product)
|
||||
.Where(x => x.Id == request.Id)
|
||||
.AsQueryable();
|
||||
|
||||
var entity = await query.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return new GetPurchaseOrderSingleResult
|
||||
{
|
||||
Data = entity
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Application.Common.Extensions;
|
||||
using AutoMapper;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace Application.Features.PurchaseOrderManager.Queries;
|
||||
|
||||
public record GetPurchaseOrderStatusListDto
|
||||
{
|
||||
public string? Id { get; init; }
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderStatusListProfile : Profile
|
||||
{
|
||||
public GetPurchaseOrderStatusListProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderStatusListResult
|
||||
{
|
||||
public List<GetPurchaseOrderStatusListDto>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseOrderStatusListRequest : IRequest<GetPurchaseOrderStatusListResult>
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public class GetPurchaseOrderStatusListHandler : IRequestHandler<GetPurchaseOrderStatusListRequest, GetPurchaseOrderStatusListResult>
|
||||
{
|
||||
|
||||
public GetPurchaseOrderStatusListHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<GetPurchaseOrderStatusListResult> Handle(GetPurchaseOrderStatusListRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var statuses = Enum.GetValues(typeof(PurchaseOrderStatus))
|
||||
.Cast<PurchaseOrderStatus>()
|
||||
.Select(status => new GetPurchaseOrderStatusListDto
|
||||
{
|
||||
Id = ((int)status).ToString(),
|
||||
Name = status.ToFriendlyName()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return new GetPurchaseOrderStatusListResult
|
||||
{
|
||||
Data = statuses
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user