diff --git a/build.gradle b/build.gradle index 8eb34a8..1e4312c 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ repositories { jcenter() } -version = '2.2.0' +version = '2.3.0' // coveralls plugin depends on xml format report diff --git a/src/main/java/com/invoiced/entity/Connection.java b/src/main/java/com/invoiced/entity/Connection.java index e4ad476..8cf3eaf 100644 --- a/src/main/java/com/invoiced/entity/Connection.java +++ b/src/main/java/com/invoiced/entity/Connection.java @@ -37,8 +37,8 @@ protected String post(String url, HashMap queryParms, String jso try { HttpResponse response = Unirest.post(url).basicAuth(this.apiKey, "") - .header("accept", Connection.Accept).header("Content-Type", "application/json") - .queryString(queryParms).body(jsonBody).asString(); + .header("accept", Connection.Accept).header("Content-Type", "application/json") + .queryString(queryParms).body(jsonBody).asString(); responseString = response.getBody().toString(); responseCode = response.getStatus(); @@ -72,8 +72,8 @@ protected String patch(String url, String jsonBody) throws InvoicedException { try { HttpResponse response = Unirest.patch(url).basicAuth(this.apiKey, "") - .header("accept", Connection.Accept).header("Content-Type", "application/json").body(jsonBody) - .asString(); + .header("accept", Connection.Accept).header("Content-Type", "application/json").body(jsonBody) + .asString(); responseString = response.getBody().toString(); responseCode = response.getStatus(); @@ -99,8 +99,8 @@ protected String get(String url, HashMap queryParms) throws Invo try { HttpResponse response = Unirest.get(url).basicAuth(this.apiKey, "") - .header("accept", Connection.Accept).header("Content-Type", "application/json") - .queryString(queryParms).asString(); + .header("accept", Connection.Accept).header("Content-Type", "application/json") + .queryString(queryParms).asString(); responseString = response.getBody().toString(); responseCode = response.getStatus(); @@ -129,8 +129,8 @@ protected ListResponse getList(String url, HashMap queryParms) t try { HttpResponse response = Unirest.get(url).basicAuth(this.apiKey, "") - .header("accept", Connection.Accept).header("Content-Type", "application/json") - .queryString(queryParms).asString(); + .header("accept", Connection.Accept).header("Content-Type", "application/json") + .queryString(queryParms).asString(); responseString = response.getBody().toString(); responseCode = response.getStatus(); @@ -165,7 +165,7 @@ protected void delete(String url) throws InvoicedException { try { HttpResponse response = Unirest.delete(url).basicAuth(this.apiKey, "") - .header("accept", Connection.Accept).header("Content-Type", "application/json").asString(); + .header("accept", Connection.Accept).header("Content-Type", "application/json").asString(); responseCode = response.getStatus(); @@ -215,6 +215,10 @@ public final Subscription newSubscription() { return new Subscription(this); } + public final CreditNote newCreditNote() { + return new CreditNote(this); + } + public final Event newEvent() { return new Event(this); } diff --git a/src/main/java/com/invoiced/entity/CreditNote.java b/src/main/java/com/invoiced/entity/CreditNote.java new file mode 100644 index 0000000..a31294f --- /dev/null +++ b/src/main/java/com/invoiced/entity/CreditNote.java @@ -0,0 +1,201 @@ +package com.invoiced.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.invoiced.exception.EntityException; +import com.invoiced.util.Util; + + +public class CreditNote extends AbstractEntity { + + public CreditNote(Connection conn) { + super(conn, CreditNote.class); + } + + CreditNote() { + super(CreditNote.class); + } + + @Override + @JsonIgnore + protected long getEntityId() { + return this.id; + } + + @Override + @JsonIgnore + protected String getEntityName() { + return "credit_notes"; + } + + @Override + @JsonIgnore + protected boolean hasCRUD() { + return true; + } + + @Override + @JsonIgnore + protected boolean hasList() { + return true; + } + + @Override + @JsonIgnore + protected boolean isSubEntity() { + return false; + } + + @Override + @JsonIgnore + protected void setParentID(long parentID) { + + } + + @Override + @JsonIgnore + protected long getParentID() { + return -1; + } + + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + @JsonProperty("id") + public long id; + + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + public String object; + + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + @JsonProperty("customer") + public long customer; + + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + public long invoice; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("name") + public String name; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("number") + public String number; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("currency") + public String currency; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("draft") + public boolean draft; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("closed") + public boolean closed; + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + public boolean paid; + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + public String status; + + @JsonInclude(JsonInclude.Include.NON_DEFAULT) + @JsonProperty("date") + public long date; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("items") + public LineItem[] items; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("notes") + public String notes; + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + public double subtotal; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("discounts") + public Discount[] discounts; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("taxes") + public Tax[] taxes; + + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + public double total; + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + public double balance; + + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + public String url; + + @JsonProperty(value = "pdf_url", access = JsonProperty.Access.WRITE_ONLY) + public String pdfUrl; + + @JsonProperty(value = "created_at", access = JsonProperty.Access.WRITE_ONLY) + public long createdAt; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("metadata") + public Object metadata; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("attachments") + public long[] attachments; + + + @JsonIgnore + public Email[] send(EmailRequest emailRequest) throws EntityException { + + String url = this.getConnection().baseUrl() + "/" + this.getEntityName() + "/" + + String.valueOf(this.getEntityId()) + "/emails"; + + Email[] emails = null; + + try { + + String emailRequestJson = emailRequest.toJsonString(); + + String response = this.getConnection().post(url, null, emailRequestJson); + + emails = Util.getMapper().readValue(response, Email[].class); + + } catch (Throwable c) { + + throw new EntityException(c); + } + + return emails; + } + + + @JsonIgnore + public Attachment[] listAttachments() throws EntityException { + + String url = this.getConnection().baseUrl() + "/" + this.getEntityName() + "/" + + String.valueOf(this.getEntityId()) + "/attachments"; + + Attachment[] attachments = null; + + try { + + String response = this.getConnection().post(url, null, ""); + + attachments = Util.getMapper().readValue(response, Attachment[].class); + + } catch (Throwable c) { + + throw new EntityException(c); + } + + return attachments; + } + +} diff --git a/src/main/java/com/invoiced/entity/Invoice.java b/src/main/java/com/invoiced/entity/Invoice.java index a1ef696..40a0969 100644 --- a/src/main/java/com/invoiced/entity/Invoice.java +++ b/src/main/java/com/invoiced/entity/Invoice.java @@ -187,6 +187,14 @@ protected long getParentID() { @JsonProperty("ship_to") public Object shipTo; + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("attachments") + public long[] attachments; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("disabled_payment_methods") + public String[] disabledPaymentMethods; + @JsonIgnore public Email[] send(EmailRequest emailRequest) throws EntityException { diff --git a/src/test/java/com/invoiced/entity/CreditNoteTest.java b/src/test/java/com/invoiced/entity/CreditNoteTest.java new file mode 100644 index 0000000..8ed46b5 --- /dev/null +++ b/src/test/java/com/invoiced/entity/CreditNoteTest.java @@ -0,0 +1,85 @@ + +package com.invoiced.entity; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.sql.Timestamp; + +import org.junit.Rule; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.tomakehurst.wiremock.junit.WireMockRule; + +public class CreditNoteTest { + + @Rule + public WireMockRule wireMockRule = new WireMockRule(); + + @Test + public void testParentID() { + Connection conn = new Connection("", true); + conn.testModeOn(); + + CreditNote creditNote = conn.newCreditNote(); + assertTrue("Credit Note Parent Id is incorrect", creditNote .getParentID() == -1); + creditNote.setParentID(-4); + assertTrue("Credit Note Parent Id is incorrect", creditNote .getParentID() == -1); + + } + + + + @Test + public void testJsonSerialization() { + new CreditNote(null); + + ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + try { + String jsonInString = "{\"id\":2048,\"object\":\"credit_note\",\"customer\":15444,\"invoice\":46225,\"name\":null,\"currency\":\"usd\",\"draft\":false,\"closed\":false,\"paid\":false,\"status\":\"open\",\"number\":\"CN-0016\",\"date\":1416290400,\"items\":[{\"id\":7,\"object\":\"line_item\",\"catalog_item\":null,\"type\":\"product\",\"name\":\"Copy Paper, Case\",\"description\":null,\"quantity\":1,\"unit_cost\":45,\"amount\":45,\"discountable\":true,\"discounts\":[],\"taxable\":true,\"taxes\":[],\"metadata\":{}},{\"id\":8,\"object\":\"line_item\",\"catalog_item\":\"delivery\",\"type\":\"service\",\"name\":\"Delivery\",\"description\":null,\"quantity\":1,\"unit_cost\":10,\"amount\":10,\"discountable\":true,\"discounts\":[],\"taxable\":true,\"taxes\":[],\"metadata\":{}}],\"notes\":null,\"subtotal\":55,\"discounts\":[],\"taxes\":[{\"id\":20554,\"object\":\"tax\",\"amount\":3.85,\"tax_rate\":null}],\"total\":51.15,\"balance\":51.15,\"url\":\"https://dundermifflin.invoiced.com/credit_notes/IZmXbVOPyvfD3GPBmyd6FwXY\",\"pdf_url\":\"https://dundermifflin.invoiced.com/credit_notes/IZmXbVOPyvfD3GPBmyd6FwXY/pdf\",\"created_at\":1415229884,\"metadata\":{}}"; + + CreditNote i1 = mapper.readValue(jsonInString, CreditNote.class); + + assertTrue("Id is incorrect", i1.id == 2048L); + assertTrue("Customer is incorrect", i1.customer == 15444L); + assertTrue("Name is incorrect", i1.name == null); + assertTrue("Object is credit_note", i1.name == null); + assertTrue("Invoice is incorrect", i1.invoice == 46225L); + assertTrue("Currency is incorrect", i1.currency.equals("usd")); + assertTrue("Draft is incorrect", i1.draft == false); + assertTrue("Closed is incorrect", i1.closed == false); + assertTrue("Paid is incorrect", i1.paid == false); + assertTrue("Status is incorrect", i1.status.equals("open")); + + + assertTrue("Number is incorrect", i1.number.equals("CN-0016")); + + assertTrue("Date is incorrect", i1.date == 1416290400L); + + + assertTrue("Metadata is incorrect", i1.metadata != null); + + assertTrue("There should be 2 items", i1.items.length == 2); + + assertTrue("Line item amount should be 45.0", i1.items[0].amount == 45.0); + + } catch (JsonGenerationException e) { + e.printStackTrace(); + fail(); + } catch (JsonMappingException e) { + e.printStackTrace(); + fail(); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } + } + + +} \ No newline at end of file