Introducing a new "simple tax plugin", written in Java

316 views
Skip to first unread message

Benjamin Gandon

unread,
Sep 10, 2015, 5:31:34 AM9/10/15
to Kill Bill users mailing-list
Hi guys,

I've been investigating quite a lot lately on how to integrate regulatory-compilant French VAT items into kill bill invoices.
This explains why I didn't answer in the code format thread. But I did not forget about it :) That's just a question of priorities.

So, in the first place I've been hacking invoice formatters, hum hum...
Then of course I realized that was definitely not the right way! :)

I had a look at killbill-base-plugin (Java) and killbill-invoice-test-plugin (Ruby).
I concluded there was no "ready-to-go" solution for a fixed-rate VAT implementation. (Is this correct, btw?)

I then also understood I could just copy/paste the killbill-invoice-test-plugin and change the rate,
but God know why, I wanted it in Java instead.
In fact, I have further plans about properly implementing cutoff dates (for VAT changes),
which I wanted to leverage JodaTime because I know the lib is rock solid.

Anyway.

I just pushed the first pieces of code I wrote into a PR at <https://github.com/bgandon/killbill-simple-tax-plugin/pull/1>.
Could you please review my code and share your thoughts about it?

In the review, I have a few points I'd like you to look at, because some functional aspects are out of my knowledge.

1. My main concern is about the creation of missing tax items into historical invoices.
I summarized the implemented behavior into these class comments:

Should we really create any missing tax items into historical invoices?
I just copied that from the killbill-invoice-test-plugin Ruby code, but I'm wondering whether it's correct or not.
In which case could we face such situation?
Are the modified invoices sent again to customers? (I mean when all notification settings are properly activated)

2. My second concern is a potential inconsistency in the dates we give when creating tax items or tax adjustment items into historical invoices.
In the first case, the created tax item gets the date of the historical invoice it is added to, as I documented here:

In the second case, the tax adjustment item is added to the historical invoice too, but it gets the date of the new invoice that is being created.

Is this really correct?
If yes, what is the meaning of doing so?
And here again, are the modified invoices sent again to customers? (In case all notification settings are properly activated)

Thanks for your help!
If anything is missing in the Github setup for you to comment the PR, don't hesitate to tell!

Cheers

stephane brossier

unread,
Sep 10, 2015, 5:23:03 PM9/10/15
to Benjamin Gandon, Kill Bill users mailing-list
Benjamin,

I took a quick look at your code but Pierre wrote the original invoice-test-plugin, so he may a better candidate to answer your specific questions (he is traveling at moment and will be back early next week). I have a few high level comments though:

1. Tax can be very complicated (all kinds of weird rules, and keep changing every year). In the US, we discourage people to build a tax plugin by hand and we are now working with Avalara (currently going through certification process for our existing plugin). Now of course, if you want to stay purely open-source, you have no choice, and we are also sympathetic to that argument...
FYI: The invoice-test-plugin was an initial prototype we did do validate our plugin APIs, but we don't spend too much maintaining it. So, that being said, France may have a simpler tax system (although knowing the french bureaucracy i doubt it ;-) ), so i don't want to discourage you to build your own tax plugin.

2. You current pom shows a package of 'org.kill-bill.' and i am guessing this is why you submitted a PR. It might be in your advantage to own the code (and we would happily fork it from github/killbill so other folks could see it and benefit from it): If you are the primary user of the plugin, i think this is in your interest to stay in control of the code (e.g deploy quick fixes if needed as opposed to have us approve your PR each time).

@pierre: Can you answer Benjamin 's specific questions about the historical invoices (and the tax items we added on those).

Good job on the code, seems like you already have a good understanding of the system!

Stéphane


--
You received this message because you are subscribed to the Google Groups "Kill Bill users mailing-list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to killbilling-us...@googlegroups.com.
To post to this group, send email to killbill...@googlegroups.com.
Visit this group at http://groups.google.com/group/killbilling-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/killbilling-users/8144ccad-94cc-4756-b33d-90e9153e4c1a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Benjamin Gandon

