diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
index 4d1ea22..1d0345b 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
@@ -32,7 +32,7 @@ import org.killbill.billing.util.config.catalog.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultFixed extends ValidatingConfig<StandaloneCatalog> implements Fixed {
-
+
@XmlAttribute(required = false)
private FixedType type = FixedType.ONE_TIME;
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/UsageJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/UsageJson.java
new file mode 100644
index 0000000..47661e6
--- /dev/null
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/UsageJson.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014 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.json;
+
+import java.math.BigDecimal;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.usage.api.RolledUpUsage;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class UsageJson {
+
+ private final String subscriptionId;
+ private final String unitType;
+ private final DateTime startTime;
+ private final DateTime endTime;
+ private final BigDecimal amount;
+
+ @JsonCreator
+ public UsageJson(@JsonProperty("subscriptionId") final String subscriptionId,
+ @JsonProperty("unitType") final String unitType,
+ @JsonProperty("startTime") final DateTime startTime,
+ @JsonProperty("endTime") final DateTime endTime,
+ @JsonProperty("amount") final BigDecimal amount) {
+ this.subscriptionId = subscriptionId;
+ this.unitType = unitType;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.amount = amount;
+ }
+
+ public UsageJson(final RolledUpUsage usage) {
+ this(usage.getSubscriptionId().toString(), usage.getUnitType(), usage.getStartTime(), usage.getEndTime(), usage.getAmount());
+ }
+
+ public String getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ public String getUnitType() {
+ return unitType;
+ }
+
+ public DateTime getStartTime() {
+ return startTime;
+ }
+
+ public DateTime getEndTime() {
+ return endTime;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof UsageJson)) {
+ return false;
+ }
+
+ final UsageJson usageJson = (UsageJson) o;
+
+ if (amount != null ? !amount.equals(usageJson.amount) : usageJson.amount != null) {
+ return false;
+ }
+ if (endTime != null ? !endTime.equals(usageJson.endTime) : usageJson.endTime != null) {
+ return false;
+ }
+ if (startTime != null ? !startTime.equals(usageJson.startTime) : usageJson.startTime != null) {
+ return false;
+ }
+ if (subscriptionId != null ? !subscriptionId.equals(usageJson.subscriptionId) : usageJson.subscriptionId != null) {
+ return false;
+ }
+ if (unitType != null ? !unitType.equals(usageJson.unitType) : usageJson.unitType != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = subscriptionId != null ? subscriptionId.hashCode() : 0;
+ result = 31 * result + (unitType != null ? unitType.hashCode() : 0);
+ result = 31 * result + (startTime != null ? startTime.hashCode() : 0);
+ result = 31 * result + (endTime != null ? endTime.hashCode() : 0);
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ return result;
+ }
+}
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 27e781a..70ccb3e 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
@@ -93,6 +93,9 @@ public interface JaxrsResource {
public static final String QUERY_PAY_ALL_UNPAID_INVOICES = "payAllUnpaidInvoices";
public static final String QUERY_PAY_INVOICE = "payInvoice";
+ public static final String QUERY_START_TIME = "startTime";
+ public static final String QUERY_END_TIME = "endTime";
+
public static final String QUERY_BUNDLE_TRANSFER_ADDON = "transferAddOn";
public static final String QUERY_BUNDLE_TRANSFER_CANCEL_IMM = "cancelImmediately";
@@ -165,6 +168,9 @@ public interface JaxrsResource {
public static final String TENANTS = "tenants";
public static final String TENANTS_PATH = PREFIX + "/" + TENANTS;
+ public static final String USAGES = "usages";
+ public static final String USAGES_PATH = PREFIX + "/" + USAGES;
+
public static final String EXPORT = "export";
public static final String EXPORT_PATH = PREFIX + "/" + EXPORT;
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/UsageResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/UsageResource.java
new file mode 100644
index 0000000..1d8d781
--- /dev/null
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/UsageResource.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2014 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.UUID;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+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;
+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.UriInfo;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.account.api.AccountUserApi;
+import org.killbill.billing.jaxrs.json.UsageJson;
+import org.killbill.billing.jaxrs.util.Context;
+import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
+import org.killbill.billing.usage.api.RolledUpUsage;
+import org.killbill.billing.usage.api.UsageUserApi;
+import org.killbill.billing.util.api.AuditUserApi;
+import org.killbill.billing.util.api.CustomFieldUserApi;
+import org.killbill.billing.util.api.TagUserApi;
+import org.killbill.billing.util.callcontext.CallContext;
+import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.clock.Clock;
+
+import com.google.inject.Singleton;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+@Singleton
+@Path(JaxrsResource.USAGES_PATH)
+public class UsageResource extends JaxRsResourceBase {
+
+ private final UsageUserApi usageUserApi;
+
+ @Inject
+ public UsageResource(final JaxrsUriBuilder uriBuilder,
+ final TagUserApi tagUserApi,
+ final CustomFieldUserApi customFieldUserApi,
+ final AuditUserApi auditUserApi,
+ final AccountUserApi accountUserApi,
+ final UsageUserApi usageUserApi,
+ final Clock clock,
+ final Context context) {
+ super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, accountUserApi, clock, context);
+ this.usageUserApi = usageUserApi;
+ }
+
+ @POST
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ public Response recordUsage(final UsageJson json,
+ @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) {
+
+ final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+ usageUserApi.recordRolledUpUsage(UUID.fromString(json.getSubscriptionId()), json.getUnitType(), json.getStartTime(), json.getEndTime(), json.getAmount(), callContext);
+ return Response.status(Status.CREATED).build();
+ }
+
+ @GET
+ @Path("/{subscriptionId:" + UUID_PATTERN + "}/{unitType}")
+ @Produces(APPLICATION_JSON)
+ public Response getUsage(@PathParam("subscriptionId") final String subscriptionId,
+ @PathParam("unitType") final String unitType,
+ @QueryParam(QUERY_START_TIME) final String startTime,
+ @QueryParam(QUERY_END_TIME) final String endTime,
+ @javax.ws.rs.core.Context final HttpServletRequest request) {
+
+ final TenantContext tenantContext = context.createContext(request);
+
+ final DateTime usageStartTime = DATE_TIME_FORMATTER.parseDateTime(startTime);
+ final DateTime usageEndTime = DATE_TIME_FORMATTER.parseDateTime(endTime);
+
+ final RolledUpUsage usage = usageUserApi.getUsageForSubscription(UUID.fromString(subscriptionId), unitType, usageStartTime, usageEndTime, tenantContext);
+ final UsageJson result = new UsageJson(usage);
+ return Response.status(Status.OK).entity(result).build();
+ }
+
+}
+