Skip to content

Commit

Permalink
fix: product creation and unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
PedroNetto404 committed Aug 5, 2024
1 parent 0fda384 commit f777a26
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 138 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ public static class Product
public static readonly DomainError<ProductEntity> DeleteProductFailed = new("delete_product_failed", "Failed to delete product.");
public static readonly DomainError<ProductEntity> InvalidProductReviewScore = new("invalid_product_review_score", "Product can't have invalid review score");
public static readonly DomainError<ProductEntity> CannotDecreaseReviewScore = new("cannot_decrease_review_score", "Product review score can't be decreased");
public static readonly DomainError<ProductEntity> AlreadyExists = new("product_already_exists", "Product already exists.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Ardalis.Specification;
using FavoriteProducts.Domain.Resources.Products.ValueObjects;

namespace FavoriteProducts.Domain.Resources.Products.Specifications;

public sealed class GetProductByTitleSpecification : SingleResultSpecification<Product>
{
public GetProductByTitleSpecification(ProductTitle title) =>
Query
.Where(product => product.Title == title);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public sealed class ProductMapping : AuditableEntityMapping<Product>
public override void Configure(EntityTypeBuilder<Product> builder)
{
base.Configure(builder);

builder.ToTable("products");

builder.Property(x => x.Title)
Expand All @@ -23,7 +23,10 @@ public override void Configure(EntityTypeBuilder<Product> builder)
)
.HasAnnotation("MaxLength", ProductTitle.MaxLength)
.HasAnnotation("MinLength", ProductTitle.MinLength);


builder.HasIndex(x => x.Title)
.IsUnique();

builder.Property(p => p.ReviewScore)
.HasColumnName("review_score")
.IsRequired()
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace FavoriteProducts.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class addproducttitleuniqueindex : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_products_title",
table: "products",
column: "title",
unique: true);
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_products_title",
table: "products");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)

b.HasKey("Id");

b.HasIndex("Title")
.IsUnique();

b.ToTable("products", (string)null);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using FavoriteProducts.Domain.Core.Abstractions;
using FavoriteProducts.Domain.Core.Results;
using FavoriteProducts.Domain.Resources.Errors;
using FavoriteProducts.Domain.Resources.Products;
using FavoriteProducts.Domain.Resources.Products.Specifications;
using FavoriteProducts.Domain.Resources.Products.ValueObjects;
using FavoriteProducts.UseCases.Abstractions;
using FavoriteProducts.UseCases.Features.Products.Dtos;
Expand All @@ -12,27 +12,34 @@ public sealed class CreateProductCommandHandler(
IRepository<Product> productRepository) : ICommandHandler<CreateProductCommand, ProductDto>
{
public async Task<Result<ProductDto>> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
var maybeFields = TryBuildFields(request);
if (maybeFields.IsFailure)
{
var maybeTitle = ProductTitle.Create(request.Title);
var maybeDescription = ProductDescription.Create(request.Description);
var maybePrice = ProductPrice.Create(request.Price);
var maybeBrand = ProductBrand.Create(request.Brand);
var maybeReviewScore = ProductReviewScore.Create(request.ReviewScore);
var composed = new List<Result>
{
return maybeFields.Error;
}

var (
maybeTitle,
maybeBrand,
maybeDescription,
maybePrice,
maybeBrand,
maybeReviewScore
) = maybeFields.Value;
};
if (composed.Any(result => result.IsFailure))
{
return Error.MultipleErrors(composed.Select(result => result.Error));
}

var existingProduct = await productRepository.SingleOrDefaultAsync(
new GetProductByTitleSpecification(maybeTitle.Value), cancellationToken);

var maybeProduct = Product.Create(
maybeTitle,
maybeDescription,
maybePrice,
maybeBrand,
maybeReviewScore,
maybeTitle.Value,
maybeDescription.Value,
maybePrice.Value,
maybeBrand.Value,
maybeReviewScore.Value,
request.ImageUrl);
if (maybeProduct.IsFailure)
{
Expand All @@ -42,47 +49,4 @@ public async Task<Result<ProductDto>> Handle(CreateProductCommand request, Cance
var product = await productRepository.AddAsync(maybeProduct.Value, cancellationToken);
return ProductDto.FromEntity(product);
}

private static Result<(ProductTitle, ProductBrand, ProductDescription, ProductPrice, ProductReviewScore)>
TryBuildFields(
CreateProductCommand request)
{
var maybeTitle = ProductTitle.Create(request.Title);
if (maybeTitle.IsFailure)
{
return maybeTitle.Error;
}

var maybeBrand = ProductBrand.Create(request.Brand);
if (maybeBrand.IsFailure)
{
return maybeBrand.Error;
}

var maybeDescription = ProductDescription.Create(request.Description);
if (maybeDescription.IsFailure)
{
return maybeDescription.Error;
}

var maybePrice = ProductPrice.Create(request.Price);
if (maybePrice.IsFailure)
{
return maybePrice.Error;
}

var maybeReviewScore = ProductReviewScore.Create(request.ReviewScore);
if (maybeReviewScore.IsFailure)
{
return maybeReviewScore.Error;
}

return (
maybeTitle.Value,
maybeBrand.Value,
maybeDescription.Value,
maybePrice.Value,
maybeReviewScore.Value
);
}
}
Loading

0 comments on commit f777a26

Please sign in to comment.