killbill-memoizeit

Merge pull request #838 from wwjbatista/work-for-release-0.19.x Create

1/19/2018 1:46:18 PM

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceItemResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceItemResource.java
new file mode 100644
index 0000000..7235277
--- /dev/null
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceItemResource.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.jaxrs.resources;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.killbill.billing.ObjectType;
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.account.api.AccountApiException;
+import org.killbill.billing.account.api.AccountUserApi;
+import org.killbill.billing.entitlement.api.SubscriptionApi;
+import org.killbill.billing.jaxrs.json.CustomFieldJson;
+import org.killbill.billing.jaxrs.json.TagJson;
+import org.killbill.billing.jaxrs.util.Context;
+import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
+import org.killbill.billing.payment.api.PaymentApi;
+import org.killbill.billing.util.api.AuditUserApi;
+import org.killbill.billing.util.api.CustomFieldApiException;
+import org.killbill.billing.util.api.CustomFieldUserApi;
+import org.killbill.billing.util.api.TagApiException;
+import org.killbill.billing.util.api.TagDefinitionApiException;
+import org.killbill.billing.util.api.TagUserApi;
+import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.clock.Clock;
+import org.killbill.commons.metrics.TimedResource;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+@Path(JaxrsResource.INVOICES_ITEMS_PATH)
+@Api(value = JaxrsResource.INVOICES_ITEMS_PATH, description = "Operations on invoice items")
+public class InvoiceItemResource extends JaxRsResourceBase {
+    private static final String ID_PARAM_NAME = "invoiceItemId";
+
+    @Inject
+    public InvoiceItemResource(final JaxrsUriBuilder uriBuilder, final TagUserApi tagUserApi, final CustomFieldUserApi customFieldUserApi,
+                               final AuditUserApi auditUserApi, final AccountUserApi accountUserApi, final PaymentApi paymentApi,
+                               final SubscriptionApi subscriptionApi, final Clock clock, final Context context) {
+        super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, accountUserApi, paymentApi, subscriptionApi, clock, context);
+    }
+
+    @TimedResource
+    @GET
+    @Path("/{invoiceItemId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Retrieve invoice item custom fields", response = CustomFieldJson.class, responseContainer = "List")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice item id supplied")})
+    public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+                                    @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+                                    @javax.ws.rs.core.Context final HttpServletRequest request) {
+        return super.getCustomFields(UUID.fromString(id), auditMode, context.createTenantContextNoAccountId(request));
+    }
+
+    @TimedResource
+    @POST
+    @Path("/{invoiceItemId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Add custom fields to invoice item")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice item id supplied")})
+    public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+                                       final List<CustomFieldJson> customFields,
+                                       @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 CustomFieldApiException {
+        return super.createCustomFields(UUID.fromString(id), customFields,
+                                        context.createCallContextNoAccountId(createdBy, reason, comment, request), uriInfo, request);
+    }
+
+
+    @TimedResource
+    @PUT
+    @Path("/{invoiceItemId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Modify custom fields to invoice item")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice item id supplied")})
+    public Response modifyCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+                                       final List<CustomFieldJson> customFields,
+                                       @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) throws CustomFieldApiException {
+        return super.modifyCustomFields(UUID.fromString(id), customFields,
+                                        context.createCallContextNoAccountId(createdBy, reason, comment, request));
+    }
+
+
+    @TimedResource
+    @DELETE
+    @Path("/{invoiceItemId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Remove custom fields from invoice item")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice item id supplied")})
+    public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+                                       @QueryParam(QUERY_CUSTOM_FIELDS) final String customFieldList,
+                                       @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) throws CustomFieldApiException {
+        return super.deleteCustomFields(UUID.fromString(id), customFieldList,
+                                        context.createCallContextNoAccountId(createdBy, reason, comment, request));
+    }
+
+    @TimedResource
+    @GET
+    @Path("/{invoiceItemId:" + UUID_PATTERN + "}/" + TAGS)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Retrieve invoice item tags", response = TagJson.class, responseContainer = "List")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice item id supplied"),
+                           @ApiResponse(code = 404, message = "Account not found")})
+    public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+                            @QueryParam(QUERY_ACCOUNT_ID) final String accountIdStr,
+                            @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+                            @QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
+                            @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, AccountApiException {
+        final UUID accountId = UUID.fromString(accountIdStr);
+        final TenantContext tenantContext = context.createTenantContextWithAccountId(accountId, request);
+        final Account account = accountUserApi.getAccountById(accountId, tenantContext);
+
+        return super.getTags(account.getId(), UUID.fromString(id), auditMode, includedDeleted, tenantContext);
+    }
+
+    @TimedResource
+    @POST
+    @Path("/{invoiceItemId:" + UUID_PATTERN + "}/" + TAGS)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Add tags to invoice item")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice item id supplied")})
+    public Response createTags(@PathParam(ID_PARAM_NAME) final String id,
+                               @QueryParam(QUERY_TAGS) final String tagList,
+                               @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 UriInfo uriInfo,
+                               @javax.ws.rs.core.Context final HttpServletRequest request) throws TagApiException {
+        return super.createTags(UUID.fromString(id), tagList, uriInfo,
+                                context.createCallContextNoAccountId(createdBy, reason, comment, request), request);
+    }
+
+    @TimedResource
+    @DELETE
+    @Path("/{invoiceItemId:" + UUID_PATTERN + "}/" + TAGS)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Remove tags from invoice item")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid invoice item id supplied")})
+    public Response deleteTags(@PathParam(ID_PARAM_NAME) final String id,
+                               @QueryParam(QUERY_TAGS) final String tagList,
+                               @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) throws TagApiException {
+        return super.deleteTags(UUID.fromString(id), tagList,
+                                context.createCallContextNoAccountId(createdBy, reason, comment, request));
+    }
+
+    @Override
+    protected ObjectType getObjectType() {
+        return ObjectType.INVOICE_ITEM;
+    }
+}
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 7923488..8a27ee3 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
@@ -188,6 +188,9 @@ public interface JaxrsResource {
     public static final String INVOICES = "invoices";
     public static final String INVOICES_PATH = PREFIX + "/" + INVOICES;
 
+    public static final String INVOICE_ITEMS = "invoiceItems";
+    public static final String INVOICES_ITEMS_PATH = PREFIX + "/" + INVOICE_ITEMS;
+
     public static final String CHARGES = "charges";
     public static final String CHARGES_PATH = PREFIX + "/" + INVOICES + "/" + CHARGES;
 
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java
index 92668d3..b182e9e 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java
@@ -34,6 +34,7 @@ import org.killbill.billing.jaxrs.resources.CatalogResource;
 import org.killbill.billing.jaxrs.resources.CreditResource;
 import org.killbill.billing.jaxrs.resources.CustomFieldResource;
 import org.killbill.billing.jaxrs.resources.ExportResource;
+import org.killbill.billing.jaxrs.resources.InvoiceItemResource;
 import org.killbill.billing.jaxrs.resources.InvoicePaymentResource;
 import org.killbill.billing.jaxrs.resources.InvoiceResource;
 import org.killbill.billing.jaxrs.resources.NodesInfoResource;
@@ -208,6 +209,7 @@ public class KillbillServerModule extends KillbillPlatformModule {
         bind(TenantResource.class).asEagerSingleton();
         bind(TransactionResource.class).asEagerSingleton();
         bind(UsageResource.class).asEagerSingleton();
+        bind(InvoiceItemResource.class).asEagerSingleton();
 
         bind(KillbillEventHandler.class).asEagerSingleton();
     }
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java
index cd4b396..ffdbd07 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/KillbillClient.java
@@ -151,7 +151,7 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         input.setBillingPeriod(billingPeriod);
         input.setPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-        return killBillClient.createSubscription(input, null, waitCompletion ? DEFAULT_WAIT_COMPLETION_TIMEOUT_SEC : -1, requestOptions);
+        return killBillClient.createSubscription(input, null, null,  waitCompletion ? DEFAULT_WAIT_COMPLETION_TIMEOUT_SEC : -1, false, requestOptions);
     }
 
     protected Account createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice() throws Exception {
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoiceItem.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoiceItem.java
new file mode 100644
index 0000000..a846d1b
--- /dev/null
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoiceItem.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.jaxrs;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.killbill.billing.GuicyKillbillTestSuite;
+import org.killbill.billing.ObjectType;
+import org.killbill.billing.client.RequestOptions;
+import org.killbill.billing.client.model.Account;
+import org.killbill.billing.client.model.AuditLog;
+import org.killbill.billing.client.model.CustomField;
+import org.killbill.billing.client.model.InvoiceItem;
+import org.killbill.billing.client.model.Invoices;
+import org.killbill.billing.client.model.Tag;
+import org.killbill.billing.client.model.TagDefinition;
+import org.killbill.billing.jaxrs.resources.JaxrsResource;
+import org.killbill.billing.util.api.AuditLevel;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multimap;
+
+public class TestInvoiceItem extends TestJaxrsBase {
+
+    @Test(groups = "slow", description = "Add tags to invoice item")
+    public void testTags() throws Exception {
+        final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
+        final Invoices invoicesJson = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
+
+        Assert.assertNotNull(invoicesJson);
+        Assert.assertEquals(invoicesJson.size(), 2);
+
+        final List<InvoiceItem> invoiceItems = invoicesJson.get(0).getItems();
+
+        Assert.assertNotNull(invoiceItems);
+
+        // Create tag definition
+        final TagDefinition input = new TagDefinition(null, false, "tagtest", "invoice item tag test", ImmutableList.<ObjectType>of(ObjectType.INVOICE_ITEM));
+
+        final TagDefinition objFromJson = killBillClient.createTagDefinition(input, requestOptions);
+        Assert.assertNotNull(objFromJson);
+        Assert.assertEquals(objFromJson.getName(), input.getName());
+        Assert.assertEquals(objFromJson.getDescription(), input.getDescription());
+
+        // Add a tag
+        final Multimap<String, String> followQueryParams = HashMultimap.create();
+        followQueryParams.put(JaxrsResource.QUERY_ACCOUNT_ID, accountJson.getAccountId().toString());
+        final RequestOptions followRequestOptions = requestOptions.extend().withQueryParamsForFollow(followQueryParams).build();
+        killBillClient.createInvoiceItemTag(invoiceItems.get(0).getInvoiceItemId(),objFromJson.getId(), followRequestOptions);
+
+        // Add account id to request
+        final Multimap<String, String> queryParams = HashMultimap.create();
+        queryParams.put(JaxrsResource.QUERY_ACCOUNT_ID, accountJson.getAccountId().toString());
+        final RequestOptions addedRequestOptions = requestOptions.extend().withQueryParams(queryParams).build();
+        
+        // Retrieves all tags
+        final List<Tag> tags1 = killBillClient.getInvoiceItemTags(invoiceItems.get(0).getInvoiceItemId(), AuditLevel.FULL, addedRequestOptions);
+        Assert.assertEquals(tags1.size(), 1);
+        Assert.assertEquals(tags1.get(0).getTagDefinitionId(), objFromJson.getId());
+
+        // Verify adding the same tag a second time doesn't do anything
+        killBillClient.createInvoiceItemTag(invoiceItems.get(0).getInvoiceItemId(), objFromJson.getId(), followRequestOptions);
+
+        // Retrieves all tags again
+        final List<Tag> tags2 = killBillClient.getInvoiceItemTags(invoiceItems.get(0).getInvoiceItemId(), AuditLevel.FULL, addedRequestOptions);
+        Assert.assertEquals(tags2, tags1);
+
+        // Verify audit logs
+        Assert.assertEquals(tags2.get(0).getAuditLogs().size(), 1);
+        final AuditLog auditLogJson = tags2.get(0).getAuditLogs().get(0);
+        Assert.assertEquals(auditLogJson.getChangeType(), "INSERT");
+        Assert.assertEquals(auditLogJson.getChangedBy(), createdBy);
+        Assert.assertEquals(auditLogJson.getReasonCode(), reason);
+        Assert.assertEquals(auditLogJson.getComments(), comment);
+        Assert.assertNotNull(auditLogJson.getChangeDate());
+        Assert.assertNotNull(auditLogJson.getUserToken());
+
+        // remove it
+        killBillClient.deleteInvoiceItemTag(invoiceItems.get(0).getInvoiceItemId(), objFromJson.getId(), requestOptions);
+        final List<Tag> tags3 = killBillClient.getInvoiceItemTags(invoiceItems.get(0).getInvoiceItemId(), AuditLevel.FULL, addedRequestOptions);
+        Assert.assertEquals(tags3.size(), 0);
+
+        killBillClient.deleteTagDefinition(objFromJson.getId(),requestOptions);
+        List<TagDefinition> objsFromJson = killBillClient.getTagDefinitions(requestOptions);
+        Assert.assertNotNull(objsFromJson);
+        Boolean isFound = false;
+        for (TagDefinition tagDefinition : objsFromJson){
+            isFound |= tagDefinition.getId().equals(objFromJson.getId());
+        }
+        Assert.assertFalse(isFound);
+    }
+
+    @Test(groups = "slow", description = "Add custom fields to invoice item")
+    public void testCustomFields() throws Exception {
+        final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
+        final Invoices invoicesJson = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
+
+        Assert.assertNotNull(invoicesJson);
+        Assert.assertEquals(invoicesJson.size(), 2);
+
+        final List<InvoiceItem> invoiceItems = invoicesJson.get(0).getItems();
+
+        Assert.assertNotNull(invoiceItems);
+
+        final Collection<CustomField> customFields = new LinkedList<CustomField>();
+        customFields.add(new CustomField(null, invoiceItems.get(0).getInvoiceItemId(), ObjectType.INVOICE_ITEM, "1", "value1", null));
+        customFields.add(new CustomField(null, invoiceItems.get(0).getInvoiceItemId(), ObjectType.INVOICE_ITEM, "2", "value2", null));
+        customFields.add(new CustomField(null, invoiceItems.get(0).getInvoiceItemId(), ObjectType.INVOICE_ITEM, "3", "value3", null));
+
+        killBillClient.createInvoiceItemCustomField(invoiceItems.get(0).getInvoiceItemId(), customFields, requestOptions);
+
+        final List<CustomField> invoiceItemCustomFields = killBillClient.getInvoiceItemCustomFields(invoiceItems.get(0).getInvoiceItemId(), requestOptions);
+        Assert.assertEquals(invoiceItemCustomFields.size(), 3);
+
+        // Delete all custom fields for account
+        killBillClient.deleteInvoiceItemCustomFields(invoiceItems.get(0).getInvoiceItemId(), requestOptions);
+
+        final List<CustomField> remainingCustomFields = killBillClient.getInvoiceItemCustomFields(invoiceItems.get(0).getInvoiceItemId(), requestOptions);
+        Assert.assertEquals(remainingCustomFields.size(), 0);
+    }
+}