Design help - Tax Calculation Command

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

Hi Marco,

The road I’d likely take is to introduce a domain service, the ‘TaxCalculator’, in the scenario.
The TaxCalculator would contain the domain logic necessary to calculate the tax for a giving Order aggregate, taking the right money fields and country into account when being called.
You can wire the TaxCalculator in your Command Handling function as a parameter through the Parameter Resolver set up in Axon.

If you’re in a Spring environment, simply making this TaxCalculator class a bean is sufficient for Axon to automatically provide it as a parameter on your command handling function, like so:

@CommandHandler
public void handle(CalculateTaxCommand command, TaxCalculator taxCalculator) { … }

I hope this suggestion helps you out Marco.
If not, please send some follow up questions under this topic!

Cheers,
Steven

Hi Marco,

Speaking in patterns, you could implement a TaxCalculationStrategy interface and provide different implementations for this… The TaxCalculator suggested by Steven would for example pick the correct strategy based on the command payload and calculate the tax.In doing so, you would create a clear separation of the algorithmic tax calculation from the commands / events handled by Axon.

Cheers,

Simon