unread,
Sep 11, 2015, 3:28:22 AM9/11/15
to Kill Bill users mailing-list, benj...@gandon.org
Hi Stéphane!


1. Tax can be very complicated (all kinds of weird rules, and keep changing every year).

That's right indeed. The point for me was to add a fixed 20% VAT rate so that I can issue my first bills, and later improve the thing when I make money and affect a pair on this. In my specific context, 20% is the one and only rate to apply.


FYI: The invoice-test-plugin was an initial prototype we did do validate our plugin APIs, but we don't spend too much maintaining it.

In fact, my mid-term plan is to give the simple-tax-plugin back to the community. I definitely don't mean to be a key person on this in the long term. That's why I want it fairly documented and covered by automated tests, so that the community can properly maintain it.

2. You current pom shows a package of 'org.kill-bill.' and i am guessing this is why you submitted a PR.

Both 'org.kill-bill.' package and PR are intentional as regards to my plan I mentioned above.
Would this cause any difficulty to you?


If you are the primary user of the plugin, i think this is in your interest to stay in control of the code (e.g deploy quick fixes if needed as opposed to have us approve your PR each time).

Well, I don't mind running a customized version compared to a master that would be in the github/killbill organization. For me, not being a key person in this project is a bigger mid-term goal.
But for the time being we can start the way you suggest, with just a clone in the killbill github organization indeed.


@pierre: Can you answer Benjamin 's specific questions about the historical invoices (and the tax items we added on those).

 Would love that indeed. @pierre: we can setup a Skype call with shared screen so that you can share your feedback. Doing it live would be a good way for us to get to know each other. Though I'm in CET, I'm available on PST workday hours with no pb. What would be your best time?


Yesterday I implemented the per-tenant config. Which had me rase a few more questions.

1. Should we i18n-ize the Tax Items descriptions? If yes, which resources bundle would be appropriate to use? And how would the plugin get it?

2. Should we differentiate the Tax Item Adjustment descriptions from original Tax Items descriptions?

3. Is it possible to use the config-magic library in a plugin that has a per-tenant config? Do you have any working example of this?

 
Good job on the code, seems like you already have a good understanding of the system!

Thanks :)

Cheers


 

Pierre-Alexandre Meyer

unread,
Sep 11, 2015, 10:04:55 AM9/11/15
to Benjamin Gandon, stephane brossier, Kill Bill users mailing-list
On Thu, Sep 10, 2015 at 5:23 PM, stephane brossier <step...@kill-bill.org> wrote:
I took a quick look at your code but Pierre wrote the original invoice-test-plugin, so he may a better candidate to answer your specific questions

The original invoice-test-plugin was indeed a proof-of-concept to validate our APIs. Since then, the AvaTax plugin was developed and is a reference implementation for tax plugins.

The core of the invoice-related logic has been extracted however. I would suggest re-using the base classes from the Java plugin framework in your plugin, in the same way the AvaTax plugin does it. This is to minimize the Kill Bill-specific invoice logic in your plugin and have a centralized place to modify things if behaviors change in the future.

On Thu, Sep 10, 2015 at 5:31 AM, Benjamin Gandon <benj...@gandon.org> wrote:
Should we really create any missing tax items into historical invoices?

This will depend on the company, but most likely you don't want to do that. Imagine someone enabling the tax plugin 2 years after running Kill Bill in production: most customers would be in an overdue state very quickly!

On Fri, Sep 11, 2015 at 3:28 AM, Benjamin Gandon <benj...@gandon.org> wrote:
That's right indeed. The point for me was to add a fixed 20% VAT rate so that I can issue my first bills, and later improve the thing when I make money and affect a pair on this. In my specific context, 20% is the one and only rate to apply.

I would echo Stéphane's sentiment here. While this will solve your immediate use-case, solving VAT correctly even for one country is actually quite difficult. Keeping up with the regulations is even more difficult (think about the VAT 2015 changes we just went though). I would strongly encourage you to investigate outsourcing it (and would be curious why you can't or you don't want to).

