Skip to content

feat: separate payment domain #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 17, 2024
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
2 changes: 1 addition & 1 deletion Bmb Payment.sln
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bmb.Orders.Gateway.Test", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bmb.Payment.DynamoDb.Test", "tests\Bmb.Payment.DynamoDb.Test\Bmb.Payment.DynamoDb.Test.csproj", "{C5464D10-B602-4B01-A14C-560536BB9563}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bmb.Payment.Core", "src\Bmb.Payment.Core\Bmb.Payment.Core.csproj", "{C616857B-CB67-4904-9787-4FC78963CE50}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bmb.Payment.Domain", "src\Bmb.Payment.Domain\Bmb.Payment.Domain.csproj", "{C616857B-CB67-4904-9787-4FC78963CE50}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bmb.Payment.Masstransit", "src\Bmb.Payment.Masstransit\Bmb.Payment.Masstransit.csproj", "{FA002C5A-0B24-4986-BA44-A9E09A8BA553}"
EndProject
Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Orders.Gateway/Bmb.Orders.Gateway.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Bmb.Payment.Core\Bmb.Payment.Core.csproj" />
<ProjectReference Include="..\Bmb.Payment.Domain\Bmb.Payment.Domain.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Orders.Gateway/Presenter.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Text.Json;
using Amazon.DynamoDBv2.Model;
using Bmb.Domain.Core.Entities;
using Bmb.Payment.Core;
using Bmb.Payment.Domain;

namespace Bmb.Orders.Gateway;

Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Orders.Gateway/Repository/InMemoryOrdersGateway.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Core;
using Bmb.Payment.Domain;

namespace Bmb.Orders.Gateway.Repository;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Amazon.DynamoDBv2.Model;
using Bmb.Domain.Core.Base;
using Bmb.Domain.Core.Entities;
using Bmb.Payment.Core;
using Bmb.Payment.Domain;

namespace Bmb.Orders.Gateway.Repository;

Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Orders.Gateway/ServiceCollectionsExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Bmb.Orders.Gateway.Repository;
using Bmb.Payment.Core;
using Bmb.Payment.Domain;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Refactor cross-domain dependency to respect bounded contexts

The verification reveals a significant coupling between Orders and Payment domains:

  • OrderDto is defined in Payment.Domain but represents an Order entity
  • IOrdersGateway interface is also defined in Payment.Domain but implemented in Orders.Gateway
  • The DTO contains payment-specific fields (PaymentId) mixed with order data

Recommendations:

  • Move OrderDto and IOrdersGateway to a shared kernel or contracts project
  • Split the DTO into OrderDto (in Orders domain) and PaymentOrderDto (in Payment domain)
  • Consider using domain events for cross-boundary communication instead of direct references
🔗 Analysis chain

Review the domain dependency between Orders and Payment

While the namespace change from Core to Domain better reflects DDD principles, the direct reference from Orders.Gateway to Payment.Domain might indicate a coupling between bounded contexts. Consider if this dependency could be inverted or isolated through an anti-corruption layer or domain events.

Let's analyze the usage of Payment.Domain types in the Orders context:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how Payment.Domain types are used in Orders.Gateway
# to determine if the dependency is necessary or could be decoupled

# Search for any usage of types from Payment.Domain
rg -l "Bmb\.Payment\.Domain\." src/Bmb.Orders.Gateway/

# Check for specific Payment.Domain type usages in the codebase
ast-grep --pattern 'using Bmb.Payment.Domain;'

Length of output: 1197


Script:

#!/bin/bash
# Let's check the actual usage of Payment.Domain types in Orders.Gateway files

# Check ServiceCollectionsExtensions.cs
echo "=== ServiceCollectionsExtensions.cs ==="
rg -A 5 "Bmb\.Payment\.Domain" src/Bmb.Orders.Gateway/ServiceCollectionsExtensions.cs

# Check Presenter.cs
echo "=== Presenter.cs ==="
rg -A 5 "Bmb\.Payment\.Domain" src/Bmb.Orders.Gateway/Presenter.cs

# Check OrderReplicaRepository.cs
echo "=== OrderReplicaRepository.cs ==="
rg -A 5 "Bmb\.Payment\.Domain" src/Bmb.Orders.Gateway/Repository/OrderReplicaRepository.cs

# Check InMemoryOrdersGateway.cs
echo "=== InMemoryOrdersGateway.cs ==="
rg -A 5 "Bmb\.Payment\.Domain" src/Bmb.Orders.Gateway/Repository/InMemoryOrdersGateway.cs

# Check project references
echo "=== Project References ==="
cat src/Bmb.Orders.Gateway/Bmb.Orders.Gateway.csproj

Length of output: 2022


Script:

