Skip to content

Commit

Permalink
feat: Review per reviewer (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
taustad authored Oct 4, 2023
1 parent fc4ce30 commit 0638c48
Show file tree
Hide file tree
Showing 21 changed files with 255 additions and 9 deletions.
41 changes: 41 additions & 0 deletions datasheetapi/Adapters/ReviewerAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace datasheetapi.Adapters;
public static class ReviewerAdapter
{
public static ReviewerDto? ToDtoOrNull(this Reviewer? tagDataReview)
{
if (tagDataReview is null) { return null; }
return tagDataReview.ToDto();
}

private static ReviewerDto ToDto(this Reviewer tagDataReview)
{
return new ReviewerDto
{
Status = tagDataReview.Status.MapReviewStatusModelToDto(),
ReviewerId = tagDataReview.ReviewerId,
TagDataReviewId = tagDataReview.TagDataReviewId,
CreatedDate = tagDataReview.CreatedDate,
ModifiedDate = tagDataReview.ModifiedDate,
};
}

public static List<ReviewerDto> ToDto(this List<Reviewer>? tagDataReviews)
{
if (tagDataReviews is null) { return new List<ReviewerDto>(); }
return tagDataReviews.Select(ToDto).ToList();
}

public static Reviewer ToModel(this CreateReviewerDto tagDataReviewDto)
{
return new Reviewer
{
Status = ReviewStatusEnum.New,
ReviewerId = tagDataReviewDto.ReviewerId,
};
}

public static List<Reviewer> ToModel(this List<CreateReviewerDto> tagDataReviewDtos)
{
return tagDataReviewDtos.Select(x => ToModel(x)).ToList();
}
}
7 changes: 5 additions & 2 deletions datasheetapi/Adapters/TagDataReviewAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,13 @@ public static List<TagDataReviewDto> ToDto(this List<TagDataReview>? tagDataRevi

public static TagDataReview ToModel(this CreateTagDataReviewDto tagDataReviewDto)
{
return new TagDataReview
var reviewers = tagDataReviewDto.Reviewers?.ToModel();
var model = new TagDataReview
{
TagNo = tagDataReviewDto.TagNo,
Status = tagDataReviewDto.Status.MapReviewStatusDtoToModel(),
Reviewers = reviewers ?? new List<Reviewer>(),
};

return model;
}
}
2 changes: 0 additions & 2 deletions datasheetapi/Controllers/TagDataController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public TagDataController(ILoggerFactory loggerFactory, ITagDataService tagDataSe
[HttpGet("{tagNo}", Name = "GetTagDataByTagNo")]
public async Task<ActionResult<ITagDataDto>> GetTagDataById([Required] string tagNo)
{

var tagData = await _tagDataService.GetTagDataByTagNo(tagNo);

var tagDataDto = tagData.ToDto();
Expand All @@ -37,7 +36,6 @@ public async Task<ActionResult<ITagDataDto>> GetTagDataById([Required] string ta
[HttpGet(Name = "GetAllTagData")]
public async Task<ActionResult<List<ITagDataDto>>> GetAllTagData()
{

var allTagData = await _tagDataService.GetAllTagData();
var tagDataDtos = allTagData.ToDto();

Expand Down
15 changes: 14 additions & 1 deletion datasheetapi/Controllers/TagDataReviewsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ public class TagDataReviewsController : ControllerBase
{
private readonly ILogger<TagDataReviewsController> _logger;
private readonly ITagDataReviewService _reviewService;
private readonly IReviewerService _reviewerService;

public TagDataReviewsController(ILoggerFactory loggerFactory,
ITagDataReviewService reviewService)
ITagDataReviewService reviewService, IReviewerService reviewerService)
{
_logger = loggerFactory.CreateLogger<TagDataReviewsController>();
_reviewService = reviewService;
_reviewerService = reviewerService;
}

[HttpGet("{reviewId}", Name = "GetReviewById")]
Expand All @@ -50,4 +52,15 @@ public async Task<ActionResult<List<TagDataReviewDto>>> GetReviews()
reviewDto.ToModel(), Utils.GetAzureUniqueId(HttpContext.User));
return result.ToDtoOrNull();
}

[HttpPost("{reviewId}/reviewers", Name = "CreateReviewers")]
public async Task<ActionResult<List<ReviewerDto>?>> CreateReviewers(
[NotEmptyGuid] Guid reviewId,
[Required] List<CreateReviewerDto> reviewDtos)
{
var result = await _reviewerService.CreateReviewers(
reviewId, reviewDtos.ToModel());

return result.ToDto();
}
}
6 changes: 4 additions & 2 deletions datasheetapi/Database/DatabaseContext.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;


namespace api.Database;

public class DatabaseContext : DbContext
Expand All @@ -18,11 +16,15 @@ public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options
public DbSet<RevisionContainerTagNo> RevisionContainerTagNos { get; set; } = null!;
public DbSet<RevisionContainerReview> RevisionContainerReviews { get; set; } = null!;
public DbSet<TagDataReview> TagDataReviews { get; set; } = null!;
public DbSet<Reviewer> Reviewers { get; set; } = null!;
public DbSet<Project> Projects { get; set; } = null!;

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Participant>()
.HasKey(e => new { e.UserId, e.ConversationId });

modelBuilder.Entity<Reviewer>()
.HasKey(e => new { e.ReviewerId, e.TagDataReviewId });
}
}
9 changes: 9 additions & 0 deletions datasheetapi/Dtos/CreateReviewerDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;