Also, how do you plan on doing the reconciliation with your accounting software, when submitting quarterly VAT reports to the government?

@pierre: we can setup a Skype call with shared screen so that you can share your feedback. Doing it live would be a good way for us to get to know each other. Though I'm in CET, I'm available on PST workday hours with no pb. What would be your best time?

I'm on the road for the next few weeks, so continuing over email or iterating on the GitHub PR would be easier for me.

Cheers,

--
Pierre

Benjamin Gandon

unread,
Oct 9, 2015, 10:33:58 AM10/9/15
to Pierre-Alexandre Meyer, stephane brossier, Kill Bill users mailing-list
Hi,

After a few weeks working on another project, I’m back!


On Friday, September 11, 2015 at 4:04:55 PM UTC+2, Pierre-Alexandre Meyer wrote:
On Thu, Sep 10, 2015 at 5:23 PM, stephane brossier <step...@kill-bill.org> wrote:
I took a quick look at your code but Pierre wrote the original invoice-test-plugin, so he may a better candidate to answer your specific questions

The original invoice-test-plugin was indeed a proof-of-concept to validate our APIs. Since then, the AvaTax plugin was developed and is a reference implementation for tax plugins.

The core of the invoice-related logic has been extracted however. I would suggest re-using the base classes from the Java plugin framework in your plugin, in the same way the AvaTax plugin does it. This is to minimize the Kill Bill-specific invoice logic in your plugin and have a centralized place to modify things if behaviors change in the future.

Indeed, I have used the Java plugin framework as much as possible.
I also have feedback on the PluginTaxCalculator. To my understanding, it should use of Multimap<UUID, InvoiceItem> instead of Map<UUID, Collection<InvoiceItem>>. If you look at my code, you’ll see it makes things clearer. Also I found the computeNewItemsToTaxAndExistingItemsToAdjust() not to be useful outside the context of the Avatax plugin.

 
On Thu, Sep 10, 2015 at 5:31 AM, Benjamin Gandon <benj...@gandon.org> wrote:
Should we really create any missing tax items into historical invoices?

This will depend on the company, but most likely you don't want to do that. Imagine someone enabling the tax plugin 2 years after running Kill Bill in production: most customers would be in an overdue state very quickly!

Yes indeed. That’s an important point.

I also noticed that when tax items are created on historical invoices, then the historical invoices gained a positive balance. But this positive balance doesn’t look to be collected so that it can be paid by the customer. (BTW, is it normal that those invoice balance are not added to the overall account balance?)

All in all, tax items should not be created on historical invoices.


On Fri, Sep 11, 2015 at 3:28 AM, Benjamin Gandon <benj...@gandon.org> wrote:
That's right indeed. The point for me was to add a fixed 20% VAT rate so that I can issue my first bills, and later improve the thing when I make money and affect a pair on this. In my specific context, 20% is the one and only rate to apply.

I would echo Stéphane's sentiment here. While this will solve your immediate use-case, solving VAT correctly even for one country is actually quite difficult. Keeping up with the regulations is even more difficult (think about the VAT 2015 changes we just went though). I would strongly encourage you to investigate outsourcing it (and would be curious why you can't or you don't want to).

Well, no. You’re missing my point here. The French VAT system is simple and does not deserve outsourcing. Keeping up with VAT changes is not an issue because it happens once in a while and just results in a few settings to update.

Moreover I want to stay Open Source on this.
 
 
Also, how do you plan on doing the reconciliation with your accounting software, when submitting quarterly VAT reports to the government?

I don't get your point. You might have a better overview of accounting processes than me. Do I really need an accounting software?
 
 
I'm on the road for the next few weeks, so continuing over email or iterating on the GitHub PR would be easier for me.

Indeed I had a look today and saw you didn’t comment the PR. I’ll merge it then.

Cheers,

Benjamin

Pierre-Alexandre Meyer

