Add custom fields to invoice items that don't exist *yet*?

61 views
Skip to first unread message

Benjamin Gandon

unread,
Jan 17, 2016, 7:14:47 PM1/17/16
to Kill Bill developers mailing-list
Hi,

Still testing my simple tax plugin, I'm now facing a challenging issue.
As I previously mentioned, I chose not to have any dedicated tables for my plugin, but just persist my tax codes into custom fields.
I would like to stick to this choice, otherwise I would have to change the name into “complex-tax plugin” and I definitely don't want to do that.

But most of the time, I need to add custom fields on items of an invoice that is being created.
So that I get a boom! I mean an ObjectDoesNotExist exception. (Btw, could you make this exception public please? Currently, I'm catching all IllegalStateException and filtering on the class name!)

So my question is : how could I defer the creation of custom fields so that it happens at the right time, after the invoice items are properly persisted?
Thanks for your help!

Cheers
/Benjamin

Pierre-Alexandre Meyer

unread,
Jan 18, 2016, 9:56:26 AM1/18/16
to Benjamin Gandon, Kill Bill developers mailing-list
On Sun, Jan 17, 2016 at 7:14 PM, Benjamin Gandon <benj...@gandon.org> wrote:
Still testing my simple tax plugin, I'm now facing a challenging issue.
As I previously mentioned, I chose not to have any dedicated tables for my plugin, but just persist my tax codes into custom fields.
I would like to stick to this choice, otherwise I would have to change the name into “complex-tax plugin” and I definitely don't want to do that.

FWIW, I don't think adding a table managed by your plugin complexifies it that much (all of the JDBC setup is done for you).

But most of the time, I need to add custom fields on items of an invoice that is being created.
So that I get a boom! I mean an ObjectDoesNotExist exception. (Btw, could you make this exception public please? Currently, I'm catching all IllegalStateException and filtering on the class name!)

Simply making it public probably won't help, as it wouldn't be exposed by the OSGI framework. To properly catch it, it would need to be exposed in killbill-api but we don't expose runtime exceptions today. This definitively requires more thoughts -- could you open a bug describing your use-case and current work-around?

So my question is : how could I defer the creation of custom fields so that it happens at the right time, after the invoice items are properly persisted?

You cannot: the object must first exist in order to attach a custom field to it. Taking a step back, what are you trying to do?

--
Pierre

Benjamin Gandon

unread,
Jan 18, 2016, 2:22:01 PM1/18/16
to Kill Bill developers mailing-list, benj...@gandon.org
About the ObjectDoesNotExist exception, I just had to catch it to witness my plugin work perfectly, excepted the persisting of the tax codes that are resolved for invoice items.
I mean I just wrote a workaround patch. I couldn't formalize any use case out of it. If you don't have any policy for exporting Runtime Exceptions, then don't mind with making that exception public. Nevermind.

So, what am I trying to do?

The simple-tax plugin now uses tax codes. They define properties (tax rates, cutoff dates, and targeted countries) for taxes.
And when a tax code is resolved for an invoice item, it is stored in a custom field named "taxCodes" for this very item. (The custom field is named "taxCodes" because it could be multi-valued, with the help of a comma-separated value format.)

So, when an invoice is being created, the simple tax plugin tries to resolve tax codes for its items.
When some tax code is resolved, the plugin persists it in the "taxCodes" custom field. That custom field is of type INVOICE_ITEM and refers to the invoice item for which the tax code was resoled.

This mechanism ensures the itempotency of the taxation algorithm. Old invoices are checked for the invoice plugin. If their tax codes match the amount of taxes referring to the invoice item, then nothing is done. Otherwise taxes are adjusted to match the right amount. But the plugin only defines tax codes for new invoices. Tax codes set on old invoices are considered read-only by the plugin, though they can be manually tweaked by the exposed REST API in case any custom tax would have to be applied.

Is anything is unclear in this overview of the simple-tax plugin I just made, don't hesitate to ask for any further explanations.

Now you might understand why I need to persist custom fields along with the items of a new invoice being created.

My first idea for a solution, was to post a message on the bus, to tell Kill Bill to defer the custom fields creation, hoping the server to treat messages in order and persist those custom fields properly after the invoice items are persisted.
A second alternative would be the invoice plugins being called a second time after new invoice are persisted. This would give a chance for invoice plugin to decorate the created invoices with custom fields.
An third alternative would be to allow the invoice plugin to return a set of custom fields, along with the new items to add to the invoice being created.

I could work on any extension of the API on which we would agree.
What do you say?


Cheers
/Benjamin

PS: When I say I don't want my plugin to require some SQL schema to be setup, I'm considering the user point of view. I don't want my users to be confused with clumsy setups. Currently, these setups are based on dll files to be applied to the plugin database. These dll are subject to confusion about the right version you have downloaded and I'm definitely reluctant to having my users deal with such potential confusion. That's what I meant when I said (with humor) I'm writing a "simple-tax" plugin and not a "complex-tax" plugin. :) This situation could be disappear in the event Kill Bill would adopt some schema management library like liquibase, as we earlier discussed last year. I let you give me your thoughts on this, based on the details I give you here.

PS2: At this point, we might need to talk directly through Skype instead. The delays imposed by our different time zone are just too big. My ID is benjamin.gandon. Could you please send me an invite so that we get in contact with eachother? Thanks!

Pierre-Alexandre Meyer

unread,
Jan 18, 2016, 4:54:50 PM1/18/16
to Benjamin Gandon, Kill Bill developers mailing-list
On Mon, Jan 18, 2016 at 2:22 PM, Benjamin Gandon <benj...@gandon.org> wrote:
A second alternative would be the invoice plugins being called a second time after new invoice are persisted. This would give a chance for invoice plugin to decorate the created invoices with custom fields.

This seems like a reasonable approach: we were actually wondering if we should make most plugin APIs follow the pattern priorCall/onSuccess/onFailure (similar to the control plugin API for example).

In practice though, we have currently no plan to change these APIs for 0.18 (the roadmap for 0.17 hasn't been finalized yet). That being said, you could mimic the behavior by simply listening to invoice creation events (the bus event is sent after the invoice is persisted). Would that work?

--
Pierre

Benjamin Gandon

unread,
Jan 20, 2016, 10:59:23 AM1/20/16
to Kill Bill developers mailing-list, benj...@gandon.org
So we have a long term approach, and a short term workaround.
That's great news!

I'll dig into that listening to invoice creation events, then.
I'll keep you updated.

Is the roadmap on any wiki page, btw?

Pierre-Alexandre Meyer

unread,
Jan 21, 2016, 11:17:33 AM1/21/16
to Benjamin Gandon, Kill Bill developers mailing-list
Regarding the roadmap, we use milestones on GitHub:

--
You received this message because you are subscribed to the Google Groups "Kill Bill developers mailing-list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to killbilling-d...@googlegroups.com.
To post to this group, send email to killbil...@googlegroups.com.
Visit this group at https://groups.google.com/group/killbilling-dev.
To view this discussion on the web visit https://groups.google.com/d/msgid/killbilling-dev/c764e879-5f4a-44c3-bad7-8a5f23c0b145%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Pierre

Benjamin Gandon

unread,
Jan 22, 2016, 7:16:49 AM1/22/16
to Kill Bill developers mailing-list, benj...@gandon.org
Indeed! Thanks for pointing this out to me!

Cheers
/Benjamin

Benjamin Gandon

unread,
Jan 28, 2016, 9:32:56 AM1/28/16
to Kill Bill developers mailing-list, benj...@gandon.org
Hi,

So, I went through the ExtBusEvent solution!

I started with the simple-tax plugin implementing the NotificationPluginApi interface, and its activator making a 2nd call to the registrar.registerService() method so that the invoice plugin is also registered as a NotificationPluginApi.


But the implemented onEvent(ExtBusEvent) method (of the NotificationPluginApi interface) didn't seem to be called, though the bus_ext_events_history table properly listed the INVOICE_CREATION events.



As a workaround, I implemented the listening of events as the killbill-email-notifications-plugin does. I mean as the EmailNotificationActivator does, registering an OSGIKillbillEventHandler.


Now the simple-tax activator doesn't call registrar.registerService() twice anymore. Instead, the OSGIKillbillEventHandler implementation delegates to the onEvent(ExtBusEvent) method.


And it seems to work.


Could you please confirm this the correct way for an invoice plugin to listen to ExtBusEvent events?


Cheers,
/Benjamin

Pierre-Alexandre Meyer

unread,
Jan 28, 2016, 11:12:07 AM1/28/16
to Benjamin Gandon, Kill Bill developers mailing-list
That sounds fine -- you should have a single OSGIKillbillEventHandler registered that handles the events you are interested in.

--
You received this message because you are subscribed to the Google Groups "Kill Bill developers mailing-list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to killbilling-d...@googlegroups.com.
To post to this group, send email to killbil...@googlegroups.com.
Visit this group at https://groups.google.com/group/killbilling-dev.

For more options, visit https://groups.google.com/d/optout.



--
Pierre

Benjamin Gandon

unread,
Jan 28, 2016, 11:51:47 AM1/28/16
to Kill Bill developers mailing-list, benj...@gandon.org
Ok thanks!

But do you know why registering an instance of the NotificationPluginApi interface doesn't lead to the onEvent(ExtBusEvent) method being ever called?

Pierre-Alexandre Meyer

unread,
Jan 28, 2016, 12:12:53 PM1/28/16
to Benjamin Gandon, Kill Bill developers mailing-list
Java plugins use the Java Observer/Observable mechanism to receive external bus events. The actual implementation is in OSGIKillbillEventDispatcher.java.


For more options, visit https://groups.google.com/d/optout.



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