killbill-aplcache
Changes
account/pom.xml 2(+1 -1)
api/pom.xml 2(+1 -1)
beatrix/pom.xml 2(+1 -1)
beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java 160(+160 -0)
catalog/pom.xml 2(+1 -1)
currency/pom.xml 2(+1 -1)
entitlement/pom.xml 2(+1 -1)
invoice/pom.xml 2(+1 -1)
invoice/src/test/java/com/ning/billing/invoice/generator/DefaultInvoiceGeneratorWithSwitchRepairLogic.java 4(+2 -2)
invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGeneratorRepairUnit.java 12(+6 -6)
jaxrs/pom.xml 2(+1 -1)
junction/pom.xml 2(+1 -1)
NEWS 12(+12 -0)
osgi/pom.xml 2(+1 -1)
osgi-bundles/bundles/jruby/pom.xml 2(+1 -1)
osgi-bundles/bundles/logger/pom.xml 2(+1 -1)
osgi-bundles/bundles/logger/src/main/java/com/ning/billing/osgi/bundles/logger/Activator.java 32(+15 -17)
osgi-bundles/bundles/pom.xml 2(+1 -1)
osgi-bundles/defaultbundles/pom.xml 2(+1 -1)
osgi-bundles/libs/killbill/pom.xml 2(+1 -1)
osgi-bundles/libs/pom.xml 2(+1 -1)
osgi-bundles/libs/slf4j-osgi/pom.xml 2(+1 -1)
osgi-bundles/pom.xml 2(+1 -1)
osgi-bundles/tests/beatrix/pom.xml 2(+1 -1)
osgi-bundles/tests/payment/pom.xml 2(+1 -1)
osgi-bundles/tests/pom.xml 2(+1 -1)
overdue/pom.xml 2(+1 -1)
payment/pom.xml 2(+1 -1)
pom.xml 4(+2 -2)
server/pom.xml 2(+1 -1)
subscription/pom.xml 2(+1 -1)
subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java 60(+51 -9)
subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java 29(+25 -4)
subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java 38(+33 -5)
subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg 16(+16 -0)
subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java 21(+20 -1)
tenant/pom.xml 2(+1 -1)
usage/pom.xml 2(+1 -1)
util/pom.xml 2(+1 -1)
Details
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index e0ce11c..0e574ab 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -20,6 +20,8 @@
<inspection_tool class="LocalCanBeFinal" enabled="true" level="WARNING" enabled_by_default="true">
<option name="REPORT_VARIABLES" value="true" />
<option name="REPORT_PARAMETERS" value="true" />
+ <option name="REPORT_CATCH_PARAMETERS" value="true" />
+ <option name="REPORT_FOREACH_PARAMETERS" value="true" />
</inspection_tool>
<inspection_tool class="MagicNumber" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MissortedModifiers" enabled="true" level="WARNING" enabled_by_default="true">
account/pom.xml 2(+1 -1)
diff --git a/account/pom.xml b/account/pom.xml
index 93ac27d..b295e0e 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
index 4cfd258..dd1d652 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
@@ -23,7 +23,6 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.Define;
import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
import com.ning.billing.account.api.Account;
@@ -45,7 +44,8 @@ public interface AccountSqlDao extends EntitySqlDao<AccountModelDao, Account> {
// Magic value to force MySQL to stream from the database
// See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
@FetchSize(Integer.MIN_VALUE)
- public Iterator<AccountModelDao> searchAccounts(@Define("searchKey") final String searchKey,
+ public Iterator<AccountModelDao> searchAccounts(@Bind("searchKey") final String searchKey,
+ @Bind("likeSearchKey") final String likeSearchKey,
@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
@BindBean final InternalTenantContext context);
diff --git a/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java b/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
index 3ce879e..ea710c3 100644
--- a/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
@@ -112,7 +112,7 @@ public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, Account, A
new PaginationIteratorBuilder<AccountModelDao, Account, AccountSqlDao>() {
@Override
public Iterator<AccountModelDao> build(final AccountSqlDao accountSqlDao, final Long limit) {
- return accountSqlDao.searchAccounts(searchKey, offset, limit, context);
+ return accountSqlDao.searchAccounts(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
}
},
offset,
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
index 10d4edc..c1e5255 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
@@ -86,17 +86,17 @@ getAccountByKey() ::= <<
where external_key = :externalKey <AND_CHECK_TENANT()>;
>>
-searchAccounts(searchKey, offset, rowCount) ::= <<
+searchAccounts() ::= <<
select SQL_CALC_FOUND_ROWS
<allTableFields("t.")>
from <tableName()> t
where 1 = 1
and (
- <idField("t.")> = '<searchKey>'
- or t.name like '%<searchKey>%'
- or t.email like '%<searchKey>%'
- or t.external_key like '%<searchKey>%'
- or t.company_name like '%<searchKey>%'
+ <idField("t.")> = :searchKey
+ or t.name like :likeSearchKey
+ or t.email like :likeSearchKey
+ or t.external_key like :likeSearchKey
+ or t.company_name like :likeSearchKey
)
<AND_CHECK_TENANT("t.")>
order by <recordIdField("t.")> ASC
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index 9ea3534..cc9f6a1 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-internal-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/subscription/api/SubscriptionBaseInternalApi.java b/api/src/main/java/com/ning/billing/subscription/api/SubscriptionBaseInternalApi.java
index 9662d65..8c2ce8f 100644
--- a/api/src/main/java/com/ning/billing/subscription/api/SubscriptionBaseInternalApi.java
+++ b/api/src/main/java/com/ning/billing/subscription/api/SubscriptionBaseInternalApi.java
@@ -24,21 +24,20 @@ import javax.annotation.Nullable;
import org.joda.time.DateTime;
+import com.ning.billing.callcontext.InternalCallContext;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.entitlement.api.EntitlementAOStatusDryRun;
+import com.ning.billing.events.EffectiveSubscriptionInternalEvent;
import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
-import com.ning.billing.callcontext.InternalCallContext;
-import com.ning.billing.callcontext.InternalTenantContext;
-import com.ning.billing.events.EffectiveSubscriptionInternalEvent;
-
+import com.ning.billing.util.entity.Pagination;
public interface SubscriptionBaseInternalApi {
public SubscriptionBase createSubscription(final UUID bundleId, final PlanPhaseSpecifier spec, final DateTime requestedDateWithMs,
final InternalCallContext context) throws SubscriptionBaseApiException;
-
public SubscriptionBaseBundle createBundleForAccount(final UUID accountId, final String bundleName, final InternalCallContext context)
throws SubscriptionBaseApiException;
@@ -49,6 +48,10 @@ public interface SubscriptionBaseInternalApi {
public List<SubscriptionBaseBundle> getBundlesForKey(final String bundleKey, final InternalTenantContext context);
+ public Pagination<SubscriptionBaseBundle> getBundles(final Long offset, final Long limit, final InternalTenantContext context);
+
+ public Pagination<SubscriptionBaseBundle> searchBundles(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context);
+
public Iterable<UUID> getNonAOSubscriptionIdsForKey(final String bundleKey, final InternalTenantContext context);
public List<SubscriptionBase> getSubscriptionsForBundle(final UUID bundleId, final InternalTenantContext context);
@@ -74,6 +77,5 @@ public interface SubscriptionBaseInternalApi {
public List<EntitlementAOStatusDryRun> getDryRunChangePlanStatus(final UUID subscriptionId, @Nullable final String baseProductName,
final DateTime requestedDate, final InternalTenantContext context) throws SubscriptionBaseApiException;
-
public void updateExternalKey(final UUID bundleId, final String newExternalKey, final InternalCallContext context);
}
beatrix/pom.xml 2(+1 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index c4c9f77..8d872e7 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-beatrix</artifactId>
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
index 0358452..9c1eb94 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
@@ -26,9 +26,11 @@ import javax.inject.Inject;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
+import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
+import com.ning.billing.ErrorCode;
import com.ning.billing.account.api.Account;
import com.ning.billing.api.TestApiListener.NextEvent;
import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck;
@@ -39,7 +41,9 @@ import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.DefaultEntitlement;
+import com.ning.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceApiException;
import com.ning.billing.invoice.api.InvoiceItemType;
import com.ning.billing.invoice.generator.DefaultInvoiceGeneratorWithSwitchRepairLogic;
import com.ning.billing.invoice.generator.DefaultInvoiceGeneratorWithSwitchRepairLogic.REPAIR_INVOICE_LOGIC;
@@ -700,4 +704,160 @@ public class TestIntegrationInvoiceWithRepairLogic extends TestIntegrationBase {
new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 11), new LocalDate(2012, 6, 11), InvoiceItemType.CBA_ADJ, new BigDecimal("-249.95")));
invoiceChecker.checkInvoice(invoices.get(3).getId(), callContext, toBeChecked);
}
+
+ @Test(groups = "slow")
+ public void testRepairWithFullItemAdjustment() throws Exception {
+
+ invoiceGenerator.setDefaultRepairLogic(REPAIR_INVOICE_LOGIC.PARTIAL_REPAIR);
+
+ final LocalDate today = new LocalDate(2013, 7, 19);
+ final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
+
+ final String productName = "Shotgun";
+ final BillingPeriod term = BillingPeriod.ANNUAL;
+ final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+
+ //
+ // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
+ //
+ DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.INVOICE);
+ assertNotNull(bpEntitlement);
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), callContext).size(), 1);
+
+ assertEquals(bpEntitlement.getSubscriptionBase().getCurrentPlan().getBillingPeriod(), BillingPeriod.ANNUAL);
+
+ // Move out of trials for interesting invoices adjustments
+ busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addDays(30);
+ assertListenerStatus();
+
+ List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 2);
+ ImmutableList<ExpectedInvoiceItemCheck> toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 8, 18), new LocalDate(2014, 8, 18), InvoiceItemType.RECURRING, new BigDecimal("2399.95")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+
+ // Move clock to 2013-09-17
+ clock.addDays(30);
+ busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.INVOICE_ADJUSTMENT);
+ bpEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, callContext);
+ assertListenerStatus();
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 2);
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 8, 18), new LocalDate(2014, 8, 18), InvoiceItemType.RECURRING, new BigDecimal("2399.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 9, 17), new LocalDate(2014, 8, 18), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-2202.67")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 9, 17), new LocalDate(2013, 9, 17), InvoiceItemType.CBA_ADJ, new BigDecimal("2202.67")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+
+
+ //
+ // ITEM ADJUSTMENT PRIOR TO DOING THE REPAIR
+ //
+ final Invoice invoice1 = invoices.get(1);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), callContext);
+ final ExpectedPaymentCheck expectedPaymentCheck = new ExpectedPaymentCheck(clock.getUTCNow().toLocalDate(), new BigDecimal("2399.95"), PaymentStatus.SUCCESS, invoice1.getId(), Currency.USD);
+ final Payment payment1 = payments.get(0);
+
+ final Map<UUID, BigDecimal> iias = new HashMap<UUID, BigDecimal>();
+ iias.put(invoice1.getInvoiceItems().get(0).getId(), new BigDecimal("197.28"));
+ busHandler.pushExpectedEvents(NextEvent.INVOICE_ADJUSTMENT);
+ paymentApi.createRefundWithItemsAdjustments(account, payment1.getId(), iias, callContext);
+ assertListenerStatus();
+
+ try {
+ invoiceUserApi.triggerInvoiceGeneration(account.getId(), new LocalDate(clock.getUTCToday()), false, callContext);
+ Assert.fail("Should not gnenerated an new invoice");
+ } catch (InvoiceApiException e) {
+ Assert.assertEquals(e.getCode(), ErrorCode.INVOICE_NOTHING_TO_DO.getCode());
+ }
+ }
+
+ //
+ // This is the exact same test as testRepairWithFullItemAdjustment except we now only do a partial item adjustment.
+ // The invoice code will NOT reinvoice for the remaining part as the item was both repaired and adjusted and so
+ // it does not have enough info to understand what should be re-invoiced.
+ //
+ // Note that there is no real use case for those scenarii in real life
+ //
+ @Test(groups = "slow")
+ public void testRepairWithPartialItemAdjustment() throws Exception {
+
+ invoiceGenerator.setDefaultRepairLogic(REPAIR_INVOICE_LOGIC.PARTIAL_REPAIR);
+
+ final LocalDate today = new LocalDate(2013, 7, 19);
+ final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
+
+ final String productName = "Shotgun";
+ final BillingPeriod term = BillingPeriod.ANNUAL;
+ final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+
+ //
+ // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
+ //
+ DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.INVOICE);
+ assertNotNull(bpEntitlement);
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), callContext).size(), 1);
+
+ assertEquals(bpEntitlement.getSubscriptionBase().getCurrentPlan().getBillingPeriod(), BillingPeriod.ANNUAL);
+
+ // Move out of trials for interesting invoices adjustments
+ busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addDays(30);
+ assertListenerStatus();
+
+ List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 2);
+ ImmutableList<ExpectedInvoiceItemCheck> toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 8, 18), new LocalDate(2014, 8, 18), InvoiceItemType.RECURRING, new BigDecimal("2399.95")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+
+ // Move clock to 2013-09-17
+ clock.addDays(30);
+ busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.INVOICE_ADJUSTMENT);
+ bpEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, callContext);
+ assertListenerStatus();
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 2);
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 8, 18), new LocalDate(2014, 8, 18), InvoiceItemType.RECURRING, new BigDecimal("2399.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 9, 17), new LocalDate(2014, 8, 18), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-2202.67")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 9, 17), new LocalDate(2013, 9, 17), InvoiceItemType.CBA_ADJ, new BigDecimal("2202.67")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+
+
+ //
+ // ITEM ADJUSTMENT PRIOR TO DOING THE REPAIR
+ //
+ final Invoice invoice1 = invoices.get(1);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), callContext);
+ final ExpectedPaymentCheck expectedPaymentCheck = new ExpectedPaymentCheck(clock.getUTCNow().toLocalDate(), new BigDecimal("2399.95"), PaymentStatus.SUCCESS, invoice1.getId(), Currency.USD);
+ final Payment payment1 = payments.get(0);
+
+ final Map<UUID, BigDecimal> iias = new HashMap<UUID, BigDecimal>();
+ iias.put(invoice1.getInvoiceItems().get(0).getId(), new BigDecimal("100.00"));
+ busHandler.pushExpectedEvents(NextEvent.INVOICE_ADJUSTMENT);
+ paymentApi.createRefundWithItemsAdjustments(account, payment1.getId(), iias, callContext);
+ assertListenerStatus();
+
+ try {
+ invoiceUserApi.triggerInvoiceGeneration(account.getId(), new LocalDate(clock.getUTCToday()), false, callContext);
+ Assert.fail("Should not gnenerated an new invoice");
+ } catch (InvoiceApiException e) {
+ Assert.assertEquals(e.getCode(), ErrorCode.INVOICE_NOTHING_TO_DO.getCode());
+ }
+ }
+
}
catalog/pom.xml 2(+1 -1)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index 729fca9..4630db6 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
currency/pom.xml 2(+1 -1)
diff --git a/currency/pom.xml b/currency/pom.xml
index 73f55f9..157778e 100644
--- a/currency/pom.xml
+++ b/currency/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index ca9aa82..a1c4c86 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java
index 0c18efd..cc42d68 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java
@@ -27,6 +27,8 @@ import java.util.UUID;
import javax.inject.Inject;
import org.joda.time.DateTimeZone;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.ning.billing.ErrorCode;
import com.ning.billing.ObjectType;
@@ -34,8 +36,6 @@ import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.entitlement.AccountEntitlements;
import com.ning.billing.entitlement.EntitlementInternalApi;
-import com.ning.billing.entitlement.EventsStream;
-import com.ning.billing.entitlement.api.svcs.DefaultEntitlementInternalApi;
import com.ning.billing.entitlement.engine.core.EntitlementUtils;
import com.ning.billing.subscription.api.SubscriptionBase;
import com.ning.billing.subscription.api.SubscriptionBaseInternalApi;
@@ -48,15 +48,22 @@ import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.customfield.ShouldntHappenException;
import com.ning.billing.util.dao.NonEntityDao;
+import com.ning.billing.util.entity.Pagination;
+import com.ning.billing.util.entity.dao.DefaultPaginationHelper.SourcePaginationBuilder;
+import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
+import static com.ning.billing.util.entity.dao.DefaultPaginationHelper.getEntityPaginationNoException;
+
public class DefaultSubscriptionApi implements SubscriptionApi {
+ private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionApi.class);
+
private static final Comparator<SubscriptionBundle> SUBSCRIPTION_BUNDLE_COMPARATOR = new Comparator<SubscriptionBundle>() {
@Override
public int compare(final SubscriptionBundle o1, final SubscriptionBundle o2) {
@@ -164,7 +171,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
}
final SubscriptionBase subscriptionBase = subscriptionBaseInternalApi.getSubscriptionFromId(activeSubscriptionIdForKey, internalContext);
return getSubscriptionBundle(subscriptionBase.getBundleId(), context);
- } catch (SubscriptionBaseApiException e) {
+ } catch (final SubscriptionBaseApiException e) {
throw new SubscriptionApiException(e);
}
}
@@ -188,12 +195,60 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
return getSubscriptionBundlesForAccount(accountId, context);
}
+ @Override
+ public Pagination<SubscriptionBundle> getSubscriptionBundles(final Long offset, final Long limit, final TenantContext context) {
+ final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(context);
+ return getEntityPaginationNoException(limit,
+ new SourcePaginationBuilder<SubscriptionBaseBundle, SubscriptionApiException>() {
+ @Override
+ public Pagination<SubscriptionBaseBundle> build() {
+ return subscriptionBaseInternalApi.getBundles(offset, limit, internalContext);
+ }
+ },
+ new Function<SubscriptionBaseBundle, SubscriptionBundle>() {
+ @Override
+ public SubscriptionBundle apply(final SubscriptionBaseBundle subscriptionBaseBundle) {
+ try {
+ return getSubscriptionBundle(subscriptionBaseBundle.getId(), context);
+ } catch (final SubscriptionApiException e) {
+ log.warn("Error retrieving subscription", e);
+ return null;
+ }
+ }
+ }
+ );
+ }
+
+ @Override
+ public Pagination<SubscriptionBundle> searchSubscriptionBundles(final String searchKey, final Long offset, final Long limit, final TenantContext context) {
+ final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(context);
+ return getEntityPaginationNoException(limit,
+ new SourcePaginationBuilder<SubscriptionBaseBundle, SubscriptionApiException>() {
+ @Override
+ public Pagination<SubscriptionBaseBundle> build() {
+ return subscriptionBaseInternalApi.searchBundles(searchKey, offset, limit, internalContext);
+ }
+ },
+ new Function<SubscriptionBaseBundle, SubscriptionBundle>() {
+ @Override
+ public SubscriptionBundle apply(final SubscriptionBaseBundle subscriptionBaseBundle) {
+ try {
+ return getSubscriptionBundle(subscriptionBaseBundle.getId(), context);
+ } catch (final SubscriptionApiException e) {
+ log.warn("Error retrieving subscription", e);
+ return null;
+ }
+ }
+ }
+ );
+ }
+
private List<SubscriptionBundle> getSubscriptionBundlesForAccount(final UUID accountId, final TenantContext tenantContext) throws SubscriptionApiException {
// Retrieve entitlements
final AccountEntitlements accountEntitlements;
try {
accountEntitlements = entitlementInternalApi.getAllEntitlementsForAccountId(accountId, tenantContext);
- } catch (EntitlementApiException e) {
+ } catch (final EntitlementApiException e) {
throw new SubscriptionApiException(e);
}
invoice/pom.xml 2(+1 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 84d1e39..81c461a 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-invoice</artifactId>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 171d337..e8fec16 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -134,6 +134,25 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
}
@Override
+ public Pagination<Invoice> searchInvoices(final String searchKey, final Long offset, final Long limit, final TenantContext context) {
+ return getEntityPaginationNoException(limit,
+ new SourcePaginationBuilder<InvoiceModelDao, AccountApiException>() {
+ @Override
+ public Pagination<InvoiceModelDao> build() {
+ // Invoices will be shallow, i.e. won't contain items nor payments
+ return dao.searchInvoices(searchKey, offset, limit, internalCallContextFactory.createInternalTenantContext(context));
+ }
+ },
+ new Function<InvoiceModelDao, Invoice>() {
+ @Override
+ public Invoice apply(final InvoiceModelDao invoiceModelDao) {
+ return new DefaultInvoice(invoiceModelDao);
+ }
+ }
+ );
+ }
+
+ @Override
public BigDecimal getAccountBalance(final UUID accountId, final TenantContext context) {
final BigDecimal result = dao.getAccountBalance(accountId, internalCallContextFactory.createInternalTenantContext(accountId, context));
return result == null ? BigDecimal.ZERO : result;
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index 754b74d..441eba2 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -17,6 +17,7 @@
package com.ning.billing.invoice.dao;
import java.math.BigDecimal;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -45,6 +46,8 @@ import com.ning.billing.invoice.notification.NextBillingDatePoster;
import com.ning.billing.util.cache.CacheControllerDispatcher;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.dao.NonEntityDao;
+import com.ning.billing.util.entity.Pagination;
+import com.ning.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.PaginationIteratorBuilder;
import com.ning.billing.util.entity.dao.EntityDaoBase;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
@@ -248,6 +251,21 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
}
@Override
+ public Pagination<InvoiceModelDao> searchInvoices(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
+ return paginationHelper.getPagination(InvoiceSqlDao.class,
+ new PaginationIteratorBuilder<InvoiceModelDao, Invoice, InvoiceSqlDao>() {
+ @Override
+ public Iterator<InvoiceModelDao> build(final InvoiceSqlDao invoiceSqlDao, final Long limit) {
+ return invoiceSqlDao.searchInvoices(searchKey, offset, limit, context);
+ }
+ },
+ offset,
+ limit,
+ context);
+
+ }
+
+ @Override
public BigDecimal getAccountBalance(final UUID accountId, final InternalTenantContext context) {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<BigDecimal>() {
@Override
@@ -285,7 +303,6 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
});
}
-
@Override
public UUID getInvoiceIdByPaymentId(final UUID paymentId, final InternalTenantContext context) {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<UUID>() {
@@ -540,7 +557,6 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
final InvoiceItemSqlDao transInvoiceItemDao = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class);
transInvoiceItemDao.create(externalCharge, context);
-
cbaDao.doCBAComplexity(accountId, entitySqlDaoWrapperFactory, context);
// Notify the bus since the balance of the invoice changed
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index 8f2c668..73f1185 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -31,6 +31,7 @@ import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.util.entity.Pagination;
import com.ning.billing.util.entity.dao.EntityDao;
public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceApiException> {
@@ -46,6 +47,8 @@ public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceA
List<InvoiceModelDao> getInvoicesBySubscription(UUID subscriptionId, InternalTenantContext context);
+ public Pagination<InvoiceModelDao> searchInvoices(String searchKey, Long offset, Long limit, InternalTenantContext context);
+
UUID getInvoiceIdByPaymentId(UUID paymentId, InternalTenantContext context);
List<InvoicePaymentModelDao> getInvoicePayments(UUID paymentId, InternalTenantContext context);
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
index 90099ac..a0824db 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
@@ -16,15 +16,17 @@
package com.ning.billing.invoice.dao;
+import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
-import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
@@ -36,6 +38,15 @@ public interface InvoiceSqlDao extends EntitySqlDao<InvoiceModelDao, Invoice> {
@BindBean final InternalTenantContext context);
@SqlQuery
+ // Magic value to force MySQL to stream from the database
+ // See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
+ @FetchSize(Integer.MIN_VALUE)
+ public Iterator<InvoiceModelDao> searchInvoices(@Bind("searchKey") final String searchKey,
+ @Bind("offset") final Long offset,
+ @Bind("rowCount") final Long rowCount,
+ @BindBean final InternalTenantContext context);
+
+ @SqlQuery
UUID getInvoiceIdByPaymentId(@Bind("paymentId") final String paymentId,
@BindBean final InternalTenantContext context);
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
index 2d4d2e8..358c04c 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
@@ -64,7 +64,7 @@ import com.google.inject.Inject;
* Terminology for repair scenarii:
* <p/>
* - A 'repaired' item is an item that was generated and that needs to be repaired because the plan changed for that subscription on that period of time
- * - The 'repair' item is the item that cancels the (to be) repaired item; the repair item amount might not match (to be) repaired item because:
+ * - The 'repair' item is the item that cancels the (to be) repaired item; the repair item amount might not match the (to be) repaired item because:
* * the (to be) repaired item was already adjusted so we will only repair what is left
* * in case of partial repair we only repair the part that is not used
* - The 'reparee' item is only present on disk-- in the existing item list -- in case of full repair; in that case it represents the portion of the item that should still
@@ -179,7 +179,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
final BigDecimal amountNegated = existingItem.getAmount() == null ? null : existingItem.getAmount().subtract(existingAdjustedPositiveAmount).negate();
if (amountNegated != null && amountNegated.compareTo(BigDecimal.ZERO) < 0) {
final RepairAdjInvoiceItem candidateRepairItem = new RepairAdjInvoiceItem(existingItem.getInvoiceId(), existingItem.getAccountId(), existingItem.getStartDate(), existingItem.getEndDate(), amountNegated, existingItem.getCurrency(), existingItem.getId());
- addRepairItem(existingItem, candidateRepairItem, proposedItems);
+ addRepairsForItem(existingItem, candidateRepairItem, proposedItems);
}
}
}
@@ -192,7 +192,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
* @param candidateRepairItem the repair item we would have if we were to repair the full period
* @param proposedItems the list of proposed items
*/
- void addRepairItem(final InvoiceItem repairedItem, final RepairAdjInvoiceItem candidateRepairItem, final List<InvoiceItem> proposedItems) {
+ void addRepairsForItem(final InvoiceItem repairedItem, final RepairAdjInvoiceItem candidateRepairItem, final List<InvoiceItem> proposedItems) {
int nbTotalRepaireeDays = 0;
@@ -222,7 +222,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
}
});
- //Build the reparees
+ //Build the repaired
BigDecimal totalRepairItemAmount = BigDecimal.ZERO;
List<InvoiceItem> repairedItems = new ArrayList<InvoiceItem>();
InvoiceItem prevReparee = null;
@@ -389,10 +389,10 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
itemsToRemove.add(repairItem.getLinkedItemId());
final InvoiceItem repairedItem = getRepairedInvoiceItem(repairItem.getLinkedItemId(), existingItems);
- // if this is a full repair there is no reparee so nothing to remove; if not reparees need to be removed from proposed list
- if (!isFullRepair(repairedItem, repairItem, existingItems)) {
- removeProposedRepareesForPartialrepair(repairedItem, repairItem, proposedItems);
- }
+ // Always look for reparees; if this is a full repair there may not be any reparee to remove, but
+ // if this is a partial repair with an additional invoice item adjustment, this is seen as a full repair
+ // and yet there is a reparee to remove
+ removeProposedRepareesForPartialrepair(repairedItem, repairItem, proposedItems);
}
}
final Iterator<InvoiceItem> iterator = existingItems.iterator();
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
index 5fd95ce..304da69 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
@@ -36,6 +36,23 @@ getInvoicesBySubscription() ::= <<
;
>>
+searchInvoices() ::= <<
+select SQL_CALC_FOUND_ROWS
+<allTableFields("t.")>
+from <tableName()> t
+where 1 = 1
+and (
+ <idField("t.")> = :searchKey
+ or <recordIdField("t.")> = :searchKey
+ or t.account_id = :searchKey
+ or t.currency = :searchKey
+)
+<AND_CHECK_TENANT("t.")>
+order by <recordIdField("t.")> ASC
+limit :offset, :rowCount
+;
+>>
+
getInvoiceIdByPaymentId() ::= <<
SELECT i.id
FROM <tableName()> i, invoice_payments ip
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index 5006858..6ce801b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -156,6 +156,21 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
}
@Override
+ public Pagination<InvoiceModelDao> searchInvoices(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
+ final List<InvoiceModelDao> results = new LinkedList<InvoiceModelDao>();
+ for (final InvoiceModelDao invoice : getAll(context)) {
+ if (invoice.getId().toString().equals(searchKey) ||
+ invoice.getAccountId().toString().equals(searchKey) ||
+ invoice.getInvoiceNumber().toString().equals(searchKey) ||
+ invoice.getCurrency().toString().equals(searchKey)) {
+ results.add(invoice);
+ }
+ }
+
+ return DefaultPagination.<InvoiceModelDao>build(offset, limit, results);
+ }
+
+ @Override
public void test(final InternalTenantContext context) {
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/generator/DefaultInvoiceGeneratorWithSwitchRepairLogic.java b/invoice/src/test/java/com/ning/billing/invoice/generator/DefaultInvoiceGeneratorWithSwitchRepairLogic.java
index 34c48c7..4c43c7c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/generator/DefaultInvoiceGeneratorWithSwitchRepairLogic.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/generator/DefaultInvoiceGeneratorWithSwitchRepairLogic.java
@@ -48,9 +48,9 @@ public class DefaultInvoiceGeneratorWithSwitchRepairLogic extends DefaultInvoice
}
@Override
- void addRepairItem(final InvoiceItem repairedItem, final RepairAdjInvoiceItem candidateRepairItem, final List<InvoiceItem> proposedItems) {
+ void addRepairsForItem(final InvoiceItem repairedItem, final RepairAdjInvoiceItem candidateRepairItem, final List<InvoiceItem> proposedItems) {
if (repairtLogic == REPAIR_INVOICE_LOGIC.PARTIAL_REPAIR) {
- super.addRepairItem(repairedItem, candidateRepairItem, proposedItems);
+ super.addRepairsForItem(repairedItem, candidateRepairItem, proposedItems);
} else {
proposedItems.add(candidateRepairItem);
return;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGeneratorRepairUnit.java b/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGeneratorRepairUnit.java
index 3a5620d..45f2647 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGeneratorRepairUnit.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGeneratorRepairUnit.java
@@ -54,7 +54,7 @@ public class TestDefaultInvoiceGeneratorRepairUnit extends InvoiceTestSuiteNoDB
this.defaultInvoiceGenerator = (DefaultInvoiceGenerator) generator;
}
- /********************************************* addRepairItem logic ********************************/
+ /********************************************* addRepairsForItem logic ********************************/
// repairedItem
// |-----------------------------------------------|
@@ -82,7 +82,7 @@ public class TestDefaultInvoiceGeneratorRepairUnit extends InvoiceTestSuiteNoDB
final InvoiceItem proposed2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startProposed2, endDate, BigDecimal.TEN, rate, currency);
proposed.add(proposed2);
- defaultInvoiceGenerator.addRepairItem(repairedItem, candidateRepairItem, proposed);
+ defaultInvoiceGenerator.addRepairsForItem(repairedItem, candidateRepairItem, proposed);
assertEquals(proposed.size(), 1);
assertEquals(proposed.get(0).getStartDate(), endDateProposed1);
@@ -115,7 +115,7 @@ public class TestDefaultInvoiceGeneratorRepairUnit extends InvoiceTestSuiteNoDB
final InvoiceItem proposed1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDateProposed1, BigDecimal.TEN, rate, currency);
proposed.add(proposed1);
- defaultInvoiceGenerator.addRepairItem(repairedItem, candidateRepairItem, proposed);
+ defaultInvoiceGenerator.addRepairsForItem(repairedItem, candidateRepairItem, proposed);
assertEquals(proposed.size(), 1);
assertEquals(proposed.get(0).getStartDate(), endDateProposed1);
@@ -149,7 +149,7 @@ public class TestDefaultInvoiceGeneratorRepairUnit extends InvoiceTestSuiteNoDB
final InvoiceItem proposed1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDateProposed1, endDate, BigDecimal.TEN, rate, currency);
proposed.add(proposed1);
- defaultInvoiceGenerator.addRepairItem(repairedItem, candidateRepairItem, proposed);
+ defaultInvoiceGenerator.addRepairsForItem(repairedItem, candidateRepairItem, proposed);
assertEquals(proposed.size(), 1);
assertEquals(proposed.get(0).getStartDate(), startDate);
@@ -189,7 +189,7 @@ public class TestDefaultInvoiceGeneratorRepairUnit extends InvoiceTestSuiteNoDB
final InvoiceItem proposed3 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDateProposed3, endDate, BigDecimal.TEN, rate, currency);
proposed.add(proposed3);
- defaultInvoiceGenerator.addRepairItem(repairedItem, candidateRepairItem, proposed);
+ defaultInvoiceGenerator.addRepairsForItem(repairedItem, candidateRepairItem, proposed);
assertEquals(proposed.size(), 2);
assertEquals(proposed.get(0).getStartDate(), endDateProposed1);
@@ -206,7 +206,7 @@ public class TestDefaultInvoiceGeneratorRepairUnit extends InvoiceTestSuiteNoDB
}
- /********************************************* addRepairItems logic ********************************/
+ /********************************************* addRepairsForItems logic ********************************/
@Test(groups = "fast")
public void testAddRepairedItemsItemsRecurringPrice() {
jaxrs/pom.xml 2(+1 -1)
diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index 9e39912..8304c93 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-jaxrs</artifactId>
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
index 6d0664a..bc833cd 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
@@ -17,13 +17,17 @@
package com.ning.billing.jaxrs.json;
import java.math.BigDecimal;
+import java.util.List;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.joda.time.DateTimeZone;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountData;
import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -54,8 +58,8 @@ public class AccountJson extends JsonBase {
private final Boolean isMigrated;
private final Boolean isNotifiedForInvoices;
- public AccountJson(final Account account, final BigDecimal accountBalance, final BigDecimal accountCBA) {
- super(null);
+ public AccountJson(final Account account, final BigDecimal accountBalance, final BigDecimal accountCBA, @Nullable final AccountAuditLogs accountAuditLogs) {
+ super(toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForAccount()));
this.accountCBA = accountCBA;
this.accountBalance = accountBalance;
this.accountId = account.getId().toString();
@@ -102,8 +106,9 @@ public class AccountJson extends JsonBase {
@JsonProperty("isMigrated") final Boolean isMigrated,
@JsonProperty("isNotifiedForInvoices") final Boolean isNotifiedForInvoices,
@JsonProperty("accountBalance") final BigDecimal accountBalance,
- @JsonProperty("accountCBA") final BigDecimal accountCBA) {
- super(null);
+ @JsonProperty("accountCBA") final BigDecimal accountCBA,
+ @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
+ super(auditLogs);
this.accountBalance = accountBalance;
this.externalKey = externalKey;
this.accountId = accountId;
@@ -236,7 +241,7 @@ public class AccountJson extends JsonBase {
}
};
}
-
+
public BigDecimal getAccountBalance() {
return accountBalance;
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
index 21507b8..09e326e 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
@@ -90,7 +90,7 @@ public class AccountTimelineJson {
public AccountTimelineJson(final Account account, final List<Invoice> invoices, final List<Payment> payments,
final List<SubscriptionBundle> bundles, final Multimap<UUID, Refund> refundsByPayment,
final Multimap<UUID, InvoicePayment> chargebacksByPayment, final AccountAuditLogs accountAuditLogs) {
- this.account = new AccountJson(account, null, null);
+ this.account = new AccountJson(account, null, null, accountAuditLogs);
this.bundles = new LinkedList<BundleJson>();
for (final SubscriptionBundle bundle : bundles) {
final List<AuditLog> bundleAuditLogs = accountAuditLogs.getAuditLogsForBundle(bundle.getId());
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java
index 6a44dc1..8c45ff1 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java
@@ -21,12 +21,15 @@ import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.joda.time.DateTime;
import com.ning.billing.account.api.Account;
import com.ning.billing.payment.api.PaymentMethod;
import com.ning.billing.payment.api.PaymentMethodKVInfo;
import com.ning.billing.payment.api.PaymentMethodPlugin;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -46,7 +49,9 @@ public class PaymentMethodJson extends JsonBase {
@JsonProperty("accountId") final String accountId,
@JsonProperty("isDefault") final Boolean isDefault,
@JsonProperty("pluginName") final String pluginName,
- @JsonProperty("pluginInfo") final PaymentMethodPluginDetailJson pluginInfo) {
+ @JsonProperty("pluginInfo") final PaymentMethodPluginDetailJson pluginInfo,
+ @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
+ super(auditLogs);
this.paymentMethodId = paymentMethodId;
this.accountId = accountId;
this.isDefault = isDefault;
@@ -54,7 +59,7 @@ public class PaymentMethodJson extends JsonBase {
this.pluginInfo = pluginInfo;
}
- public static PaymentMethodJson toPaymentMethodJson(final Account account, final PaymentMethod in) {
+ public static PaymentMethodJson toPaymentMethodJson(final Account account, final PaymentMethod in, @Nullable final AccountAuditLogs accountAuditLogs) {
final boolean isDefault = account.getPaymentMethodId() != null && account.getPaymentMethodId().equals(in.getId());
final PaymentMethodPlugin pluginDetail = in.getPluginDetail();
PaymentMethodPluginDetailJson pluginDetailJson = null;
@@ -84,7 +89,8 @@ public class PaymentMethodJson extends JsonBase {
pluginDetail.getCountry(),
properties);
}
- return new PaymentMethodJson(in.getId().toString(), account.getId().toString(), isDefault, in.getPluginName(), pluginDetailJson);
+ return new PaymentMethodJson(in.getId().toString(), account.getId().toString(), isDefault, in.getPluginName(),
+ pluginDetailJson, toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForPaymentMethod(in.getId())));
}
public PaymentMethod toPaymentMethod(final String accountId) {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index ae53882..607fa3b 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -80,6 +80,7 @@ import com.ning.billing.payment.api.PaymentApi;
import com.ning.billing.payment.api.PaymentApiException;
import com.ning.billing.payment.api.PaymentMethod;
import com.ning.billing.payment.api.Refund;
+import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.AuditUserApi;
import com.ning.billing.util.api.CustomFieldApiException;
import com.ning.billing.util.api.CustomFieldUserApi;
@@ -143,10 +144,12 @@ public class AccountResource extends JaxRsResourceBase {
public Response getAccount(@PathParam("accountId") final String accountId,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE) @DefaultValue("false") final Boolean accountWithBalance,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE_AND_CBA) @DefaultValue("false") final Boolean accountWithBalanceAndCBA,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException {
final TenantContext tenantContext = context.createContext(request);
final Account account = accountUserApi.getAccountById(UUID.fromString(accountId), tenantContext);
- final AccountJson accountJson = getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(account.getId(), auditMode.getLevel(), tenantContext);
+ final AccountJson accountJson = getAccount(account, accountWithBalance, accountWithBalanceAndCBA, accountAuditLogs, tenantContext);
return Response.status(Status.OK).entity(accountJson).build();
}
@@ -157,16 +160,19 @@ public class AccountResource extends JaxRsResourceBase {
@QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE) @DefaultValue("false") final Boolean accountWithBalance,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE_AND_CBA) @DefaultValue("false") final Boolean accountWithBalanceAndCBA,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException {
final TenantContext tenantContext = context.createContext(request);
final Pagination<Account> accounts = accountUserApi.getAccounts(offset, limit, tenantContext);
final URI nextPageUri = uriBuilder.nextPage(AccountResource.class, "getAccounts", accounts.getNextOffset(), limit, ImmutableMap.<String, String>of(QUERY_ACCOUNT_WITH_BALANCE, accountWithBalance.toString(),
- QUERY_ACCOUNT_WITH_BALANCE_AND_CBA, accountWithBalanceAndCBA.toString()));
+ QUERY_ACCOUNT_WITH_BALANCE_AND_CBA, accountWithBalanceAndCBA.toString(),
+ QUERY_AUDIT, auditMode.getLevel().toString()));
return buildStreamingPaginationResponse(accounts,
new Function<Account, AccountJson>() {
@Override
public AccountJson apply(final Account account) {
- return getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(account.getId(), auditMode.getLevel(), tenantContext);
+ return getAccount(account, accountWithBalance, accountWithBalanceAndCBA, accountAuditLogs, tenantContext);
}
},
nextPageUri);
@@ -180,17 +186,20 @@ public class AccountResource extends JaxRsResourceBase {
@QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE) @DefaultValue("false") final Boolean accountWithBalance,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE_AND_CBA) @DefaultValue("false") final Boolean accountWithBalanceAndCBA,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException {
final TenantContext tenantContext = context.createContext(request);
final Pagination<Account> accounts = accountUserApi.searchAccounts(searchKey, offset, limit, tenantContext);
final URI nextPageUri = uriBuilder.nextPage(AccountResource.class, "searchAccounts", accounts.getNextOffset(), limit, ImmutableMap.<String, String>of("searchKey", searchKey,
QUERY_ACCOUNT_WITH_BALANCE, accountWithBalance.toString(),
- QUERY_ACCOUNT_WITH_BALANCE_AND_CBA, accountWithBalanceAndCBA.toString()));
+ QUERY_ACCOUNT_WITH_BALANCE_AND_CBA, accountWithBalanceAndCBA.toString(),
+ QUERY_AUDIT, auditMode.getLevel().toString()));
return buildStreamingPaginationResponse(accounts,
new Function<Account, AccountJson>() {
@Override
public AccountJson apply(final Account account) {
- return getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(account.getId(), auditMode.getLevel(), tenantContext);
+ return getAccount(account, accountWithBalance, accountWithBalanceAndCBA, accountAuditLogs, tenantContext);
}
},
nextPageUri);
@@ -225,23 +234,26 @@ public class AccountResource extends JaxRsResourceBase {
public Response getAccountByKey(@QueryParam(QUERY_EXTERNAL_KEY) final String externalKey,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE) @DefaultValue("false") final Boolean accountWithBalance,
@QueryParam(QUERY_ACCOUNT_WITH_BALANCE_AND_CBA) @DefaultValue("false") final Boolean accountWithBalanceAndCBA,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException {
final TenantContext tenantContext = context.createContext(request);
final Account account = accountUserApi.getAccountByKey(externalKey, tenantContext);
- final AccountJson accountJson = getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(account.getId(), auditMode.getLevel(), tenantContext);
+ final AccountJson accountJson = getAccount(account, accountWithBalance, accountWithBalanceAndCBA, accountAuditLogs, tenantContext);
return Response.status(Status.OK).entity(accountJson).build();
}
- private AccountJson getAccount(final Account account, final Boolean accountWithBalance, final Boolean accountWithBalanceAndCBA, final TenantContext tenantContext) {
+ private AccountJson getAccount(final Account account, final Boolean accountWithBalance, final Boolean accountWithBalanceAndCBA,
+ final AccountAuditLogs auditLogs, final TenantContext tenantContext) {
if (accountWithBalanceAndCBA) {
final BigDecimal accountBalance = invoiceApi.getAccountBalance(account.getId(), tenantContext);
final BigDecimal accountCBA = invoiceApi.getAccountCBA(account.getId(), tenantContext);
- return new AccountJson(account, accountBalance, accountCBA);
+ return new AccountJson(account, accountBalance, accountCBA, auditLogs);
} else if (accountWithBalance) {
final BigDecimal accountBalance = invoiceApi.getAccountBalance(account.getId(), tenantContext);
- return new AccountJson(account, accountBalance, null);
+ return new AccountJson(account, accountBalance, null, auditLogs);
} else {
- return new AccountJson(account, null, null);
+ return new AccountJson(account, null, null, auditLogs);
}
}
@@ -272,7 +284,7 @@ public class AccountResource extends JaxRsResourceBase {
final AccountData data = json.toAccountData();
final UUID uuid = UUID.fromString(accountId);
accountUserApi.updateAccount(uuid, data, context.createContext(createdBy, reason, comment, request));
- return getAccount(accountId, false, false, request);
+ return getAccount(accountId, false, false, new AuditMode(AuditLevel.NONE.toString()), request);
}
// Not supported
@@ -506,15 +518,17 @@ public class AccountResource extends JaxRsResourceBase {
@Produces(APPLICATION_JSON)
public Response getPaymentMethods(@PathParam("accountId") final String accountId,
@QueryParam(QUERY_PAYMENT_METHOD_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException, PaymentApiException {
final TenantContext tenantContext = context.createContext(request);
final Account account = accountUserApi.getAccountById(UUID.fromString(accountId), tenantContext);
final List<PaymentMethod> methods = paymentApi.getPaymentMethods(account, withPluginInfo, tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(account.getId(), auditMode.getLevel(), tenantContext);
final List<PaymentMethodJson> json = new ArrayList<PaymentMethodJson>(Collections2.transform(methods, new Function<PaymentMethod, PaymentMethodJson>() {
@Override
public PaymentMethodJson apply(final PaymentMethod input) {
- return PaymentMethodJson.toPaymentMethodJson(account, input);
+ return PaymentMethodJson.toPaymentMethodJson(account, input, accountAuditLogs);
}
}));
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
index ef4a230..413559b 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
@@ -16,8 +16,12 @@
package com.ning.billing.jaxrs.resources;
+import java.net.URI;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
@@ -57,9 +61,13 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
+import com.ning.billing.util.entity.Pagination;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@@ -107,6 +115,58 @@ public class BundleResource extends JaxRsResourceBase {
return Response.status(Status.OK).entity(json).build();
}
+ @GET
+ @Path("/" + PAGINATION)
+ @Produces(APPLICATION_JSON)
+ public Response getBundles(@QueryParam(QUERY_SEARCH_OFFSET) @DefaultValue("0") final Long offset,
+ @QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
+ final TenantContext tenantContext = context.createContext(request);
+ final Pagination<SubscriptionBundle> bundles = subscriptionApi.getSubscriptionBundles(offset, limit, tenantContext);
+ final URI nextPageUri = uriBuilder.nextPage(BundleResource.class, "getBundles", bundles.getNextOffset(), limit, ImmutableMap.<String, String>of(QUERY_AUDIT, auditMode.getLevel().toString()));
+ final AtomicReference<Map<UUID, AccountAuditLogs>> accountsAuditLogs = new AtomicReference<Map<UUID, AccountAuditLogs>>(new HashMap<UUID, AccountAuditLogs>());
+ return buildStreamingPaginationResponse(bundles,
+ new Function<SubscriptionBundle, BundleJson>() {
+ @Override
+ public BundleJson apply(final SubscriptionBundle bundle) {
+ // Cache audit logs per account
+ if (accountsAuditLogs.get().get(bundle.getAccountId()) == null) {
+ accountsAuditLogs.get().put(bundle.getAccountId(), auditUserApi.getAccountAuditLogs(bundle.getAccountId(), auditMode.getLevel(), tenantContext));
+ }
+ return new BundleJson(bundle, accountsAuditLogs.get().get(bundle.getAccountId()));
+ }
+ },
+ nextPageUri);
+ }
+
+ @GET
+ @Path("/" + SEARCH + "/{searchKey:" + ANYTHING_PATTERN + "}")
+ @Produces(APPLICATION_JSON)
+ public Response searchBundles(@PathParam("searchKey") final String searchKey,
+ @QueryParam(QUERY_SEARCH_OFFSET) @DefaultValue("0") final Long offset,
+ @QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
+ final TenantContext tenantContext = context.createContext(request);
+ final Pagination<SubscriptionBundle> bundles = subscriptionApi.searchSubscriptionBundles(searchKey, offset, limit, tenantContext);
+ final URI nextPageUri = uriBuilder.nextPage(BundleResource.class, "searchBundles", bundles.getNextOffset(), limit, ImmutableMap.<String, String>of("searchKey", searchKey,
+ QUERY_AUDIT, auditMode.getLevel().toString()));
+ final AtomicReference<Map<UUID, AccountAuditLogs>> accountsAuditLogs = new AtomicReference<Map<UUID, AccountAuditLogs>>(new HashMap<UUID, AccountAuditLogs>());
+ return buildStreamingPaginationResponse(bundles,
+ new Function<SubscriptionBundle, BundleJson>() {
+ @Override
+ public BundleJson apply(final SubscriptionBundle bundle) {
+ // Cache audit logs per account
+ if (accountsAuditLogs.get().get(bundle.getAccountId()) == null) {
+ accountsAuditLogs.get().put(bundle.getAccountId(), auditUserApi.getAccountAuditLogs(bundle.getAccountId(), auditMode.getLevel(), tenantContext));
+ }
+ return new BundleJson(bundle, accountsAuditLogs.get().get(bundle.getAccountId()));
+ }
+ },
+ nextPageUri);
+ }
+
@PUT
@Path("/{bundleId:" + UUID_PATTERN + "}/" + PAUSE)
@Consumes(APPLICATION_JSON)
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
index f034473..ed14584 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
@@ -51,6 +51,7 @@ import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.api.SubscriptionApiException;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceApiException;
import com.ning.billing.invoice.api.InvoiceItem;
@@ -186,6 +187,35 @@ public class InvoiceResource extends JaxRsResourceBase {
nextPageUri);
}
+ @GET
+ @Path("/" + SEARCH + "/{searchKey:" + ANYTHING_PATTERN + "}")
+ @Produces(APPLICATION_JSON)
+ public Response searchInvoices(@PathParam("searchKey") final String searchKey,
+ @QueryParam(QUERY_SEARCH_OFFSET) @DefaultValue("0") final Long offset,
+ @QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit,
+ @QueryParam(QUERY_INVOICE_WITH_ITEMS) @DefaultValue("false") final Boolean withItems,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
+ final TenantContext tenantContext = context.createContext(request);
+ final Pagination<Invoice> invoices = invoiceApi.searchInvoices(searchKey, offset, limit, tenantContext);
+ final URI nextPageUri = uriBuilder.nextPage(InvoiceResource.class, "searchInvoices", invoices.getNextOffset(), limit, ImmutableMap.<String, String>of("searchKey", searchKey,
+ QUERY_INVOICE_WITH_ITEMS, withItems.toString(),
+ QUERY_AUDIT, auditMode.getLevel().toString()));
+ final AtomicReference<Map<UUID, AccountAuditLogs>> accountsAuditLogs = new AtomicReference<Map<UUID, AccountAuditLogs>>(new HashMap<UUID, AccountAuditLogs>());
+ return buildStreamingPaginationResponse(invoices,
+ new Function<Invoice, InvoiceJson>() {
+ @Override
+ public InvoiceJson apply(final Invoice invoice) {
+ // Cache audit logs per account
+ if (accountsAuditLogs.get().get(invoice.getAccountId()) == null) {
+ accountsAuditLogs.get().put(invoice.getAccountId(), auditUserApi.getAccountAuditLogs(invoice.getAccountId(), auditMode.getLevel(), tenantContext));
+ }
+ return new InvoiceJson(invoice, withItems, accountsAuditLogs.get().get(invoice.getAccountId()));
+ }
+ },
+ nextPageUri);
+ }
+
@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
index fadb479..8c2165a 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
@@ -85,12 +85,14 @@ public class PaymentMethodResource extends JaxRsResourceBase {
@Produces(APPLICATION_JSON)
public Response getPaymentMethod(@PathParam("paymentMethodId") final String paymentMethodId,
@QueryParam(QUERY_PAYMENT_METHOD_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException, PaymentApiException {
final TenantContext tenantContext = context.createContext(request);
final PaymentMethod paymentMethod = paymentApi.getPaymentMethodById(UUID.fromString(paymentMethodId), false, withPluginInfo, tenantContext);
final Account account = accountUserApi.getAccountById(paymentMethod.getAccountId(), tenantContext);
- final PaymentMethodJson json = PaymentMethodJson.toPaymentMethodJson(account, paymentMethod);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(paymentMethod.getAccountId(), auditMode.getLevel(), tenantContext);
+ final PaymentMethodJson json = PaymentMethodJson.toPaymentMethodJson(account, paymentMethod, accountAuditLogs);
return Response.status(Status.OK).entity(json).build();
}
@@ -138,8 +140,7 @@ public class PaymentMethodResource extends JaxRsResourceBase {
}
}
- // TODO populate audit logs
- return PaymentMethodJson.toPaymentMethodJson(accounts.get(paymentMethod.getAccountId()), paymentMethod);
+ return PaymentMethodJson.toPaymentMethodJson(accounts.get(paymentMethod.getAccountId()), paymentMethod, accountsAuditLogs.get().get(paymentMethod.getAccountId()));
}
},
nextPageUri);
@@ -191,8 +192,7 @@ public class PaymentMethodResource extends JaxRsResourceBase {
}
}
- // TODO populate audit logs
- return PaymentMethodJson.toPaymentMethodJson(accounts.get(paymentMethod.getAccountId()), paymentMethod);
+ return PaymentMethodJson.toPaymentMethodJson(accounts.get(paymentMethod.getAccountId()), paymentMethod, accountsAuditLogs.get().get(paymentMethod.getAccountId()));
}
},
nextPageUri);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
index 7f14aee..124b563 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
@@ -65,6 +66,7 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.entity.Pagination;
@@ -140,25 +142,30 @@ public class PaymentResource extends JaxRsResourceBase {
public Response getPayments(@QueryParam(QUERY_SEARCH_OFFSET) @DefaultValue("0") final Long offset,
@QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit,
@QueryParam(QUERY_PAYMENT_PLUGIN_NAME) final String pluginName,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final TenantContext tenantContext = context.createContext(request);
final Pagination<Payment> payments;
- final Map<String, String> nextUriParams = new HashMap<String, String>();
if (Strings.isNullOrEmpty(pluginName)) {
payments = paymentApi.getPayments(offset, limit, tenantContext);
} else {
payments = paymentApi.getPayments(offset, limit, pluginName, tenantContext);
- nextUriParams.put(QUERY_PAYMENT_PLUGIN_NAME, pluginName);
}
- final URI nextPageUri = uriBuilder.nextPage(PaymentResource.class, "getPayments", payments.getNextOffset(), limit, nextUriParams);
+ final URI nextPageUri = uriBuilder.nextPage(PaymentResource.class, "getPayments", payments.getNextOffset(), limit, ImmutableMap.<String, String>of(QUERY_PAYMENT_METHOD_PLUGIN_NAME, Strings.nullToEmpty(pluginName),
+ QUERY_AUDIT, auditMode.getLevel().toString()));
+ final AtomicReference<Map<UUID, AccountAuditLogs>> accountsAuditLogs = new AtomicReference<Map<UUID, AccountAuditLogs>>(new HashMap<UUID, AccountAuditLogs>());
return buildStreamingPaginationResponse(payments,
new Function<Payment, PaymentJson>() {
@Override
public PaymentJson apply(final Payment payment) {
- return new PaymentJson(payment, null);
+ // Cache audit logs per account
+ if (accountsAuditLogs.get().get(payment.getAccountId()) == null) {
+ accountsAuditLogs.get().put(payment.getAccountId(), auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext));
+ }
+ return new PaymentJson(payment, accountsAuditLogs.get().get(payment.getAccountId()).getAuditLogsForPayment(payment.getId()));
}
},
nextPageUri);
@@ -171,6 +178,7 @@ public class PaymentResource extends JaxRsResourceBase {
@QueryParam(QUERY_SEARCH_OFFSET) @DefaultValue("0") final Long offset,
@QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit,
@QueryParam(QUERY_PAYMENT_PLUGIN_NAME) final String pluginName,
+ @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final TenantContext tenantContext = context.createContext(request);
@@ -182,13 +190,20 @@ public class PaymentResource extends JaxRsResourceBase {
payments = paymentApi.searchPayments(searchKey, offset, limit, pluginName, tenantContext);
}
- final URI nextPageUri = uriBuilder.nextPage(PaymentResource.class, "searchPayments", payments.getNextOffset(), limit, ImmutableMap.<String, String>of());
+ final URI nextPageUri = uriBuilder.nextPage(PaymentResource.class, "searchPayments", payments.getNextOffset(), limit, ImmutableMap.<String, String>of("searchKey", searchKey,
+ QUERY_PAYMENT_METHOD_PLUGIN_NAME, Strings.nullToEmpty(pluginName),
+ QUERY_AUDIT, auditMode.getLevel().toString()));
+ final AtomicReference<Map<UUID, AccountAuditLogs>> accountsAuditLogs = new AtomicReference<Map<UUID, AccountAuditLogs>>(new HashMap<UUID, AccountAuditLogs>());
return buildStreamingPaginationResponse(payments,
new Function<Payment, PaymentJson>() {
@Override
public PaymentJson apply(final Payment payment) {
- return new PaymentJson(payment, null);
+ // Cache audit logs per account
+ if (accountsAuditLogs.get().get(payment.getAccountId()) == null) {
+ accountsAuditLogs.get().put(payment.getAccountId(), auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext));
+ }
+ return new PaymentJson(payment, accountsAuditLogs.get().get(payment.getAccountId()).getAuditLogsForPayment(payment.getId()));
}
},
nextPageUri);
diff --git a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java
index 9ab3e24..4e6a0ca 100644
--- a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java
+++ b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java
@@ -55,7 +55,7 @@ public class TestAccountJson extends JaxrsTestSuiteNoDB {
final AccountJson accountJson = new AccountJson(accountId, name, length, externalKey,
email, billCycleDayLocal, currency, paymentMethodId,
timeZone, address1, address2, postalCode, company, city, state,
- country, locale, phone, isMigrated, isNotifiedForInvoice, null, null);
+ country, locale, phone, isMigrated, isNotifiedForInvoice, null, null, null);
Assert.assertEquals(accountJson.getAccountId(), accountId);
Assert.assertEquals(accountJson.getName(), name);
Assert.assertEquals(accountJson.getFirstNameLength(), length);
@@ -107,7 +107,7 @@ public class TestAccountJson extends JaxrsTestSuiteNoDB {
accountBuilder.timeZone(DateTimeZone.UTC);
final Account account = accountBuilder.build();
- final AccountJson accountJson = new AccountJson(account, null, null);
+ final AccountJson accountJson = new AccountJson(account, null, null, null);
Assert.assertEquals(accountJson.getAddress1(), account.getAddress1());
Assert.assertEquals(accountJson.getAddress2(), account.getAddress2());
Assert.assertEquals(accountJson.getBillCycleDayLocal(), (Integer) bcd);
junction/pom.xml 2(+1 -1)
diff --git a/junction/pom.xml b/junction/pom.xml
index a3910c1..0065f5c 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-junction</artifactId>
NEWS 12(+12 -0)
diff --git a/NEWS b/NEWS
index 5268436..c7dbbbe 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+0.8.12
+ Implement bundles pagination and search APIs
+ Implement invoices search API
+ https://github.com/killbill/killbill/issues/154
+ Update killbill-oss-parent to 0.5.23
+
+0.8.11
+ [SECURITY] Fix SQL injection in search APIs
+ Fix bug when retrieving refund information from plugins
+ Add system tag definitions support to tag search
+ https://github.com/killbill/killbill/issues/100
+
0.8.10
Upgrade JRuby and add support for OpenSSL in plugins
payment: pagination bugfix
osgi/pom.xml 2(+1 -1)
diff --git a/osgi/pom.xml b/osgi/pom.xml
index 43233d1..aeb0ea8 100644
--- a/osgi/pom.xml
+++ b/osgi/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi</artifactId>
osgi-bundles/bundles/jruby/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/bundles/jruby/pom.xml b/osgi-bundles/bundles/jruby/pom.xml
index 75747c6..60094c2 100644
--- a/osgi-bundles/bundles/jruby/pom.xml
+++ b/osgi-bundles/bundles/jruby/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill-osgi-bundles</artifactId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-jruby</artifactId>
osgi-bundles/bundles/logger/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/bundles/logger/pom.xml b/osgi-bundles/bundles/logger/pom.xml
index 643cef5..cdf2599 100644
--- a/osgi-bundles/bundles/logger/pom.xml
+++ b/osgi-bundles/bundles/logger/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-logger</artifactId>
diff --git a/osgi-bundles/bundles/logger/src/main/java/com/ning/billing/osgi/bundles/logger/Activator.java b/osgi-bundles/bundles/logger/src/main/java/com/ning/billing/osgi/bundles/logger/Activator.java
index 7ab3d97..8dbd9b4 100644
--- a/osgi-bundles/bundles/logger/src/main/java/com/ning/billing/osgi/bundles/logger/Activator.java
+++ b/osgi-bundles/bundles/logger/src/main/java/com/ning/billing/osgi/bundles/logger/Activator.java
@@ -28,7 +28,6 @@ import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogReaderService;
-import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,8 +55,7 @@ public class Activator implements BundleActivator {
if (event.getType() == ServiceEvent.REGISTERED) {
registerLogReaderService(logReaderService);
} else if (event.getType() == ServiceEvent.UNREGISTERING) {
- logReaderService.removeLogListener(killbillLogListener);
- logReaderServices.remove(logReaderService);
+ unregisterLogReaderService(logReaderService);
}
}
}
@@ -65,25 +63,18 @@ public class Activator implements BundleActivator {
@Override
public void start(final BundleContext context) throws Exception {
- // Get a list of all the registered LogReaderService, and add the killbill listener
- final ServiceTracker logReaderTracker = new ServiceTracker(context, LogReaderService.class.getName(), null);
- logReaderTracker.open();
- final Object[] readers = logReaderTracker.getServices();
- if (readers != null) {
- for (final Object reader : readers) {
- final LogReaderService service = (LogReaderService) reader;
- registerLogReaderService(service);
- }
- }
- logReaderTracker.close();
-
- // Add the ServiceListener
final String filter = "(objectclass=" + LogReaderService.class.getName() + ")";
try {
context.addServiceListener(logReaderServiceListener, filter);
- } catch (InvalidSyntaxException e) {
+ } catch (final InvalidSyntaxException e) {
logger.warn("Unable to register the killbill LogReaderService listener", e);
}
+
+ // If the LogReaderService was already registered, manually construct a REGISTERED ServiceEvent
+ final ServiceReference[] serviceReferences = context.getServiceReferences((String) null, filter);
+ for (int i = 0; serviceReferences != null && i < serviceReferences.length; i++) {
+ logReaderServiceListener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, serviceReferences[i]));
+ }
}
@Override
@@ -96,7 +87,14 @@ public class Activator implements BundleActivator {
}
private void registerLogReaderService(final LogReaderService service) {
+ logger.info("Registering the killbill LogReaderService listener");
logReaderServices.add(service);
service.addLogListener(killbillLogListener);
}
+
+ private void unregisterLogReaderService(final LogReaderService logReaderService) {
+ logger.info("Unregistering the killbill LogReaderService listener");
+ logReaderService.removeLogListener(killbillLogListener);
+ logReaderServices.remove(logReaderService);
+ }
}
osgi-bundles/bundles/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/bundles/pom.xml b/osgi-bundles/bundles/pom.xml
index b0d837c..80bae86 100644
--- a/osgi-bundles/bundles/pom.xml
+++ b/osgi-bundles/bundles/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles</artifactId>
diff --git a/osgi-bundles/bundles/webconsolebranding/pom.xml b/osgi-bundles/bundles/webconsolebranding/pom.xml
index 9c67b6c..72a8cf7 100644
--- a/osgi-bundles/bundles/webconsolebranding/pom.xml
+++ b/osgi-bundles/bundles/webconsolebranding/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-webconsolebranding</artifactId>
osgi-bundles/defaultbundles/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/defaultbundles/pom.xml b/osgi-bundles/defaultbundles/pom.xml
index 1d78cbf..58872d4 100644
--- a/osgi-bundles/defaultbundles/pom.xml
+++ b/osgi-bundles/defaultbundles/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-defaultbundles</artifactId>
osgi-bundles/libs/killbill/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/libs/killbill/pom.xml b/osgi-bundles/libs/killbill/pom.xml
index 94eec24..9cfec3d 100644
--- a/osgi-bundles/libs/killbill/pom.xml
+++ b/osgi-bundles/libs/killbill/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-lib-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-lib-killbill</artifactId>
osgi-bundles/libs/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/libs/pom.xml b/osgi-bundles/libs/pom.xml
index 17dc35b..14b0ef0 100644
--- a/osgi-bundles/libs/pom.xml
+++ b/osgi-bundles/libs/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-lib-bundles</artifactId>
osgi-bundles/libs/slf4j-osgi/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/libs/slf4j-osgi/pom.xml b/osgi-bundles/libs/slf4j-osgi/pom.xml
index 6df1b8d..0079622 100644
--- a/osgi-bundles/libs/slf4j-osgi/pom.xml
+++ b/osgi-bundles/libs/slf4j-osgi/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-lib-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-lib-slf4j-osgi</artifactId>
osgi-bundles/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/pom.xml b/osgi-bundles/pom.xml
index 057a5cf..05d35e7 100644
--- a/osgi-bundles/pom.xml
+++ b/osgi-bundles/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
osgi-bundles/tests/beatrix/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/tests/beatrix/pom.xml b/osgi-bundles/tests/beatrix/pom.xml
index d156ae6..fe9cfc0 100644
--- a/osgi-bundles/tests/beatrix/pom.xml
+++ b/osgi-bundles/tests/beatrix/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-test-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-test-beatrix</artifactId>
osgi-bundles/tests/payment/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/tests/payment/pom.xml b/osgi-bundles/tests/payment/pom.xml
index a3bf05b..ae7dd7b 100644
--- a/osgi-bundles/tests/payment/pom.xml
+++ b/osgi-bundles/tests/payment/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-test-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-test-payment</artifactId>
osgi-bundles/tests/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/tests/pom.xml b/osgi-bundles/tests/pom.xml
index 2cdc1af..78bdb05 100644
--- a/osgi-bundles/tests/pom.xml
+++ b/osgi-bundles/tests/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-test-bundles</artifactId>
overdue/pom.xml 2(+1 -1)
diff --git a/overdue/pom.xml b/overdue/pom.xml
index 1db8ea8..09d35df 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-overdue</artifactId>
payment/pom.xml 2(+1 -1)
diff --git a/payment/pom.xml b/payment/pom.xml
index 02f7d86..af77090 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
index 78fecf3..09e4a78 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
@@ -181,12 +181,12 @@ public class PaymentMethodProcessor extends ProcessorBase {
new Function<PaymentMethodModelDao, PaymentMethod>() {
@Override
public PaymentMethod apply(final PaymentMethodModelDao paymentMethodModelDao) {
- final PaymentMethodPlugin paymentMethodPlugin;
+ PaymentMethodPlugin paymentMethodPlugin = null;
try {
paymentMethodPlugin = pluginApi.getPaymentMethodDetail(paymentMethodModelDao.getAccountId(), paymentMethodModelDao.getId(), tenantContext);
- } catch (PaymentPluginApiException e) {
+ } catch (final PaymentPluginApiException e) {
log.warn("Unable to find payment method id " + paymentMethodModelDao.getId() + " in plugin " + pluginName);
- return null;
+ // We still want to return a payment method object, even though the plugin details are missing
}
return new DefaultPaymentMethod(paymentMethodModelDao, paymentMethodPlugin);
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
index 8178f38..9a71d07 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
@@ -174,12 +174,12 @@ public class PaymentProcessor extends ProcessorBase {
new Function<PaymentModelDao, Payment>() {
@Override
public Payment apply(final PaymentModelDao paymentModelDao) {
- final PaymentInfoPlugin pluginInfo;
+ PaymentInfoPlugin pluginInfo = null;
try {
pluginInfo = pluginApi.getPaymentInfo(paymentModelDao.getAccountId(), paymentModelDao.getId(), tenantContext);
} catch (final PaymentPluginApiException e) {
- log.warn("Unable to find payment id " + paymentModelDao.getId() + " in plugin " + pluginName);
- return null;
+ log.warn("Unable to find payment id " + paymentModelDao.getId() + " in plugin " + pluginName);
+ // We still want to return a payment object, even though the plugin details are missing
}
return fromPaymentModelDao(paymentModelDao, pluginInfo, internalTenantContext);
diff --git a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
index 827590f..401b0f4 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
@@ -256,18 +256,16 @@ public class RefundProcessor extends ProcessorBase {
result = paymentDao.getRefund(refundId, context);
}
- final Account account;
- try {
- account = accountInternalApi.getAccountById(result.getAccountId(), context);
- } catch (final AccountApiException e) {
- throw new PaymentApiException(e);
+ final PaymentModelDao payment = paymentDao.getPayment(result.getPaymentId(), context);
+ if (payment == null) {
+ throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT, result.getPaymentId());
}
- final PaymentPluginApi plugin = withPluginInfo ? getPaymentProviderPlugin(account, context) : null;
+ final PaymentPluginApi plugin = withPluginInfo ? getPaymentProviderPlugin(payment.getPaymentMethodId(), context) : null;
List<RefundInfoPlugin> refundInfoPlugins = ImmutableList.<RefundInfoPlugin>of();
if (plugin != null) {
try {
- refundInfoPlugins = plugin.getRefundInfo(account.getId(), result.getPaymentId(), buildTenantContext(context));
+ refundInfoPlugins = plugin.getRefundInfo(result.getAccountId(), result.getPaymentId(), buildTenantContext(context));
} catch (final PaymentPluginApiException e) {
throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_GET_REFUND_INFO, refundId, e.toString());
}
@@ -326,15 +324,15 @@ public class RefundProcessor extends ProcessorBase {
new Function<RefundModelDao, Refund>() {
@Override
public Refund apply(final RefundModelDao refundModelDao) {
- final List<RefundInfoPlugin> refundInfoPlugins;
+ List<RefundInfoPlugin> refundInfoPlugins = null;
try {
refundInfoPlugins = pluginApi.getRefundInfo(refundModelDao.getAccountId(), refundModelDao.getId(), tenantContext);
} catch (final PaymentPluginApiException e) {
log.warn("Unable to find refund id " + refundModelDao.getId() + " in plugin " + pluginName);
- return null;
+ // We still want to return a refund object, even though the plugin details are missing
}
- final RefundInfoPlugin refundInfoPlugin = findRefundInfoPlugin(refundModelDao, refundInfoPlugins);
+ final RefundInfoPlugin refundInfoPlugin = refundInfoPlugins == null ? null : findRefundInfoPlugin(refundModelDao, refundInfoPlugins);
return new DefaultRefund(refundModelDao, refundInfoPlugin);
}
}
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java
index d5af8bf..3ad3b72 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentMethodSqlDao.java
@@ -23,7 +23,6 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.Define;
import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
import com.ning.billing.callcontext.InternalCallContext;
pom.xml 4(+2 -2)
diff --git a/pom.xml b/pom.xml
index 3d6021d..e5be8a7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,10 +19,10 @@
<parent>
<artifactId>killbill-oss-parent</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.5.21</version>
+ <version>0.5.23</version>
</parent>
<artifactId>killbill</artifactId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<packaging>pom</packaging>
<name>killbill</name>
<description>Library for managing recurring subscriptions and the associated billing</description>
server/pom.xml 2(+1 -1)
diff --git a/server/pom.xml b/server/pom.xml
index b8e13a9..53ecc5a 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-server</artifactId>
diff --git a/server/src/main/resources/update-checker/killbill-server-update-list.properties b/server/src/main/resources/update-checker/killbill-server-update-list.properties
index f2fee54..3c963db 100644
--- a/server/src/main/resources/update-checker/killbill-server-update-list.properties
+++ b/server/src/main/resources/update-checker/killbill-server-update-list.properties
@@ -1,86 +1,91 @@
## Top level keys
# general.notice = This notice should rarely, if ever, be used as everyone will see it
-## 0.8.10 -- latest release
-0.8.10.updates =
-0.8.10.notices = This is the latest GA release.
+## 0.8.11 -- latest release
+0.8.11.updates =
+0.8.11.notices = This is the latest GA release.
+0.8.11.release-notes = http://kill-bill.org
+
+## 0.8.10
+0.8.10.updates = 0.8.11
+0.8.10.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.10.release-notes = http://kill-bill.org
## 0.8.9
-0.8.9.updates = 0.8.10
-0.8.9.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.9.updates = 0.8.11
+0.8.9.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.9.release-notes = http://kill-bill.org
## 0.8.8
-0.8.8.updates = 0.8.10
-0.8.8.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.8.updates = 0.8.11
+0.8.8.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.8.release-notes = http://kill-bill.org
## 0.8.7
-0.8.7.updates = 0.8.10
-0.8.7.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.7.updates = 0.8.11
+0.8.7.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.7.release-notes = http://kill-bill.org
## 0.8.6
-0.8.6.updates = 0.8.10
-0.8.6.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.6.updates = 0.8.11
+0.8.6.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.6.release-notes = http://kill-bill.org
## 0.8.5
-0.8.5.updates = 0.8.10
-0.8.5.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.5.updates = 0.8.11
+0.8.5.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.5.release-notes = http://kill-bill.org
## 0.8.4
-0.8.4.updates = 0.8.10
-0.8.4.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.4.updates = 0.8.11
+0.8.4.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.4.release-notes = http://kill-bill.org
## 0.8.3
-0.8.3.updates = 0.8.10
-0.8.3.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.3.updates = 0.8.11
+0.8.3.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.3.release-notes = http://kill-bill.org
## 0.8.2
-0.8.2.updates = 0.8.10
-0.8.2.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.2.updates = 0.8.11
+0.8.2.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.2.release-notes = http://kill-bill.org
## 0.8.1
-0.8.1.updates = 0.8.10
-0.8.1.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.1.updates = 0.8.11
+0.8.1.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.1.release-notes = http://kill-bill.org
## 0.8.0
-0.8.0.updates = 0.8.10
-0.8.0.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.8.0.updates = 0.8.11
+0.8.0.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.8.0.release-notes = http://kill-bill.org
### 0.7.x series ###
## 0.7.2
0.7.2.updates =
-0.7.2.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.7.2.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.7.2.release-notes = http://kill-bill.org
## 0.7.1
0.7.1.updates = 0.7.2
-0.7.1.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.7.1.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.7.1.release-notes = http://kill-bill.org
## 0.7.0
0.7.0.updates = 0.7.2
-0.7.0.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.7.0.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.7.0.release-notes = http://kill-bill.org
### 0.6.x series ###
## 0.6.17
0.6.17.updates =
-0.6.17.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.6.17.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.6.17.release-notes = http://kill-bill.org
## 0.6.16
0.6.16.updates = 0.6.17
-0.6.16.notices = We recommend upgrading to 0.8.10, our latest GA release.
+0.6.16.notices = We recommend upgrading to 0.8.11, our latest GA release.
0.6.16.release-notes = http://kill-bill.org
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
index 5f90877..77da877 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
@@ -27,6 +27,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.client.model.Account;
import com.ning.billing.client.model.Bundle;
+import com.ning.billing.client.model.Bundles;
import com.ning.billing.client.model.Subscription;
import static org.testng.Assert.assertEquals;
@@ -99,4 +100,31 @@ public class TestBundle extends TestJaxrsBase {
assertEquals(newBundle.getExternalKey(), originalBundle.getExternalKey());
assertEquals(newBundle.getAccountId(), newAccount.getAccountId());
}
+
+ @Test(groups = "slow", description = "Can paginate and search through all bundles")
+ public void testBundlesPagination() throws Exception {
+ final Account accountJson = createAccount();
+
+ for (int i = 0; i < 5; i++) {
+ createEntitlement(accountJson.getAccountId(), UUID.randomUUID().toString(), "Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, true);
+ }
+
+ final Bundles allBundles = killBillClient.getBundles();
+ Assert.assertEquals(allBundles.size(), 5);
+
+ for (final Bundle bundle : allBundles) {
+ Assert.assertEquals(killBillClient.searchBundles(bundle.getBundleId().toString()).size(), 1);
+ Assert.assertEquals(killBillClient.searchBundles(bundle.getAccountId().toString()).size(), 5);
+ Assert.assertEquals(killBillClient.searchBundles(bundle.getExternalKey()).size(), 1);
+ }
+
+ Bundles page = killBillClient.getBundles(0L, 1L);
+ for (int i = 0; i < 5; i++) {
+ Assert.assertNotNull(page);
+ Assert.assertEquals(page.size(), 1);
+ Assert.assertEquals(page.get(0), allBundles.get(i));
+ page = page.getNext();
+ }
+ Assert.assertNull(page);
+ }
}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
index 6d904a2..0622059 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
@@ -450,7 +450,7 @@ public class TestInvoice extends TestJaxrsBase {
assertEquals(adjustedInvoice.getBalance().compareTo(adjustedInvoiceBalance), 0);
}
- @Test(groups = "slow", description = "Can paginate through all invoices")
+ @Test(groups = "slow", description = "Can paginate and search through all invoices")
public void testInvoicesPagination() throws Exception {
createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
@@ -462,6 +462,13 @@ public class TestInvoice extends TestJaxrsBase {
final Invoices allInvoices = killBillClient.getInvoices();
Assert.assertEquals(allInvoices.size(), 5);
+ for (final Invoice invoice : allInvoices) {
+ Assert.assertEquals(killBillClient.searchInvoices(invoice.getInvoiceId().toString()).size(), 1);
+ Assert.assertEquals(killBillClient.searchInvoices(invoice.getAccountId().toString()).size(), 5);
+ Assert.assertEquals(killBillClient.searchInvoices(invoice.getInvoiceNumber().toString()).size(), 1);
+ Assert.assertEquals(killBillClient.searchInvoices(invoice.getCurrency().toString()).size(), 5);
+ }
+
Invoices page = killBillClient.getInvoices(0L, 1L);
for (int i = 0; i < 5; i++) {
Assert.assertNotNull(page);
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestTag.java b/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
index 3ea5658..50f0b4c 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
@@ -30,6 +30,8 @@ import com.ning.billing.client.model.Account;
import com.ning.billing.client.model.Tag;
import com.ning.billing.client.model.TagDefinition;
import com.ning.billing.client.model.Tags;
+import com.ning.billing.util.tag.ControlTag;
+import com.ning.billing.util.tag.ControlTagType;
import com.google.common.collect.ImmutableList;
@@ -92,6 +94,22 @@ public class TestTag extends TestJaxrsBase {
assertEquals(objFromJson.size(), 3 + sizeSystemTag);
}
+ @Test(groups = "slow", description = "Can search system tags")
+ public void testSystemTagsPagination() throws Exception {
+ final Account account = createAccount();
+ for (final ControlTagType controlTagType : ControlTagType.values()) {
+ killBillClient.createAccountTag(account.getAccountId(), controlTagType.getId(), createdBy, reason, comment);
+ }
+
+ final Tags allTags = killBillClient.getTags();
+ Assert.assertEquals(allTags.size(), ControlTagType.values().length);
+
+ for (final ControlTagType controlTagType : ControlTagType.values()) {
+ Assert.assertEquals(killBillClient.searchTags(controlTagType.toString()).size(), 1);
+ Assert.assertEquals(killBillClient.searchTags(controlTagType.getDescription()).size(), 1);
+ }
+ }
+
@Test(groups = "slow", description = "Can paginate through all tags")
public void testTagsPagination() throws Exception {
final Account account = createAccount();
subscription/pom.xml 2(+1 -1)
diff --git a/subscription/pom.xml b/subscription/pom.xml
index 5e016b0..bd9d7ae 100644
--- a/subscription/pom.xml
+++ b/subscription/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-subscription</artifactId>
diff --git a/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index b19d8ed..36d6d61 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -30,6 +30,8 @@ import org.slf4j.LoggerFactory;
import com.ning.billing.ErrorCode;
import com.ning.billing.ObjectType;
+import com.ning.billing.callcontext.InternalCallContext;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.catalog.api.Catalog;
import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.catalog.api.CatalogService;
@@ -43,8 +45,10 @@ import com.ning.billing.clock.DefaultClock;
import com.ning.billing.entitlement.api.Entitlement.EntitlementState;
import com.ning.billing.entitlement.api.EntitlementAOStatusDryRun;
import com.ning.billing.entitlement.api.EntitlementAOStatusDryRun.DryRunChangeReason;
+import com.ning.billing.events.EffectiveSubscriptionInternalEvent;
import com.ning.billing.subscription.api.SubscriptionApiBase;
import com.ning.billing.subscription.api.SubscriptionBase;
+import com.ning.billing.subscription.api.SubscriptionBaseInternalApi;
import com.ning.billing.subscription.api.user.DefaultEffectiveSubscriptionEvent;
import com.ning.billing.subscription.api.user.DefaultSubscriptionBase;
import com.ning.billing.subscription.api.user.DefaultSubscriptionBaseApiService;
@@ -57,18 +61,19 @@ import com.ning.billing.subscription.api.user.SubscriptionBaseTransitionData;
import com.ning.billing.subscription.api.user.SubscriptionBuilder;
import com.ning.billing.subscription.engine.addon.AddonUtils;
import com.ning.billing.subscription.engine.dao.SubscriptionDao;
+import com.ning.billing.subscription.engine.dao.model.SubscriptionBundleModelDao;
import com.ning.billing.subscription.exceptions.SubscriptionBaseError;
-import com.ning.billing.callcontext.InternalCallContext;
-import com.ning.billing.callcontext.InternalTenantContext;
-import com.ning.billing.events.EffectiveSubscriptionInternalEvent;
-import com.ning.billing.subscription.api.SubscriptionBaseInternalApi;
import com.ning.billing.util.dao.NonEntityDao;
+import com.ning.billing.util.entity.Pagination;
+import com.ning.billing.util.entity.dao.DefaultPaginationHelper.SourcePaginationBuilder;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
+import static com.ning.billing.util.entity.dao.DefaultPaginationHelper.getEntityPaginationNoException;
+
public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implements SubscriptionBaseInternalApi {
private final Logger log = LoggerFactory.getLogger(DefaultSubscriptionInternalApi.class);
@@ -187,11 +192,48 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
@Override
+ public Pagination<SubscriptionBaseBundle> getBundles(final Long offset, final Long limit, final InternalTenantContext context) {
+ return getEntityPaginationNoException(limit,
+ new SourcePaginationBuilder<SubscriptionBundleModelDao, SubscriptionBaseApiException>() {
+ @Override
+ public Pagination<SubscriptionBundleModelDao> build() {
+ return dao.get(offset, limit, context);
+ }
+ },
+ new Function<SubscriptionBundleModelDao, SubscriptionBaseBundle>() {
+ @Override
+ public SubscriptionBaseBundle apply(final SubscriptionBundleModelDao bundleModelDao) {
+ return SubscriptionBundleModelDao.toSubscriptionbundle(bundleModelDao);
+ }
+ }
+ );
+ }
+
+ @Override
+ public Pagination<SubscriptionBaseBundle> searchBundles(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
+ return getEntityPaginationNoException(limit,
+ new SourcePaginationBuilder<SubscriptionBundleModelDao, SubscriptionBaseApiException>() {
+ @Override
+ public Pagination<SubscriptionBundleModelDao> build() {
+ return dao.searchSubscriptionBundles(searchKey, offset, limit, context);
+ }
+ },
+ new Function<SubscriptionBundleModelDao, SubscriptionBaseBundle>() {
+ @Override
+ public SubscriptionBaseBundle apply(final SubscriptionBundleModelDao bundleModelDao) {
+ return SubscriptionBundleModelDao.toSubscriptionbundle(bundleModelDao);
+ }
+ }
+ );
+
+ }
+
+ @Override
public Iterable<UUID> getNonAOSubscriptionIdsForKey(final String bundleKey, final InternalTenantContext context) {
return dao.getNonAOSubscriptionIdsForKey(bundleKey, context);
}
- public static SubscriptionBaseBundle getActiveBundleForKeyNotException(final List<SubscriptionBaseBundle> existingBundles, final SubscriptionDao dao, final Clock clock, final InternalTenantContext context) {
+ public static SubscriptionBaseBundle getActiveBundleForKeyNotException(final List<SubscriptionBaseBundle> existingBundles, final SubscriptionDao dao, final Clock clock, final InternalTenantContext context) {
for (SubscriptionBaseBundle cur : existingBundles) {
final List<SubscriptionBase> subscriptions = dao.getSubscriptions(cur.getId(), context);
for (SubscriptionBase s : subscriptions) {
@@ -330,10 +372,10 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
reason = DryRunChangeReason.AO_NOT_AVAILABLE_IN_NEW_PLAN;
}
final EntitlementAOStatusDryRun status = new DefaultSubscriptionStatusDryRun(cur.getId(),
- cur.getCurrentPlan().getProduct().getName(),
- cur.getCurrentPhase().getPhaseType(),
- cur.getCurrentPlan().getBillingPeriod(),
- cur.getCurrentPriceList().getName(), reason);
+ cur.getCurrentPlan().getProduct().getName(),
+ cur.getCurrentPhase().getPhaseType(),
+ cur.getCurrentPlan().getBillingPeriod(),
+ cur.getCurrentPriceList().getName(), reason);
result.add(status);
}
return result;
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java
index 5fce8b0..7746e81 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/BundleSqlDao.java
@@ -17,18 +17,20 @@
package com.ning.billing.subscription.engine.dao;
import java.util.Date;
+import java.util.Iterator;
import java.util.List;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
-import com.ning.billing.subscription.engine.dao.model.SubscriptionBundleModelDao;
-import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
-import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
+import com.ning.billing.subscription.engine.dao.model.SubscriptionBundleModelDao;
+import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.entity.dao.Audited;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
@@ -60,4 +62,13 @@ public interface BundleSqlDao extends EntitySqlDao<SubscriptionBundleModelDao, S
@SqlQuery
public List<SubscriptionBundleModelDao> getBundlesForKey(@Bind("externalKey") String externalKey,
@BindBean final InternalTenantContext context);
+
+ @SqlQuery
+ // Magic value to force MySQL to stream from the database
+ // See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
+ @FetchSize(Integer.MIN_VALUE)
+ public Iterator<SubscriptionBundleModelDao> searchBundles(@Bind("searchKey") final String searchKey,
+ @Bind("offset") final Long offset,
+ @Bind("rowCount") final Long rowCount,
+ @BindBean final InternalTenantContext context);
}
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java
index a183a12..3c876f8 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/DefaultSubscriptionDao.java
@@ -46,6 +46,7 @@ import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.api.SubscriptionApiException;
import com.ning.billing.entity.EntityPersistenceException;
import com.ning.billing.events.EffectiveSubscriptionInternalEvent;
import com.ning.billing.events.RepairSubscriptionInternalEvent;
@@ -85,6 +86,9 @@ import com.ning.billing.subscription.events.user.ApiEventType;
import com.ning.billing.subscription.exceptions.SubscriptionBaseError;
import com.ning.billing.util.cache.CacheControllerDispatcher;
import com.ning.billing.util.dao.NonEntityDao;
+import com.ning.billing.util.entity.Pagination;
+import com.ning.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.PaginationIteratorBuilder;
+import com.ning.billing.util.entity.dao.EntityDaoBase;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
@@ -96,15 +100,13 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
-public class DefaultSubscriptionDao implements SubscriptionDao {
+public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleModelDao, SubscriptionBaseBundle, SubscriptionApiException> implements SubscriptionDao {
private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionDao.class);
private final Clock clock;
- private final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
private final NotificationQueueService notificationQueueService;
private final AddonUtils addonUtils;
private final PersistentBus eventBus;
@@ -114,8 +116,8 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
public DefaultSubscriptionDao(final IDBI dbi, final Clock clock, final AddonUtils addonUtils,
final NotificationQueueService notificationQueueService, final PersistentBus eventBus, final CatalogService catalogService,
final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao) {
+ super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao), BundleSqlDao.class);
this.clock = clock;
- this.transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao);
this.notificationQueueService = notificationQueueService;
this.addonUtils = addonUtils;
this.eventBus = eventBus;
@@ -123,6 +125,11 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
}
@Override
+ protected SubscriptionApiException generateAlreadyExistsException(final SubscriptionBundleModelDao entity, final InternalCallContext context) {
+ return new SubscriptionApiException(ErrorCode.SUB_CREATE_ACTIVE_BUNDLE_KEY_EXISTS, entity.getExternalKey());
+ }
+
+ @Override
public List<SubscriptionBaseBundle> getSubscriptionBundlesForAccountAndKey(final UUID accountId, final String bundleKey, final InternalTenantContext context) {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<SubscriptionBaseBundle>>() {
@Override
@@ -183,6 +190,20 @@ public class DefaultSubscriptionDao implements SubscriptionDao {
}
@Override
+ public Pagination<SubscriptionBundleModelDao> searchSubscriptionBundles(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
+ return paginationHelper.getPagination(BundleSqlDao.class,
+ new PaginationIteratorBuilder<SubscriptionBundleModelDao, SubscriptionBaseBundle, BundleSqlDao>() {
+ @Override
+ public Iterator<SubscriptionBundleModelDao> build(final BundleSqlDao bundleSqlDao, final Long limit) {
+ return bundleSqlDao.searchBundles(searchKey, offset, limit, context);
+ }
+ },
+ offset,
+ limit,
+ context);
+ }
+
+ @Override
public Iterable<UUID> getNonAOSubscriptionIdsForKey(final String bundleKey, final InternalTenantContext context) {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Iterable<UUID>>() {
@Override
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java
index 26f50cd..bffc74c 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/RepairSubscriptionDao.java
@@ -27,6 +27,16 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
+import javax.inject.Inject;
+
+import org.skife.jdbi.v2.IDBI;
+
+import com.ning.billing.ErrorCode;
+import com.ning.billing.callcontext.InternalCallContext;
+import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.api.SubscriptionApiException;
+import com.ning.billing.subscription.api.SubscriptionBase;
import com.ning.billing.subscription.api.migration.AccountMigrationData;
import com.ning.billing.subscription.api.migration.AccountMigrationData.BundleMigrationData;
import com.ning.billing.subscription.api.timeline.RepairSubscriptionLifecycleDao;
@@ -34,22 +44,35 @@ import com.ning.billing.subscription.api.timeline.SubscriptionDataRepair;
import com.ning.billing.subscription.api.transfer.TransferCancelData;
import com.ning.billing.subscription.api.user.DefaultSubscriptionBase;
import com.ning.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
+import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
+import com.ning.billing.subscription.engine.dao.model.SubscriptionBundleModelDao;
import com.ning.billing.subscription.events.SubscriptionBaseEvent;
import com.ning.billing.subscription.exceptions.SubscriptionBaseError;
-import com.ning.billing.subscription.api.SubscriptionBase;
-import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
-import com.ning.billing.callcontext.InternalCallContext;
-import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.cache.CacheControllerDispatcher;
+import com.ning.billing.util.dao.NonEntityDao;
+import com.ning.billing.util.entity.Pagination;
+import com.ning.billing.util.entity.dao.EntityDaoBase;
+import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
-public class RepairSubscriptionDao implements SubscriptionDao, RepairSubscriptionLifecycleDao {
+public class RepairSubscriptionDao extends EntityDaoBase<SubscriptionBundleModelDao, SubscriptionBaseBundle, SubscriptionApiException> implements SubscriptionDao, RepairSubscriptionLifecycleDao {
private static final String NOT_IMPLEMENTED = "Not implemented";
private final ThreadLocal<Map<UUID, SubscriptionRepairEvent>> preThreadsInRepairSubscriptions = new ThreadLocal<Map<UUID, SubscriptionRepairEvent>>();
+ @Inject
+ public RepairSubscriptionDao(final IDBI dbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao) {
+ super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao), BundleSqlDao.class);
+ }
+
+ @Override
+ protected SubscriptionApiException generateAlreadyExistsException(final SubscriptionBundleModelDao entity, final InternalCallContext context) {
+ return new SubscriptionApiException(ErrorCode.SUB_CREATE_ACTIVE_BUNDLE_KEY_EXISTS, entity.getExternalKey());
+ }
+
private static final class SubscriptionEventWithOrderingId {
private final SubscriptionBaseEvent event;
@@ -311,6 +334,11 @@ public class RepairSubscriptionDao implements SubscriptionDao, RepairSubscriptio
}
@Override
+ public Pagination<SubscriptionBundleModelDao> searchSubscriptionBundles(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
+ throw new SubscriptionBaseError(NOT_IMPLEMENTED);
+ }
+
+ @Override
public List<UUID> getNonAOSubscriptionIdsForKey(final String bundleKey, final InternalTenantContext context) {
throw new SubscriptionBaseError(NOT_IMPLEMENTED);
}
diff --git a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java
index 3caa123..165a868 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/engine/dao/SubscriptionDao.java
@@ -20,6 +20,10 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
+import com.ning.billing.callcontext.InternalCallContext;
+import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.entitlement.api.SubscriptionApiException;
+import com.ning.billing.subscription.api.SubscriptionBase;
import com.ning.billing.subscription.api.migration.AccountMigrationData;
import com.ning.billing.subscription.api.migration.AccountMigrationData.BundleMigrationData;
import com.ning.billing.subscription.api.timeline.SubscriptionDataRepair;
@@ -27,19 +31,21 @@ import com.ning.billing.subscription.api.transfer.TransferCancelData;
import com.ning.billing.subscription.api.user.DefaultSubscriptionBase;
import com.ning.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
+import com.ning.billing.subscription.engine.dao.model.SubscriptionBundleModelDao;
import com.ning.billing.subscription.events.SubscriptionBaseEvent;
-import com.ning.billing.subscription.api.SubscriptionBase;
-import com.ning.billing.callcontext.InternalCallContext;
-import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.entity.Pagination;
+import com.ning.billing.util.entity.dao.EntityDao;
-public interface SubscriptionDao {
+public interface SubscriptionDao extends EntityDao<SubscriptionBundleModelDao, SubscriptionBaseBundle, SubscriptionApiException> {
// Bundle apis
public List<SubscriptionBaseBundle> getSubscriptionBundleForAccount(UUID accountId, InternalTenantContext context);
public List<SubscriptionBaseBundle> getSubscriptionBundlesForKey(String bundleKey, InternalTenantContext context);
- public Iterable<UUID> getNonAOSubscriptionIdsForKey(final String bundleKey, final InternalTenantContext context);
+ public Pagination<SubscriptionBundleModelDao> searchSubscriptionBundles(String searchKey, Long offset, Long limit, InternalTenantContext context);
+
+ public Iterable<UUID> getNonAOSubscriptionIdsForKey(String bundleKey, InternalTenantContext context);
public List<SubscriptionBaseBundle> getSubscriptionBundlesForAccountAndKey(UUID accountId, String bundleKey, InternalTenantContext context);
@@ -80,7 +86,7 @@ public interface SubscriptionDao {
public void cancelSubscription(DefaultSubscriptionBase subscription, SubscriptionBaseEvent cancelEvent, InternalCallContext context, int cancelSeq);
- public void cancelSubscriptions(final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context);
+ public void cancelSubscriptions(List<DefaultSubscriptionBase> subscriptions, List<SubscriptionBaseEvent> cancelEvents, InternalCallContext context);
public void uncancelSubscription(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> uncancelEvents, InternalCallContext context);
@@ -90,7 +96,7 @@ public interface SubscriptionDao {
public void transfer(UUID srcAccountId, UUID destAccountId, BundleMigrationData data, List<TransferCancelData> transferCancelData, InternalCallContext fromContext, InternalCallContext toContext);
- public void updateBundleExternalKey(UUID bundleId, String externalKey, final InternalCallContext context);
+ public void updateBundleExternalKey(UUID bundleId, String externalKey, InternalCallContext context);
// Repair
public void repair(UUID accountId, UUID bundleId, List<SubscriptionDataRepair> inRepair, InternalCallContext context);
diff --git a/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg b/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg
index 7238aee..f5f9ade 100644
--- a/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg
+++ b/subscription/src/main/resources/com/ning/billing/subscription/engine/dao/BundleSqlDao.sql.stg
@@ -77,3 +77,19 @@ account_id = :accountId
<defaultOrderBy()>
;
>>
+
+searchBundles() ::= <<
+select SQL_CALC_FOUND_ROWS
+<allTableFields("t.")>
+from <tableName()> t
+where 1 = 1
+and (
+ <idField("t.")> = :searchKey
+ or t.external_key = :searchKey
+ or t.account_id = :searchKey
+)
+<AND_CHECK_TENANT("t.")>
+order by <recordIdField("t.")> ASC
+limit :offset, :rowCount
+;
+>>
diff --git a/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java b/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
index 79f9e47..3ffe068 100644
--- a/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
+++ b/subscription/src/test/java/com/ning/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
@@ -36,6 +36,7 @@ import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.api.SubscriptionApiException;
import com.ning.billing.notificationq.api.NotificationEvent;
import com.ning.billing.notificationq.api.NotificationQueue;
import com.ning.billing.notificationq.api.NotificationQueueService;
@@ -52,16 +53,20 @@ import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
import com.ning.billing.subscription.api.user.SubscriptionBuilder;
import com.ning.billing.subscription.engine.core.DefaultSubscriptionBaseService;
import com.ning.billing.subscription.engine.core.SubscriptionNotificationKey;
+import com.ning.billing.subscription.engine.dao.model.SubscriptionBundleModelDao;
import com.ning.billing.subscription.events.SubscriptionBaseEvent;
import com.ning.billing.subscription.events.SubscriptionBaseEvent.EventType;
import com.ning.billing.subscription.events.user.ApiEvent;
import com.ning.billing.subscription.events.user.ApiEventType;
+import com.ning.billing.util.entity.DefaultPagination;
+import com.ning.billing.util.entity.Pagination;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
+import com.ning.billing.util.entity.dao.MockEntityDaoBase;
import com.google.inject.Inject;
-public class MockSubscriptionDaoMemory implements SubscriptionDao {
+public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBundleModelDao, SubscriptionBaseBundle, SubscriptionApiException> implements SubscriptionDao {
protected static final Logger log = LoggerFactory.getLogger(SubscriptionDao.class);
@@ -114,6 +119,20 @@ public class MockSubscriptionDaoMemory implements SubscriptionDao {
}
@Override
+ public Pagination<SubscriptionBundleModelDao> searchSubscriptionBundles(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
+ final List<SubscriptionBundleModelDao> results = new LinkedList<SubscriptionBundleModelDao>();
+ for (final SubscriptionBundleModelDao bundleModelDao : getAll(context)) {
+ if (bundleModelDao.getId().toString().equals(searchKey) ||
+ bundleModelDao.getExternalKey().equals(searchKey) ||
+ bundleModelDao.getAccountId().toString().equals(searchKey)) {
+ results.add(bundleModelDao);
+ }
+ }
+
+ return DefaultPagination.<SubscriptionBundleModelDao>build(offset, limit, results);
+ }
+
+ @Override
public List<UUID> getNonAOSubscriptionIdsForKey(final String bundleKey, final InternalTenantContext context) {
throw new UnsupportedOperationException();
}
tenant/pom.xml 2(+1 -1)
diff --git a/tenant/pom.xml b/tenant/pom.xml
index 5deb95c..78f9795 100644
--- a/tenant/pom.xml
+++ b/tenant/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-tenant</artifactId>
usage/pom.xml 2(+1 -1)
diff --git a/usage/pom.xml b/usage/pom.xml
index 152b472..39ba106 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-usage</artifactId>
util/pom.xml 2(+1 -1)
diff --git a/util/pom.xml b/util/pom.xml
index c619b8b..62c03e4 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -12,7 +12,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.11-SNAPSHOT</version>
+ <version>0.8.12-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java
index 963eb20..4927c33 100644
--- a/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java
@@ -91,6 +91,11 @@ public class DefaultAccountAuditLogs implements AccountAuditLogs {
}
@Override
+ public List<AuditLog> getAuditLogsForPaymentMethod(final UUID paymentMethodId) {
+ return getAuditLogs(ObjectType.PAYMENT_METHOD).getAuditLogs(paymentMethodId);
+ }
+
+ @Override
public List<AuditLog> getAuditLogsForRefund(final UUID refundId) {
return getAuditLogs(ObjectType.REFUND).getAuditLogs(refundId);
}
diff --git a/util/src/main/java/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.java b/util/src/main/java/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.java
index 1961d2b..c257b74 100644
--- a/util/src/main/java/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.java
@@ -24,7 +24,6 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.Define;
import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
import com.ning.billing.ObjectType;
@@ -53,7 +52,8 @@ public interface CustomFieldSqlDao extends EntitySqlDao<CustomFieldModelDao, Cus
// Magic value to force MySQL to stream from the database
// See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
@FetchSize(Integer.MIN_VALUE)
- public Iterator<CustomFieldModelDao> searchCustomFields(@Define("searchKey") final String searchKey,
+ public Iterator<CustomFieldModelDao> searchCustomFields(@Bind("searchKey") final String searchKey,
+ @Bind("likeSearchKey") final String likeSearchKey,
@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
@BindBean final InternalTenantContext context);
diff --git a/util/src/main/java/com/ning/billing/util/customfield/dao/DefaultCustomFieldDao.java b/util/src/main/java/com/ning/billing/util/customfield/dao/DefaultCustomFieldDao.java
index 8eaf2a0..092d95a 100644
--- a/util/src/main/java/com/ning/billing/util/customfield/dao/DefaultCustomFieldDao.java
+++ b/util/src/main/java/com/ning/billing/util/customfield/dao/DefaultCustomFieldDao.java
@@ -148,7 +148,7 @@ public class DefaultCustomFieldDao extends EntityDaoBase<CustomFieldModelDao, Cu
new PaginationIteratorBuilder<CustomFieldModelDao, CustomField, CustomFieldSqlDao>() {
@Override
public Iterator<CustomFieldModelDao> build(final CustomFieldSqlDao customFieldSqlDao, final Long limit) {
- return customFieldSqlDao.searchCustomFields(searchKey, offset, limit, context);
+ return customFieldSqlDao.searchCustomFields(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
}
},
offset,
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java
index e559df7..4a4abaa 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java
@@ -223,7 +223,7 @@ public class DefaultTagDao extends EntityDaoBase<TagModelDao, Tag, TagApiExcepti
new PaginationIteratorBuilder<TagModelDao, Tag, TagSqlDao>() {
@Override
public Iterator<TagModelDao> build(final TagSqlDao tagSqlDao, final Long limit) {
- return tagSqlDao.searchTags(searchKey, offset, limit, context);
+ return tagSqlDao.searchTags(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
}
},
offset,
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
index 53ebbc5..668553b 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
@@ -24,7 +24,6 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.Define;
import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
import com.ning.billing.ObjectType;
@@ -58,7 +57,8 @@ public interface TagSqlDao extends EntitySqlDao<TagModelDao, Tag> {
// Magic value to force MySQL to stream from the database
// See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
@FetchSize(Integer.MIN_VALUE)
- public Iterator<TagModelDao> searchTags(@Define("searchKey") final String searchKey,
+ public Iterator<TagModelDao> searchTags(@Bind("searchKey") final String searchKey,
+ @Bind("likeSearchKey") final String likeSearchKey,
@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
@BindBean final InternalTenantContext context);
diff --git a/util/src/main/resources/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.sql.stg
index 0367199..1d01add 100644
--- a/util/src/main/resources/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/customfield/dao/CustomFieldSqlDao.sql.stg
@@ -52,16 +52,16 @@ and is_active
;
>>
-searchCustomFields(searchKey, offset, rowCount) ::= <<
+searchCustomFields() ::= <<
select SQL_CALC_FOUND_ROWS
<allTableFields("t.")>
from <tableName()> t
where 1 = 1
and (
- <idField("t.")> = '<searchKey>'
- or t.object_type like '%<searchKey>%'
- or t.field_name like '%<searchKey>%'
- or t.field_value like '%<searchKey>%'
+ <idField("t.")> = :searchKey
+ or t.object_type like :likeSearchKey
+ or t.field_name like :likeSearchKey
+ or t.field_value like :likeSearchKey
)
<AND_CHECK_TENANT("t.")>
order by <recordIdField("t.")> ASC
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
index 7b14556..8dbc6dc 100644
--- a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
@@ -58,17 +58,58 @@ and t.object_type = :objectType
;
>>
-searchTags(searchKey, offset, rowCount) ::= <<
+searchTags() ::= <<
select SQL_CALC_FOUND_ROWS
<allTableFields("t.")>
from <tableName()> t
-join tag_definitions td on td.id = t.tag_definition_id
+join (
+ select
+ id
+ , name
+ , description
+ from tag_definitions
+ union
+ select
+ \'00000000-0000-0000-0000-000000000001\' id
+ , \'AUTO_PAY_OFF\' name
+ , \'Suspends payments until removed.\' description
+ union
+ select
+ \'00000000-0000-0000-0000-000000000001\' id
+ , \'AUTO_INVOICING_OFF\' name
+ , \'Suspends invoicing until removed.\' description
+ union
+ select
+ \'00000000-0000-0000-0000-000000000003\' id
+ , \'OVERDUE_ENFORCEMENT_OFF\' name
+ , \'Suspends overdue enforcement behaviour until removed.\' description
+ union
+ select
+ \'00000000-0000-0000-0000-000000000004\' id
+ , \'WRITTEN_OFF\' name
+ , \'Indicates that an invoice is written off. No billing or payment effect.\' description
+ union
+ select
+ \'00000000-0000-0000-0000-000000000005\' id
+ , \'MANUAL_PAY\' name
+ , \'Indicates that Killbill doesn\\\\\'t process payments for that account (external payments only)\' description
+ union
+ select
+ \'00000000-0000-0000-0000-000000000006\' id
+ , \'TEST\' name
+ , \'Indicates that this is a test account\' description
+ union
+ select
+ \'00000000-0000-0000-0000-000000000007\' id
+ , \'PARTNER\' name
+ , \'Indicates that this is a partner account\' description
+) td on td.id = t.tag_definition_id
where 1 = 1
and (
- <idField("t.")> = '<searchKey>'
- or t.object_type like '%<searchKey>%'
- or td.name like '%<searchKey>%'
- or td.description like '%<searchKey>%'
+ <idField("t.")> = :searchKey
+ or t.object_type like :likeSearchKey
+ or td.name like :likeSearchKey
+ or td.description like :likeSearchKey
)
<AND_CHECK_TENANT("t.")>
order by <recordIdField("t.")> ASC
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java
index 34211b4..3bf8b8d 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java
@@ -23,9 +23,11 @@ import java.util.UUID;
import org.testng.Assert;
import org.testng.annotations.Test;
+import com.ning.billing.ErrorCode;
import com.ning.billing.ObjectType;
import com.ning.billing.api.TestApiListener.NextEvent;
import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
+import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.tag.ControlTagType;
import com.ning.billing.util.tag.DescriptiveTag;
@@ -153,4 +155,25 @@ public class TestDefaultTagDao extends UtilTestSuiteWithEmbeddedDB {
Assert.assertEquals(tagDao.getTagsForObject(objectId, objectType, true, internalCallContext).size(), 1);
Assert.assertEquals(tagDao.getTagsForAccount(true, internalCallContext).size(), 1);
}
+
+ @Test(groups = "slow")
+ public void testInsertMultipleTags() throws TagApiException {
+ final UUID objectId = UUID.randomUUID();
+ final ObjectType objectType = ObjectType.INVOICE_ITEM;
+
+ eventsListener.pushExpectedEvent(NextEvent.TAG);
+ final Tag tag = new DescriptiveTag(ControlTagType.AUTO_INVOICING_OFF.getId(), objectType, objectId, internalCallContext.getCreatedDate());
+ tagDao.create(new TagModelDao(tag), internalCallContext);
+ assertListenerStatus();
+
+ try {
+ final Tag tag2 = new DescriptiveTag(ControlTagType.AUTO_INVOICING_OFF.getId(), objectType, objectId, internalCallContext.getCreatedDate());
+ tagDao.create(new TagModelDao(tag2), internalCallContext);
+ Assert.fail("Should not be able to create twice the same tag");
+ assertListenerStatus();
+ } catch (final TagApiException e) {
+ Assert.assertEquals(ErrorCode.TAG_ALREADY_EXISTS.getCode(), e.getCode());
+ }
+ }
+
}