killbill-uncached

Details

diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CustomFieldJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CustomFieldJson.java
new file mode 100644
index 0000000..cb9e36b
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CustomFieldJson.java
@@ -0,0 +1,51 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.jaxrs.json;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+
+import com.ning.billing.util.customfield.CustomField;
+
+public class CustomFieldJson {
+
+    private final String name;
+    private final String value;
+    
+    public CustomFieldJson() {
+        this.name = null;
+        this.value = null;
+    }
+    
+    @JsonCreator
+    public CustomFieldJson(String name, String value) {
+        super();
+        this.name = name;
+        this.value = value;
+    }
+    
+    public CustomFieldJson(CustomField input) {
+        this.name = input.getName();
+        this.value = input.getValue();
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
index 30264d7..1a33a04 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
@@ -23,6 +23,8 @@ import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonView;
 import org.joda.time.DateTime;
 
+import com.ning.billing.invoice.api.Invoice;
+
 public class InvoiceJson {
 
     @JsonView(BundleTimelineViews.Base.class)
@@ -40,6 +42,15 @@ public class InvoiceJson {
     @JsonView(BundleTimelineViews.Base.class)
     private final BigDecimal balance;
 
+    
+    public InvoiceJson() {
+        this.amount = null;
+        this.invoiceId = null;
+        this.invoiceDate = null;
+        this.invoiceNumber = null;
+        this.balance = null;
+    }
+    
     @JsonCreator
     public InvoiceJson(@JsonProperty("amount") BigDecimal amount,
             @JsonProperty("invoice_id") String invoiceId,
@@ -54,6 +65,14 @@ public class InvoiceJson {
         this.balance = balance;
     }
 
+    public InvoiceJson(Invoice input) {
+        this.amount = input.getTotalAmount();
+        this.invoiceId = input.getId().toString();
+        this.invoiceDate = input.getInvoiceDate();
+        this.invoiceNumber = String.valueOf(input.getInvoiceNumber());
+        this.balance = input.getBalance();
+    }
+    
     public BigDecimal getAmount() {
         return amount;
     }
@@ -73,4 +92,56 @@ public class InvoiceJson {
     public BigDecimal getBalance() {
         return balance;
     }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((amount == null) ? 0 : amount.hashCode());
+        result = prime * result + ((balance == null) ? 0 : balance.hashCode());
+        result = prime * result
+                + ((invoiceDate == null) ? 0 : invoiceDate.hashCode());
+        result = prime * result
+                + ((invoiceId == null) ? 0 : invoiceId.hashCode());
+        result = prime * result
+                + ((invoiceNumber == null) ? 0 : invoiceNumber.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        InvoiceJson other = (InvoiceJson) obj;
+        if (amount == null) {
+            if (other.amount != null)
+                return false;
+        } else if (!amount.equals(other.amount))
+            return false;
+        if (balance == null) {
+            if (other.balance != null)
+                return false;
+        } else if (!balance.equals(other.balance))
+            return false;
+        if (invoiceDate == null) {
+            if (other.invoiceDate != null)
+                return false;
+        } else if (!invoiceDate.equals(other.invoiceDate))
+            return false;
+        if (invoiceId == null) {
+            if (other.invoiceId != null)
+                return false;
+        } else if (!invoiceId.equals(other.invoiceId))
+            return false;
+        if (invoiceNumber == null) {
+            if (other.invoiceNumber != null)
+                return false;
+        } else if (!invoiceNumber.equals(other.invoiceNumber))
+            return false;
+        return true;
+    }
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index ad0ce21..9061eac 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -18,7 +18,7 @@ package com.ning.billing.jaxrs.resources;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
-import java.net.URI;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -38,13 +38,11 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.UriBuilder;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
-import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.inject.Inject;
@@ -64,6 +62,7 @@ import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.AccountTimelineJson;
 import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.CustomFieldJson;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
 import com.ning.billing.jaxrs.util.TagHelper;
@@ -72,6 +71,8 @@ import com.ning.billing.payment.api.PaymentAttempt;
 import com.ning.billing.payment.api.PaymentInfoEvent;
 import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.customfield.StringCustomField;
 import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.TagDefinition;
 
@@ -274,6 +275,8 @@ public class AccountResource implements BaseJaxrsResource {
     }
     
     
+    /****************************      TAGS     ******************************/
+    
     @GET
     @Path(BaseJaxrsResource.TAGS + "/{accountId:" + UUID_PATTERN + "}")
     @Produces(APPLICATION_JSON)
@@ -367,4 +370,77 @@ public class AccountResource implements BaseJaxrsResource {
             return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
         }
     }
+    
+    /************************   CUSTOM FIELDS   ******************************/
+    
+    @GET
+    @Path(BaseJaxrsResource.CUSTOM_FIELDS + "/{accountId:" + UUID_PATTERN + "}")
+    @Produces(APPLICATION_JSON)
+    public Response getAccountCustomFields(@PathParam("accountId") String accountId) {
+        try {
+            Account account = accountApi.getAccountById(UUID.fromString(accountId));
+            List<CustomField> fields = account.getFieldList();
+            List<CustomFieldJson> result = new LinkedList<CustomFieldJson>();
+            for (CustomField cur : fields) {
+                result.add(new CustomFieldJson(cur));
+            }
+            return Response.status(Status.OK).entity(result).build();
+        } catch (AccountApiException e) {
+            return Response.status(Status.NO_CONTENT).build();
+        }
+    }
+    
+    
+    @POST
+    @Path(BaseJaxrsResource.CUSTOM_FIELDS + "/{accountId:" + UUID_PATTERN + "}")    
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response createCustomField(@PathParam("accountId") final String accountId,
+            List<CustomFieldJson> customFields,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+
+        try {
+            
+            Account account = accountApi.getAccountById(UUID.fromString(accountId));
+            LinkedList<CustomField> input = new LinkedList<CustomField>();
+            for (CustomFieldJson cur : customFields) {
+                input.add(new StringCustomField(cur.getName(), cur.getValue()));
+            }
+            account.saveFields(input, context.createContext(createdBy, reason, comment));
+            Response response = uriBuilder.buildResponse(AccountResource.class, "getAccountCustomFields", account.getId());            
+            return response;
+        } catch (AccountApiException e) {
+            return Response.status(Status.NO_CONTENT).build();
+        } catch (IllegalArgumentException e) {
+            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+        } catch (NullPointerException e) {
+            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+        }
+    }
+    
+    @DELETE
+    @Path(BaseJaxrsResource.CUSTOM_FIELDS +  "/{accountId:" + UUID_PATTERN + "}")    
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteCustomFields(@PathParam("accountId") final String accountId,
+            @QueryParam(QUERY_CUSTOM_FIELDS) final String cutomFieldList,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+
+        try {
+            Account account = accountApi.getAccountById(UUID.fromString(accountId));
+            // STEPH missing API to delete custom fields
+            return Response.status(Status.OK).build();
+        } catch (AccountApiException e) {
+            return Response.status(Status.NO_CONTENT).build();
+        } catch (IllegalArgumentException e) {
+            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+        } catch (NullPointerException e) {
+            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+        }
+    }
+    
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
index f90a49c..2a9e2ee 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
@@ -45,8 +45,12 @@ public interface BaseJaxrsResource {
 	public static final String QUERY_REQUESTED_DT = "requested_date";
 	public static final String QUERY_CALL_COMPLETION = "call_completion";
 	public static final String QUERY_CALL_TIMEOUT = "call_timeout_sec";    
+	public static final String QUERY_DRY_RUN = "dry_run";      
+	public static final String QUERY_TARGET_DATE = "target_date";          
+	public static final String QUERY_ACCOUNT_ID = "account_id";           	
 	
-	public static final String QUERY_TAGS = "taglist";    
+	public static final String QUERY_TAGS = "tag_list";    
+	public static final String QUERY_CUSTOM_FIELDS = "custom_field_list";    	
 	
 	public static final String ACCOUNTS = "accounts";  
     public static final String ACCOUNTS_PATH = PREFIX + "/" + ACCOUNTS;
@@ -60,5 +64,10 @@ public interface BaseJaxrsResource {
     public static final String TAG_DEFINITIONS = "tag_definitions";     
     public static final String TAG_DEFINITIONS_PATH = PREFIX + "/" + TAG_DEFINITIONS;
 
+    public static final String INVOICES = "invoices";     
+    public static final String INVOICES_PATH = PREFIX + "/" + INVOICES;
+
+    
     public static final String TAGS = "tags";
+    public static final String CUSTOM_FIELDS = "custom_fields";    
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
index e5a1c97..5cc35bd 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
@@ -18,8 +18,14 @@ package com.ning.billing.jaxrs.resources;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -29,34 +35,117 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.InvoiceJson;
+import com.ning.billing.jaxrs.util.Context;
+import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
+import com.ning.billing.jaxrs.util.TagHelper;
+import com.ning.billing.payment.api.PaymentApi;
+import com.ning.billing.util.api.TagUserApi;
+
 
 
+@Path(BaseJaxrsResource.INVOICES_PATH)
+public class InvoiceResource implements BaseJaxrsResource {
 
-@Path("/1.0/invoice")
-public class InvoiceResource {
 
+    private static final Logger log = LoggerFactory.getLogger(AccountResource.class);
 
+    private final DateTimeFormatter DATE_TIME_FORMATTER = ISODateTimeFormat.dateTime();
+    
+    private final AccountUserApi accountApi;
+    private final InvoiceUserApi invoiceApi;
+    private final Context context;
+    private final JaxrsUriBuilder uriBuilder;
+    
+    @Inject
+    public InvoiceResource(final AccountUserApi accountApi,
+            final InvoiceUserApi invoiceApi,
+            final Context context,
+            final JaxrsUriBuilder uriBuilder) {
+        this.accountApi = accountApi;
+        this.invoiceApi = invoiceApi;
+        this.context = context;
+        this.uriBuilder = uriBuilder;
+    }
+    
     @GET
     @Produces(APPLICATION_JSON)
-    public Response getInvoices(@QueryParam("accountId") String accountId) {
-        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+    public Response getInvoices(@QueryParam(QUERY_ACCOUNT_ID) final String accountId) {
+        try {
+            
+            Preconditions.checkNotNull(accountId, "% query parameter must be specified", QUERY_ACCOUNT_ID);
+            accountApi.getAccountById(UUID.fromString(accountId));
+            List<Invoice> invoices = invoiceApi.getInvoicesByAccount(UUID.fromString(accountId));
+            List<InvoiceJson> result = new LinkedList<InvoiceJson>();
+            for (Invoice cur : invoices) {
+                result.add(new InvoiceJson(cur));
+            }
+            return Response.status(Status.OK).entity(result).build();
+        } catch (AccountApiException e) {
+            return Response.status(Status.NO_CONTENT).build();            
+        } catch (NullPointerException e) {
+            return Response.status(Status.BAD_REQUEST).build();            
+        }
     }
 
     @GET
     @Path("/{invoiceId:\\w+-\\w+-\\w+-\\w+-\\w+}")
     @Produces(APPLICATION_JSON)
-    public Response getInvoice(@PathParam("invoiceId") String accountId) {
-        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+    public Response getInvoice(@PathParam("invoiceId") String invoiceId) {
+        Invoice invoice = invoiceApi.getInvoice(UUID.fromString(invoiceId));
+        InvoiceJson json = new InvoiceJson(invoice);
+        return Response.status(Status.OK).entity(json).build();
     }
 
     @POST
-    @Path("/{accountId:\\w+-\\w+-\\w+-\\w+-\\w+}")
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
-    public Response createFutureInvoice(InvoiceJson invoice,
-            @PathParam("accountId") String accountId,
-            @QueryParam("targetDate") String targetDate) {
-        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+    public Response createFutureInvoice(final InvoiceJson invoice,
+            @QueryParam(QUERY_ACCOUNT_ID) final String accountId,
+            @QueryParam(QUERY_TARGET_DATE) final String targetDate,
+            @QueryParam(QUERY_DRY_RUN) @DefaultValue("false") final Boolean dryRun,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+
+        try {
+            
+            Preconditions.checkNotNull(accountId, "% needs to be specified", QUERY_ACCOUNT_ID);
+            Preconditions.checkNotNull(targetDate, "% needs to be specified", QUERY_TARGET_DATE);
+            
+            DateTime inputDate = (targetDate != null) ? DATE_TIME_FORMATTER.parseDateTime(targetDate) : null;        
+            
+            accountApi.getAccountById(UUID.fromString(accountId));
+            Invoice generatedInvoice = invoiceApi.triggerInvoiceGeneration(UUID.fromString(accountId), inputDate, dryRun.booleanValue(),
+                    context.createContext(createdBy, reason, comment));
+            if (dryRun) {
+                return Response.status(Status.OK).entity(new InvoiceJson(generatedInvoice)).build();
+            } else {
+               return uriBuilder.buildResponse(InvoiceResource.class, "getInvoice", generatedInvoice.getId());
+            }
+        } catch (AccountApiException e) {
+            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();  
+        } catch (InvoiceApiException e) {
+            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();  
+        } catch (NullPointerException e) {
+            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();            
+        }
     }
 }
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
index 7eb6efa..15d4018 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -20,6 +20,8 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 
@@ -39,6 +41,7 @@ import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.AccountTimelineJson;
 import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.CustomFieldJson;
 import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.json.TagDefinitionJson;
 import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
@@ -142,7 +145,7 @@ public class TestAccount extends TestJaxrsBase {
         Assert.assertEquals(objFromJson.getBundles().get(0).getSubscriptions().get(0).getEvents().size(), 2);        
  	}
 
-	@Test(groups="slow", enabled=true)
+	@Test(groups="slow", enabled=false)
 	public void testAccountWithTags() throws Exception {
 	    //Create Tag definition
 	    TagDefinitionJson input = new TagDefinitionJson("yoyo", "nothing more to say");
@@ -172,6 +175,28 @@ public class TestAccount extends TestJaxrsBase {
         */
 
 	}
+	
+    @Test(groups="slow", enabled=false)
+	public void testAccountWithCustomFields() throws Exception {
+        
+        AccountJson accountJson = createAccount("carafe", "shdwhwgaz", "carafe@yahoo.com");
+        assertNotNull(accountJson);
+        
+        List<CustomFieldJson> customFields =  new LinkedList<CustomFieldJson>();
+        customFields.add(new CustomFieldJson("1", "value1"));
+        customFields.add(new CustomFieldJson("2", "value2"));
+        customFields.add(new CustomFieldJson("3", "value3"));  
+        String baseJson = mapper.writeValueAsString(customFields);
+
+        String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + BaseJaxrsResource.CUSTOM_FIELDS + "/" + accountJson.getAcountId() ;
+        Response response = doPost(uri,baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+        String location = response.getHeader("Location");
+        Assert.assertNotNull(location);
 
-
+        // Retrieves by Id based on Location returned
+        response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        
+	}
 }
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
new file mode 100644
index 0000000..3db547f
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
@@ -0,0 +1,126 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.jaxrs;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.codehaus.jackson.type.TypeReference;
+import org.joda.time.DateTime;
+import org.joda.time.Interval;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.InvoiceJson;
+import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
+import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+import com.ning.http.client.Response;
+
+public class TestInvoice extends TestJaxrsBase  {
+
+    private final DateTimeFormatter DATE_TIME_FORMATTER = ISODateTimeFormat.dateTime();
+    
+    private static final Logger log = LoggerFactory.getLogger(TestInvoice.class);
+
+
+    @Test(groups="slow", enabled=true)
+    public void testInvoiceOk() throws Exception {
+        
+        DateTime initialDate = new DateTime(2012, 4, 25, 0, 3, 42, 0);
+        clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+        
+        
+        AccountJson accountJson = createAccount("poupou", "qhddffrwe", "poupou@yahoo.com");
+        assertNotNull(accountJson);
+        
+        BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAcountId(), "9967599");
+        assertNotNull(bundleJson);
+        
+        SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), "Shotgun", ProductCategory.BASE.toString(), BillingPeriod.MONTHLY.toString(), true);
+        assertNotNull(subscriptionJson);
+        
+        // MOVE AFTER TRIAL
+        Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(3).plusDays(1));
+        clock.addDeltaFromReality(it.toDurationMillis());
+
+        crappyWaitForLackOfProperSynchonization();
+        
+        String uri = BaseJaxrsResource.INVOICES_PATH;
+        Map<String, String> queryParams = new HashMap<String, String>();
+        queryParams.put(BaseJaxrsResource.QUERY_ACCOUNT_ID, accountJson.getAcountId());
+        
+        Response response = doGet(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        String baseJson = response.getResponseBody();
+        List<InvoiceJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<InvoiceJson>>() {});
+        assertNotNull(objFromJson);
+        log.info(baseJson);
+        assertEquals(objFromJson.size(), 4);
+        
+        // Check we can retrieve an individual invoice
+        uri = BaseJaxrsResource.INVOICES_PATH + "/" + objFromJson.get(0).getInvoiceId();
+        response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());        
+        baseJson = response.getResponseBody();
+        InvoiceJson firstInvoiceJson = mapper.readValue(baseJson, InvoiceJson.class);
+        assertNotNull(objFromJson);    
+        assertEquals(firstInvoiceJson, objFromJson.get(0));
+        
+        // Then create a dryRun Invoice
+        DateTime futureDate = clock.getUTCNow().plusMonths(1).plusDays(3);
+        uri = BaseJaxrsResource.INVOICES_PATH;
+        queryParams.put(BaseJaxrsResource.QUERY_TARGET_DATE, futureDate.toString());
+        queryParams.put(BaseJaxrsResource.QUERY_DRY_RUN, "true");        
+        response = doPost(uri, null, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode()); 
+        baseJson = response.getResponseBody();
+        InvoiceJson futureInvoice = mapper.readValue(baseJson, InvoiceJson.class);
+        assertNotNull(futureInvoice);    
+        log.info(baseJson);
+        
+        // The one more time with no DryRun
+        queryParams.remove(BaseJaxrsResource.QUERY_DRY_RUN);
+        response = doPost(uri, null, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+        
+        String location = response.getHeader("Location");
+        Assert.assertNotNull(location);
+        
+        // Check again # invoices, should be 5 this time
+        uri = BaseJaxrsResource.INVOICES_PATH;
+        response = doGet(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+        assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        baseJson = response.getResponseBody();
+        objFromJson = mapper.readValue(baseJson, new TypeReference<List<InvoiceJson>>() {});
+        assertNotNull(objFromJson);
+        log.info(baseJson);
+        assertEquals(objFromJson.size(), 5);
+    }
+}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index e697f62..4858552 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -88,7 +88,7 @@ public class TestJaxrsBase {
 
     private final static String PLUGIN_NAME = "noop";
 
-    protected static final int DEFAULT_HTTP_TIMEOUT_SEC =  1000; /* 5;  STEPH */
+    protected static final int DEFAULT_HTTP_TIMEOUT_SEC = 5;
 
     protected static final Map<String, String> DEFAULT_EMPTY_QUERY = new HashMap<String, String>();