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
19 changes: 18 additions & 1 deletion OrderTrackingApp.Api/Controllers/OrdersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
using Microsoft.AspNetCore.Mvc;
using OrderTrackingApp.Api.Examples;
using OrderTrackingApp.Api.Models;
using OrderTrackingApp.Application.Commands.Orders;
using OrderTrackingApp.Application.Orders.Commands;
using OrderTrackingApp.Application.Orders.Queries;
using Swashbuckle.AspNetCore.Filters;

namespace OrderTrackingApp.Api.Controllers
Expand All @@ -23,5 +24,21 @@ public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest reque

return CreatedAtAction(nameof(CreateOrder), new { id = orderId }, new { OrderId = orderId });
}

[HttpGet("{id}")]
public async Task<IActionResult> GetOrderById(Guid id)
{
var order = await mediator.Send(new GetOrderByIdQuery(id));
return Ok(order);
}

[HttpGet]
public async Task<IActionResult> GetOrders([FromQuery] GetOrdersRequest request)
{
var query = mapper.Map<GetOrdersQuery>(request);

var orders = await mediator.Send(query);
return Ok(orders);
}
}
}
1 change: 1 addition & 0 deletions OrderTrackingApp.Api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ WORKDIR /src

COPY ["OrderTrackingApp.Api/OrderTrackingApp.Api.csproj", "OrderTrackingApp.Api/"]
COPY ["OrderTrackingApp.Application/OrderTrackingApp.Application.csproj", "OrderTrackingApp.Application/"]
COPY ["OrderTrackingApp.Application.Contracts/OrderTrackingApp.Application.Contracts.csproj", "OrderTrackingApp.Application.Contracts/"]
COPY ["OrderTrackingApp.Domain/OrderTrackingApp.Domain.csproj", "OrderTrackingApp.Domain/"]
COPY ["OrderTrackingApp.Infrastructure/OrderTrackingApp.Infrastructure.csproj", "OrderTrackingApp.Infrastructure/"]
COPY ["OrderTrackingApp.Persistence/OrderTrackingApp.Persistence.csproj", "OrderTrackingApp.Persistence/"]
Expand Down
2 changes: 1 addition & 1 deletion OrderTrackingApp.Api/Extensions/ApiServiceRegistrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static IServiceCollection AddApiServices(this IServiceCollection services
});

services.AddValidatorsFromAssemblyContaining<CreateOrderRequestValidator>();
services.AddAutoMapper(config => { }, typeof(OrderMappingProfile).Assembly);
services.AddAutoMapper(config => { }, typeof(OrderProfile).Assembly);

return services;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using AutoMapper;
using OrderTrackingApp.Api.Models;
using OrderTrackingApp.Application.Commands.Orders;
using OrderTrackingApp.Application.Orders.Commands;
using OrderTrackingApp.Application.Orders.Queries;