unread,
Oct 9, 2015, 11:22:21 AM10/9/15
to Benjamin Gandon, Kill Bill users mailing-list
On Fri, Oct 9, 2015 at 10:33 AM, Benjamin Gandon <benj...@gandon.org> wrote:
I also have feedback on the PluginTaxCalculator. To my understanding, it should use of Multimap<UUID, InvoiceItem> instead of Map<UUID, Collection<InvoiceItem>>. If you look at my code, you’ll see it makes things clearer.

Yup, I'm just old-fashioned here :-)
 
Also I found the computeNewItemsToTaxAndExistingItemsToAdjust() not to be useful outside the context of the Avatax plugin.

Why not? This helps break down which items are new and which ones are adjustments (tax handling may be different for returns, i.e. you probably need to use the original invoice date to report these).

I also noticed that when tax items are created on historical invoices, then the historical invoices gained a positive balance. But this positive balance doesn’t look to be collected so that it can be paid by the customer. (BTW, is it normal that those invoice balance are not added to the overall account balance?)

The overall account balance should be impacted. Kill Bill won't trigger automatic payments for them though.

I don't get your point. You might have a better overview of accounting processes than me. Do I really need an accounting software?

You either need to integrate with an accounting software to report the VAT to the government or hire an accountant which will do it for you (procédure EDI-TVA).

Cheers,

--
Pierre

Benjamin Gandon

unread,
Oct 9, 2015, 11:40:31 AM10/9/15
to Kill Bill users mailing-list, benj...@gandon.org, step...@kill-bill.org
Hi,


On Thu, Sep 10, 2015 at 5:31 AM, Benjamin Gandon <benj...@gandon.org> wrote:
Should we really create any missing tax items into historical invoices?

This will depend on the company, but most likely you don't want to do that. Imagine someone enabling the tax plugin 2 years after running Kill Bill in production: most customers would be in an overdue state very quickly!

So, I'm in the process of not creating tax items on historical invoices.

While updating my unit tests, I wonder if my test case was correct or not. Here it is:

Let's say the VAT rate is 20%.

a. An invoice #1 is created with a taxable item #1 of €10.
b. A tax item #2 of €2 on item #1 is added to invoice #1.

c. Then an item adjustment #3 of €-1 is added to invoice #1. (-> Is it possible in real life that after this stage "c.", the tax plugin is not triggered?)

d. An invoice #2 is created with a taxable item #4 of €10.
e. The invoice #2 also has an item adjustment #5 of €-1 that relates to item #1 of invoice #1. (-> Is it possible to have such "cross-invoices" adjustments?)

f. The tax plugin is triggered.
g. An adjustment item #6 is added to invoice #1 for €-0.4 (taking into account the item adjustments #3 and #5)
h. A tax item #7 of €2 is added to invoice #2

Well if you want, the code is easier to read :)

Here is the setup:

And here is the outcome:

I would like to understand what is real in this test case, and what did just spin out my imagination when I wrote that?

In a broader sense, I need to understand in which invoices can item adjustments get created for some taxable item ? And what actions the server performs right after that ?

Cheers,
Benjamin

Benjamin Gandon

unread,
Oct 9, 2015, 12:21:29 PM10/9/15
to Kill Bill users mailing-list, benj...@gandon.org

Hi Pierre,
 
Also I found the computeNewItemsToTaxAndExistingItemsToAdjust() not to be useful outside the context of the Avatax plugin.

Why not? This helps break down which items are new and which ones are adjustments (tax handling may be different for returns, i.e. you probably need to use the original invoice date to report these).

That's right. I'll have a second look at it.

Yeah right. I had worked on it, but the code is awful to catch! The test cases don't help either. Very hard to read.
And then I was fooled by the Ruby invoice-test-plugin. But I now understand I've dug into the Ruby code because it is easier to catch.