#!/bin/bash
# Let's check what types from Payment.Domain are actually used in the Orders.Gateway

# Check for specific Payment.Domain type usages in OrderReplicaRepository
echo "=== OrderReplicaRepository Implementation ==="
rg -C 10 "class OrderReplicaRepository" src/Bmb.Orders.Gateway/Repository/OrderReplicaRepository.cs

# Check for specific Payment.Domain type usages in InMemoryOrdersGateway
echo "=== InMemoryOrdersGateway Implementation ==="
rg -C 10 "class InMemoryOrdersGateway" src/Bmb.Orders.Gateway/Repository/InMemoryOrdersGateway.cs

# Check for interface definition
echo "=== IOrdersGateway Interface ==="
ast-grep --pattern 'interface IOrdersGateway'

Length of output: 2621


Script:

#!/bin/bash
# Let's check the IOrdersGateway interface definition and OrderDto to understand the coupling

# Check IOrdersGateway interface
echo "=== IOrdersGateway Interface Definition ==="
rg -C 10 "interface IOrdersGateway" src/Bmb.Payment.Domain/IOrdersGateway.cs

# Check OrderDto definition
echo "=== OrderDto Definition ==="
rg -C 10 "class OrderDto" src/Bmb.Payment.Domain/

# Check if OrderDto is used elsewhere in the Payment domain
echo "=== OrderDto Usage in Payment Domain ==="
rg -l "OrderDto" src/Bmb.Payment.Domain/

Length of output: 2094

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Payment.Api/Controllers/NotificationsController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Api.Auth;
using Bmb.Payment.Controllers.Contracts;
using Bmb.Payment.Domain.ValueObjects;
using Bmb.Payment.MercadoPago.Gateway.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Payment.Api/Mappers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Bmb.Payment.Api.Model;
using Bmb.Payment.Controllers.Dto;
using PaymentType = Bmb.Domain.Core.ValueObjects.PaymentType;
using Bmb.Payment.Domain.ValueObjects;

namespace Bmb.Payment.Api;

Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Payment.Application/Bmb.Payment.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Bmb.Payment.Core\Bmb.Payment.Core.csproj" />
<ProjectReference Include="..\Bmb.Payment.Domain\Bmb.Payment.Domain.csproj" />
</ItemGroup>

</Project>
7 changes: 4 additions & 3 deletions src/Bmb.Payment.Application/UseCases/CreatePaymentUseCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
using Bmb.Domain.Core.Events;
using Bmb.Domain.Core.Events.Notifications;
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Core;
using Bmb.Payment.Core.Contracts;
using Bmb.Payment.Domain;
using Bmb.Payment.Domain.Contracts;
using Bmb.Payment.Domain.ValueObjects;

namespace Bmb.Payment.Application.UseCases;

Expand All @@ -22,7 +23,7 @@ public CreatePaymentUseCase(IPaymentGatewayFactoryMethod paymentGatewayFactory,
_dispatcher = dispatcher;
}

