Hi guys, I would need some advice about how to design the aggregate + commands for the following scenario:
I have got order and i’ve got this command which is used to calculate the tax amount for my order. Let’s call it CalculateTaxCommand
Now, tax calculation is something quite complex if the order can be placed in different counties, so if i am in Europe, for example, there is a flat tax that you pay, the x % of the order. In US, on the other hand, the tax calculated based on the shipping address.
How could i model this in an efficient way ? I came up with 2 solutions but i am not fond of any of them.
1st - I could have 2 distinct commands, use one or the other and have in my aggregate 2 command handlers one for each case.
But this approach feels off, since the aggregate shouldn’t care about the way the tax is calculated, but should just know that there is the tax field which has certain constraints.
2md - The other way that I had in mind was to have the command as in interface or an abstract class and implement the different behaviours inside the command itself. So when i say calculatetaxCmd.getTaxAmount() it would calculate the tax for me. Except that now the command has to now the aggregate, since it requires date from the order to calculate the tax amount. In this case, would it be ok have a function like
abstract Double calculateTaxAmount(OrderAggregate order) ?
Would it work correctly with the @CommandHandler annotated function taking as argument the abstract class ?
Just to be al little more clear about this second case, here is an example:
I would have AbstractCalculateTaxCmd, extended by VatBasedTaxCalculationCmd and ShippingAddressBasedTaxCalcula**tionCmd. the aggregate would have a method like
@CommandHandler
public void handle(AbstractCalculateTaxCmd cmd) {
this.tax = cmd.calculateTaxAmount(this);
}
Then a custom CommandFactory which takes in the country of the order and creates an instance of the correct class to send to the commandGateway.
Can you propose a better approach to the problem ?
Thank you
Marco