Well, would you allow me to suggest a rewritten and clearer version of that Java code and tests? :)

 
I also noticed that when tax items are created on historical invoices, then the historical invoices gained a positive balance. But this positive balance doesn’t look to be collected so that it can be paid by the customer. (BTW, is it normal that those invoice balance are not added to the overall account balance?)

The overall account balance should be impacted. Kill Bill won't trigger automatic payments for them though.

Good to know.
How can I check the actual value of that overall account balance in the DB or with the API?
 

I don't get your point. You might have a better overview of accounting processes than me. Do I really need an accounting software?

You either need to integrate with an accounting software to report the VAT to the government or hire an accountant which will do it for you (procédure EDI-TVA).
 
Ok, now I see the tricky part. :)

And back to the "reconciliation" you mentioned earlier, do you have experience with French or American companies doing that?
I imagine you get listings our of the KB server and then compare with what data the accounting system has, in order to make adjustments where it doesn't match, is that correct?
I don't mean to dig very deep into this, but in your experience, what kind of adjustments (and on which side) this can result in?

Cheers,
/Benjamin

Pierre-Alexandre Meyer

unread,
Oct 12, 2015, 10:03:51 AM10/12/15
to Benjamin Gandon, Kill Bill users mailing-list
On Fri, Oct 9, 2015 at 11:40 AM, Benjamin Gandon <benj...@gandon.org> wrote:
I would like to understand what is real in this test case, and what did just spin out my imagination when I wrote that?

It's difficult to say what Kill Bill configuration would trigger such a scenario. I would instead start with your current billing use-cases and add test cases as you discover them.

In a broader sense, I need to understand in which invoices can item adjustments get created for some taxable item ?

Item adjustments can happen either because they are externally triggered via API, or because of "repairs" (i.e. the system generating a pro-ration, in case of an upgrade for instance).
 
And what actions the server performs right after that ?

The server will always call the invoice plugin, right before committing the invoice to disk.

On Fri, Oct 9, 2015 at 12:21 PM, Benjamin Gandon <benj...@gandon.org> wrote:
How can I check the actual value of that overall account balance in the DB or with the API?


And back to the "reconciliation" you mentioned earlier, do you have experience with French or American companies doing that? 
I imagine you get listings our of the KB server and then compare with what data the accounting system has, in order to make adjustments where it doesn't match, is that correct?
I don't mean to dig very deep into this, but in your experience, what kind of adjustments (and on which side) this can result in?
 
Requirements for internal and/or external (i.e. with audit firms) reconciliation will depend on the company size and juridiction (e.g. SOX). I would suggest consulting your financial advisor or tax accountant for more details.

--
Pierre

Benjamin Gandon

unread,
Oct 13, 2015, 10:11:19 AM10/13/15
to Kill Bill users mailing-list, benj...@gandon.org
Hi Pierre,


On Monday, October 12, 2015 at 4:03:51 PM UTC+2, Pierre-Alexandre Meyer wrote:

In a broader sense, I need to understand in which invoices can item adjustments get created for some taxable item ?

Item adjustments can happen either because they are externally triggered via API, or because of "repairs" (i.e. the system generating a pro-ration, in case of an upgrade for instance).

Ok thanks, but is it possible that an invoice B contains an item adjustment referring to a taxable item A that belongs to another invoice A?

 
On Fri, Oct 9, 2015 at 12:21 PM, Benjamin Gandon <benj...@gandon.org> wrote:
How can I check the actual value of that overall account balance in the DB or with the API?

Doing it at the database level is hard. Instead, use the getAccountBalance API:


Fine, thanks.
So there is no REST endpoint for that?

 
And back to the "reconciliation" you mentioned earlier, do you have experience with French or American companies doing that? 
I imagine you get listings our of the KB server and then compare with what data the accounting system has, in order to make adjustments where it doesn't match, is that correct?
I don't mean to dig very deep into this, but in your experience, what kind of adjustments (and on which side) this can result in?
 
Requirements for internal and/or external (i.e. with audit firms) reconciliation will depend on the company size and juridiction (e.g. SOX). I would suggest consulting your financial advisor or tax accountant for more details.

