killbill-aplcache
Changes
invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java 9(+6 -3)
invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java 141(+116 -25)
invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java 48(+27 -21)
Details
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemModelDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemModelDao.java
index 1f8e56a..8104474 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemModelDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemModelDao.java
@@ -76,6 +76,7 @@ public class InvoiceItemModelDao extends EntityModelDaoBase implements EntityMod
this.quantity = quantity;
this.itemDetails = itemDetails;
}
+
public InvoiceItemModelDao(final UUID id, final DateTime createdDate, final InvoiceItemType type, final UUID invoiceId, final UUID accountId,
final UUID childAccountId, final UUID bundleId, final UUID subscriptionId, final String description, final String planName,
final String phaseName, final String usageName, final LocalDate startDate, final LocalDate endDate, final BigDecimal amount,
@@ -119,138 +120,146 @@ public class InvoiceItemModelDao extends EntityModelDaoBase implements EntityMod
return type;
}
+ public void setType(final InvoiceItemType type) {
+ this.type = type;
+ }
+
public UUID getInvoiceId() {
return invoiceId;
}
+ public void setInvoiceId(final UUID invoiceId) {
+ this.invoiceId = invoiceId;
+ }
+
public UUID getAccountId() {
return accountId;
}
+ public void setAccountId(final UUID accountId) {
+ this.accountId = accountId;
+ }
+
public UUID getChildAccountId() {
return childAccountId;
}
+ public void setChildAccountId(final UUID childAccountId) {
+ this.childAccountId = childAccountId;
+ }
+
public UUID getBundleId() {
return bundleId;
}
- public UUID getSubscriptionId() {
- return subscriptionId;
+ public void setBundleId(final UUID bundleId) {
+ this.bundleId = bundleId;
}
- public String getDescription() {
- return description;
+ public UUID getSubscriptionId() {
+ return subscriptionId;
}
- public String getPlanName() {
- return planName;
+ public void setSubscriptionId(final UUID subscriptionId) {
+ this.subscriptionId = subscriptionId;
}
- public String getPhaseName() {
- return phaseName;
+ public String getDescription() {
+ return description;
}
- public String getUsageName() {
- return usageName;
+ public void setDescription(final String description) {
+ this.description = description;
}
- public LocalDate getStartDate() {
- return startDate;
+ public String getPlanName() {
+ return planName;
}
- public LocalDate getEndDate() {
- return endDate;
+ public void setPlanName(final String planName) {
+ this.planName = planName;
}
- public BigDecimal getAmount() {
- return amount;
+ public String getPhaseName() {
+ return phaseName;
}
- public BigDecimal getRate() {
- return rate;
+ public void setPhaseName(final String phaseName) {
+ this.phaseName = phaseName;
}
- public Currency getCurrency() {
- return currency;
+ public String getUsageName() {
+ return usageName;
}
- public UUID getLinkedItemId() {
- return linkedItemId;
+ public void setUsageName(final String usageName) {
+ this.usageName = usageName;
}
- public Integer getQuantity() { return quantity; }
-
- public String getItemDetails() { return itemDetails; }
-
- public void setType(final InvoiceItemType type) {
- this.type = type;
+ public LocalDate getStartDate() {
+ return startDate;
}
- public void setInvoiceId(final UUID invoiceId) {
- this.invoiceId = invoiceId;
+ public void setStartDate(final LocalDate startDate) {
+ this.startDate = startDate;
}
- public void setAccountId(final UUID accountId) {
- this.accountId = accountId;
+ public LocalDate getEndDate() {
+ return endDate;
}
- public void setChildAccountId(final UUID childAccountId) {
- this.childAccountId = childAccountId;
+ public void setEndDate(final LocalDate endDate) {
+ this.endDate = endDate;
}
- public void setBundleId(final UUID bundleId) {
- this.bundleId = bundleId;
+ public BigDecimal getAmount() {
+ return amount;
}
- public void setSubscriptionId(final UUID subscriptionId) {
- this.subscriptionId = subscriptionId;
+ public void setAmount(final BigDecimal amount) {
+ this.amount = amount;
}
- public void setDescription(final String description) {
- this.description = description;
+ public BigDecimal getRate() {
+ return rate;
}
- public void setPlanName(final String planName) {
- this.planName = planName;
+ public void setRate(final BigDecimal rate) {
+ this.rate = rate;
}
- public void setPhaseName(final String phaseName) {
- this.phaseName = phaseName;
+ public Currency getCurrency() {
+ return currency;
}
- public void setUsageName(final String usageName) {
- this.usageName = usageName;
+ public void setCurrency(final Currency currency) {
+ this.currency = currency;
}
- public void setStartDate(final LocalDate startDate) {
- this.startDate = startDate;
+ public UUID getLinkedItemId() {
+ return linkedItemId;
}
- public void setEndDate(final LocalDate endDate) {
- this.endDate = endDate;
+ public void setLinkedItemId(final UUID linkedItemId) {
+ this.linkedItemId = linkedItemId;
}
- public void setAmount(final BigDecimal amount) {
- this.amount = amount;
+ public Integer getQuantity() {
+ return quantity;
}
- public void setRate(final BigDecimal rate) {
- this.rate = rate;
+ public void setQuantity(final Integer quantity) {
+ this.quantity = quantity;
}
- public void setCurrency(final Currency currency) {
- this.currency = currency;
+ public String getItemDetails() {
+ return itemDetails;
}
- public void setLinkedItemId(final UUID linkedItemId) {
- this.linkedItemId = linkedItemId;
+ public void setItemDetails(final String itemDetails) {
+ this.itemDetails = itemDetails;
}
- public void setQuantity(final Integer quantity) { this.quantity = quantity; }
-
- public void setItemDetails(final String itemDetails) { this.itemDetails = itemDetails; }
-
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("InvoiceItemModelDao{");
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
index 64e6c4c..cbb9f8c 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
@@ -45,6 +45,7 @@ import org.killbill.billing.invoice.usage.SubscriptionUsageInArrear;
import org.killbill.billing.invoice.usage.SubscriptionUsageInArrear.SubscriptionUsageInArrearItemsAndNextNotificationDate;
import org.killbill.billing.junction.BillingEvent;
import org.killbill.billing.junction.BillingEventSet;
+import org.killbill.billing.util.config.definition.InvoiceConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,10 +62,12 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
private static final Logger log = LoggerFactory.getLogger(UsageInvoiceItemGenerator.class);
private final RawUsageOptimizer rawUsageOptimizer;
+ private final InvoiceConfig invoiceConfig;
@Inject
- public UsageInvoiceItemGenerator(final RawUsageOptimizer rawUsageOptimizer) {
+ public UsageInvoiceItemGenerator(final RawUsageOptimizer rawUsageOptimizer, final InvoiceConfig invoiceConfig) {
this.rawUsageOptimizer = rawUsageOptimizer;
+ this.invoiceConfig = invoiceConfig;
}
@Override
@@ -115,7 +118,7 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
final UUID subscriptionId = event.getSubscription().getId();
if (curSubscriptionId != null && !curSubscriptionId.equals(subscriptionId)) {
- final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext);
+ final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext, invoiceConfig);
final List<InvoiceItem> usageInArrearItems = perSubscriptionInArrearUsageItems.get(curSubscriptionId);
final SubscriptionUsageInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionUsageInArrear.computeMissingUsageInvoiceItems(usageInArrearItems != null ? usageInArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
@@ -128,7 +131,7 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
curEvents.add(event);
}
if (curSubscriptionId != null) {
- final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext);
+ final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext, invoiceConfig);
final List<InvoiceItem> usageInArrearItems = perSubscriptionInArrearUsageItems.get(curSubscriptionId);
final SubscriptionUsageInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionUsageInArrear.computeMissingUsageInvoiceItems(usageInArrearItems != null ? usageInArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemFactory.java b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemFactory.java
index b93a20f..a7d0924 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemFactory.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemFactory.java
@@ -103,7 +103,7 @@ public class InvoiceItemFactory {
item = new ItemAdjInvoiceItem(id, createdDate, invoiceId, accountId, startDate, description, amount, currency, linkedItemId);
break;
case USAGE:
- item = new UsageInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usageName, prettyPlanName, prettyPlanPhaseName, prettyUsageName, startDate, endDate, description, amount, currency, quantity, itemDetails);
+ item = new UsageInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usageName, prettyPlanName, prettyPlanPhaseName, prettyUsageName, startDate, endDate, description, amount, rate, currency, quantity, itemDetails);
break;
case TAX:
item = new TaxInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usageName, prettyPlanName, prettyPlanPhaseName, prettyUsageName, startDate, description, amount, currency, linkedItemId);
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java
index 0af4a8e..e5841aa 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java
@@ -35,21 +35,21 @@ public class UsageInvoiceItem extends InvoiceItemCatalogBase {
public UsageInvoiceItem(final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId, @Nullable final UUID subscriptionId,
final String planName, final String phaseName, final String usageName,
final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final Currency currency) {
- this(UUIDs.randomUUID(), null, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usageName, null, null, null, startDate, endDate, null, amount, currency, null, null);
+ this(UUIDs.randomUUID(), null, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usageName, null, null, null, startDate, endDate, null, amount, null, currency, null, null);
}
public UsageInvoiceItem(final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId, @Nullable final UUID subscriptionId,
final String planName, final String phaseName, final String usageName,
- final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final Currency currency, @Nullable final Integer quantity, @Nullable final String itemDetails) {
- this(UUIDs.randomUUID(), null, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usageName, null, null, null, startDate, endDate, null, amount, currency, quantity, itemDetails);
+ final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final Integer quantity, @Nullable final String itemDetails) {
+ this(UUIDs.randomUUID(), null, invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usageName, null, null, null, startDate, endDate, null, amount, rate, currency, quantity, itemDetails);
}
public UsageInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID bundleId,
final UUID subscriptionId, final String planName, final String phaseName, final String usageName,
final String prettyPlanName, final String prettyPhaseName, final String prettyUsageName,
- final LocalDate startDate, final LocalDate endDate, @Nullable final String description, final BigDecimal amount, final Currency currency,
- @Nullable final Integer quantity, @Nullable final String itemDetails) {
- super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, startDate, endDate, amount, null, currency, null, quantity, itemDetails);
+ final LocalDate startDate, final LocalDate endDate, @Nullable final String description, final BigDecimal amount, final BigDecimal rate,
+ final Currency currency, @Nullable final Integer quantity, @Nullable final String itemDetails) {
+ super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, startDate, endDate, amount, rate, currency, null, quantity, itemDetails);
}
@Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java
index f9f9b85..ac4f2a2 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java
@@ -17,6 +17,7 @@
package org.killbill.billing.invoice.usage;
+import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
@@ -29,6 +30,7 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
+import javax.inject.Inject;
import org.joda.time.LocalDate;
import org.killbill.billing.ErrorCode;
@@ -49,10 +51,15 @@ import org.killbill.billing.junction.BillingEvent;
import org.killbill.billing.usage.RawUsage;
import org.killbill.billing.usage.api.RolledUpUnit;
import org.killbill.billing.usage.api.RolledUpUsage;
+import org.killbill.billing.util.config.definition.InvoiceConfig;
+import org.killbill.billing.util.config.definition.InvoiceConfig.UsageDetailMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
@@ -89,6 +96,7 @@ public class ContiguousIntervalUsageInArrear {
private final AtomicBoolean isBuilt;
private final LocalDate rawUsageStartDate;
private final InternalTenantContext internalTenantContext;
+ private final InvoiceConfig invoiceConfig;
public ContiguousIntervalUsageInArrear(final Usage usage,
final UUID accountId,
@@ -96,7 +104,8 @@ public class ContiguousIntervalUsageInArrear {
final List<RawUsage> rawSubscriptionUsage,
final LocalDate targetDate,
final LocalDate rawUsageStartDate,
- final InternalTenantContext internalTenantContext) {
+ final InternalTenantContext internalTenantContext,
+ final InvoiceConfig invoiceConfig) {
this.usage = usage;
this.accountId = accountId;
this.invoiceId = invoiceId;
@@ -108,6 +117,7 @@ public class ContiguousIntervalUsageInArrear {
this.billingEvents = Lists.newLinkedList();
this.transitionTimes = Lists.newLinkedList();
this.isBuilt = new AtomicBoolean(false);
+ this.invoiceConfig = invoiceConfig;
}
/**
@@ -206,20 +216,30 @@ public class ContiguousIntervalUsageInArrear {
}
toBeBilledUsage = toBeBilledForUnit(toBeBilledUsageDetails);
+
// Retrieves current price amount billed for that period of time (and usage section)
final Iterable<InvoiceItem> billedItems = getBilledItems(ru.getStart(), ru.getEnd(), existingUsage);
final BigDecimal billedUsage = computeBilledUsage(billedItems);
// Compare the two and add the missing piece if required.
if (!billedItems.iterator().hasNext() || billedUsage.compareTo(toBeBilledUsage) < 0) {
- final BigDecimal amountToBill = toBeBilledUsage.subtract(billedUsage);
- if (billedUsage.compareTo(BigDecimal.ZERO) > 0){
- toBeBilledUsageDetails.add(new ToBeBilledConsumableInArrearDetail(-1, "billedUsage", billedUsage, -1));
- }
+ toBeBilledUsageDetails = reconcileExistedBilledWithToBeBilled(billedItems, toBeBilledUsageDetails);
+ final BigDecimal amountToBill = toBeBilledForUnit(toBeBilledUsageDetails);
+
+ //final BigDecimal amountToBill = toBeBilledUsage.subtract(billedUsage);
+
if (amountToBill.compareTo(BigDecimal.ZERO) > 0) {
- final InvoiceItem item = new UsageInvoiceItem(invoiceId, accountId, getBundleId(), getSubscriptionId(), getPlanName(),
- getPhaseName(), usage.getName(), ru.getStart(), ru.getEnd(), amountToBill, getCurrency(),null,toJson(toBeBilledUsageDetails));
- result.add(item);
+ if (UsageDetailMode.DETAIL.compareTo(invoiceConfig.getItemResultBehaviorMode(internalTenantContext)) == 0){
+ for (ConsumableInArrearDetail toBeBilledUsageDetail : toBeBilledUsageDetails){
+ final InvoiceItem item = new UsageInvoiceItem(invoiceId, accountId, getBundleId(), getSubscriptionId(), getPlanName(),
+ getPhaseName(), usage.getName(), ru.getStart(), ru.getEnd(), toBeBilledUsageDetail.getAmount(), toBeBilledUsageDetail.getTierPrice(), getCurrency(),toBeBilledUsageDetail.getQuantity(),null);
+ result.add(item);
+ }
+ } else {
+ final InvoiceItem item = new UsageInvoiceItem(invoiceId, accountId, getBundleId(), getSubscriptionId(), getPlanName(),
+ getPhaseName(), usage.getName(), ru.getStart(), ru.getEnd(), amountToBill, null, getCurrency(),null, toJson(toBeBilledUsageDetails));
+ result.add(item);
+ }
}
}
}
@@ -407,7 +427,7 @@ public class ContiguousIntervalUsageInArrear {
* @throws CatalogApiException
*/
@VisibleForTesting
- List<ToBeBilledConsumableInArrearDetail> computeToBeBilledConsumableInArrear(final RolledUpUnit roUnit, int tierNum) throws CatalogApiException {
+ List<ConsumableInArrearDetail> computeToBeBilledConsumableInArrear(final RolledUpUnit roUnit, int tierNum) throws CatalogApiException {
Preconditions.checkState(isBuilt.get());
final List<TieredBlock> tieredBlocks = getConsumableInArrearTieredBlocks(usage, roUnit.getUnitType());
@@ -423,9 +443,9 @@ public class ContiguousIntervalUsageInArrear {
}
- List<ToBeBilledConsumableInArrearDetail> computeToBeBilledConsumableInArrearWith_ALL_TIERS(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
+ List<ConsumableInArrearDetail> computeToBeBilledConsumableInArrearWith_ALL_TIERS(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
- List<ToBeBilledConsumableInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
+ List<ConsumableInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
BigDecimal result = BigDecimal.ZERO;
int remainingUnits = units.intValue();
for (final TieredBlock tieredBlock : tieredBlocks) {
@@ -440,12 +460,12 @@ public class ContiguousIntervalUsageInArrear {
nbUsedTierBlocks = tmp;
remainingUnits = 0;
}
- toBeBilledDetails.add(new ToBeBilledConsumableInArrearDetail(tierNum, tieredBlock.getUnit().getName(), tieredBlock.getPrice().getPrice(getCurrency()), nbUsedTierBlocks));
+ toBeBilledDetails.add(new ConsumableInArrearDetail(tierNum, tieredBlock.getUnit().getName(), tieredBlock.getPrice().getPrice(getCurrency()), nbUsedTierBlocks));
}
return toBeBilledDetails;
}
- ToBeBilledConsumableInArrearDetail computeToBeBilledConsumableInArrearWith_TOP_TIER(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
+ ConsumableInArrearDetail computeToBeBilledConsumableInArrearWith_TOP_TIER(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
int remainingUnits = units.intValue();
@@ -466,7 +486,7 @@ public class ContiguousIntervalUsageInArrear {
final int lastBlockTierSize = targetBlock.getSize().intValue();
final int nbBlocks = units.intValue() / lastBlockTierSize + (units.intValue() % lastBlockTierSize == 0 ? 0 : 1);
- return new ToBeBilledConsumableInArrearDetail(tierNum, targetBlock.getUnit().getName(), targetBlock.getPrice().getPrice(getCurrency()), nbBlocks);
+ return new ConsumableInArrearDetail(tierNum, targetBlock.getUnit().getName(), targetBlock.getPrice().getPrice(getCurrency()), nbBlocks);
}
@@ -573,53 +593,124 @@ public class ContiguousIntervalUsageInArrear {
}
}
- private BigDecimal toBeBilledForUnit(List<ToBeBilledConsumableInArrearDetail> toBeBilledDetails){
+ public BigDecimal toBeBilledForUnit(List<ConsumableInArrearDetail> toBeBilledDetails){
BigDecimal result = BigDecimal.ZERO;
- for (ToBeBilledConsumableInArrearDetail toBeBilled: toBeBilledDetails){
+ for (ConsumableInArrearDetail toBeBilled: toBeBilledDetails){
result = result.add(toBeBilled.getAmount());
}
return result;
}
- private String toJson(List<ToBeBilledConsumableInArrearDetail> toBeBilledConsumableInArrearDetails) throws CatalogApiException {
+ private List<ConsumableInArrearDetail> reconcileExistedBilledWithToBeBilled(Iterable<InvoiceItem> billedItems, List<ConsumableInArrearDetail> toBeBilledConsumableInArrearDetails) {
+ for (final InvoiceItem bi : billedItems) {
+ List<ConsumableInArrearDetail> billedUsageItemDetails = fromJson(bi.getItemDetails());
+
+ if (billedUsageItemDetails != null && billedUsageItemDetails.size() > 0) {
+
+ for (final ConsumableInArrearDetail toBeBilledConsumable : toBeBilledConsumableInArrearDetails) {
+ billedUsageItemDetails = toBeBilledConsumable.reconcile(billedUsageItemDetails);
+ }
+
+ if (billedUsageItemDetails != null && billedUsageItemDetails.size() > 0) {
+ for (final ConsumableInArrearDetail billedUsage : billedUsageItemDetails) {
+ toBeBilledConsumableInArrearDetails.add(new ConsumableInArrearDetail(billedUsage.getTier(), billedUsage.getTierUnit(), billedUsage.getTierPrice(),
+ billedUsage.getQuantity(), billedUsage.getAmount().negate(), null, bi.getId().toString()));
+ }
+ }
+ } else {
+ toBeBilledConsumableInArrearDetails.add(new ConsumableInArrearDetail(bi.getRate(), bi.getQuantity(), bi.getAmount().negate(), bi.getId().toString()));
+ }
+ }
+
+ return toBeBilledConsumableInArrearDetails;
+ }
+
+ private static final String toJson(List<ConsumableInArrearDetail> toBeBilledConsumableInArrearDetails) {
String result = null;
if (toBeBilledConsumableInArrearDetails != null && toBeBilledConsumableInArrearDetails.size() > 0){
ObjectMapper objectMapper = new ObjectMapper();
try {
result = objectMapper.writeValueAsString(toBeBilledConsumableInArrearDetails);
} catch (JsonProcessingException e) {
- throw new CatalogApiException(e, ErrorCode.__UNKNOWN_ERROR_CODE);
+ Preconditions.checkState(false, e.getMessage());
}
}
return result;
}
- public class ToBeBilledConsumableInArrearDetail {
+ private static final List<ConsumableInArrearDetail> fromJson(String itemDetails){
+ List<ConsumableInArrearDetail> toBeBilledConsumableInArrearDetails = null;
+ if (itemDetails != null){
+ ObjectMapper objectMapper = new ObjectMapper();
+ try {
+ toBeBilledConsumableInArrearDetails = objectMapper.reader()
+ .forType(new TypeReference<List<ConsumableInArrearDetail>>() {})
+ .readValue(itemDetails);
+ } catch (IOException e) {
+ Preconditions.checkState(false, e.getMessage());
+ }
+ }
+
+ return toBeBilledConsumableInArrearDetails;
+ }
+
+ public class ConsumableInArrearDetail {
private final int tier;
private final String tierUnit;
private final BigDecimal tierPrice;
- private final int quantity;
- private final BigDecimal amount;
+ private final Integer quantity;
+ private String reference;
+ private BigDecimal existingUsageAmount;
+ private BigDecimal amount;
+
+ public ConsumableInArrearDetail(BigDecimal tierPrice, Integer quantity, BigDecimal existingUsageAmount, String reference){
+ this(0, null, tierPrice, quantity, existingUsageAmount, BigDecimal.ZERO, reference);
+ }
- public ToBeBilledConsumableInArrearDetail(int tier, String tierUnit, BigDecimal tierPrice, int quantity){
- this(tier, tierUnit, tierPrice, quantity, tierPrice.multiply(new BigDecimal(quantity)));
+ public ConsumableInArrearDetail(int tier, String tierUnit, BigDecimal tierPrice, Integer quantity){
+ this(tier, tierUnit, tierPrice, quantity, tierPrice.multiply(new BigDecimal(quantity)), null, null);
}
- public ToBeBilledConsumableInArrearDetail(int tier, String tierUnit, BigDecimal tierPrice, int quantity, BigDecimal amount){
+ @JsonCreator
+ public ConsumableInArrearDetail(@JsonProperty("tier") int tier, @JsonProperty("tierUnit") String tierUnit,
+ @JsonProperty("tierPrice") BigDecimal tierPrice, @JsonProperty("quantity") Integer quantity,
+ @JsonProperty("amount") BigDecimal amount, @JsonProperty("existingUsageAmount") BigDecimal existingUsageAmount,
+ @JsonProperty("reference") String reference){
this.tier = tier;
this.tierUnit = tierUnit;
this.tierPrice = tierPrice;
this.quantity = quantity;
this.amount = amount;
+ this.existingUsageAmount = existingUsageAmount;
+ this.reference = reference;
}
public int getTier() { return tier; };
public String getTierUnit() { return tierUnit; }
public BigDecimal getTierPrice() { return tierPrice; }
- public int getQuantity() { return quantity; }
+ public Integer getQuantity() { return quantity; }
+ public BigDecimal getExistingUsageAmount() { return existingUsageAmount; }
public BigDecimal getAmount() {
return amount;
}
+
+ public void setAmount(BigDecimal amount) { this.amount = amount; }
+ public void setExistingUsageAmount(BigDecimal existingUsageAmount) { this.existingUsageAmount = existingUsageAmount; }
+ public void setReference(String reference) { this.reference = reference; }
+
+ public List<ConsumableInArrearDetail> reconcile(List<ConsumableInArrearDetail> billedUsageItemDetails){
+ List<ConsumableInArrearDetail> unreconciledUsage = Lists.newLinkedList();
+ for (ConsumableInArrearDetail billedUsageDetail : billedUsageItemDetails){
+ if( tierUnit == billedUsageDetail.tierUnit ) {
+ existingUsageAmount = billedUsageDetail.amount.abs();
+ amount = amount.subtract(existingUsageAmount);
+ } else {
+ unreconciledUsage.add(billedUsageDetail);
+ }
+ }
+
+ return unreconciledUsage;
+ }
}
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java
index b308c68..d7567ca 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java
@@ -38,6 +38,7 @@ import org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGe
import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearItemsAndNextNotificationDate;
import org.killbill.billing.junction.BillingEvent;
import org.killbill.billing.usage.RawUsage;
+import org.killbill.billing.util.config.definition.InvoiceConfig;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@@ -78,6 +79,7 @@ public class SubscriptionUsageInArrear {
private final List<RawUsage> rawSubscriptionUsage;
private final LocalDate rawUsageStartDate;
private final InternalTenantContext internalTenantContext;
+ private final InvoiceConfig invoiceConfig;
public SubscriptionUsageInArrear(final UUID accountId,
final UUID invoiceId,
@@ -85,7 +87,8 @@ public class SubscriptionUsageInArrear {
final List<RawUsage> rawUsage,
final LocalDate targetDate,
final LocalDate rawUsageStartDate,
- final InternalTenantContext internalTenantContext) {
+ final InternalTenantContext internalTenantContext,
+ final InvoiceConfig invoiceConfig) {
this.accountId = accountId;
this.invoiceId = invoiceId;
@@ -100,6 +103,7 @@ public class SubscriptionUsageInArrear {
return input.getSubscriptionId().equals(subscriptionBillingEvents.get(0).getSubscription().getId());
}
}));
+ this.invoiceConfig = invoiceConfig;
}
/**
@@ -149,7 +153,7 @@ public class SubscriptionUsageInArrear {
// Add inflight usage interval if non existent
ContiguousIntervalUsageInArrear existingInterval = inFlightInArrearUsageIntervals.get(usage.getName());
if (existingInterval == null) {
- existingInterval = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawSubscriptionUsage, targetDate, rawUsageStartDate, internalTenantContext);
+ existingInterval = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawSubscriptionUsage, targetDate, rawUsageStartDate, internalTenantContext, invoiceConfig);
inFlightInArrearUsageIntervals.put(usage.getName(), existingInterval);
}
// Add billing event for that usage interval
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java b/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java
index dcd4a44..b61dd1b 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java
@@ -39,6 +39,7 @@ import org.killbill.billing.usage.api.UsageUserApi;
import org.killbill.billing.util.api.TagUserApi;
import org.killbill.billing.util.cache.CacheControllerDispatcher;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.killbill.billing.util.config.definition.InvoiceConfig;
import org.killbill.bus.api.PersistentBus;
import org.killbill.clock.Clock;
import org.killbill.commons.locker.GlobalLocker;
@@ -67,6 +68,8 @@ public abstract class InvoiceTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
@Inject
protected InvoiceGenerator generator;
@Inject
+ protected InvoiceConfig invoiceConfig;
+ @Inject
protected BillingInternalApi billingApi;
@Inject
protected AccountInternalApi accountApi;
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
index d91f639..c04219b 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
@@ -37,7 +37,7 @@ import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.model.FixedPriceInvoiceItem;
import org.killbill.billing.invoice.model.UsageInvoiceItem;
-import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.ToBeBilledConsumableInArrearDetail;
+import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.ConsumableInArrearDetail;
import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearItemsAndNextNotificationDate;
import org.killbill.billing.junction.BillingEvent;
import org.killbill.billing.usage.RawUsage;
@@ -145,7 +145,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
Collections.<Usage>emptyList())
);
- List<ToBeBilledConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L), 1);
+ List<ConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L), 1);
assertEquals(result.size(), 3);
// 111 = 10 (tier1) + 100 (tier2) + 1 (tier3) => 10 * 1.5 + 100 * 1 + 1 * 0.5 = 115.5
assertEquals(result.get(0).getAmount(), new BigDecimal("15.0"));
@@ -173,7 +173,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
Collections.<Usage>emptyList())
);
- List<ToBeBilledConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 5325L),1);
+ List<ConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 5325L),1);
assertEquals(result.size(), 2);
// 5000 = 1000 (tier1) + 4325 (tier2) => 10 + 5 = 15
@@ -207,23 +207,23 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
//
// In this model unit amount is first used to figure out which tier we are in, and then we price all unit at that 'target' tier
//
- List<ToBeBilledConsumableInArrearDetail> inputTier1 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 1000L), 1);
+ List<ConsumableInArrearDetail> inputTier1 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 1000L), 1);
assertEquals(inputTier1.size(), 1);
// 1000 units => (tier1) : 1000 / 100 + 1000 % 100 = 10
assertEquals(inputTier1.get(0).getAmount(), new BigDecimal("10"));
- List<ToBeBilledConsumableInArrearDetail> inputTier2 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101000L), 1);
+ List<ConsumableInArrearDetail> inputTier2 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101000L), 1);
assertEquals(inputTier2.size(), 1);
// 101000 units => (tier2) : 101000 / 1000 + 101000 % 1000 = 101 + 0 = 101
assertEquals(inputTier2.get(0).getAmount(), new BigDecimal("101"));
- List<ToBeBilledConsumableInArrearDetail> inputTier3 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101001L), 1);
+ List<ConsumableInArrearDetail> inputTier3 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101001L), 1);
assertEquals(inputTier3.size(), 1);
// 101001 units => (tier3) : 101001 / 1000 + 101001 % 1000 = 101 + 1 = 102 units => $51
assertEquals(inputTier3.get(0).getAmount(), new BigDecimal("51.0"));
// If we pass the maximum of the last tier, we price all units at the last tier
- List<ToBeBilledConsumableInArrearDetail> inputLastTier = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 300000L), 1);
+ List<ConsumableInArrearDetail> inputLastTier = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 300000L), 1);
assertEquals(inputLastTier.size(), 1);
// 300000 units => (tier3) : 300000 / 1000 + 300000 % 1000 = 300 units => $150
assertEquals(inputLastTier.get(0).getAmount(), new BigDecimal("150.0"));
@@ -252,7 +252,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
Collections.<Usage>emptyList())
);
- List<ToBeBilledConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L),1);
+ List<ConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L),1);
assertEquals(result.size(), 1);
// 111 = 111 * 0.5 =
@@ -321,8 +321,8 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
// check item detail
List<MockToBeBilledConsumableInArrearDetail> itemDetails = objectMapper.reader()
- .forType(new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {})
- .readValue(result.get(0).getItemDetails());
+ .forType(new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {})
+ .readValue(result.get(0).getItemDetails());
assertEquals(itemDetails.size(), 2);
assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("5")),0);
assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("-1")),0);
@@ -342,8 +342,8 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
// check item detail
List<MockToBeBilledConsumableInArrearDetail> itemDetails2 = objectMapper.reader()
- .forType(new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {})
- .readValue(result.get(1).getItemDetails());
+ .forType(new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {})
+ .readValue(result.get(1).getItemDetails());
assertEquals(itemDetails2.size(), 2);
assertEquals(itemDetails2.get(0).getAmount().compareTo(new BigDecimal("2")),0);
assertEquals(itemDetails2.get(1).getAmount().compareTo(new BigDecimal("-1")),0);
@@ -442,7 +442,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
final BillingEvent event2 = createMockBillingEvent(new LocalDate(2014, 10, 16).toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
- final ContiguousIntervalUsageInArrear intervalConsumableInArrear = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, rawUsageStartDate, internalCallContext);
+ final ContiguousIntervalUsageInArrear intervalConsumableInArrear = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, rawUsageStartDate, internalCallContext, invoiceConfig);
intervalConsumableInArrear.addBillingEvent(event1);
intervalConsumableInArrear.addBillingEvent(event2);
@@ -452,27 +452,33 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
public static class MockToBeBilledConsumableInArrearDetail {
- private int tier;
- private String tierUnit;
- private BigDecimal tierPrice;
- private int quantity;
- private BigDecimal amount;
+ private final int tier;
+ private final String tierUnit;
+ private final BigDecimal tierPrice;
+ private final Integer quantity;
+ private final String reference;
+ private final BigDecimal existingUsageAmount;
+ private final BigDecimal amount;
@JsonCreator
public MockToBeBilledConsumableInArrearDetail(@JsonProperty("tier") int tier, @JsonProperty("tierUnit") String tierUnit,
- @JsonProperty("tierPrice") BigDecimal tierPrice, @JsonProperty("quantity") int quantity,
- @JsonProperty("amount") BigDecimal amount){
+ @JsonProperty("tierPrice") BigDecimal tierPrice, @JsonProperty("quantity") Integer quantity,
+ @JsonProperty("amount") BigDecimal amount, @JsonProperty("existingUsageAmount") BigDecimal existingUsageAmount,
+ @JsonProperty("reference") String reference){
this.tier = tier;
this.tierUnit = tierUnit;
this.tierPrice = tierPrice;
this.quantity = quantity;
this.amount = amount;
+ this.existingUsageAmount = existingUsageAmount;
+ this.reference = reference;
}
public int getTier() { return tier; };
public String getTierUnit() { return tierUnit; }
public BigDecimal getTierPrice() { return tierPrice; }
- public int getQuantity() { return quantity; }
+ public Integer getQuantity() { return quantity; }
+ public BigDecimal getExistingUsageAmount() { return existingUsageAmount; }
public BigDecimal getAmount() {
return amount;
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
index eb02634..fdde084 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
@@ -75,7 +75,7 @@ public class TestSubscriptionConsumableInArrear extends TestUsageInArrearBase {
LocalDate targetDate = new LocalDate(2013, 6, 23);
- final SubscriptionUsageInArrear foo = new SubscriptionUsageInArrear(accountId, invoiceId, billingEvents, ImmutableList.<RawUsage>of(), targetDate, new LocalDate(dt1, DateTimeZone.UTC), internalCallContext);
+ final SubscriptionUsageInArrear foo = new SubscriptionUsageInArrear(accountId, invoiceId, billingEvents, ImmutableList.<RawUsage>of(), targetDate, new LocalDate(dt1, DateTimeZone.UTC), internalCallContext, invoiceConfig);
final List<ContiguousIntervalUsageInArrear> result = foo.computeInArrearUsageInterval();
assertEquals(result.size(), 3);
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
index 0c1f557..3280df5 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
@@ -74,7 +74,7 @@ public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
}
protected ContiguousIntervalUsageInArrear createContiguousIntervalConsumableInArrear(final DefaultUsage usage, final List<RawUsage> rawUsages, final LocalDate targetDate, final boolean closedInterval, final BillingEvent... events) {
- final ContiguousIntervalUsageInArrear intervalConsumableInArrear = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, new LocalDate(events[0].getEffectiveDate()), internalCallContext);
+ final ContiguousIntervalUsageInArrear intervalConsumableInArrear = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, new LocalDate(events[0].getEffectiveDate()), internalCallContext, invoiceConfig);
for (final BillingEvent event : events) {
intervalConsumableInArrear.addBillingEvent(event);
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoiceItemJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoiceItemJson.java
index 7de2870..85fb439 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoiceItemJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoiceItemJson.java
@@ -63,6 +63,7 @@ public class InvoiceItemJson extends JsonBase {
private final LocalDate startDate;
private final LocalDate endDate;
private final BigDecimal amount;
+ private final BigDecimal rate;
private final String currency;
private final Integer quantity;
private final String itemDetails;
@@ -87,11 +88,12 @@ public class InvoiceItemJson extends JsonBase {
@JsonProperty("startDate") final LocalDate startDate,
@JsonProperty("endDate") final LocalDate endDate,
@JsonProperty("amount") final BigDecimal amount,
+ @JsonProperty("rate") final BigDecimal rate,
@JsonProperty("currency") final String currency,
- @JsonProperty("childItems") final List<InvoiceItemJson> childItems,
- @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs,
@JsonProperty("quantity") final Integer quantity,
- @JsonProperty("itemDetails") final String itemDetails) {
+ @JsonProperty("itemDetails") final String itemDetails,
+ @JsonProperty("childItems") final List<InvoiceItemJson> childItems,
+ @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
super(auditLogs);
this.invoiceItemId = invoiceItemId;
this.invoiceId = invoiceId;
@@ -111,6 +113,7 @@ public class InvoiceItemJson extends JsonBase {
this.startDate = startDate;
this.endDate = endDate;
this.amount = amount;
+ this.rate = rate;
this.currency = currency;
this.childItems = childItems;
this.quantity = quantity;
@@ -124,8 +127,8 @@ public class InvoiceItemJson extends JsonBase {
item.getPrettyPlanName(), item.getPrettyPhaseName(), item.getPrettyUsageName(),
item.getInvoiceItemType().toString(),
item.getDescription(), item.getStartDate(), item.getEndDate(),
- item.getAmount(), item.getCurrency().name(), toInvoiceItemJson(childItems), toAuditLogJson(auditLogs),
- item.getQuantity(), item.getItemDetails());
+ item.getAmount(), item.getRate(), item.getCurrency().name(),
+ item.getQuantity(), item.getItemDetails(), toInvoiceItemJson(childItems), toAuditLogJson(auditLogs));
}
private static List<InvoiceItemJson> toInvoiceItemJson(final List<InvoiceItem> childItems) {
@@ -229,7 +232,7 @@ public class InvoiceItemJson extends JsonBase {
@Override
public BigDecimal getRate() {
- return null;
+ return rate;
}
@Override
@@ -341,6 +344,8 @@ public class InvoiceItemJson extends JsonBase {
return amount;
}
+ public BigDecimal getRate() { return rate; }
+
public String getCurrency() {
return currency;
}
@@ -371,6 +376,7 @@ public class InvoiceItemJson extends JsonBase {
sb.append(", startDate=").append(startDate);
sb.append(", endDate=").append(endDate);
sb.append(", amount=").append(amount);
+ sb.append(", rate=").append(rate);
sb.append(", currency=").append(currency);
sb.append(", quantity=").append(quantity);
sb.append(", itemDetails=").append(itemDetails);
@@ -446,6 +452,9 @@ public class InvoiceItemJson extends JsonBase {
if (itemDetails != null ? !itemDetails.equals(that.itemDetails) : that.itemDetails != null) {
return false;
}
+ if (rate != null ? !rate.equals(that.rate) : that.rate != null) {
+ return false;
+ }
return true;
}
@@ -466,10 +475,11 @@ public class InvoiceItemJson extends JsonBase {
result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
result = 31 * result + (endDate != null ? endDate.hashCode() : 0);
result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ result = 31 * result + (rate != null ? rate.hashCode() : 0);
result = 31 * result + (currency != null ? currency.hashCode() : 0);
- result = 31 * result + (childItems != null ? childItems.hashCode() : 0);
result = 31 * result + (quantity != null ? quantity.hashCode() : 0);
result = 31 * result + (itemDetails != null ? itemDetails.hashCode() : 0);
+ result = 31 * result + (childItems != null ? childItems.hashCode() : 0);
return result;
}
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
index 354f8ab..f98623f 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
@@ -576,11 +576,12 @@ public class InvoiceResource extends JaxRsResourceBase {
input.getStartDate(),
input.getEndDate(),
input.getAmount(),
+ input.getRate(),
accountCurrency.name(),
- null,
- null,
input.getQuantity(),
- input.getItemDetails());
+ input.getItemDetails(),
+ null,
+ null);
}
}
});
diff --git a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestInvoiceItemJsonSimple.java b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestInvoiceItemJsonSimple.java
index 3e72b3c..f61257d 100644
--- a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestInvoiceItemJsonSimple.java
+++ b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestInvoiceItemJsonSimple.java
@@ -56,7 +56,7 @@ public class TestInvoiceItemJsonSimple extends JaxrsTestSuiteNoDB {
bundleId, subscriptionId, planName, phaseName, usageName,
null, null, null,
type, description,
- startDate, endDate, amount, currency.name(), null, auditLogs, null, null);
+ startDate, endDate, amount, null, currency.name(), null, null, null, auditLogs);
Assert.assertEquals(invoiceItemJson.getInvoiceItemId(), invoiceItemId);
Assert.assertEquals(invoiceItemJson.getInvoiceId(), invoiceId);
Assert.assertEquals(invoiceItemJson.getLinkedInvoiceItemId(), linkedInvoiceItemId);