boomerdigital / solidus_avatax_certified

Improve your Solidus store's sales tax decision automation with Avalara AvaTax
BSD 3-Clause "New" or "Revised" License
9 stars 44 forks source link

Support for :short_ship_notifier #54

Open ericsaupe opened 7 years ago

ericsaupe commented 7 years ago

Solidus has a hook that allows third-party tax services to be updated when an item is cancelled. Does solidus_avatax_certified hook into this?

https://github.com/solidusio/solidus/blob/master/core/app/models/spree/order_cancellations.rb#L8

dhonig commented 7 years ago

Not sure we do....We'll get back to you shortly on this.

acreilly commented 7 years ago

Currently, we have it where if the whole order is canceled, a cancel tax request is sent.

In order to support item cancellation tax updates, we will need to integrate the SOAP api. I plan to add that to my to do list.

ericsaupe commented 7 years ago

Avatax released a V2 of their API which is more restful.

dhonig commented 7 years ago

Can you quickly summarize how this impacts the business? Then we can see if this is an appropriate change for all stores or provide guidance in the documentation for custom implementation if it is not something that should be global.

ericsaupe commented 7 years ago

I'm unsure how much it impacts the business because I haven't dived into it too deeply but it does seem to be easier to work with from a developer perspective as opposed to the V1 SOAP-type implementation

dhonig commented 7 years ago

We need to have some understanding of line item records vs the order as a whole before implementing this change. Probably we can interview a few customers such as yourself, and others to build up the right context for implementing this. Then we can decide if it is something that should be left as custom or an option that is configurable. REST is indeed much easier to work with in Ruby than SOAP, even with the excellent Savon package. Let's try to make a call on this in the next week and if appropriate we can get it included in a coming release of the gem.

jasonfb commented 7 years ago

From my understanding of Avatax (not necessarily this gem), you basically have a process that looks like this:

(1) A tax transaction is created in uncommitted state (2) When the order is completed, a tax transaction is then committed

Between 1 and 2, you can change the transaction. After you commit the transaction, you then need to issue tax refund transaction against the original tax transactions to reverse them. (This is in accordance with accounting rules.)

Here's the critical question (for me at least): Does 2 (the commitment) happen when the order is completed or when the order ships?

I believe in our spree_avatax_certified implementation (on Spree 2.4), it actually commits the tax transactions when the order is completed, not when it ships. We live with this as-is (we also don't pay much tax as we only pay tax in one state), but I believe it is not an appropriate design in accordance with accounting.

In my opinion, the heart of the issue is that #2 (committing) should happen when the order ships, not when the order is completed. If that were true, then you should write code to handle short-shipments before the tax transactions are committed, which means you can adjust them accordingly to the new (corrected) amounts before committing them. I also believe this becuase we count the revenue when the order ships, not when it is completed. (So an order placed on March 31 but shipping on April 1st counts for April's revenue, and so too should be paid tax as-if it was money owed for the month of April not March.)

My reasoning for this is that from a legal perspective, the order isn't actually "finished" (and I mean truly finished, not just Spree's concept of 'completed') until you (the store) complete your end of the bargain, which is to ship the goods out.

Of course, different businesses may operate differently and may use different accounting rules.

In the current design, if you commit when the order is completed but before it ships, then the only way to deal with a short-shipment that may incur a need for taking that tax money back is to issue refund transactions against the original tax transactions.

If the design were re-arranged so that the committing didn't happen until the order ships, then you could simply adjust the tax transactions before they are committed, correcting them to the right amounts before committing them.

In our store (Spree 2.4), we have special code with our 3PL that checks the shipment manifest (what actually got shipped) against what the customer ordered, and in the case of short-shipments, we retroactive adjust the line items on the order (which also adjusts the order's total) to correct it to the accurate price. Essentially, we say "Even though you ordered $X, we only have $Y in stock, so we're going to treat your order as-is you placed it at $Y and remove the out-of-stock items from your order."

So.... I think you either have to change it so that Avatax commitment doesn't happen until shipping, or if that doesn't work for you change it so that short-shipments create refund transactions in Avatax, reversing the original transactions themselves. I'm not actually sure how much Avatax supports that, but essentially it is very similar to a return tax transactions — it's just a "return" that happens before the order even goes out.

Sorry, no easy answer here but that's my 2¢

acreilly commented 7 years ago

@jasonfb Currently we have it where it comments when a payment is captured, not when the order is completed. I think that makes sense since capturing a payment usually means that you are not going to be making any more changes to the order. What do you think?

jasonfb commented 7 years ago

@acreilly -- Yes you are correct, I hadn't read the code that carefully. I see the indeed the avalara_finalize method on the Payment object is on the before_transition to complete, which is exactly the same moment that we ship the goods, so this is in fact already committing-upon-shipping as I had hoped/dreamed would be the case.

In that case, a short-shipment solution would only need to adjust the (tax) transactions before the payment goes from pending -> complete, re-evaluating them if the original order total is changing. In this scenario I'd say the only thing to make sure is that you run your short-shipment code before you complete the payment (in ours we capture at a lower amount, so this is built-in by design)

ericsaupe commented 7 years ago

Solidus supports Auto-capture on completion of the order (what our store does). Since the FTC gives a 30-day window to actual ship/fulfill the order. This is the window of time where we could possibly have a cancellation on an item including backordered items that we later find out will not be fulfilled in time.

jasonfb commented 7 years ago

@ericsaupe -- if you do auto-capture, then you can't build it the way I've suggested above. You must issue refunds (to the customer) and tax refund transactions (which are like reverse tax transactions that go back to the gov't), because in that scenario you must treat the 'giving back' of money as a new ledger-able transactions (from an accounting perspective).

While auto-capture is 'allowed', my understanding is that it is generally frowned upon by the Visa & Mastercard (the giant gorillas of credit card processing), but acceptable for businesses that have no other choice. (I say this having had this conversation with several veterans of the CC industry who have broad exposure to several different stores)

In fact, to allow for adjusted-after-the-fact payments amount and/or adjusted-after-the-fact tax transactions is precisely why we don't do auto-capture and capture at the time of shipment.

acreilly commented 7 years ago

The REST V2 API has the ability to adjust tax after document commit, which will solve all the issues listed above. We are currently working on integrating the V2 API into this gem, but it will take some time.