Ok, right. I shall do that.


Now I'd like my plugin to establish a mapping between taxation rates and catalog products.
I guess the avatax plugins delegates this mapping to the 3rd party application, is this correct?

Is it possible to tag products?
It is possible to annotate products in catalogs?


Cheers,
/Benjamin

Pierre-Alexandre Meyer

unread,
Oct 13, 2015, 10:29:59 AM10/13/15
to Benjamin Gandon, Kill Bill users mailing-list
On Tue, Oct 13, 2015 at 10:11 AM, Benjamin Gandon <benj...@gandon.org> wrote:
Ok thanks, but is it possible that an invoice B contains an item adjustment referring to a taxable item A that belongs to another invoice A?
 So there is no REST endpoint for that?

Now I'd like my plugin to establish a mapping between taxation rates and catalog products.
I guess the avatax plugins delegates this mapping to the 3rd party application, is this correct?

Is it possible to tag products?
It is possible to annotate products in catalogs?

Benjamin Gandon

unread,
Oct 13, 2015, 10:54:23 AM10/13/15
to Kill Bill users mailing-list, benj...@gandon.org
Thank you Pierre, these pointers are going to help me a lot!

What about my "cross-invoice item adjustments" question? Can you confirm that it cannot happen?

Pierre-Alexandre Meyer

unread,
Oct 13, 2015, 11:43:28 AM10/13/15
to Benjamin Gandon, Kill Bill users mailing-list
On Tue, Oct 13, 2015 at 10:54 AM, Benjamin Gandon <benj...@gandon.org> wrote:
What about my "cross-invoice item adjustments" question? Can you confirm that it cannot happen?

Yes, it can happen: in case of an upgrade for instance, the old invoice will be untouched, while the new one will contain both the pro-rated taxable item for the new plan and the "repair" item (i.e. adjustment item) for the existing item on the old invoice.

Additionally, the REST API doesn't prevent you to create an item adjustment on a different invoice than the invoice item it points to.

--
Pierre

Benjamin Gandon

unread,
Oct 29, 2015, 10:03:52 AM10/29/15
to Kill Bill users mailing-list, benj...@gandon.org
Thank you Pierre. This was for me the basis of the plugin rewrite.
I just posted updates to the developers mailing-list.
In the future it looks a better place to discuss my work.

Cheers

Benjamin Gandon

unread,
Nov 16, 2015, 3:10:40 AM11/16/15
to Kill Bill users mailing-list, benj...@gandon.org
Hi Pierre,


On Tuesday, October 13, 2015 at 4:29:59 PM UTC+2, Pierre-Alexandre Meyer wrote:

In the simple tax plugin, I also chose to support custom fields on invoice items.
Well, now that I'm testing it in a kill bill server, I wonder : is there any REST end point to set such custom fields on invoice items?
Looking at the JAXRS resources, all I can conclude is that invoice items don't have any such endpoint because they are not exposed as first-class objects web API.

Looking at the AvaTaxServlet, I just see it delegating to the AvaTaxDao.
How does the AvaTax plugin support setting custom fields on invoice items?

cheers,
/Benjamin

Pierre-Alexandre Meyer

unread,
Nov 16, 2015, 7:42:20 AM11/16/15
to Benjamin Gandon, Kill Bill users mailing-list
Hi Benjamin,

On Mon, Nov 16, 2015 at 3:10 AM, Benjamin Gandon <benj...@gandon.org> wrote:
Well, now that I'm testing it in a kill bill server, I wonder : is there any REST end point to set such custom fields on invoice items?
Looking at the JAXRS resources, all I can conclude is that invoice items don't have any such endpoint because they are not exposed as first-class objects web API.

Indeed, this is not yet supported at the JAR-RS level (you can only do it using the Java API).

If you need it, feel free to submit a PR for it (it should be quite similar to this pull request: https://github.com/killbill/killbill/pull/427).

--
Pierre
Reply all
Reply to author
Forward
0 new messages