@GET @Path("/{creditId:" + UUID_PATTERN + "}") @Produces(APPLICATION_JSON) @ApiOperation(value = "Retrieve a credit by id", response = CreditJson.class) @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid credit id supplied"), @ApiResponse(code = 404, message = "Credit not found")}) public Response getCredit(@PathParam("creditId") final UUID creditId, @javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException, AccountApiException { final TenantContext tenantContext = context.createTenantContextNoAccountId(request); final InvoiceItem credit = invoiceUserApi.getCreditById(creditId, tenantContext); final Invoice invoice = invoiceUserApi.getInvoice(credit.getInvoiceId(), tenantContext); final CreditJson creditJson = new CreditJson(invoice, credit); return Response.status(Response.Status.OK).entity(creditJson).build(); }
@TimedResource @GET @Path("/{invoiceId:" + UUID_PATTERN + "}/") @Produces(APPLICATION_JSON) @ApiOperation(value = "Retrieve an invoice by id", response = InvoiceJson.class) @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice id supplied"), @ApiResponse(code = 404, message = "Invoice not found")}) public Response getInvoice(@PathParam("invoiceId") final UUID invoiceId, @QueryParam(QUERY_INVOICE_WITH_ITEMS) @DefaultValue("false") final boolean withItems, @QueryParam(QUERY_INVOICE_WITH_CHILDREN_ITEMS) @DefaultValue("false") final boolean withChildrenItems, @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode, @javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException { final TenantContext tenantContext = context.createTenantContextNoAccountId(request); final Invoice invoice = invoiceApi.getInvoice(invoiceId, tenantContext); if (invoice == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceId); } final List<InvoiceItem> childInvoiceItems = withChildrenItems ? invoiceApi.getInvoiceItemsByParentInvoice(invoice.getId(), tenantContext) : null; final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(invoice.getAccountId(), auditMode.getLevel(), tenantContext); final InvoiceJson json = new InvoiceJson(invoice, withItems, childInvoiceItems, accountAuditLogs); return Response.status(Status.OK).entity(json).build(); }
@TimedResource @GET @Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS) @Produces(APPLICATION_JSON) @ApiOperation(value = "Retrieve invoice tags", response = TagJson.class, responseContainer = "List", nickname = "getInvoiceTags") @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice id supplied"), @ApiResponse(code = 404, message = "Invoice not found")}) public Response getTags(@PathParam(ID_PARAM_NAME) final UUID invoiceId, @QueryParam(QUERY_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted, @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode, @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, InvoiceApiException { final TenantContext tenantContext = context.createTenantContextNoAccountId(request); final Invoice invoice = invoiceApi.getInvoice(invoiceId, tenantContext); return super.getTags(invoice.getAccountId(), invoiceId, auditMode, includedDeleted, tenantContext); }
final Invoice invoice = invoiceApi.getInvoice(invoiceId, tenantContext);
public void checkInvoice(final UUID invoiceId, final CallContext context, final List<ExpectedInvoiceItemCheck> expected) throws InvoiceApiException { final Invoice invoice = invoiceUserApi.getInvoice(invoiceId, context); Assert.assertNotNull(invoice); checkInvoice(invoice, context, expected); }
@Test(groups = "slow") public void testVoidInvoice() throws Exception { // try to void invoice invoiceUserApi.voidInvoice(invoiceId, callContext); final Invoice invoice = invoiceUserApi.getInvoice(invoiceId, callContext); Assert.assertEquals(invoice.getStatus(), InvoiceStatus.VOID); }
@Test(groups = "slow") public void testAddRemoveWrittenOffTag() throws InvoiceApiException, TagApiException { final Invoice originalInvoice = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(originalInvoice.getBalance().compareTo(BigDecimal.ZERO), 1); invoiceUserApi.tagInvoiceAsWrittenOff(invoiceId, callContext); List<Tag> tags = tagUserApi.getTagsForObject(invoiceId, ObjectType.INVOICE, false, callContext); assertEquals(tags.size(), 1); assertEquals(tags.get(0).getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId()); final Invoice invoiceWithTag = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoiceWithTag.getBalance().compareTo(BigDecimal.ZERO), 0); invoiceUserApi.tagInvoiceAsNotWrittenOff(invoiceId, callContext); tags = tagUserApi.getTagsForObject(invoiceId, ObjectType.INVOICE, false, callContext); assertEquals(tags.size(), 0); final Invoice invoiceAfterTagRemoval = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoiceAfterTagRemoval.getBalance().compareTo(BigDecimal.ZERO), 1); }
@Test(groups = "slow", description = "Verify invoice/account balance with migrated invoice. Verify account credit is not consumed and that invoice/account balance does not take into account migrated invoice.") public void testMigratedInvoiceWithAccountCredit() throws Exception { // Add credit on the account invoiceUserApi.insertCredit(accountId, BigDecimal.TEN, null, accountCurrency, true, null, null, null, callContext); final UUID invoiceId = invoiceUserApi.createMigrationInvoice(accountId, null, ImmutableList.<InvoiceItem>of(new FixedPriceInvoiceItem(UUID.randomUUID(), clock.getUTCNow(), null, accountId, null, null, null, "foo", "bar", null, null, BigDecimal.ONE, accountCurrency)), callContext); final Invoice invoice1 = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoice1.getBalance().compareTo(BigDecimal.ZERO), 0); // Verify credit is **not applied** against migration invoice final BigDecimal accountBalance0 = invoiceUserApi.getAccountBalance(accountId, callContext); assertEquals(accountBalance0.compareTo(new BigDecimal("-10.0")), 0); final BigDecimal accountCBA0 = invoiceUserApi.getAccountCBA(accountId, callContext); assertEquals(accountCBA0.compareTo(BigDecimal.TEN), 0); }
@Test(groups = "slow") public void testOriginalAmountCharged() throws Exception { // Post an external charge final BigDecimal externalChargeAmount = BigDecimal.TEN; final InvoiceItem externalCharge = new ExternalChargeInvoiceItem(null, accountId, null, UUID.randomUUID().toString(), clock.getUTCToday(), null, externalChargeAmount, accountCurrency, null); final InvoiceItem externalChargeInvoiceItem = invoiceUserApi.insertExternalCharges(accountId, clock.getUTCToday(), ImmutableList.<InvoiceItem>of(externalCharge), true, null, callContext).get(0); final Invoice newInvoice = invoiceUserApi.getInvoice(externalChargeInvoiceItem.getInvoiceId(), callContext); final BigDecimal newAmountCharged = newInvoice.getChargedAmount(); Assert.assertEquals(newInvoice.getOriginalChargedAmount().compareTo(externalChargeAmount), 0); Assert.assertEquals(newAmountCharged.compareTo(externalChargeAmount), 0); }
@Test(groups = "slow") public void testCantAdjustInvoiceItemWithNegativeAmount() throws Exception { final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId, callContext).getInvoiceItems().get(0); try { invoiceUserApi.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItem.getId(), clock.getUTCToday(), BigDecimal.TEN.negate(), accountCurrency, null, null, null, callContext); Assert.fail("Should not have been able to adjust an item with a negative amount"); } catch (InvoiceApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.INVOICE_ITEM_ADJUSTMENT_AMOUNT_SHOULD_BE_POSITIVE.getCode()); } }
@Test(groups = "slow") public void testRefundWithNoAdjustments() throws Exception { // Although we don't adjust the invoice, the invoicing system sends an event because invoice balance changes and overdue system-- in particular-- needs to know about it. refundPaymentAndCheckForCompletion(account, payment, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT); refundChecker.checkRefund(payment.getId(), callContext, new ExpectedRefundCheck(payment.getId(), false, new BigDecimal("233.82"), Currency.USD, initialCreationDate.toLocalDate())); final Invoice invoiceRefreshed = invoiceUserApi.getInvoice(invoice.getId(), callContext); assertTrue(invoiceRefreshed.getBalance().compareTo(new BigDecimal("233.82")) == 0); final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(account.getId(), callContext); assertTrue(accountBalance.compareTo(new BigDecimal("233.82")) == 0); }
private void verifyExternalChargeOnNewInvoice(final BigDecimal initialAccountBalance, @Nullable final UUID bundleId, final BigDecimal externalChargeAmount, final InvoiceItem externalChargeInvoiceItem) throws InvoiceApiException { Assert.assertNotNull(externalChargeInvoiceItem.getInvoiceId()); Assert.assertNotEquals(externalChargeInvoiceItem.getInvoiceId(), invoiceId); Assert.assertEquals(externalChargeInvoiceItem.getBundleId(), bundleId); Assert.assertEquals(externalChargeInvoiceItem.getInvoiceItemType(), InvoiceItemType.EXTERNAL_CHARGE); Assert.assertEquals(externalChargeInvoiceItem.getAccountId(), accountId); Assert.assertEquals(externalChargeInvoiceItem.getAmount().compareTo(externalChargeAmount), 0); Assert.assertEquals(externalChargeInvoiceItem.getCurrency(), accountCurrency); Assert.assertNull(externalChargeInvoiceItem.getLinkedItemId()); // Verify the adjusted invoice balance final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(externalChargeInvoiceItem.getInvoiceId(), callContext).getBalance(); Assert.assertEquals(adjustedInvoiceBalance.compareTo(externalChargeAmount), 0); // Verify the adjusted account balance final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId, callContext); Assert.assertEquals(adjustedAccountBalance, initialAccountBalance.add(externalChargeAmount)); }
@Test(groups = "slow", description = "Verify invoice/account balance with DRAFT invoice. Verify that invoice/account balance are ZERO in DRAFT mode but becomes visible after it hasa been COMMITTED." ) public void testDraftInvoiceWithAccountCredit() throws Exception { // Add credit on the account invoiceUserApi.insertCredit(accountId, BigDecimal.TEN, null, accountCurrency, true, null, null, null, callContext); // Create new invoice with one charge and expect account credit to be used final List<InvoiceItem> items = invoiceUserApi.insertExternalCharges(accountId, clock.getUTCToday(), ImmutableList.<InvoiceItem>of(new ExternalChargeInvoiceItem(UUID.randomUUID(), clock.getUTCNow(), null, accountId, null, null, null, null, new BigDecimal("4.0"), accountCurrency, null)), false, null, callContext); assertEquals(items.size(), 1); final UUID invoiceId = items.get(0).getInvoiceId(); final Invoice invoice1 = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoice1.getStatus(), InvoiceStatus.DRAFT); // Verify CBA was *NOT* applied against DRAFT invoice assertEquals(invoice1.getInvoiceItems().size(), 1); // And balance is ZERO because DRAFT mode assertEquals(invoice1.getBalance().compareTo(BigDecimal.ZERO), 0); // Verify credit is not applied against migration invoice final BigDecimal accountBalance0 = invoiceUserApi.getAccountBalance(accountId, callContext); assertEquals(accountBalance0.compareTo(new BigDecimal("-10.0")), 0); final BigDecimal accountCBA0 = invoiceUserApi.getAccountCBA(accountId, callContext); assertEquals(accountCBA0.compareTo(BigDecimal.TEN), 0); invoiceUserApi.commitInvoice(invoiceId, callContext); final Invoice invoice2 = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoice2.getStatus(), InvoiceStatus.COMMITTED); // Verify this time credit was applied against COMMITTED invoice assertEquals(invoice2.getBalance().compareTo(BigDecimal.ZERO), 0); final BigDecimal accountBalance1 = invoiceUserApi.getAccountBalance(accountId, callContext); assertEquals(accountBalance1.compareTo(new BigDecimal("-6.0")), 0); final BigDecimal accountCBA1 = invoiceUserApi.getAccountCBA(accountId, callContext); assertEquals(accountCBA1.compareTo(new BigDecimal("6.0")), 0); }
@Test(groups = "slow") public void testVoidInvoiceThatIsPaid() throws Exception { InternalCallContext context = internalCallContextFactory.createInternalCallContext(accountId, callContext); // 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); // create payment final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoiceId, new DateTime(), invoiceBalance, Currency.USD, Currency.USD, null, true); invoiceUtil.createPayment(payment, context); // try to void invoice, it should fail try { invoiceUserApi.voidInvoice(invoiceId, callContext); Assert.fail("Should fail to void invoice that is already paid"); } catch (final InvoiceApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.CAN_NOT_VOID_INVOICE_THAT_IS_PAID.getCode()); } } }
@Test(groups = "slow", expectedExceptions = InvoiceApiException.class, expectedExceptionsMessageRegExp = ".*it is already in COMMITTED status") public void testAdjustCommittedInvoice() 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 InvoiceItem creditInvoiceItem = invoiceUserApi.insertCreditForInvoice(accountId, invoiceId, invoiceBalance, clock.getUTCToday(), accountCurrency, "some description", null, null, callContext); Assert.assertEquals(creditInvoiceItem.getInvoiceId(), invoiceId); Assert.assertEquals(creditInvoiceItem.getInvoiceItemType(), InvoiceItemType.CREDIT_ADJ); Assert.assertEquals(creditInvoiceItem.getAccountId(), accountId); Assert.assertEquals(creditInvoiceItem.getAmount().compareTo(invoiceBalance.negate()), 0); Assert.assertEquals(creditInvoiceItem.getCurrency(), accountCurrency); Assert.assertEquals(creditInvoiceItem.getDescription(), "some description"); Assert.assertNull(creditInvoiceItem.getLinkedItemId()); // Verify the adjusted invoice balance final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(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); }
final Invoice invoice0 = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoice0.getBalance().compareTo(BigDecimal.TEN), 0); final BigDecimal accountBalance0 = invoiceUserApi.getAccountBalance(accountId, callContext); final Invoice invoice1 = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoice1.getBalance().compareTo(BigDecimal.ZERO), 0); final Invoice invoice2 = invoiceUserApi.getInvoice(invoiceId, callContext); assertEquals(invoice2.getBalance().compareTo(BigDecimal.ZERO), 0); assertEquals(invoice2.getInvoiceItems().size(), 1);
@Test(groups = "slow") public void testAdjustFullInvoiceItem() throws Exception { final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId, callContext).getInvoiceItems().get(0); // Verify we picked a non zero item Assert.assertEquals(invoiceItem.getAmount().compareTo(BigDecimal.ZERO), 1); // 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 InvoiceItem adjInvoiceItem = invoiceUserApi.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItem.getId(), clock.getUTCToday(), null, null, null, callContext); Assert.assertEquals(adjInvoiceItem.getInvoiceId(), invoiceId); Assert.assertEquals(adjInvoiceItem.getInvoiceItemType(), InvoiceItemType.ITEM_ADJ); Assert.assertEquals(adjInvoiceItem.getAccountId(), accountId); Assert.assertEquals(adjInvoiceItem.getAmount(), invoiceItem.getAmount().negate()); Assert.assertEquals(adjInvoiceItem.getCurrency(), accountCurrency); Assert.assertEquals(adjInvoiceItem.getLinkedItemId(), invoiceItem.getId()); // Verify the adjusted invoice balance final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance(); verifyAdjustedInvoiceBalance(invoiceBalance, invoiceItem.getAmount(), invoiceItem.getCurrency(), adjustedInvoiceBalance); // Verify the adjusted account balance final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId, callContext); Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance); // Verify idempotency Assert.assertNull(invoiceUserApi.insertInvoiceItemAdjustment(accountId, invoiceId, invoiceItem.getId(), clock.getUTCToday(), null, null, null, callContext)); }
final UUID invoiceId = invoiceUtil.generateRegularInvoice(account, fixedPrice, recurringPrice, null, callContext); final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId, callContext).getInvoiceItems().get(0); final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance(); Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1); final BigDecimal adjustedInvoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance(); verifyAdjustedInvoiceBalance(invoiceBalance, adjAmount, accountCurrency, adjustedInvoiceBalance);
@Test(groups = "slow") public void testCommitInvoice() throws Exception { final BigDecimal invoiceBalance = invoiceUserApi.getInvoice(invoiceId, callContext).getBalance(); Assert.assertEquals(invoiceBalance.compareTo(BigDecimal.ZERO), 1); Invoice creditInvoice = invoiceUserApi.getInvoice(invoiceId, callContext); Assert.assertEquals(creditInvoice.getStatus(), InvoiceStatus.DRAFT); Assert.assertEquals(creditInvoiceItem.getInvoiceId(), creditInvoice.getId()); creditInvoice = invoiceUserApi.getInvoice(invoiceId, callContext); Assert.assertEquals(creditInvoice.getStatus(), InvoiceStatus.COMMITTED);
final Invoice unpaidInvoice = invoiceUserApi.getInvoice(unpaidInvoiceId, callContext); assertTrue(unpaidInvoice.getBalance().compareTo(new BigDecimal("249.95")) == 0); assertTrue(accountBalance2.compareTo(new BigDecimal("-50.05")) == 0); final Invoice unpaidInvoice2 = invoiceUserApi.getInvoice(unpaidInvoiceId, callContext); assertTrue(unpaidInvoice2.getBalance().compareTo(BigDecimal.ZERO) == 0);