public async Task<Bmb.Domain.Core.Entities.Payment?> Execute(Guid orderId, PaymentType paymentType)
public async Task<Domain.Entities.Payment?> Execute(Guid orderId, PaymentType paymentType)
{
var order = await _ordersGateway.GetCopyAsync(orderId);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using Bmb.Domain.Core.ValueObjects;

namespace Bmb.Payment.Application.UseCases;

public interface ICreatePaymentUseCase
{
Task<Bmb.Domain.Core.Entities.Payment?> Execute(Guid orderId, PaymentType paymentType);
Task<Domain.Entities.Payment?> Execute(Guid orderId, Domain.ValueObjects.PaymentType paymentType);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Domain.ValueObjects;

namespace Bmb.Payment.Application.UseCases;

public interface IUpdatePaymentStatusUseCase
{
Task<bool> Execute(Bmb.Domain.Core.Entities.Payment? payment, PaymentStatus status);
Task<bool> Execute(Domain.Entities.Payment? payment, PaymentStatus status);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Bmb.Domain.Core.Events;
using Bmb.Domain.Core.Events.Notifications;
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Core.Contracts;
using Bmb.Payment.Domain.Contracts;
using Bmb.Payment.Domain.ValueObjects;

namespace Bmb.Payment.Application.UseCases;

Expand All @@ -16,7 +16,7 @@ public UpdatePaymentStatusUseCase(IPaymentRepository paymentRepository, IDispatc
_dispatcher = dispatcher;
}

public async Task<bool> Execute(Bmb.Domain.Core.Entities.Payment? payment, PaymentStatus status)
public async Task<bool> Execute(Domain.Entities.Payment? payment, PaymentStatus status)
{
if (payment is not null && payment.Status
is not PaymentStatus.Approved
Expand Down
2 changes: 1 addition & 1 deletion src/Bmb.Payment.Controllers/Contracts/IPaymentService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Controllers.Dto;
using Bmb.Payment.Domain.ValueObjects;

namespace Bmb.Payment.Controllers.Contracts;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Domain.ValueObjects;

namespace Bmb.Payment.Controllers.Dto;

Expand Down
4 changes: 2 additions & 2 deletions src/Bmb.Payment.Controllers/PaymentGatewayFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Bmb.Domain.Core.Base;
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Core.Contracts;
using Bmb.Payment.Domain.Contracts;
using Bmb.Payment.Domain.ValueObjects;
using Microsoft.Extensions.DependencyInjection;

namespace Bmb.Payment.Controllers;
Expand Down
3 changes: 2 additions & 1 deletion src/Bmb.Payment.Controllers/PaymentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using Bmb.Payment.Application.UseCases;
using Bmb.Payment.Controllers.Contracts;
using Bmb.Payment.Controllers.Dto;
using Bmb.Payment.Core.Contracts;
using Bmb.Payment.Domain.Contracts;
using Bmb.Payment.Domain.ValueObjects;

namespace Bmb.Payment.Controllers;

Expand Down
88 changes: 2 additions & 86 deletions src/Bmb.Payment.Controllers/Presenter.cs
Original file line number Diff line number Diff line change
@@ -1,48 +1,10 @@
using Bmb.Domain.Core.Entities;
using Bmb.Domain.Core.ValueObjects;
using Bmb.Payment.Controllers.Dto;
using Bmb.Payment.Controllers.Dto;

namespace Bmb.Payment.Controllers;

public static class Presenter
{
// public static CustomerDto FromEntityToDto(this Customer customer)
// {
// if (customer is null) return null;
//
// return new CustomerDto
// {
// Id = customer.Id,
// Cpf = customer.Cpf,
// Name = customer.Name,
// Email = customer.Email
// };
// }

// public static ProductDto FromEntityToDto(this Product product)
// {
// return new ProductDto
// {
// Id = product.Id,
// Name = product.Name,
// Description = product.Description,
// Category = product.Category.FromEntityToDto(),
// Price = product.Price,
// Images = product.Images.ToArray()
// };
// }

// public static IReadOnlyCollection<ProductDto> FromEntityToDto(this IEnumerable<Product> products)
// {
// return products.Select(p => p.FromEntityToDto()).ToList();
// }

// public static ProductCategoryDto FromEntityToDto(this ProductCategory category)
// {
// return (ProductCategoryDto)category;
// }

public static PaymentDto FromEntityToDto(this Domain.Core.Entities.Payment payment)
public static PaymentDto FromEntityToDto(this Domain.Entities.Payment payment)
{
return new PaymentDto
{
Expand All @@ -55,50 +17,4 @@ public static PaymentDto FromEntityToDto(this Domain.Core.Entities.Payment payme
QrCode = payment.QrCode
};
}

// public static OrderListItemDto FromEntityToListDto(this Order order)
// {
// return new OrderListItemDto(order.Id, order.TrackingCode.Value, order.Total,
// (OrderStatusDto)order.Status,
// order.Created,
// order.Updated);
// }

// public static IReadOnlyCollection<OrderListItemDto> FromDomainToDto(this IEnumerable<Order> orders)
// {
// return orders.Select(o => o.FromEntityToListDto()).ToList();
// }

// public static OrderDetailDto? FromEntityToDto(this Order? order)
// {
// if (order is null) return null;
// return new OrderDetailDto
// {
// Id = order.Id,
// TrackingCode = order.TrackingCode.Value,
// Total = order.Total,
// Status = (OrderStatusDto)order.Status,
// CreationDate = order.Created,
// LastUpdate = order.Updated,
// OrderItems = order.OrderItems.Select(o => o.FromEntityToDto()).ToList(),
// Customer = order.Customer is null ? null : order.Customer!.FromEntityToDto()
// };
// }

// public static OrderItemDto FromEntityToDto(this OrderItem orderItem)
// {
// return new OrderItemDto()
// {
// OrderId = orderItem.OrderId,
// ProductId = orderItem.ProductId,
// Quantity = orderItem.Quantity,
// UnitPrice = orderItem.UnitPrice,
// ProductName = orderItem.ProductName
// };
// }

// public static NewOrderDto FromEntityToCreatedDto(this Order order)
// {
// return new NewOrderDto(order.Id, order.TrackingCode.Value);
// }
}
10 changes: 0 additions & 10 deletions src/Bmb.Payment.Core/Contracts/IPaymentGateway.cs

This file was deleted.

This file was deleted.

14 changes: 0 additions & 14 deletions src/Bmb.Payment.Core/Contracts/IPaymentRepository.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Bmb.Payment.DI/ServiceCollectionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Bmb.Orders.Gateway;
using Bmb.Payment.Application;
using Bmb.Payment.Controllers;
using Bmb.Payment.Core.Contracts;
using Bmb.Payment.Domain.Contracts;
using Bmb.Payment.DI.HealthChecks;
using Bmb.Payment.FakePayment.Gateway;
using Bmb.Payment.MercadoPago.Gateway;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Bmb.Domain.Core" Version="0.0.9" />
<PackageReference Include="Bmb.Domain.Core" Version="0.0.14" />
</ItemGroup>

</Project>
12 changes: 12 additions & 0 deletions src/Bmb.Payment.Domain/Contracts/IPaymentGateway.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Bmb.Domain.Core.ValueObjects;
using PaymentStatus = Bmb.Payment.Domain.ValueObjects.PaymentStatus;
using ValueObjects_PaymentStatus = Bmb.Payment.Domain.ValueObjects.PaymentStatus;
Comment on lines +1 to +3
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify PaymentStatus references to improve clarity

The current setup has multiple PaymentStatus references which could lead to confusion:

  1. One from Domain.Core
  2. Two aliases from Payment.Domain

This might indicate a violation of DDD bounded contexts or unnecessary complexity.

Consider:

  1. Consolidating PaymentStatus to a single location
  2. If different PaymentStatus types are needed, use more meaningful aliases
-using Bmb.Domain.Core.ValueObjects;
-using PaymentStatus = Bmb.Payment.Domain.ValueObjects.PaymentStatus;
-using ValueObjects_PaymentStatus = Bmb.Payment.Domain.ValueObjects.PaymentStatus;
+using Bmb.Payment.Domain.ValueObjects;

Committable suggestion skipped: line range outside the PR's diff.


namespace Bmb.Payment.Domain.Contracts;

public interface IPaymentGateway
{
Task<Entities.Payment> CreatePaymentAsync(OrderDto order);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace OrderDto with domain entity in gateway interface

Using OrderDto in the domain layer violates clean architecture principles. The domain layer should be independent of application concerns and should use domain entities or value objects instead of DTOs.

Consider:

  1. Creating a domain entity/aggregate for Order
  2. Moving DTO transformation to the application layer
-Task<Entities.Payment> CreatePaymentAsync(OrderDto order);
+Task<Entities.Payment> CreatePaymentAsync(Order order);

Committable suggestion skipped: line range outside the PR's diff.


Task<ValueObjects_PaymentStatus?> GetPaymentStatusAsync(string paymentId);
}
10 changes: 10 additions & 0 deletions src/Bmb.Payment.Domain/Contracts/IPaymentGatewayFactoryMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Bmb.Domain.Core.ValueObjects;
using PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
using ValueObjects_PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
Comment on lines +1 to +3
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify PaymentType imports to avoid confusion

The current import structure with multiple PaymentType references and aliases creates unnecessary complexity. Consider consolidating the PaymentType references to avoid confusion.

-using Bmb.Domain.Core.ValueObjects;
-using PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
-using ValueObjects_PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
+using Bmb.Payment.Domain.ValueObjects;

Committable suggestion skipped: line range outside the PR's diff.


namespace Bmb.Payment.Domain.Contracts;

public interface IPaymentGatewayFactoryMethod
{
IPaymentGateway Create(ValueObjects_PaymentType paymentType);
}
16 changes: 16 additions & 0 deletions src/Bmb.Payment.Domain/Contracts/IPaymentRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Bmb.Domain.Core.ValueObjects;
using PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
using ValueObjects_PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
Comment on lines +1 to +3
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify import statements to avoid confusion

The current import statements create unnecessary complexity with aliases:

  1. Two imports for PaymentType with different aliases
  2. The alias ValueObjects_PaymentType doesn't follow C# naming conventions

Consider this simplified approach:

using Bmb.Domain.Core.ValueObjects;
-using PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
-using ValueObjects_PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
+using DomainPaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
using Bmb.Domain.Core.ValueObjects;
using PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
using ValueObjects_PaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;
using Bmb.Domain.Core.ValueObjects;
using DomainPaymentType = Bmb.Payment.Domain.ValueObjects.PaymentType;


namespace Bmb.Payment.Domain.Contracts;

public interface IPaymentRepository
{
Task<Entities.Payment> SaveAsync(Entities.Payment payment);

Task<Entities.Payment?> GetPaymentAsync(PaymentId paymentId);

Task<Entities.Payment?> GetPaymentAsync(string externalReference, ValueObjects_PaymentType paymentType);

Task<bool> UpdatePaymentStatusAsync(Entities.Payment payment);
}
Loading