namespace OrderTrackingApp.Api.MappingProfiles
{
public class OrderMappingProfile : Profile
public class OrderProfile : Profile
{
public OrderMappingProfile()
public OrderProfile()
{
CreateMap<CreateOrderRequest, CreateOrderCommand>();
CreateMap<CreateOrderItemRequest, CreateOrderItemDto>();

CreateMap<GetOrdersRequest, GetOrdersQuery>();
}
}
}
15 changes: 15 additions & 0 deletions OrderTrackingApp.Api/Models/GetOrdersRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace OrderTrackingApp.Api.Models
{
public class GetOrdersRequest
{
public int Page { get; set; } = 1;

public int PageSize { get; set; } = 50;

public string? Status { get; set; }

public DateTime? FromDate { get; set; }

public DateTime? ToDate { get; set; }
}
}
2 changes: 1 addition & 1 deletion OrderTrackingApp.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"AllowedHosts": "*",
"ConnectionStrings": {
"SqlConnection": "Server=localhost,1433;Database=OrderDb;User=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True",
"MongoDb": "mongodb://mongoadmin:secret123@localhost:27017",
"MongoDb": "mongodb://admin:secret@localhost:27017",
"RabbitMq": "amqp://guest:guest@localhost:5672/"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\OrderTrackingApp.Domain\OrderTrackingApp.Domain.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

namespace OrderTrackingApp.Application.Contracts.Orders
{
public interface IOrderReadRepository
{
Task<OrderDto?> GetByIdAsync(Guid id);

Task<List<OrderDto>> GetAllAsync();

Task InsertAsync(OrderDto order);

Task<PaginatedResult<OrderDto>> GetPaginatedOrdersAsync(int page, int pageSize, string? status,
DateTime? fromDate, DateTime? toDate,
CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace OrderTrackingApp.Application.Contracts.Orders
{
public interface IOrderWriteRepository
{
Task AddAsync(OrderDto order);

Task UpdateAsync(OrderDto order);

Task DeleteAsync(Guid id);

Task<OrderDto?> GetByIdAsync(Guid id);
}
}
28 changes: 28 additions & 0 deletions OrderTrackingApp.Application.Contracts/Orders/OrderDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using OrderTrackingApp.Domain.Entities;

namespace OrderTrackingApp.Application.Contracts.Orders
{
public class OrderDto
{
public Guid Id { get; set; }

public string OrderNumber { get; set; } = string.Empty;

public OrderStatus Status { get; set; }

public DateTime CreatedAt { get; set; }

public Guid CustomerId { get; set; }

public List<OrderItemDto> Items { get; set; } = [];
}

public class OrderItemDto
{
public Guid ProductId { get; set; }

public int Quantity { get; set; }

public decimal UnitPrice { get; set; }
}
}
13 changes: 13 additions & 0 deletions OrderTrackingApp.Application.Contracts/PaginatedResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace OrderTrackingApp.Application.Contracts
{
public class PaginatedResult<T>(List<T> items, long totalCount, int page, int pageSize)
{
public List<T> Items { get; } = items;

public long TotalCount { get; } = totalCount;

public int Page { get; } = page;

public int PageSize { get; } = pageSize;
}
}
15 changes: 0 additions & 15 deletions OrderTrackingApp.Application/DTOs/OrderDto.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using OrderTrackingApp.Application.Commands.Orders;
using OrderTrackingApp.Application.MappingProfiles;
using OrderTrackingApp.Application.Orders.Commands;

namespace OrderTrackingApp.Application.Extensions
{
Expand All @@ -8,6 +9,7 @@ public static class ApplicationServiceRegistrations
public static IServiceCollection AddApplicationServices(this IServiceCollection services)
{
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(CreateOrderCommandHandler).Assembly));
services.AddAutoMapper(config => { }, typeof(OrderProfile).Assembly);
return services;
}
}
Expand Down
15 changes: 0 additions & 15 deletions OrderTrackingApp.Application/Interfaces/IOrderWriteRepository.cs

This file was deleted.

15 changes: 15 additions & 0 deletions OrderTrackingApp.Application/MappingProfiles/OrderProfile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using AutoMapper;
using OrderTrackingApp.Application.Contracts.Orders;
using OrderTrackingApp.Domain.Entities;

namespace OrderTrackingApp.Application.MappingProfiles
{
public class OrderProfile : Profile
{
public OrderProfile()
{
CreateMap<Order, OrderDto>().ReverseMap();
CreateMap<OrderItem, OrderItemDto>().ReverseMap();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="15.0.1" />
<PackageReference Include="MediatR" Version="13.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\OrderTrackingApp.Application.Contracts\OrderTrackingApp.Application.Contracts.csproj" />
<ProjectReference Include="..\OrderTrackingApp.Domain\OrderTrackingApp.Domain.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using MediatR;

namespace OrderTrackingApp.Application.Commands.Orders
namespace OrderTrackingApp.Application.Orders.Commands
{
public class CreateOrderCommand : IRequest<Guid>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
using MediatR;
using OrderTrackingApp.Application.Interfaces;
using OrderTrackingApp.Application.Contracts.Orders;
using OrderTrackingApp.Domain.Entities;
using OrderTrackingApp.Domain.Events;
using OrderTrackingApp.Domain.Interfaces;

namespace OrderTrackingApp.Application.Commands.Orders
namespace OrderTrackingApp.Application.Orders.Commands
{
public class CreateOrderCommandHandler(IOrderWriteRepository orderRepository, IProductRepository productRepository, IMediator mediator)
public class CreateOrderCommandHandler(IOrderWriteRepository orderRepository, IProductRepository productRepository, IMediator mediator)
: IRequestHandler<CreateOrderCommand, Guid>
{
public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
{
var orderItems = new List<OrderItem>();
var orderItems = new List<OrderItemDto>();
var updatedProducts = new List<Product>();

var productIds = request.Items.Select(item => item.ProductId).ToList();
Expand All @@ -30,7 +30,7 @@ public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken can
throw new InvalidOperationException($"Insufficient stock for product {product.Name}. Available: {product.StockQuantity}, Requested: {item.Quantity}.");
}

orderItems.Add(new OrderItem { ProductId = item.ProductId, Quantity = item.Quantity, UnitPrice = product.Price });
orderItems.Add(new OrderItemDto { ProductId = item.ProductId, Quantity = item.Quantity, UnitPrice = product.Price });

product.StockQuantity -= item.Quantity;

Expand All @@ -39,12 +39,12 @@ public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken can

await productRepository.UpdateProducts(updatedProducts);

var order = new Order
var order = new OrderDto
{
Id = Guid.NewGuid(),
OrderNumber = $"ORD-{DateTime.UtcNow.Ticks}",
CustomerId = request.CustomerId,
OrderDate = DateTime.UtcNow,
CreatedAt = DateTime.UtcNow,
Status = OrderStatus.Pending,
Items = orderItems
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using MediatR;
using OrderTrackingApp.Application.Contracts.Orders;

namespace OrderTrackingApp.Application.Orders.Queries
{
public record GetOrderByIdQuery(Guid OrderId) : IRequest<OrderDto>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using MediatR;
using OrderTrackingApp.Application.Contracts.Orders;

namespace OrderTrackingApp.Application.Orders.Queries
{
public class GetOrderByIdQueryHandler(IOrderReadRepository orderReadRepository) : IRequestHandler<GetOrderByIdQuery, OrderDto>
{
public async Task<OrderDto> Handle(GetOrderByIdQuery request, CancellationToken cancellationToken)
{
var order = await orderReadRepository.GetByIdAsync(request.OrderId);
return order ?? throw new Exception($"Order not found for ID {request.OrderId}");
}
}
}
19 changes: 19 additions & 0 deletions OrderTrackingApp.Application/Orders/Queries/GetOrdersQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using MediatR;
using OrderTrackingApp.Application.Contracts;
using OrderTrackingApp.Application.Contracts.Orders;

namespace OrderTrackingApp.Application.Orders.Queries
{
public record GetOrdersQuery : IRequest<PaginatedResult<OrderDto>>
{
public int Page { get; set; } = 1;

public int PageSize { get; set; } = 50;

public string? Status { get; set; }

public DateTime? FromDate { get; set; }

public DateTime? ToDate { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using MediatR;
using OrderTrackingApp.Application.Contracts;
using OrderTrackingApp.Application.Contracts.Orders;

namespace OrderTrackingApp.Application.Orders.Queries
{
public class GetOrdersQueryHandler(IOrderReadRepository orderReadRepository) : IRequestHandler<GetOrdersQuery, PaginatedResult<OrderDto>>
{
public async Task<PaginatedResult<OrderDto>> Handle(GetOrdersQuery request, CancellationToken cancellationToken)
{
return await orderReadRepository.GetPaginatedOrdersAsync(
page: request.Page,
pageSize: request.PageSize,
status: request.Status,
fromDate: request.FromDate,
toDate: request.ToDate,
cancellationToken: cancellationToken);
}
}
}
1 change: 1 addition & 0 deletions OrderTrackingApp.Consumer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ WORKDIR /src

COPY ["OrderTrackingApp.Consumer/OrderTrackingApp.Consumer.csproj", "OrderTrackingApp.Consumer/"]
COPY ["OrderTrackingApp.Application/OrderTrackingApp.Application.csproj", "OrderTrackingApp.Application/"]
COPY ["OrderTrackingApp.Application.Contracts/OrderTrackingApp.Application.Contracts.csproj", "OrderTrackingApp.Application.Contracts/"]
COPY ["OrderTrackingApp.Domain/OrderTrackingApp.Domain.csproj", "OrderTrackingApp.Domain/"]
COPY ["OrderTrackingApp.Infrastructure/OrderTrackingApp.Infrastructure.csproj", "OrderTrackingApp.Infrastructure/"]
COPY ["OrderTrackingApp.Persistence/OrderTrackingApp.Persistence.csproj", "OrderTrackingApp.Persistence/"]
Expand Down
1 change: 1 addition & 0 deletions OrderTrackingApp.Consumer/OrderTrackingApp.Consumer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\OrderTrackingApp.Application\OrderTrackingApp.Application.csproj" />
<ProjectReference Include="..\OrderTrackingApp.Persistence\OrderTrackingApp.Persistence.csproj" />
<ProjectReference Include="..\OrderTrackingApp.ReadPersistence\OrderTrackingApp.ReadPersistence.csproj" />
</ItemGroup>
Expand Down
Loading