How Can jBilling Help You?
Who’s Using jBilling?

“I can certainly recommend jBilling.”
Kevin Nelson
Web Conferencing Central
See all testimonials >

How treat a CDR in late when its purchase order is on finished status ?

Configuration :
Jbilling 2.0 and the mediation is set up and running perfectly.
A first billing cycle for a period of september has been succesfully run and the purchase order of september got is a status : "finished"

TEST:
What is the behaviour for a cdr in late ?

I launched a cdr for September, we expect about Jbilling a basic result like : the cdr can't be rated on a finished Purchase order and then the cdr is rejected and the next cdr in the file can be processed.

In the reality, Jbilling raises an exception like during the mediation trigger updating current order:

Is this a problem of configuration or bug?

2009-11-17 09:47:01,806 DEBUG [com.sapienter.jbilling.server.order.CurrentOrder] Current order constructed with user 30 event date Wed Oct 14 12:23:54 CEST 2009
2009-11-17 09:47:01,814 DEBUG [com.sapienter.jbilling.server.order.CurrentOrder] Calculating one timer date. Future periods 0
2009-11-17 09:47:01,832 DEBUG [com.sapienter.jbilling.server.order.CurrentOrder] Found one timer 802 but status is finished
2009-11-17 09:47:01,834 DEBUG [com.sapienter.jbilling.server.order.CurrentOrder] Calculating one timer date. Future periods 1
2009-11-17 09:47:01,834 FATAL [com.sapienter.jbilling.server.order.OrderBL] Updating current ordernull
java.lang.NullPointerException
at com.sapienter.jbilling.server.order.CurrentOrder.calculateDate(CurrentOrder.java:155)
at com.sapienter.jbilling.server.order.CurrentOrder.getCurrent(CurrentOrder.java:86)
at com.sapienter.jbilling.server.order.OrderBL.updateCurrent(OrderBL.java:1255)
at com.sapienter.jbilling.server.mediation.MediationSessionBean.normalizeRecordGroup(MediationSessionBean.java:289)
at sun.reflect.GeneratedMethodAccessor912.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy14.normalizeRecordGroup(Unknown Source)
at com.sapienter.jbilling.server.mediation.MediationSessionBean.trigger(MediationSessionBean.java:116)
at sun.reflect.GeneratedMethodAccessor881.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy14.trigger(Unknown Source)
at com.sapienter.jbilling.client.process.Trigger.execute(Trigger.java:209)
at org.quartz.core.JobRunShell.run(JobRunShell.java:191)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:516)

2009-11-17 09:47:01,841 FATAL [com.sapienter.jbilling.server.mediation.MediationSessionBean] Exception in mediation triggerUpdating current order
com.sapienter.jbilling.common.SessionInternalError: Updating current order
at com.sapienter.jbilling.server.order.OrderBL.updateCurrent(OrderBL.java:1322)
at com.sapienter.jbilling.server.mediation.MediationSessionBean.normalizeRecordGroup(MediationSessionBean.java:289)
at sun.reflect.GeneratedMethodAccessor912.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy14.normalizeRecordGroup(Unknown Source)
at com.sapienter.jbilling.server.mediation.MediationSessionBean.trigger(MediationSessionBean.java:116)
at sun.reflect.GeneratedMethodAccessor881.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy14.trigger(Unknown Source)
at com.sapienter.jbilling.client.process.Trigger.execute(Trigger.java:209)
at org.quartz.core.JobRunShell.run(JobRunShell.java:191)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:516)

 
vinay wrote 1 year 41 weeks ago
econde wrote 1 year 46 weeks ago

Hi there, As you can see,

Hi there,

As you can see, jBilling will find the right current order that matches the event's billing cycle. If that current order is finished, then it means that you have billed that month already... you can't generate another invoice for that same month.

But of course, things like this happen. What we need is to add some logic to push those events to the next (not yet invoiced) billing cycle. I can think of two ways to go about this:

- Modify CurrentOrder.java so if the found order is 'finished', go to the next cycle.
- In the date assignment rule, add some logic where if the date is 'too old', add some time.

The first one is much better, because it preserves the original date of the event, but it requires changes to the code.

The second one is easier (configuration rather than customization), but then the invoice will show that event with a fake date.

Cheers,

Emiliano Conde
Lead Developer - jBilling

 
macw wrote 1 year 46 weeks ago

Found the solution the do while loop was misplaced...

Replace in CurrentOrder.java:

public Integer getCurrent() {
Integer subscriptionId = user.getEntity().getCustomer().getCurrentOrderId();
Integer entityId = null;
Integer currencyId = null;
if (subscriptionId == null) {
return null;
}
try {
order = new OrderBL(subscriptionId);
entityId = order.getEntity().getBaseUserByUserId().getCompany().getId();
currencyId = order.getEntity().getCurrencyId();
} catch (Exception e) {
throw new SessionInternalError("Error looking for main subscription order",
CurrentOrder.class, e);
}

int futurePeriods = 0;
boolean orderFound = false;
do {
LOG.debug("Calculating one timer date. Future periods " + futurePeriods);

with:

public Integer getCurrent() {
Integer subscriptionId = user.getEntity().getCustomer().getCurrentOrderId();
Integer entityId = null;
Integer currencyId = null;
if (subscriptionId == null) {
return null;
}

int futurePeriods = 0;
boolean orderFound = false;
do {
try {
order = new OrderBL(subscriptionId);
entityId = order.getEntity().getBaseUserByUserId().getCompany().getId();
currencyId = order.getEntity().getCurrencyId();
} catch (Exception e) {
throw new SessionInternalError("Error looking for main subscription order",
CurrentOrder.class, e);
}

LOG.debug("Calculating one timer date. Future periods " + futurePeriods);

econde wrote 1 year 45 weeks ago

Disregard my previous

Disregard my previous comment.

You are right, there is a bug. Well, there was, we committed the fix a few days ago.

So the expected functionality is actually to use the next cycle current order when the one that the event should go is in status 'finished.

Thanks you!

Emiliano Conde
Lead Developer - jBilling

 
macw wrote 1 year 47 weeks ago

Same with me

Have you ever found a solution?

Please register or login to post a comment.