namespace datasheetapi.Dtos;
public record CreateReviewerDto
{
[Required]
[NotEmptyGuid]
public Guid ReviewerId { get; set; }
}
1 change: 1 addition & 0 deletions datasheetapi/Dtos/CreateTagDataReviewDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ public record CreateTagDataReviewDto
public string TagNo { get; set; } = string.Empty;
[Required]
public ReviewStatusDto Status { get; set; }
public List<CreateReviewerDto>? Reviewers { get; set; }
}
14 changes: 14 additions & 0 deletions datasheetapi/Dtos/ReviewerDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;

namespace datasheetapi.Dtos;
public record ReviewerDto
{
[Required]
public ReviewStatusDto Status { get; set; }

public DateTime CreatedDate { get; set; }
public DateTime ModifiedDate { get; set; }

public Guid ReviewerId { get; set; }
public Guid TagDataReviewId { get; set; }
}
2 changes: 0 additions & 2 deletions datasheetapi/Models/Conversation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.ComponentModel.DataAnnotations;

namespace datasheetapi.Models;

public class Conversation : BaseEntity
Expand Down
12 changes: 12 additions & 0 deletions datasheetapi/Models/Reviewer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace datasheetapi.Models;

public class Reviewer
{
public ReviewStatusEnum Status { get; set; }

public DateTime CreatedDate { get; set; }
public DateTime ModifiedDate { get; set; }

public Guid TagDataReviewId { get; set; }
public Guid ReviewerId { get; set; }
}
1 change: 1 addition & 0 deletions datasheetapi/Models/TagDataReview.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class TagDataReview : BaseEntity
// Relationships
public string? TagNo { get; set; }
public List<Conversation> Conversations { get; set; } = new List<Conversation>();
public List<Reviewer> Reviewers { get; set; } = new List<Reviewer>();
}

public enum ReviewStatusEnum
Expand Down
2 changes: 2 additions & 0 deletions datasheetapi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@
builder.Services.AddScoped<IFusionService, FusionService>();
builder.Services.AddScoped<IProjectService, ProjectService>();
builder.Services.AddScoped<IFusionPeopleService, FusionPeopleService>();
builder.Services.AddScoped<IReviewerService, ReviewerService>();
builder.Services.AddScoped<IReviewerRepository, ReviewerRepository>();

builder.Services.AddSingleton<IFAMService, DummyFAMService>();

