More rules and states between aggregates

92 views
Skip to first unread message

Maksim Ivanov

unread,
Feb 18, 2012, 4:36:48 PM2/18/12
to DDD/CQRS
In light of recent very informative discussion on AR collaborations,
it is very interesting to see what community thinks where we not only
have to check “Rules between aggregates”, but also have to return
state from performing an action on AR.

Let’s take a simple example where we have Invoice modeled as AR and it
contains complex business logic.

1. There can be [0 … n] invoices;

2. When we receive bank transaction from customer we have to repay
Invoices:
a. When customer doesn’t have any Invoice, then money received
should be sent back;
b. When customer specifies Invoice number, then Invoice should
be repaid;
1. If there is money left after Invoice repayment,
then next Invoice by due date should be repaid;
2. If there is money left after Invoice repayment and
there are no more Invoice due, then money should be sent back;
c. When customer doesn’t specify Invoice number, then first
invoice by due date should be repaid;
1. If there is money left after Invoice repayment,
then next invoice by due date should be repaid;
2. If there is money left and no more invoices due
after invoice repayment, then money should be sent back;

3. Fees and penalties can be charged on Invoice, so Invoice total
amount due can change daily;

Do we always have to have immediate consistency across all Invoices
because of that use-case? What are the options for modeling that
collaboration between aggregates?

perpigne

unread,
Feb 18, 2012, 6:27:52 PM2/18/12
to ddd...@googlegroups.com

Do we always have to have immediate consistency across all Invoices
because of that use-case?
 
Based on your description, I would say yes. It looks like your invoices should be kept consistent wrt a payment.
 

What are the options for modeling that
collaboration between aggregates?  

 
I would consider the collection of invoices as the AR with invoices as entities inside the aggregate. This collection of invoices might be the CustomerAccount or CustomerFolio or something other depending on the language of the domain and would be responsible for the consistency rules between invoices when recieving a Payment. So in the end, I would only have one aggregate.
 
What do you think ? Would that be a valid option in your domain ?
 
Ernst

Maksim Ivanov

unread,
Feb 18, 2012, 7:06:57 PM2/18/12
to DDD/CQRS
Thank you, Ernst.

> What do you think ? Would that be a valid option in your domain ?

Yes, absolutely. Account AR seems like a natural fit for that
particular use-case.

It would be interesting to hear if there are any options where we can
satisfy this use-case as well as keep invoice as a separate concept.

perpigne

unread,
Feb 18, 2012, 9:10:01 PM2/18/12
to ddd...@googlegroups.com

It would be interesting to hear if there are any options where we can
satisfy this use-case as well as keep invoice as a separate concept.
 
The fact that you are insisting on having invoice as a separate concept leads me to think that in your domain there are other use cases that pushes for this. Having the Account AR is not necessarily at odds with this. Your domain might have several Bounded Contexts. One of them being the Payment/Transaction context that houses the Account AR as described above for handling bank transactions. Another one being the Ordering context with Invoices as aggregates for handling the customer actually buying whatever the business is selling. 
 
The Invoice concept in the different contexts would not be the same. In the Payment/Transaction context Invoice would contain amountToBePaid and DueDate. In the Ordering context the Invoices might actually be the list of items bought together by the customer.
 
So the use cases that pushes you to think about invoices as separate concepts might be use cases for a different context than the payment context. You may want to consider not having one model for all the contexts.
 
Ernst  
 
 

Philip Jander

unread,
Feb 19, 2012, 1:58:09 AM2/19/12
to ddd...@googlegroups.com

 
I would consider the collection of invoices as the AR with invoices as entities inside the aggregate. This collection of invoices might be the CustomerAccount or CustomerFolio or something other depending on the language of the domain and would be responsible for the consistency rules between invoices when recieving a Payment. So in the end, I would only have one aggregate. 


I second the Account notion, but I would consider invoice seperate from account. There is no need to carry around all of the invoice just for tracking payments. Instead use accounts for payments-due, taxes, customer balances etc. Your standard chart of accounts will already have all of that.
Actually book-keeping is a quite well established domain, they have even been using event sourcing for around 600-700 yrs iirc ;)

Maybe use an off the shelf accounting software?

Cheers
Phil

Nuno Lopes

unread,
Feb 20, 2012, 7:24:20 AM2/20/12
to ddd...@googlegroups.com
Hi,
This might come too late, but here is a suggestion:

So you have an event ... BankTransactionReceived -> PaymentReceived. You also have a list of Pending Invoices.

class InvoicesPending // some Aggregate
{
List<PendingInvoice> listOfPendingInvoices;

void Pay(Money amount); // declares InvoicePaid
void Pay(Guid invoiceId, Money amount); // declares one or more InvoicePaid. It may also declare a MoneyLeft event
void AddPendingInvoice(PendingInvoice i);
void CancelPendingInvoice(PendingInvoice i);

Handle(PaymentReceived fact) {}
Handle(InvoiceIssued fact) {}
Handle(InvoiceCancelled fact) {}

Declare(InvoicePaid fact) {}
Declare(MoneyLeft fact) {}
}

PendingInvoice is a value object representing the invoice within this context. Some other object will take care of returning MoneyLeft over's. Different companies have different rules about when the money is returned.

There might be a case where say an Invoice is payed just before is cancelled. In which case you might also have to return the money. So you would issue in those case a MoneyLeft event.

Cheers,

Nuno

So you have a list of invoices yet to be paid.

Customer Invoice Payment Queue ?

Don't know if this is an account in a traditional sense. But it seams to be a domain concept. It might be implicit in some other concept, but you can make it explicit (SRP?).

Cheers,

Nuno

Maksim Ivanov

unread,
Feb 20, 2012, 3:25:28 PM2/20/12
to DDD/CQRS
Thank you all, very insightful. Reply inline, not to a particular
message.

> The fact that you are insisting on having invoice as a separate concept
> leads me to think that in your domain there are other use cases that pushes
> for this. Having the Account AR is not necessarily at odds with this. Your
> domain might have several Bounded Contexts. One of them being the
> Payment/Transaction context that houses the Account AR as described above
> for handling bank transactions. Another one being the Ordering context with
> Invoices as aggregates for handling the customer actually buying whatever
> the business is selling.

I think Ernst is spot on here with several bounded contexts. This
particular bounded context is responsible for charging fees and
handling payments.


> Maybe use an off the shelf accounting software?

Philip, if only things were that simple :)


> Customer Invoice Payment Queue ?
>
> Don't know if this is an account in a traditional sense. But it seams to be a domain concept. It might be implicit in some other concept, but you can make it explicit (SRP?).

Nuno, I think you you purposed better name for a domain concept, as it
is actually not an account in a traditional sense.
Reply all
Reply to author
Forward
0 new messages