How to model and maintain invariants across aggregates in a Domain-Driven Design for a payment and refund system?

38 Views Asked by At

I'm working on a payment system where payments can be split among multiple payees. Additionally, we have refunds, which also can be split among these payees. I have some business rules that need to be enforced:

  1. The sum of payment splits should not exceed the total payment amount.
  2. The sum of refund splits should not exceed the net payment amount (i.e., the total payment amount minus the total refunded amount).
  3. A specific refund split for a payee should not exceed the amount that was originally paid to that payee.

I've tried modeling Payment and Refund as separate aggregate roots, with associated entities for their splits (PaymentSplit and RefundSplit respectively). However, I'm facing challenges ensuring the invariants, especially since some rules require cross-referencing between aggregates.

How can I design my aggregates to enforce these rules effectively without breaking DDD principles?

1

There are 1 best solutions below

0
Sylvain Lecoy On

The payment receipt should be modelled as ValueObject referencing the PayeeId and the amount.

Those receipts will be part of your root aggregate so you don't break the Transactional scope, and all your invariants rules will be part of the same transaction.