Skip to content

WIP MOSS refactoring#747

Closed
mamhoff wants to merge 13 commits intomasterfrom
unknown repository
Closed

WIP MOSS refactoring#747
mamhoff wants to merge 13 commits intomasterfrom
unknown repository

Conversation

@mamhoff
Copy link
Copy Markdown
Contributor

@mamhoff mamhoff commented Jan 27, 2016

This is the PR that will actually bring about behaviour changes. Notably, taxable items (line items, shipping rates, and shipments) will have their price adjusted to the correct price including any applicable VAT. There shall be no refunds.

This is still work in progress. It depends on #685 (which it includes).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unnecessary : ) The tests below would fail anyhow.

The BigDecimal one is also superfluous imo

mamhoff and others added 13 commits January 28, 2016 11:19
For the time being, these two POROs (one for orders, another for items) call
the already defined methods on `Spree::TaxRate`.

The idea is, though, that the responsibilities between `Spree::Tax::{Item,Order}Adjuster` and
`Spree::TaxRate` are divided as follows: `Spree::TaxRate` stores and selects rates,
while `Spree::Tax::{Item,Order}Adjuster` create tax adjustments.
The code in `Spree::TaxRate.adjust!` is hard to understand, and the
adjusting should happen in dedicated adjuster classes. This commit
ports the functionality of `TaxRate.match` over to two classes:

* An `OrderAdjuster` which iterates over all items (line items and shipments)
  in an order and runs the

* `ItemAdjuster`, which actually creates adjustments for every item.

The code should read a lot easier now.

In order to reduce database load, the tax rate array for an order can be passed
into the `ItemAdjuster.new`. Considering the performance benefits, I think
that's justifiable amount of shared knowledge between the two Adjuster classes.
TaxRate.for_zone will return all tax rates that are valid for a given zone.
It does not care about the default VAT zone, as that should be handled by the
Adjuster classes.
When using .with_shared_members, sometimes you pass nil - and that should just
yield an empty ActiveRecord relation.

Same goes for Spree::TaxRate.for_zone(nil).
This is really an intermediary step. I'm using for_zone already in
Spree::TaxRate.match, which should result in a constant eight DB calls per
.match call. Previously, the number of DB calls would depend on how many
tax rates there are, and how these are configured (as Spree::Zone.contains?
would be run for every tax rate in the system).

A side effect of this refactoring is that the reimbursement specs had to be
amended a little: The zones had to be created `:with_country`, because otherwise
there'd be no shared members and the tax rates wouldn't apply. This actually makes
the tests slightly more realistic (what is a zone without members, anyway?).

Also, I had to change an expectation: The included tax total of the reimbursement
was previously expected to be negative (which is something that IMO should never
happen, as negative included taxes at the moment become positive additional taxes).
The order adjuster and the item adjuster share code, because I need to run
some methods on the order level and cache them. This extracts these methods
into a module.

Inheritance would've also worked, but in this case I find a mixin
more fitting as the behaviour of the two classes is still quite different.
TaxRate.match does some pretty weird things, and I want to change them.
This commit moves that code to a temporary `applicable_rates` helper.
Before this commit, the taxation system would handle default VATs and
rates that *actually* apply to the order's item with the same code.
However, they do fundamentally different things: For example, the
`pre_tax_amount` should only be calculated from default VAT rates.

This commit introduces a new private method on the ItemAdjuster to
handle "deductable" VAT rates. This fixes some of the taxation specs,
because now the pre tax amount is calculated correctly, and it opens the
path for a cleverer handling of default VATs (namely, changing the line
item's price).

Additionally, this commit introduces cached options for the entire order
to be passed into the item adjuster.
The "initial price" is the price in the default tax zone. It will be used when
calculating net amounts and new prices for foreign VAT zones.

This has been discussed in #532
This is the simplest thing that could possibly work. It does.
Since now there can be no VAT refunds anymore, we can get rid
of all the code in tax_rate.rb that exclusively deals with refunds.
Which tax rates are applicable is for the moment determined by the tax
category of the item. There is cases though where more things apply (the customer,
for example, might be a business customer). Besides, putting this into a method on
TaxRate unifies that check.
With the new VAT taxation system, a default zone
is no longer mandatory. It is perfectly valid to have
taxes that are included in price only for specific foreign zones.
@mamhoff
Copy link
Copy Markdown
Contributor Author

mamhoff commented Jan 29, 2016

Rebased on #685, and removed the work on shipping rates present in RfC Make shipping rates taxable like line items or shipments (on which this will have to be rebased as well).

@mamhoff
Copy link
Copy Markdown
Contributor Author

mamhoff commented Jan 29, 2016

After chat on slack with @jhawthorn reverted the instance variable names to names without an underscore (as they're actually used by the classes that use the TaxHelpers mix-in.

@tvdeyen
Copy link
Copy Markdown
Member

tvdeyen commented Jan 29, 2016

That's reasonable and I'm fine with it. Although @rates_for_items is not used outside of ItemAdjuster and therefore could have the underscore in the name, but I will stop complaining now and won't hold this back anymore.

Great work. Thanks, @mamhoff

@mamhoff
Copy link
Copy Markdown
Contributor Author

mamhoff commented Mar 31, 2016

I'm closing this. Much of it is already merged into master, and for all the following work, #989 is the guide.

@mamhoff mamhoff closed this Mar 31, 2016
@mamhoff mamhoff deleted the moss-refactoring branch May 24, 2016 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants