Merge pull request #10 from bytegrip/dev

Dev
This commit was merged in pull request #10.
This commit is contained in:
Daniel
2025-06-21 23:38:41 +03:00
committed by GitHub
115 changed files with 1064 additions and 630 deletions

View File

@@ -1,9 +1,8 @@
using Imprink.Application.Categories.Dtos;
using Imprink.Application.Products.Dtos;
using Imprink.Domain.Entities.Products;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
using MediatR;
namespace Imprink.Application.Categories.Commands;
namespace Imprink.Application.Commands.Categories;
public class CreateCategoryCommand : IRequest<CategoryDto>
{

View File

@@ -1,10 +1,10 @@
using MediatR;
namespace Imprink.Application.Categories.Commands;
namespace Imprink.Application.Commands.Categories;
public class DeleteCategoryCommand : IRequest<bool>
{
public Guid Id { get; set; }
public Guid Id { get; init; }
}
public class DeleteCategoryHandler(IUnitOfWork unitOfWork) : IRequestHandler<DeleteCategoryCommand, bool>

View File

@@ -1,9 +1,8 @@
using Imprink.Application.Categories.Dtos;
using Imprink.Application.Products.Dtos;
using Imprink.Domain.Entities.Products;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
using MediatR;
namespace Imprink.Application.Categories.Commands;
namespace Imprink.Application.Commands.Categories;
public class GetCategoriesQuery : IRequest<IEnumerable<CategoryDto>>
{

View File

@@ -1,9 +1,8 @@
using Imprink.Application.Categories.Dtos;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Products.Dtos;
using MediatR;
namespace Imprink.Application.Categories.Commands;
namespace Imprink.Application.Commands.Categories;
public class UpdateCategoryCommand : IRequest<CategoryDto>
{

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using Imprink.Application.ProductVariants.Dtos;
using Imprink.Domain.Entities.Products;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
using MediatR;
namespace Imprink.Application.ProductVariants.Commands;
namespace Imprink.Application.Commands.ProductVariants;
public class CreateProductVariantCommand : IRequest<ProductVariantDto>
{

View File

@@ -1,6 +1,6 @@
using MediatR;
namespace Imprink.Application.ProductVariants.Commands;
namespace Imprink.Application.Commands.ProductVariants;
public class DeleteProductVariantCommand : IRequest<bool>
{

View File

@@ -1,10 +1,10 @@
using AutoMapper;
using Imprink.Application.ProductVariants.Dtos;
using Imprink.Domain.Entities.Products;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
using MediatR;
using Microsoft.Extensions.Logging;
namespace Imprink.Application.ProductVariants.Commands;
namespace Imprink.Application.Commands.ProductVariants;
public class GetProductVariantsQuery : IRequest<IEnumerable<ProductVariantDto>>
{

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.ProductVariants.Dtos;
using MediatR;
namespace Imprink.Application.ProductVariants.Commands;
namespace Imprink.Application.Commands.ProductVariants;
public class UpdateProductVariantCommand : IRequest<ProductVariantDto>
{

View File

@@ -0,0 +1,37 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
using MediatR;
namespace Imprink.Application.Commands.Products;
public class CreateProductCommand : IRequest<ProductDto>
{
public string Name { get; set; } = null!;
public string? Description { get; set; }
public decimal BasePrice { get; set; }
public bool IsCustomizable { get; set; }
public bool IsActive { get; set; } = true;
public string? ImageUrl { get; set; }
public Guid? CategoryId { get; set; }
}
public class CreateProductHandler(IUnitOfWork uw, IMapper mapper) : IRequestHandler<CreateProductCommand, ProductDto>
{
public async Task<ProductDto> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
return await uw.TransactAsync(async () =>
{
var product = mapper.Map<Product>(request);
var createdProduct = await uw.ProductRepository.AddAsync(product, cancellationToken);
if (createdProduct.CategoryId.HasValue)
{
createdProduct.Category =
(await uw.CategoryRepository.GetByIdAsync(createdProduct.CategoryId.Value, cancellationToken))!;
}
return mapper.Map<ProductDto>(createdProduct);
}, cancellationToken);
}
}

View File

@@ -0,0 +1,27 @@
using Imprink.Application.Exceptions;
using MediatR;
namespace Imprink.Application.Commands.Products;
public class DeleteProductCommand : IRequest
{
public Guid Id { get; set; }
}
public class DeleteProductHandler(IUnitOfWork uw) : IRequestHandler<DeleteProductCommand>
{
public async Task Handle(DeleteProductCommand request, CancellationToken cancellationToken)
{
await uw.TransactAsync(async () =>
{
var exists = await uw.ProductRepository.ExistsAsync(request.Id, cancellationToken);
if (!exists)
{
throw new NotFoundException($"Product with id {request.Id} not found");
}
await uw.ProductRepository.DeleteAsync(request.Id, cancellationToken);
}, cancellationToken);
}
}

View File

@@ -1,9 +1,8 @@
using Imprink.Application.Categories.Dtos;
using Imprink.Application.Products.Dtos;
using Imprink.Application.Dtos;
using Imprink.Domain.Models;
using MediatR;
namespace Imprink.Application.Products.Commands;
namespace Imprink.Application.Commands.Products;
public class GetProductsQuery : IRequest<PagedResultDto<ProductDto>>
{

View File

@@ -1,9 +1,8 @@
using Imprink.Application.Categories.Dtos;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Products.Dtos;
using MediatR;
namespace Imprink.Application.Products.Commands;
namespace Imprink.Application.Commands.Products;
public class UpdateProductCommand : IRequest<ProductDto>
{

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Users.Dtos;
using MediatR;
namespace Imprink.Application.Users.Commands;
namespace Imprink.Application.Commands.Users;
public record DeleteUserRoleCommand(string Sub, Guid RoleId) : IRequest<UserRoleDto?>;

View File

@@ -1,8 +1,8 @@
using AutoMapper;
using Imprink.Application.Users.Dtos;
using Imprink.Application.Dtos;
using MediatR;
namespace Imprink.Application.Users.Commands;
namespace Imprink.Application.Commands.Users;
public record GetAllRolesCommand : IRequest<IEnumerable<RoleDto>>;

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Users.Dtos;
using MediatR;
namespace Imprink.Application.Users.Commands;
namespace Imprink.Application.Commands.Users;
public record GetUserRolesCommand(string Sub) : IRequest<IEnumerable<RoleDto>>;

View File

@@ -1,10 +1,10 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Users.Dtos;
using Imprink.Application.Users.Services;
using Imprink.Application.Services;
using MediatR;
namespace Imprink.Application.Users.Commands;
namespace Imprink.Application.Commands.Users;
public record SetUserFullNameCommand(string FirstName, string LastName) : IRequest<UserDto?>;

View File

@@ -1,10 +1,10 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Users.Dtos;
using Imprink.Application.Users.Services;
using Imprink.Application.Services;
using MediatR;
namespace Imprink.Application.Users.Commands;
namespace Imprink.Application.Commands.Users;
public record SetUserPhoneCommand(string PhoneNumber) : IRequest<UserDto?>;

View File

@@ -1,10 +1,10 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Users.Dtos;
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
using MediatR;
namespace Imprink.Application.Users.Commands;
namespace Imprink.Application.Commands.Users;
public record SetUserRoleCommand(string Sub, Guid RoleId) : IRequest<UserRoleDto?>;

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using Imprink.Application.Users.Dtos;
using Imprink.Application.Dtos;
using Imprink.Domain.Models;
using MediatR;
namespace Imprink.Application.Users.Commands;
namespace Imprink.Application.Commands.Users;
public record SyncUserCommand(Auth0User User) : IRequest<UserDto?>;

View File

@@ -1,4 +1,4 @@
namespace Imprink.Application.Categories.Dtos;
namespace Imprink.Application.Dtos;
public class CategoryDto
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Application.Products.Dtos;
namespace Imprink.Application.Dtos;
public class PagedResultDto<T>
{

View File

@@ -1,6 +1,4 @@
using Imprink.Application.Categories.Dtos;
namespace Imprink.Application.Products.Dtos;
namespace Imprink.Application.Dtos;
public class ProductDto
{

View File

@@ -1,6 +1,4 @@
using Imprink.Application.Products.Dtos;
namespace Imprink.Application.ProductVariants.Dtos;
namespace Imprink.Application.Dtos;
public class ProductVariantDto
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Application.Users.Dtos;
namespace Imprink.Application.Dtos;
public class RoleDto
{

View File

@@ -1,7 +1,6 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
namespace Imprink.Application.Users.Dtos;
namespace Imprink.Application.Dtos;
public class UserDto
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Application.Users.Dtos;
namespace Imprink.Application.Dtos;
public class UserRoleDto
{

View File

@@ -1,7 +1,4 @@
using Imprink.Domain.Repositories;
using Imprink.Domain.Repositories.Orders;
using Imprink.Domain.Repositories.Products;
using Imprink.Domain.Repositories.Users;
namespace Imprink.Application;
@@ -20,4 +17,6 @@ public interface IUnitOfWork
Task BeginTransactionAsync(CancellationToken cancellationToken = default);
Task CommitTransactionAsync(CancellationToken cancellationToken = default);
Task RollbackTransactionAsync(CancellationToken cancellationToken = default);
Task<T> TransactAsync<T>(Func<Task<T>> operation, CancellationToken cancellationToken = default);
Task TransactAsync(Func<Task> operation, CancellationToken cancellationToken = default);
}

View File

@@ -2,4 +2,4 @@ using AutoMapper;
namespace Imprink.Application;
public abstract class MappingProfile : Profile { }
public abstract class MappingProfile : Profile;

View File

@@ -1,12 +1,10 @@
using AutoMapper;
using Imprink.Application.Categories.Dtos;
using Imprink.Application.Products.Commands;
using Imprink.Application.Products.Dtos;
using Imprink.Application.ProductVariants.Commands;
using Imprink.Application.ProductVariants.Dtos;
using Imprink.Domain.Entities.Products;
using Imprink.Application.Commands.Products;
using Imprink.Application.Commands.ProductVariants;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
namespace Imprink.Application.Products.Mappings;
namespace Imprink.Application.Mappings;
public class ProductMappingProfile: Profile
{

View File

@@ -1,10 +1,10 @@
using System.Security.Claims;
using AutoMapper;
using Imprink.Application.Users.Dtos;
using Imprink.Domain.Entities.Users;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
using Imprink.Domain.Models;
namespace Imprink.Application.Users.Mappings;
namespace Imprink.Application.Mappings;
public class UserMappingProfile: Profile
{

View File

@@ -1,46 +0,0 @@
using AutoMapper;
using Imprink.Application.Products.Dtos;
using Imprink.Domain.Entities.Products;
using MediatR;
namespace Imprink.Application.Products.Commands;
public class CreateProductCommand : IRequest<ProductDto>
{
public string Name { get; set; } = null!;
public string? Description { get; set; }
public decimal BasePrice { get; set; }
public bool IsCustomizable { get; set; }
public bool IsActive { get; set; } = true;
public string? ImageUrl { get; set; }
public Guid? CategoryId { get; set; }
}
public class CreateProductHandler(IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler<CreateProductCommand, ProductDto>
{
public async Task<ProductDto> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
await unitOfWork.BeginTransactionAsync(cancellationToken);
try
{
var product = mapper.Map<Product>(request);
var createdProduct = await unitOfWork.ProductRepository.AddAsync(product, cancellationToken);
if (createdProduct.CategoryId.HasValue)
{
createdProduct.Category = (await unitOfWork.CategoryRepository.GetByIdAsync(createdProduct.CategoryId.Value, cancellationToken))!;
}
await unitOfWork.CommitTransactionAsync(cancellationToken);
return mapper.Map<ProductDto>(createdProduct);
}
catch
{
await unitOfWork.RollbackTransactionAsync(cancellationToken);
throw;
}
}
}

View File

@@ -1,35 +0,0 @@
using MediatR;
namespace Imprink.Application.Products.Commands;
public class DeleteProductCommand : IRequest<bool>
{
public Guid Id { get; set; }
}
public class DeleteProductHandler(IUnitOfWork unitOfWork) : IRequestHandler<DeleteProductCommand, bool>
{
public async Task<bool> Handle(DeleteProductCommand request, CancellationToken cancellationToken)
{
await unitOfWork.BeginTransactionAsync(cancellationToken);
try
{
var exists = await unitOfWork.ProductRepository.ExistsAsync(request.Id, cancellationToken);
if (!exists)
{
await unitOfWork.RollbackTransactionAsync(cancellationToken);
return false;
}
await unitOfWork.ProductRepository.DeleteAsync(request.Id, cancellationToken);
await unitOfWork.CommitTransactionAsync(cancellationToken);
return true;
}
catch
{
await unitOfWork.RollbackTransactionAsync(cancellationToken);
throw;
}
}
}

View File

@@ -1,4 +1,4 @@
namespace Imprink.Application.Users.Services;
namespace Imprink.Application.Services;
public interface ICurrentUserService
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Categories.Commands;
using Imprink.Application.Commands.Categories;
namespace Imprink.Application.Categories.Validation;
namespace Imprink.Application.Validation.Categories;
public class CreateCategoryCommandValidator : AbstractValidator<CreateCategoryCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Categories.Commands;
using Imprink.Application.Commands.Categories;
namespace Imprink.Application.Categories.Validation;
namespace Imprink.Application.Validation.Categories;
public class DeleteCategoryCommandValidator : AbstractValidator<DeleteCategoryCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Categories.Commands;
using Imprink.Application.Commands.Categories;
namespace Imprink.Application.Categories.Validation;
namespace Imprink.Application.Validation.Categories;
public class UpdateCategoryCommandValidator : AbstractValidator<UpdateCategoryCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Domain.Models;
namespace Imprink.Application.Orders.Validation;
namespace Imprink.Application.Validation.Orders;
public class OrderFilterParametersValidator : AbstractValidator<OrderFilterParameters>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.ProductVariants.Commands;
using Imprink.Application.Commands.ProductVariants;
namespace Imprink.Application.ProductVariants.Validation;
namespace Imprink.Application.Validation.ProductVariants;
public class CreateProductVariantCommandValidator : AbstractValidator<CreateProductVariantCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.ProductVariants.Commands;
using Imprink.Application.Commands.ProductVariants;
namespace Imprink.Application.ProductVariants.Validation;
namespace Imprink.Application.Validation.ProductVariants;
public class DeleteProductVariantCommandValidator : AbstractValidator<DeleteProductVariantCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.ProductVariants.Commands;
using Imprink.Application.Commands.ProductVariants;
namespace Imprink.Application.ProductVariants.Validation;
namespace Imprink.Application.Validation.ProductVariants;
public class GetProductVariantsQueryValidator : AbstractValidator<GetProductVariantsQuery>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.ProductVariants.Commands;
using Imprink.Application.Commands.ProductVariants;
namespace Imprink.Application.ProductVariants.Validation;
namespace Imprink.Application.Validation.ProductVariants;
public class UpdateProductVariantCommandValidator : AbstractValidator<UpdateProductVariantCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Products.Commands;
using Imprink.Application.Commands.Products;
namespace Imprink.Application.Products.Validation;
namespace Imprink.Application.Validation.Products;
public class CreateProductCommandValidator : AbstractValidator<CreateProductCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Products.Commands;
using Imprink.Application.Commands.Products;
namespace Imprink.Application.Products.Validation;
namespace Imprink.Application.Validation.Products;
public class DeleteProductCommandValidator : AbstractValidator<DeleteProductCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Products.Commands;
using Imprink.Application.Commands.Products;
namespace Imprink.Application.Products.Validation;
namespace Imprink.Application.Validation.Products;
public class GetProductsQueryValidator : AbstractValidator<GetProductsQuery>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Domain.Models;
namespace Imprink.Application.Products.Validation;
namespace Imprink.Application.Validation.Products;
public class ProductFilterParametersValidator : AbstractValidator<ProductFilterParameters>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Products.Commands;
using Imprink.Application.Commands.Products;
namespace Imprink.Application.Products.Validation;
namespace Imprink.Application.Validation.Products;
public class UpdateProductCommandValidator : AbstractValidator<UpdateProductCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Domain.Models;
namespace Imprink.Application.Users.Validation;
namespace Imprink.Application.Validation.Users;
public class Auth0UserValidator : AbstractValidator<Auth0User>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Users.Commands;
using Imprink.Application.Commands.Users;
namespace Imprink.Application.Users.Validation;
namespace Imprink.Application.Validation.Users;
public class SetUserFullNameCommandValidator : AbstractValidator<SetUserFullNameCommand>
{

View File

@@ -1,7 +1,7 @@
using FluentValidation;
using Imprink.Application.Users.Commands;
using Imprink.Application.Commands.Users;
namespace Imprink.Application.Users.Validation;
namespace Imprink.Application.Validation.Users;
public class SetUserPhoneCommandValidator : AbstractValidator<SetUserPhoneCommand>
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Domain.Entities.Users;
namespace Imprink.Domain.Entities;
public class Address : EntityBase
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Domain.Entities.Products;
namespace Imprink.Domain.Entities;
public class Category : EntityBase
{

View File

@@ -1,6 +1,4 @@
using Imprink.Domain.Entities.Users;
namespace Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities;
public class Order : EntityBase
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities;
public class OrderAddress : EntityBase
{

View File

@@ -1,6 +1,4 @@
using Imprink.Domain.Entities.Products;
namespace Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities;
public class OrderItem : EntityBase
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities;
public class OrderStatus
{

View File

@@ -1,6 +1,4 @@
using Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities.Products;
namespace Imprink.Domain.Entities;
public class Product : EntityBase
{

View File

@@ -1,6 +1,4 @@
using Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities.Products;
namespace Imprink.Domain.Entities;
public class ProductVariant : EntityBase
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Domain.Entities.Users;
namespace Imprink.Domain.Entities;
public class Role
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities;
public class ShippingStatus
{

View File

@@ -1,6 +1,4 @@
using Imprink.Domain.Entities.Orders;
namespace Imprink.Domain.Entities.Users;
namespace Imprink.Domain.Entities;
public class User
{

View File

@@ -1,4 +1,4 @@
namespace Imprink.Domain.Entities.Users;
namespace Imprink.Domain.Entities;
public class UserRole
{

View File

@@ -0,0 +1,6 @@
namespace Imprink.Domain.Models;
public class BaseFilterParameters
{
// ToDo
}

View File

@@ -1,6 +1,6 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities;
namespace Imprink.Domain.Repositories.Products;
namespace Imprink.Domain.Repositories;
public interface ICategoryRepository
{

View File

@@ -1,6 +1,6 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
namespace Imprink.Domain.Repositories.Orders;
namespace Imprink.Domain.Repositories;
public interface IOrderItemRepository
{

View File

@@ -1,7 +1,7 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
using Imprink.Domain.Models;
namespace Imprink.Domain.Repositories.Orders;
namespace Imprink.Domain.Repositories;
public interface IOrderRepository
{

View File

@@ -1,7 +1,7 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities;
using Imprink.Domain.Models;
namespace Imprink.Domain.Repositories.Products;
namespace Imprink.Domain.Repositories;
public interface IProductRepository
{

View File

@@ -1,6 +1,6 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities;
namespace Imprink.Domain.Repositories.Products;
namespace Imprink.Domain.Repositories;
public interface IProductVariantRepository
{

View File

@@ -1,6 +1,6 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
namespace Imprink.Domain.Repositories.Users;
namespace Imprink.Domain.Repositories;
public interface IRoleRepository
{

View File

@@ -1,7 +1,7 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
using Imprink.Domain.Models;
namespace Imprink.Domain.Repositories.Users;
namespace Imprink.Domain.Repositories;
public interface IUserRepository
{

View File

@@ -1,6 +1,6 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
namespace Imprink.Domain.Repositories.Users;
namespace Imprink.Domain.Repositories;
public interface IUserRoleRepository
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Users.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class AddressConfiguration : EntityBaseConfiguration<Address>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Categories.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class CategoryConfiguration : EntityBaseConfiguration<Category>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Orders.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class OrderAddressConfiguration : EntityBaseConfiguration<OrderAddress>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Orders.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class OrderConfiguration : EntityBaseConfiguration<Order>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Orders.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class OrderItemConfiguration : EntityBaseConfiguration<OrderItem>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Orders.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class OrderStatusConfiguration : IEntityTypeConfiguration<OrderStatus>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Products.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class ProductConfiguration : EntityBaseConfiguration<Product>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.ProductVariants.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class ProductVariantConfiguration : EntityBaseConfiguration<ProductVariant>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Users.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class RoleConfiguration : IEntityTypeConfiguration<Role>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Orders.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class ShippingStatusConfiguration : IEntityTypeConfiguration<ShippingStatus>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Users.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class UserConfiguration : IEntityTypeConfiguration<User>
{

View File

@@ -1,8 +1,8 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Users.Configuration;
namespace Imprink.Infrastructure.Configuration;
public class UserRoleConfiguration : IEntityTypeConfiguration<UserRole>
{

View File

@@ -1,11 +1,5 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities.Users;
using Imprink.Infrastructure.Categories.Configuration;
using Imprink.Infrastructure.Orders.Configuration;
using Imprink.Infrastructure.Products.Configuration;
using Imprink.Infrastructure.ProductVariants.Configuration;
using Imprink.Infrastructure.Users.Configuration;
using Imprink.Domain.Entities;
using Imprink.Infrastructure.Configuration;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

View File

@@ -25,7 +25,6 @@
<ItemGroup>
<Folder Include="Migrations\" />
<Folder Include="Orders\Repositories\Repositories\" />
</ItemGroup>
</Project>

View File

@@ -1,9 +1,9 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Repositories.Products;
using Imprink.Domain.Entities;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Categories.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class CategoryRepository(ApplicationDbContext context) : ICategoryRepository
{

View File

@@ -1,9 +1,9 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Repositories.Orders;
using Imprink.Domain.Entities;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Orders.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class OrderItemRepository(ApplicationDbContext context) : IOrderItemRepository
{

View File

@@ -1,10 +1,10 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities;
using Imprink.Domain.Models;
using Imprink.Domain.Repositories.Orders;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Orders.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class OrderRepository(ApplicationDbContext context) : IOrderRepository
{

View File

@@ -1,10 +1,10 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Entities;
using Imprink.Domain.Models;
using Imprink.Domain.Repositories.Products;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Products.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class ProductRepository(ApplicationDbContext context) : IProductRepository
{

View File

@@ -1,9 +1,9 @@
using Imprink.Domain.Entities.Products;
using Imprink.Domain.Repositories.Products;
using Imprink.Domain.Entities;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.ProductVariants.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class ProductVariantRepository(ApplicationDbContext context) : IProductVariantRepository
{

View File

@@ -1,9 +1,9 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Repositories.Users;
using Imprink.Domain.Entities;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Users.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class RoleRepository(ApplicationDbContext context) : IRoleRepository
{

View File

@@ -1,10 +1,10 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Entities;
using Imprink.Domain.Models;
using Imprink.Domain.Repositories.Users;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Users.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class UserRepository(ApplicationDbContext context) : IUserRepository
{

View File

@@ -1,9 +1,9 @@
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Repositories.Users;
using Imprink.Domain.Entities;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Users.Repositories;
namespace Imprink.Infrastructure.Repositories;
public class UserRoleRepository(ApplicationDbContext context) : IUserRoleRepository
{

View File

@@ -1,5 +1,5 @@
using System.Security.Claims;
using Imprink.Application.Users.Services;
using Imprink.Application.Services;
using Microsoft.AspNetCore.Http;
namespace Imprink.Infrastructure.Services;

View File

@@ -1,8 +1,5 @@
using Imprink.Application;
using Imprink.Domain.Repositories;
using Imprink.Domain.Repositories.Orders;
using Imprink.Domain.Repositories.Products;
using Imprink.Domain.Repositories.Users;
using Imprink.Infrastructure.Database;
namespace Imprink.Infrastructure;
@@ -46,4 +43,37 @@ public class UnitOfWork(
{
await context.Database.RollbackTransactionAsync(cancellationToken);
}
public async Task<T> TransactAsync<T>(Func<Task<T>> operation, CancellationToken cancellationToken = default)
{
await BeginTransactionAsync(cancellationToken);
try
{
var result = await operation();
await SaveAsync(cancellationToken);
await CommitTransactionAsync(cancellationToken);
return result;
}
catch
{
await RollbackTransactionAsync(cancellationToken);
throw;
}
}
public async Task TransactAsync(Func<Task> operation, CancellationToken cancellationToken = default)
{
await BeginTransactionAsync(cancellationToken);
try
{
await operation();
await SaveAsync(cancellationToken);
await CommitTransactionAsync(cancellationToken);
}
catch
{
await RollbackTransactionAsync(cancellationToken);
throw;
}
}
}

View File

@@ -1,6 +1,5 @@
using Imprink.Application.Categories.Commands;
using Imprink.Application.Categories.Dtos;
using Imprink.Application.Products.Dtos;
using Imprink.Application.Commands.Categories;
using Imprink.Application.Dtos;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

View File

@@ -1,6 +1,5 @@
using Imprink.Application.Products.Dtos;
using Imprink.Application.ProductVariants.Commands;
using Imprink.Application.ProductVariants.Dtos;
using Imprink.Application.Commands.ProductVariants;
using Imprink.Application.Dtos;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

View File

@@ -1,6 +1,5 @@
using Imprink.Application.Products;
using Imprink.Application.Products.Commands;
using Imprink.Application.Products.Dtos;
using Imprink.Application.Commands.Products;
using Imprink.Application.Dtos;
using Imprink.Domain.Models;
using MediatR;
using Microsoft.AspNetCore.Authorization;
@@ -16,9 +15,9 @@ public class ProductsController(IMediator mediator) : ControllerBase
[HttpGet]
[AllowAnonymous]
public async Task<ActionResult<PagedResultDto<ProductDto>>> GetProducts(
[FromQuery] ProductFilterParameters filterParameters)
[FromQuery] ProductFilterParameters filterParameters, CancellationToken cancellationToken)
{
var result = await mediator.Send(new GetProductsQuery { FilterParameters = filterParameters});
var result = await mediator.Send(new GetProductsQuery { FilterParameters = filterParameters}, cancellationToken);
return Ok(result);
}

View File

@@ -0,0 +1,83 @@
using Microsoft.AspNetCore.Mvc;
using Stripe;
namespace Imprink.WebApi.Controllers;
public record CreatePaymentIntentRequest(int Amount, string OrderId);
[ApiController]
[Route("api/stripe")]
public class StripeController : ControllerBase
{
[HttpPost("create-payment-intent")]
public async Task<IActionResult> CreatePaymentIntent([FromBody] CreatePaymentIntentRequest request)
{
try
{
var options = new PaymentIntentCreateOptions
{
Amount = request.Amount,
Currency = "usd",
PaymentMethodTypes = ["card"],
Metadata = new Dictionary<string, string>
{
{ "order_id", request.OrderId }
}
};
var service = new PaymentIntentService();
var paymentIntent = await service.CreateAsync(options);
return Ok(new { clientSecret = paymentIntent.ClientSecret });
}
catch (StripeException ex)
{
return BadRequest(new { error = ex.Message });
}
}
[HttpPost("webhook")]
public async Task<IActionResult> HandleWebhook()
{
var json = await new StreamReader(Request.Body).ReadToEndAsync();
try
{
var stripeEvent = EventUtility.ConstructEvent(
json,
Request.Headers["Stripe-Signature"],
"whsec_9HyZxZ2HseAkiuRvr4MEP4ntcns9n7FA"
);
Console.WriteLine($"Received Stripe event: {stripeEvent.Type}");
if (stripeEvent.Type == "payment_intent.succeeded")
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
var orderId = paymentIntent?.Metadata?.GetValueOrDefault("order_id") ?? "Unknown";
Console.WriteLine($"✅ Order {orderId} confirmed");
}
else if (stripeEvent.Type == "payment_intent.payment_failed")
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
var orderId = paymentIntent?.Metadata?.GetValueOrDefault("order_id") ?? "Unknown";
Console.WriteLine($"❌ Order {orderId} payment failed");
}
return Ok();
}
catch (StripeException ex)
{
Console.WriteLine($"Webhook error: {ex.Message}");
return BadRequest();
}
}
[HttpGet("health")]
public IActionResult HealthCheck()
{
return Ok(new { status = "OK" });
}
}

View File

@@ -1,13 +1,13 @@
using System.Security.Claims;
using AutoMapper;
using Imprink.Application.Users.Commands;
using Imprink.Application.Users.Dtos;
using Imprink.Application.Commands.Users;
using Imprink.Application.Dtos;
using Imprink.Domain.Models;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Imprink.WebApi.Controllers.Users;
namespace Imprink.WebApi.Controllers;
[ApiController]
[Route("/api/users")]

Some files were not shown because too many files have changed in this diff Show More