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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/Admin.API/Controllers/ReportController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Application;
using Application.DTO;
using Application.Interfaces.Queries;
using Application.Interfaces.Services;
using Domain.Entities.Admin;

namespace Admin.API.Controllers;

[Authorize]
[ApiController]
[Route("reports")]
public class ReportController : ControllerBase
{
private readonly IReportsService _reportsService;
private readonly IReportsQueryService _reportsQueryService;

public ReportController(IReportsService reportsService, IReportsQueryService reportsQueryService)
{
_reportsService = reportsService;
_reportsQueryService = reportsQueryService;
}

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> Create(ReportDTO reportDTO)
{
await _reportsService.CreateReport(reportDTO);
return new StatusCodeResult(StatusCodes.Status201Created);
}

[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<ICollection<Report>>> GetAll() => Ok(await _reportsQueryService.GetAllAsync());

[HttpGet("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<ReportDTO>> GetById(int id) => Ok(await _reportsQueryService.GetByIdAsync(id));

[HttpGet("getByTargetEntityId")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<ICollection<Report>>> GetByTargetEntityId(ReportTargetEntities entity)
=> Ok(await _reportsQueryService.GetByTargetEntityIdAsync(entity));
}
14 changes: 14 additions & 0 deletions src/Application/DTO/ReportDTO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;

namespace Application.DTO;

public record ReportDTO
{
[Required]
public int? TargetId { get; init; }
[Required]
public int? TargetEntityId { get; init; }
[Required]
public int? CategoryId { get; init; }
public string? Description { get; init; }
}
8 changes: 8 additions & 0 deletions src/Application/Enums/ReportTargetEntities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Application;

public enum ReportTargetEntities
{
Person = 1,
Club = 2,
Post = 3
}
10 changes: 10 additions & 0 deletions src/Application/Interfaces/Queries/IReportsQueryService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Domain.Entities.Admin;

namespace Application.Interfaces.Queries;

public interface IReportsQueryService
{
public Task<ICollection<Report>> GetAllAsync();
public Task<Report> GetByIdAsync(int id);
public Task<ICollection<Report>> GetByTargetEntityIdAsync(ReportTargetEntities entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Domain.Entities.Admin;

namespace Application.Interfaces.Repositories.Admin;

public interface IReportCategoriesRepository : IRepository
{
public Task<ReportCategory?> GetByIdAsync(int id);
public Task CreateAsync(ReportCategory reportCategory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Domain.Entities.Admin;

namespace Application.Interfaces.Repositories.Admin;

public interface IReportEntitiesRepository : IRepository
{
public Task<ReportEntity?> GetByIdAsync(int id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Domain.Entities.Admin;

namespace Application.Interfaces.Repositories.Admin;

public interface IReportsRepository : IRepository
{
public Task<Report?> GetByIdAsync(int id);
public Task CreateAsync(Report report);
public Task UpdateAsync(Report report);
}
8 changes: 8 additions & 0 deletions src/Application/Interfaces/Services/IReportsService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Application.DTO;

namespace Application.Interfaces.Services;

public interface IReportsService
{
public Task CreateReport(ReportDTO report);
}
80 changes: 80 additions & 0 deletions src/Application/Services/ReportsService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using Domain.Entities.Admin;
using Domain.Entities.Club;
using Domain.Entities.Person;
using Domain.Entities.Post;
using Application.DTO;
using Application.Exceptions;
using Application.Interfaces.Repositories.Admin;
using Application.Interfaces.Repositories.Club;
using Application.Interfaces.Repositories.Person;
using Application.Interfaces.Repositories.Post;
using Application.Interfaces.Services;

namespace Application.Services;

public class ReportsService : IReportsService
{
private readonly IReportsRepository _reportsRepository;
private readonly IReportCategoriesRepository _reportCategoriesRepository;
private readonly IReportEntitiesRepository _reportEntitiesRepository;
private readonly IPersonsRepository _personsRepository;
private readonly IPostsRepository _postsRepository;
private readonly IClubsRepository _clubsRepository;
private readonly ISessionService _sessionService;

public ReportsService(IReportsRepository reportsRepository, IReportCategoriesRepository reportCategoriesRepository,
IReportEntitiesRepository reportEntitiesRepository, IPersonsRepository personsRepository,
IPostsRepository postsRepository, IClubsRepository clubsRepository, ISessionService sessionService)
{
_reportsRepository = reportsRepository;
_reportCategoriesRepository = reportCategoriesRepository;
_reportEntitiesRepository = reportEntitiesRepository;
_personsRepository = personsRepository;
_postsRepository = postsRepository;
_clubsRepository = clubsRepository;
_sessionService = sessionService;
}

public async Task CreateReport(ReportDTO reportDTO)
{
if (await _reportEntitiesRepository.GetByIdAsync(reportDTO.TargetEntityId!.Value) is null)
throw new NotFoundException(nameof(ReportEntity), reportDTO.TargetEntityId.Value);

var reportCategory = await _reportCategoriesRepository.GetByIdAsync(reportDTO.CategoryId!.Value);
if (reportCategory is null)
throw new NotFoundException(nameof(ReportCategory), reportDTO.CategoryId.Value);
if (reportCategory.ReportEntityId != reportDTO.TargetEntityId.Value)
throw new ArgumentException("Некорректная категория");

var report = new Report
{
ReporterId = _sessionService.PersonId,
CategoryId = reportDTO.CategoryId!.Value,
Description = reportDTO.Description,
IsActive = true
};

switch (reportDTO.TargetEntityId.Value)
{
case (int) ReportTargetEntities.Person:
if (await _personsRepository.GetByIdAsync(reportDTO.TargetId!.Value) is null)
throw new NotFoundException(nameof(PersonModel), reportDTO.TargetId.Value);
report.TargetPersonId = reportDTO.TargetId;
break;
case (int) ReportTargetEntities.Club:
if (await _clubsRepository.GetByIdAsync(reportDTO.TargetId!.Value) is null)
throw new NotFoundException(nameof(ClubModel), reportDTO.TargetId.Value);
report.TargetClubId = reportDTO.TargetId;
break;
case (int) ReportTargetEntities.Post:
if (await _postsRepository.GetByIdAsync(reportDTO.TargetId!.Value) is null)
throw new NotFoundException(nameof(PostModel), reportDTO.TargetId.Value);
report.TargetPostId = reportDTO.TargetId;
break;
default:
throw new ArgumentException("Указана некорректная сущность при создании жалобы");
}

await _reportsRepository.CreateAsync(report);
}
}
13 changes: 13 additions & 0 deletions src/Domain/Entities/Admin/Report.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Domain.Entities.Admin;

public class Report
{
public int Id { get; set; }
public int ReporterId { get; set; }
public int? TargetPersonId { get; set; }
public int? TargetClubId { get; set; }
public int? TargetPostId { get; set; }
public int CategoryId { get; set; }
public string? Description { get; set; }
public bool IsActive { get; set; }
}
8 changes: 8 additions & 0 deletions src/Domain/Entities/Admin/ReportCategory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Domain.Entities.Admin;

public class ReportCategory
{
public int Id { get; set; }
public int ReportEntityId { get; set; }
public string Name { get; set; }
}
7 changes: 7 additions & 0 deletions src/Domain/Entities/Admin/ReportEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Domain.Entities.Admin;

public class ReportEntity
{
public int Id { get; set; }
public string Name { get; set; }

Check warning on line 6 in src/Domain/Entities/Admin/ReportEntity.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
}
2 changes: 2 additions & 0 deletions src/Infrastructure/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public static IServiceCollection AddAdminServices(this IServiceCollection servic
_logger.Debug("Начата регистрация сервисов панели администрирования");
services.AddTransient<IClubCreationRequestsService, ClubCreationRequestsService>();
services.AddTransient<IClubCreationRequestsQueryService, ClubCreationRequestsQueryService>();
services.AddTransient<IReportsService, ReportsService>();
services.AddTransient<IReportsQueryService, ReportsQueryService>();
_logger.Debug("Завершена регистрация сервисов панели администрирования");
return services;
}
Expand Down
3 changes: 3 additions & 0 deletions src/Infrastructure/Persistence/Data/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public class ApplicationDbContext : DbContext
public DbSet<PostDetailDTO> v_PostDetails { get; set; }
public DbSet<CommentDetailDTO> v_CommentDetails { get; set; }
public DbSet<ClubCreationRequestDetailsDTO> v_ClubCreationRequestDetails { get; set; }
public DbSet<ReportEntity> t_ReportEntities { get; set; }
public DbSet<ReportCategory> t_ReportCategories { get; set; }
public DbSet<Report> t_Reports { get; set; }

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore;
using Domain.Entities.Admin;
using Application.Interfaces.Repositories.Admin;
using Infrastructure.Persistence.Data;

namespace Infrastructure.Persistence.Repositories.Admin;

public class ReportCategoriesRepository : IReportCategoriesRepository
{
private readonly ApplicationDbContext _applicationDbContext;
private readonly DbSet<ReportCategory> _reportCategories;

public ReportCategoriesRepository(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
_reportCategories = _applicationDbContext.Set<ReportCategory>();
}

public async Task<ReportCategory?> GetByIdAsync(int id) => await _reportCategories.FindAsync(id);

public async Task CreateAsync(ReportCategory reportCategory)
{
_reportCategories.Add(reportCategory);
await _applicationDbContext.SaveChangesAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.EntityFrameworkCore;
using Domain.Entities.Admin;
using Application.Interfaces.Repositories.Admin;
using Infrastructure.Persistence.Data;

namespace Infrastructure.Persistence.Repositories.Admin;

public class ReportEntitiesRepository : IReportEntitiesRepository
{
private readonly DbSet<ReportEntity> _reportEntities;
private readonly ApplicationDbContext _applicationDbContext;

public ReportEntitiesRepository(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
_reportEntities = _applicationDbContext.Set<ReportEntity>();
}

public async Task<ReportEntity?> GetByIdAsync(int id) => await _reportEntities.FindAsync(id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Application.Interfaces.Repositories.Admin;
using Domain.Entities.Admin;
using Infrastructure.Persistence.Data;
using Microsoft.EntityFrameworkCore;

namespace Infrastructure.Persistence.Repositories.Admin;

public class ReportsRepository : IReportsRepository
{
private readonly ApplicationDbContext _applicationDbContext;
private readonly DbSet<Report> _reports;

public ReportsRepository(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
_reports = _applicationDbContext.Set<Report>();
}

public async Task<Report?> GetByIdAsync(int id) => await _reports.FindAsync(id);

public async Task CreateAsync(Report report)
{
_reports.Add(report);
await _applicationDbContext.SaveChangesAsync();
}

public async Task UpdateAsync(Report report)
{
_reports.Update(report);
await _applicationDbContext.SaveChangesAsync();
}
}
46 changes: 46 additions & 0 deletions src/Infrastructure/Services/Queries/ReportsQueryService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Application;
using Microsoft.EntityFrameworkCore;
using Domain.Entities.Admin;
using Application.Exceptions;
using Application.Interfaces.Queries;
using Infrastructure.Persistence.Data;

namespace Infrastructure.Services.Queries;

public class ReportsQueryService : IReportsQueryService
{
private readonly DbSet<Report> _reports;

public ReportsQueryService(ApplicationDbContext context)
{
_reports = context.t_Reports;
}

public async Task<ICollection<Report>> GetAllAsync() => await _reports.ToListAsync();

public async Task<Report> GetByIdAsync(int id)
{
var report = await _reports.FindAsync(id);
if (report is null)
throw new NotFoundException(nameof(Report), id);
return report;
}

public async Task<ICollection<Report>> GetByTargetEntityIdAsync(ReportTargetEntities entity)
{
ICollection<Report> reports = new List<Report>();
switch (entity)
{
case ReportTargetEntities.Person:
reports = await _reports.Where(r => r.TargetPersonId != null).ToListAsync();
break;
case ReportTargetEntities.Club:
reports = await _reports.Where(r => r.TargetClubId != null).ToListAsync();
break;
case ReportTargetEntities.Post:
reports = await _reports.Where(r => r.TargetPostId != null).ToListAsync();
break;
}
return reports;
}
}
Loading