Expand Down
7 changes: 7 additions & 0 deletions datasheetapi/Repositories/IReviewerRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace datasheetapi.Repositories
{
public interface IReviewerRepository
{
Task<List<Reviewer>> CreateReviewers(List<Reviewer> review);
}
}
1 change: 1 addition & 0 deletions datasheetapi/Repositories/ITagDataReviewRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace datasheetapi.Repositories;
public interface ITagDataReviewRepository
{
Task<TagDataReview?> GetTagDataReview(Guid id);
Task<bool> AnyTagDataReview(Guid id);
Task<List<TagDataReview>> GetTagDataReviews();
Task<List<TagDataReview>> GetTagDataReviewsForTag(string tagNo);
Task<List<TagDataReview>> GetTagDataReviewsForTags(List<string> tagNos);
Expand Down
29 changes: 29 additions & 0 deletions datasheetapi/Repositories/ReviewerRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using api.Database;

namespace datasheetapi.Repositories;

public class ReviewerRepository : IReviewerRepository
{
private readonly DatabaseContext _context;
private readonly ILogger<ReviewerRepository> _logger;

public ReviewerRepository(ILoggerFactory loggerFactory, DatabaseContext context)
{
_logger = loggerFactory.CreateLogger<ReviewerRepository>();
_context = context;
}

public async Task<List<Reviewer>> CreateReviewers(List<Reviewer> reviewers)
{
reviewers.ForEach(r =>
{
r.CreatedDate = DateTime.UtcNow;
r.ModifiedDate = DateTime.UtcNow;
});

_context.Reviewers.AddRange(reviewers);
await _context.SaveChangesAsync();

return reviewers;
}
}
12 changes: 12 additions & 0 deletions datasheetapi/Repositories/TagDataReviewRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public TagDataReviewRepository(ILoggerFactory loggerFactory, DatabaseContext con
return review;
}

public async Task<bool> AnyTagDataReview(Guid id)
{
var exists = await _context.TagDataReviews.AnyAsync(c => c.Id == id);
return exists;
}

public async Task<List<TagDataReview>> GetTagDataReviews()
{
var reviews = await _context.TagDataReviews.ToListAsync();
Expand All @@ -46,6 +52,12 @@ public async Task<TagDataReview> AddTagDataReview(TagDataReview review)
review.CreatedDate = DateTime.UtcNow;
review.ModifiedDate = DateTime.UtcNow;

review.Reviewers.ForEach(r =>
{
r.CreatedDate = DateTime.UtcNow;
r.ModifiedDate = DateTime.UtcNow;
});

var savedReview = _context.TagDataReviews.Add(review);
await _context.SaveChangesAsync();

Expand Down
7 changes: 7 additions & 0 deletions datasheetapi/Services/IReviewerService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace datasheetapi.Services
{
public interface IReviewerService
{
Task<List<Reviewer>> CreateReviewers(Guid reviewId, List<Reviewer> reviewers);
}
}
1 change: 1 addition & 0 deletions datasheetapi/Services/ITagDataReviewService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace datasheetapi.Services;
public interface ITagDataReviewService
{
Task<TagDataReview> GetTagDataReview(Guid id);
Task<bool> AnyTagDataReview(Guid reviewId);
Task<List<TagDataReview>> GetTagDataReviews();
Task<List<TagDataReview>> GetTagDataReviewsForTag(string tagNo);
Task<List<TagDataReview>> GetTagDataReviewsForTags(List<string> tagNos);
Expand Down
30 changes: 30 additions & 0 deletions datasheetapi/Services/ReviewerService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using datasheetapi.Exceptions;
using datasheetapi.Repositories;

namespace datasheetapi.Services;

public class ReviewerService : IReviewerService
{
private readonly ITagDataReviewService _reviewService;

private readonly IReviewerRepository _reviewerRepository;

public ReviewerService(
ITagDataReviewService reviewService,
IReviewerRepository reviewerRepository)
{
_reviewService = reviewService;
_reviewerRepository = reviewerRepository;
}

public async Task<List<Reviewer>> CreateReviewers(Guid reviewId, List<Reviewer> reviewers)
{
if (!await _reviewService.AnyTagDataReview(reviewId)) { throw new NotFoundException($"Invalid reviewId - {reviewId}."); }

reviewers.ForEach(r => r.TagDataReviewId = reviewId);

var result = await _reviewerRepository.CreateReviewers(reviewers);

return result;
}
}
6 changes: 6 additions & 0 deletions datasheetapi/Services/TagDataReviewService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public async Task<TagDataReview> GetTagDataReview(Guid reviewId)
return review ?? throw new NotFoundException($"Invalid reviewId - {reviewId}.");
}

public async Task<bool> AnyTagDataReview(Guid reviewId)
{
var exists = await _reviewRepository.AnyTagDataReview(reviewId);
return exists;
}

public async Task<List<TagDataReview>> GetTagDataReviews()
{
var reviews = await _reviewRepository.GetTagDataReviews();
Expand Down
59 changes: 59 additions & 0 deletions tests/Services/ReviewerServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using datasheetapi.Exceptions;
using datasheetapi.Models;
using datasheetapi.Repositories;
using datasheetapi.Services;

using Moq;

namespace tests.Services;
public class ReviewerServiceTests
{
private readonly Mock<ITagDataReviewService> _reviewService = new();
private readonly Mock<IReviewerRepository> _reviewerRepository = new();

private readonly ReviewerService _reviewerService;

public ReviewerServiceTests()
{
_reviewerService = new ReviewerService(
_reviewService.Object,
_reviewerRepository.Object);
}

[Fact]
public async Task CreateReviewerTagDataReview_ThrowsIfReviewDoesNotExist()
{
List<Reviewer> reviewers = new()
{
new Reviewer { Status = 0, ReviewerId = Guid.NewGuid() }
};
var reviewId = Guid.NewGuid();

_reviewService.Setup(x => x.AnyTagDataReview(reviewId)).ThrowsAsync(new NotFoundException($"Invalid reviewId - {reviewId}."));

await Assert.ThrowsAsync<NotFoundException>(() => _reviewerService.CreateReviewers(reviewId, reviewers));
}

[Fact]
public async Task CreateReviewerTagDataReview_RunsOkayWithCorrectInput()
{
List<Reviewer> reviewers = new()
{
new Reviewer { Status = 0, ReviewerId = Guid.NewGuid() },
new Reviewer { Status = 0, ReviewerId = Guid.NewGuid() }
};

var reviewId = Guid.NewGuid();

_reviewService.Setup(x => x.AnyTagDataReview(reviewId)).ReturnsAsync(true);

_reviewerRepository.Setup(x => x.CreateReviewers(reviewers)).ReturnsAsync(reviewers);

var result = await _reviewerService.CreateReviewers(reviewId, reviewers);

Assert.NotNull(result);
Assert.Equal(reviewers, result);
_reviewService.Verify(x => x.AnyTagDataReview(reviewId), Times.Once);
_reviewerRepository.Verify(x => x.CreateReviewers(reviewers), Times.Once);
}
}

0 comments on commit 0638c48

Please sign in to comment.