Details
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 5adc2b2..677473e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -351,6 +351,12 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
invoiceForCredit = new DefaultInvoice(accountId, effectiveDate, effectiveDate, currency, InvoiceStatus.DRAFT);
} else {
invoiceForCredit = getInvoiceAndCheckCurrency(invoiceId, currency, context);
+ // TODO check with @sbrossie if really want to add this validation
+ /*
+ if (InvoiceStatus.COMMITTED.equals(invoiceForCredit.getStatus())) {
+ throw new InvoiceApiException(ErrorCode.INVOICE_INVALID_STATUS_CREDIT, invoiceId);
+ }
+ */
}
// Create the new credit
@@ -483,4 +489,9 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
return invoice;
}
+ @Override
+ public void invoiceStatusTransition(final UUID accountId, final UUID invoiceId, final CallContext context) throws InvoiceApiException {
+ final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(accountId, context);
+ dao.changeInvoiceStatus(accountId, invoiceId, InvoiceStatus.COMMITTED, internalCallContext);
+ }
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
index 1ef6f7f..a82b77f 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
@@ -41,6 +41,7 @@ import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.invoice.api.InvoicePaymentType;
+import org.killbill.billing.invoice.api.InvoiceStatus;
import org.killbill.billing.invoice.api.user.DefaultInvoiceAdjustmentEvent;
import org.killbill.billing.invoice.notification.NextBillingDatePoster;
import org.killbill.billing.util.UUIDs;
@@ -257,7 +258,10 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
createInvoiceItemFromTransaction(transInvoiceItemSqlDao, invoiceItemModelDao, context);
}
cbaDao.addCBAComplexityFromTransaction(invoice, entitySqlDaoWrapperFactory, context);
- notifyOfFutureBillingEvents(entitySqlDaoWrapperFactory, invoice.getAccountId(), callbackDateTimePerSubscriptions, context);
+ if (InvoiceStatus.COMMITTED.equals(invoice.getStatus())) {
+ // only notify on the bus if the state is COMMITTED
+ notifyOfFutureBillingEvents(entitySqlDaoWrapperFactory, invoice.getAccountId(), callbackDateTimePerSubscriptions, context);
+ }
}
return null;
}
@@ -295,6 +299,7 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
cbaDao.addCBAComplexityFromTransaction(invoiceModelDao.getId(), entitySqlDaoWrapperFactory, context);
// Notify the bus since the balance of the invoice changed
+ // TODO check invoice status before sent it to the bus
// TODO should we post an InvoiceCreationInternalEvent event instead? Note! This will trigger a payment (see InvoiceHandler)
notifyBusOfInvoiceAdjustment(entitySqlDaoWrapperFactory, invoiceModelDao.getId(), invoiceModelDao.getAccountId(), context.getUserToken(), context);
}
@@ -854,4 +859,33 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
}
}
+ @Override
+ public void changeInvoiceStatus(final UUID accountId, final UUID invoiceId, final InvoiceStatus newStatus,
+ final InternalCallContext context) throws InvoiceApiException {
+ transactionalSqlDao.execute(InvoiceApiException.class, new EntitySqlDaoTransactionWrapper<Void>() {
+ @Override
+ public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+ final InvoiceSqlDao transactional = entitySqlDaoWrapperFactory.become(InvoiceSqlDao.class);
+
+ // Retrieve the invoice and make sure it belongs to the right account
+ final InvoiceModelDao invoice = transactional.getById(invoiceId.toString(), context);
+ if (invoice == null || !invoice.getAccountId().equals(accountId)) {
+ throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceId);
+ }
+
+ if (invoice.getStatus().equals(newStatus)) {
+ throw new InvoiceApiException(ErrorCode.INVOICE_INVALID_STATUS, newStatus, invoiceId, invoice.getStatus());
+ }
+
+ transactional.updateStatus(invoiceId.toString(), accountId.toString(), newStatus.toString(), context);
+
+ if (InvoiceStatus.COMMITTED.equals(newStatus)) {
+ // now notify on the bus
+ //notifyOfFutureBillingEvents(entitySqlDaoWrapperFactory, invoice.getAccountId(), callbackDateTimePerSubscriptions, context);
+ }
+
+ return null;
+ }
+ });
+ }
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
index 25c9249..1c18499 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
@@ -32,6 +32,7 @@ import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.invoice.InvoiceDispatcher.FutureAccountNotifications;
import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
+import org.killbill.billing.invoice.api.InvoiceStatus;
import org.killbill.billing.util.entity.Pagination;
import org.killbill.billing.util.entity.dao.EntityDao;
@@ -139,4 +140,14 @@ public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceA
*/
public void consumeExstingCBAOnAccountWithUnpaidInvoices(final UUID accountId, final InternalCallContext context);
+ /**
+ * Update invoice state
+ *
+ * @param accountId the account id
+ * @param invoiceId the invoice id
+ * @param newState the new invoice state
+ * @param context the tenant context
+ * @throws InvoiceApiException
+ */
+ void changeInvoiceStatus(UUID accountId, UUID invoiceId, InvoiceStatus newState, InternalCallContext context) throws InvoiceApiException;
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
index 3b46cf6..15d7354 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
@@ -19,13 +19,17 @@ package org.killbill.billing.invoice.dao;
import java.util.List;
import java.util.UUID;
+import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.invoice.api.Invoice;
+import org.killbill.billing.util.audit.ChangeType;
+import org.killbill.billing.util.entity.dao.Audited;
import org.killbill.billing.util.entity.dao.EntitySqlDao;
import org.killbill.billing.util.entity.dao.EntitySqlDaoStringTemplate;
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;
@EntitySqlDaoStringTemplate
public interface InvoiceSqlDao extends EntitySqlDao<InvoiceModelDao, Invoice> {
@@ -38,5 +42,11 @@ public interface InvoiceSqlDao extends EntitySqlDao<InvoiceModelDao, Invoice> {
UUID getInvoiceIdByPaymentId(@Bind("paymentId") final String paymentId,
@BindBean final InternalTenantContext context);
+ @SqlUpdate
+ @Audited(ChangeType.UPDATE)
+ public void updateStatus(@Bind("id") String invoiceId,
+ @Bind("accountId") String accountId,
+ @Bind("status") String status,
+ @BindBean final InternalCallContext context);
}
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
index 6bfdcf3..0cd6e79 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
@@ -52,3 +52,11 @@ getInvoiceIdByPaymentId() ::= <<
<AND_CHECK_TENANT("i.")>
<AND_CHECK_TENANT("ip.")>
>>
+
+updateStatus() ::= <<
+ UPDATE <tableName()>
+ SET status = :status
+ WHERE id = :id
+ AND account_id = :accountId
+ <AND_CHECK_TENANT()>;
+>>
\ No newline at end of file
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java b/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
index a572def..4161dd0 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
@@ -32,6 +32,7 @@ import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoiceItemType;
+import org.killbill.billing.invoice.api.InvoiceStatus;
import org.killbill.billing.invoice.model.ExternalChargeInvoiceItem;
import org.killbill.billing.util.api.TagApiException;
import org.killbill.billing.util.callcontext.CallContext;
@@ -365,4 +366,40 @@ public class TestDefaultInvoiceUserApi extends InvoiceTestSuiteWithEmbeddedDB {
final Invoice invoiceAfterTagRemoval = invoiceUserApi.getInvoice(invoiceId, callContext);
assertEquals(invoiceAfterTagRemoval.getBalance().compareTo(BigDecimal.ZERO), 1);
}
+
+ @Test(groups = "slow")
+ public void testInvoiceStatusTransition() throws Exception {
+ // Verify the initial invoice balance
+ final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance();
+ Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1);
+
+ // Verify the initial account balance
+ final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
+ Assert.assertEquals(accountBalance, invoiceBalance);
+
+ // Adjust the invoice for the full amount
+ final BigDecimal creditAmount = BigDecimal.TEN;
+ final InvoiceItem creditInvoiceItem = invoiceUserApi.insertCreditForInvoice(accountId, null, creditAmount,
+ clock.getUTCToday(), accountCurrency, callContext);
+
+ final UUID invoiceId = creditInvoiceItem.getInvoiceId();
+ Invoice creditInvoice = invoiceUserApi.getInvoice(invoiceId, callContext);
+ Assert.assertEquals(creditInvoice.getStatus(), InvoiceStatus.DRAFT);
+ Assert.assertEquals(creditInvoiceItem.getInvoiceId(), creditInvoice.getId());
+
+ // move invoice from DRAFT to COMMITTED
+ invoiceUserApi.invoiceStatusTransition(this.accountId, creditInvoice.getId(), callContext);
+ creditInvoice = invoiceUserApi.getInvoice(invoiceId, callContext);
+ Assert.assertEquals(creditInvoice.getStatus(), InvoiceStatus.COMMITTED);
+
+ // TODO verify post actions (event bus ???)
+
+ // Verify the adjusted invoice balance
+// final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(this.invoiceId, callContext).getBalance();
+// Assert.assertEquals(adjustedInvoiceBalance.compareTo(BigDecimal.ZERO), 0);
+
+ // Verify the adjusted account balance
+// final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
+// Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance);
+ }
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
index 65e3b0e..39b4913 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
@@ -34,6 +34,7 @@ import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.invoice.InvoiceDispatcher.FutureAccountNotifications;
import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
+import org.killbill.billing.invoice.api.InvoiceStatus;
import org.killbill.billing.invoice.api.user.DefaultInvoiceCreationEvent;
import org.killbill.billing.util.entity.DefaultPagination;
import org.killbill.billing.util.entity.Pagination;
@@ -362,4 +363,8 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
throw new UnsupportedOperationException();
}
+ @Override
+ public void changeInvoiceStatus(final UUID accountId, final UUID invoiceId, final InvoiceStatus newState, final InternalCallContext context) throws InvoiceApiException {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java b/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java
index 0f90be1..87a72de 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java
@@ -38,6 +38,7 @@ import org.killbill.billing.invoice.api.InvoiceInternalApi;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoicePayment;
import org.killbill.billing.invoice.api.InvoicePaymentType;
+import org.killbill.billing.invoice.api.InvoiceStatus;
import org.killbill.billing.invoice.dao.InvoiceDao;
import org.killbill.billing.invoice.dao.InvoiceItemModelDao;
import org.killbill.billing.invoice.dao.InvoiceModelDao;
@@ -96,6 +97,7 @@ public class InvoiceTestUtils {
Mockito.when(invoice.getTargetDate()).thenReturn(clock.getUTCToday());
Mockito.when(invoice.getCurrency()).thenReturn(currency);
Mockito.when(invoice.isMigrationInvoice()).thenReturn(false);
+ Mockito.when(invoice.getStatus()).thenReturn(InvoiceStatus.COMMITTED);
final List<InvoiceItem> invoiceItems = new ArrayList<InvoiceItem>();
final List<InvoiceItemModelDao> invoiceModelItems = new ArrayList<InvoiceItemModelDao>();
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 845bfd0..4aea81f 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
@@ -940,6 +940,32 @@ public class InvoiceResource extends JaxRsResourceBase {
context.createContext(createdBy, reason, comment, request));
}
+ @TimedResource
+ @POST
+ @Path("/{invoiceId:" + UUID_PATTERN + "}/" + ACCOUNTS + "/{accountId:" + UUID_PATTERN + "}/" + INVOICE_STATUS_TRANSITION)
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ @ApiOperation(value = "Perform the invoice status transition from DRAFT to COMMITTED")
+ @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid account id or invoice id supplied"),
+ @ApiResponse(code = 404, message = "Invoice not found")})
+ public Response invoiceStatusTransition(@PathParam("accountId") final String accountIdString,
+ @PathParam("invoiceId") final String invoiceIdString,
+ @HeaderParam(HDR_CREATED_BY) final String createdBy,
+ @HeaderParam(HDR_REASON) final String reason,
+ @HeaderParam(HDR_COMMENT) final String comment,
+ @javax.ws.rs.core.Context final HttpServletRequest request,
+ @javax.ws.rs.core.Context final UriInfo uriInfo) throws InvoiceApiException {
+
+ final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+
+ final UUID accountId = UUID.fromString(accountIdString);
+ final UUID invoiceId = UUID.fromString(invoiceIdString);
+
+ invoiceApi.invoiceStatusTransition(accountId, invoiceId, callContext);
+
+ return Response.status(Response.Status.OK).build();
+ }
+
@Override
protected ObjectType getObjectType() {
return ObjectType.INVOICE;
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
index f97c91a..92f1ac8 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
@@ -236,6 +236,7 @@ public interface JaxrsResource {
public static final String INVOICE_MP_TEMPLATE = "manualPayTemplate";
public static final String INVOICE_TRANSLATION = "translation";
public static final String INVOICE_CATALOG_TRANSLATION = "catalogTranslation";
+ public static final String INVOICE_STATUS_TRANSITION = "statusTransition";
public static final String COMBO = "combo";
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
index 4457006..d76a3e7 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
@@ -30,8 +30,10 @@ import org.joda.time.LocalDate;
import org.killbill.billing.catalog.api.BillingPeriod;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.client.KillBillClientException;
import org.killbill.billing.client.model.Account;
import org.killbill.billing.client.model.AuditLog;
+import org.killbill.billing.client.model.Credit;
import org.killbill.billing.client.model.Invoice;
import org.killbill.billing.client.model.InvoiceDryRun;
import org.killbill.billing.client.model.InvoiceItem;
@@ -41,6 +43,7 @@ import org.killbill.billing.client.model.Invoices;
import org.killbill.billing.client.model.PaymentMethod;
import org.killbill.billing.entitlement.api.SubscriptionEventType;
import org.killbill.billing.invoice.api.DryRunType;
+import org.killbill.billing.invoice.api.InvoiceStatus;
import org.killbill.billing.payment.provider.ExternalPaymentProviderPlugin;
import org.killbill.billing.util.api.AuditLevel;
import org.testng.Assert;
@@ -553,4 +556,74 @@ public class TestInvoice extends TestJaxrsBase {
}
Assert.assertNull(page);
}
+
+ @Test(groups = "slow", description = "Can add a credit to a new invoice")
+ public void testCreateCreditInvoiceAndMoveStatus() throws Exception {
+
+ final Account account = createAccountWithDefaultPaymentMethod();
+
+ final DateTime effectiveDate = clock.getUTCNow();
+ final BigDecimal creditAmount = BigDecimal.TEN;
+ final Credit credit = new Credit();
+ credit.setAccountId(account.getAccountId());
+ credit.setInvoiceId(null);
+ credit.setCreditAmount(creditAmount);
+ final Credit creditJson = killBillClient.createCredit(credit, createdBy, reason, comment);
+
+ Invoice invoice = killBillClient.getInvoice(creditJson.getInvoiceId());
+ Assert.assertEquals(invoice.getStatus(), InvoiceStatus.DRAFT.toString());
+
+ killBillClient.invoiceStatusTransition(account.getAccountId(), invoice.getInvoiceId(), createdBy, reason, comment);
+
+ invoice = killBillClient.getInvoice(creditJson.getInvoiceId());
+ Assert.assertEquals(invoice.getStatus(), InvoiceStatus.COMMITTED.toString());
+
+ }
+
+ @Test(groups = "slow", description = "Forcing method to fail.", expectedExceptions = KillBillClientException.class,
+ expectedExceptionsMessageRegExp = ".* type=ACCOUNT doesn't exist!")
+ public void testMoveInvoiceStatusWithInvalidIds() throws Exception {
+
+ killBillClient.invoiceStatusTransition(UUID.randomUUID(), UUID.randomUUID(), createdBy, reason, comment);
+
+ }
+
+ /*
+ @Test(groups = "slow", description = "Forcing method to fail.", expectedExceptions = KillBillClientException.class,
+ expectedExceptionsMessageRegExp = ".* type=ACCOUNT doesn't exist!")
+ public void testErrorTransition() throws Exception {
+
+ final Account account = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
+ final Invoice invoice = killBillClient.getInvoicesForAccount(account.getAccountId()).get(0);
+ Assert.assertEquals(invoice.getStatus(), InvoiceStatus.COMMITTED.toString());
+
+ killBillClient.invoiceStatusTransition(account.getAccountId(), invoice.getInvoiceId(), createdBy, reason, comment);
+
+ }
+ */
+
+ /*
+ @Test(groups = "slow", description = "Forcing method to fail.", expectedExceptions = KillBillClientException.class,
+ expectedExceptionsMessageRegExp = "No invoice could be found .*")
+ public void testMoveInvoiceStatusWithInvalidAccount() throws Exception {
+
+ final Account account = createAccountWithDefaultPaymentMethod();
+ final Account otherAccount = createAccountWithDefaultPaymentMethod();
+
+ final DateTime effectiveDate = clock.getUTCNow();
+ final BigDecimal creditAmount = BigDecimal.TEN;
+ final Credit credit = new Credit();
+ credit.setAccountId(account.getAccountId());
+ credit.setInvoiceId(null);
+ credit.setCreditAmount(creditAmount);
+ final Credit creditJson = killBillClient.createCredit(credit, createdBy, reason, comment);
+
+ Invoice invoice = killBillClient.getInvoice(creditJson.getInvoiceId());
+ Assert.assertEquals(invoice.getStatus(), InvoiceStatus.DRAFT.toString());
+
+ killBillClient.invoiceStatusTransition(otherAccount.getAccountId(), invoice.getInvoiceId(), createdBy, reason, comment);
+
+ }
+ */
+
}