diff --git a/.gitmodules b/.gitmodules index 46ce860f9..b8ec4132e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,7 @@ [submodule "ramls/raml-util"] - path = ramls/raml-util - url = https://github.com/folio-org/raml - branch = raml1.0 + path = ramls/raml-util + url = https://github.com/folio-org/raml + branch = raml1.0 +[submodule "ramls/acq-models"] + path = ramls/acq-models + url = https://github.com/folio-org/acq-models.git diff --git a/Jenkinsfile b/Jenkinsfile index 55f88c5df..aa93b8aef 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,16 +1,14 @@ buildMvn { - publishModDescriptor = false - publishAPI = false - mvnDeploy = false - runLintRamlCop = false + publishModDescriptor = 'yes' + publishAPI = 'yes' + mvnDeploy = 'yes' + runLintRamlCop = 'yes' doDocker = { buildJavaDocker { - publishMaster = 'no' - healthChk = 'no' + publishMaster = 'yes' + healthChk = 'yes' healthChkCmd = 'curl -sS --fail -o /dev/null http://localhost:8081/apidocs/ || exit 1' } } } - - diff --git a/descriptors/DeploymentDescriptor-template.json b/descriptors/DeploymentDescriptor-template.json index ec0cc77fc..7314d9503 100644 --- a/descriptors/DeploymentDescriptor-template.json +++ b/descriptors/DeploymentDescriptor-template.json @@ -2,6 +2,6 @@ "srvcId": "${artifactId}-${version}", "nodeId": "localhost", "descriptor": { - "exec": "java -Dport=%p -jar ../${artifactId}/target/${artifactId}-fat.jar -Dhttp.port=%p embed_postgres=true" + "exec": "java -Dport=%p -jar ../${artifactId}/target/${artifactId}-fat.jar -Dhttp.port=%p" } } diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 32b1e99c0..45dfec5a7 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -9,34 +9,69 @@ "handlers": [ { "methods": ["GET"], - "pathPattern": "/invoice", - "permissionsRequired": ["invoice.collection.get"] + "pathPattern": "/invoice/invoices", + "permissionsRequired": ["invoice.invoices.collection.get"] }, { "methods": ["POST"], - "pathPattern": "/invoice", - "permissionsRequired": ["invoice.item.post"] + "pathPattern": "/invoice/invoices", + "permissionsRequired": ["invoice.invoices.item.post"] }, { "methods": ["GET"], - "pathPattern": "/invoice/{id}", - "permissionsRequired": ["invoice.item.get"] + "pathPattern": "/invoice/invoices/{id}", + "permissionsRequired": ["invoice.invoices.item.get"] }, { "methods": ["PUT"], - "pathPattern": "/invoice/{id}", - "permissionsRequired": ["invoice.item.put"] + "pathPattern": "/invoice/invoices/{id}", + "permissionsRequired": ["invoice.invoices.item.put"] }, { "methods": ["DELETE"], - "pathPattern": "/invoice/{id}", - "permissionsRequired": ["invoice.item.delete"] - } + "pathPattern": "/invoice/invoices/{id}", + "permissionsRequired": ["invoice.invoices.item.delete"] + }, + { + "methods": ["GET"], + "pathPattern": "/invoice/invoice-lines", + "permissionsRequired": ["invoice.invoice-lines.collection.get"] + }, + { + "methods": ["POST"], + "pathPattern": "/invoice/invoice-lines", + "permissionsRequired": ["invoice.invoice-lines.item.post"] + }, + { + "methods": ["GET"], + "pathPattern": "/invoice/invoice-lines/{id}", + "permissionsRequired": ["invoice.invoice-lines.item.get"] + }, + { + "methods": ["PUT"], + "pathPattern": "/invoice/invoice-lines/{id}", + "permissionsRequired": ["invoice.invoice-lines.item.put"] + }, + { + "methods": ["DELETE"], + "pathPattern": "/invoice/invoice-lines/{id}", + "permissionsRequired": ["invoice.invoice-lines.item.delete"] + }, + { + "methods": ["GET"], + "pathPattern": "/invoice/invoice-number", + "permissionsRequired": ["invoice.invoice-number.item.get"] + }, + { + "methods": ["POST"], + "pathPattern": "/invoice/invoice-number/validate", + "permissionsRequired": ["invoice.invoice-number.item.post"] + } ] }, { "id": "_tenant", - "version": "1.0", + "version": "1.2", "interfaceType": "system", "handlers": [ { @@ -56,40 +91,82 @@ ], "permissionSets": [ { - "permissionName": "invoice.collection.get", - "displayName": "Invoice - get invoice collection", - "description": "Get invoice collection" + "permissionName": "invoice.invoices.collection.get", + "displayName": "Invoice - get collection of Invoice", + "description": "Get collection of Invoice" }, { - "permissionName": "invoice.item.get", - "displayName": "Invoice - get individual invoice", - "description": "Get individual pet" + "permissionName": "invoice.invoices.item.get", + "displayName": "Invoice - get an existing Invoice", + "description": "Get an existing Invoice" }, { - "permissionName": "invoice.item.post", - "displayName": "Invoice - create invoice", - "description": "Create invoice" + "permissionName": "invoice.invoices.item.post", + "displayName": "Invoice - create a new Invoice", + "description": "Create a new invoice" }, { - "permissionName": "invoice.item.put", + "permissionName": "invoice.invoices.item.put", "displayName": "Invoice - modify invoice", - "description": "Modify invoice" + "description": "Modify an existing Invoice" + }, + { + "permissionName": "invoice.invoices.item.delete", + "displayName": "Invoice - delete an existing Invoice", + "description": "Delete an existing Invoice" }, { - "permissionName": "invoice.item.delete", - "displayName": "Invoice - delete invoice", - "description": "Delete invoice" + "permissionName": "invoice.invoice-lines.collection.get", + "displayName": "Invoice Line - get collection of Invoice lines", + "description": "Get collection of Invoice lines" + }, + { + "permissionName": "invoice.invoice-lines.item.get", + "displayName": "Invoice - get an existing Invoice line", + "description": "Get an existing Invoice line" }, + { + "permissionName": "invoice.invoice-lines.item.post", + "displayName": "Invoice - create a new Invoice line", + "description": "Create a new Invoice line" + }, + { + "permissionName": "invoice.invoice-lines.item.put", + "displayName": "Invoice - modify an existing Invoice line", + "description": "Modify an existing Invoice line" + }, + { + "permissionName": "invoice.invoice-lines.item.delete", + "displayName": "Invoice - delete an existing Invoice line", + "description": "Delete an existing Invoice line" + }, + { + "permissionName": "invoice.invoice-number.item.get", + "displayName": "Invoice - generate a Invoice Number", + "description": "Generate a Invoice Number" + }, + { + "permissionName": "invoice.invoice-number.item.post", + "displayName": "Invoice - validate a Invoice Number", + "description": "Validate a Invoice Number" + }, { "permissionName": "invoice.all", "displayName": "Invoice module - all permissions", "description": "Entire set of permissions needed to use the invoice module", "subPermissions": [ - "invoice.collection.get", - "invoice.item.get", - "invoice.item.post", - "invoice.item.put", - "invoice.item.delete" + "invoice.invoices.collection.get", + "invoice.invoices.item.get", + "invoice.invoices.item.post", + "invoice.invoices.item.put", + "invoice.invoices.item.delete", + "invoice.invoice-lines.collection.get", + "invoice.invoice-lines.item.get", + "invoice.invoice-lines.item.post", + "invoice.invoice-lines.item.put", + "invoice.invoice-lines.item.delete", + "invoice.invoice-number.item.get", + "invoice.invoice-number.item.post" ], "visible": false } diff --git a/ramls/acq-models b/ramls/acq-models new file mode 160000 index 000000000..bd0d3eef6 --- /dev/null +++ b/ramls/acq-models @@ -0,0 +1 @@ +Subproject commit bd0d3eef661caaae0e448712886f52b8ec78aae7 diff --git a/ramls/invoice.json b/ramls/invoice.json deleted file mode 100644 index a4d4da378..000000000 --- a/ramls/invoice.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "An invoice", - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "metadata": { - "description": "Metadata about creation and changes, provided by the server (client should not provide)", - "type": "object", - "$ref": "raml-util/schemas/metadata.schema", - "readonly": true - } - } -} diff --git a/ramls/invoice.raml b/ramls/invoice.raml index 87594d749..fc0ee2d3b 100644 --- a/ramls/invoice.raml +++ b/ramls/invoice.raml @@ -10,9 +10,14 @@ documentation: content: This documents the API calls that can be made to manage invoices types: - invoice: !include invoice.json - invoiceCollection: !include ./invoiceCollection.json + invoice: !include acq-models/mod-invoice-storage/schemas/invoice.json + invoiceCollection: !include acq-models/mod-invoice-storage/schemas/invoice_collection.json + invoiceLine: !include acq-models/mod-invoice-storage/schemas/invoice_line.json + invoiceLineCollection: !include acq-models/mod-invoice-storage/schemas/invoice_line_collection.json errors: !include raml-util/schemas/errors.schema + UUID: + type: string + pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$ traits: validate: !include raml-util/traits/validation.raml @@ -23,30 +28,100 @@ traits: resourceTypes: collection: !include raml-util/rtypes/collection.raml collection-item: !include raml-util/rtypes/item-collection.raml + get-only: !include raml-util/rtypes/get-only.raml -/invoices: - displayName: Invoice - description: Invoice - type: - collection: - schemaCollection: invoiceCollection - schemaItem: invoice - exampleCollection: !include examples/invoiceCollection.sample - exampleItem: !include examples/invoice.sample - - post: - is: [validate] - get: - is: [ - pageable, - validate - ] - /{id}: +/invoice: + /invoices: displayName: Invoice - description: Get, Delete or Update a specific invoice + description: Manage Invoices + type: + collection: + schemaCollection: invoiceCollection + schemaItem: invoice + exampleCollection: !include acq-models/mod-invoice-storage/examples/invoice_collection.sample + exampleItem: !include acq-models/mod-invoice-storage/examples/invoice.sample + + post: + description: Post invoice and number of invoice lines; + is: [validate] + get: + is: [ pageable, validate ] + /{id}: + displayName: Invoice + description: Get, Delete or Update a specific invoice + type: + collection-item: + schema: invoice + exampleItem: !include examples/invoice.sample + get: + description: Return an invoice with given {id} + put: + is: [validate] + delete: + description: Delete an invoice with given {id} + /invoice-lines: + displayName: Invoice Lines + description: Manage Invoice lines + type: + collection: + schemaCollection: invoiceLineCollection + schemaItem: invoiceLine + exampleCollection: !include acq-models/mod-invoice-storage/examples/invoice_line_collection.sample + exampleItem: !include acq-models/mod-invoice-storage/examples/invoice_line.sample + is: [validate] + get: + is: [ pageable, validate ] + post: + description: Post an invoice lines to corresponding invoice + /{id}: + displayName: Invoice Line + description: Manage invoice line by id + uriParameters: + id: + description: The UUID of a invoice line + type: UUID + type: + collection-item: + exampleItem: !include acq-models/mod-invoice-storage/examples/invoice_line.sample + schema: invoiceLine + is: [validate] + get: + description: Return an invoice line with given {id} + put: + description: Update an invoice line with given {id} + delete: + description: Delete an invoice line with given {id} + /invoice-number: + displayName: Invoice Number + description: Manage Invoice Number type: - collection-item: - schema: invoice - exampleItem: !include examples/invoice.sample - put: + get-only: + schema: invoiceCollection + exampleCollection: !include acq-models/mod-invoice-storage/examples/invoice_collection.sample + get: + description: Get system generated Invoice Number is: [validate] + /validate: + displayName: Invoice Number Validation + post: + description: validate if Invoice Number is unique and matches the pattern specified + is: [validate, language] + body: + application/json: + responses: + 204: + description: "Valid Invoice Number" + 400: + description: "Bad request, e.g. existing Invoice Number. Details of the error provided in the response." + body: + application/json: + example: + strict: false + value: !include raml-util/examples/errors.sample + 500: + description: "Internal server error, e.g. due to misconfiguration" + body: + application/json: + example: + strict: false + value: !include raml-util/examples/errors.sample diff --git a/ramls/invoiceCollection.json b/ramls/invoiceCollection.json deleted file mode 100644 index 9ad6a3885..000000000 --- a/ramls/invoiceCollection.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "Collection of invoices", - "properties": { - "invoices": { - "type": "array", - "items": { - "type": "object", - "$ref": "./invoice.json" - } - }, - "totalRecords": { - "type": "integer" - } - }, - "required": [ - "invoices", - "totalRecords" - ] -} diff --git a/src/main/java/org/folio/rest/impl/InvoicesImpl.java b/src/main/java/org/folio/rest/impl/InvoicesImpl.java index 1c613796a..fd8d728d4 100644 --- a/src/main/java/org/folio/rest/impl/InvoicesImpl.java +++ b/src/main/java/org/folio/rest/impl/InvoicesImpl.java @@ -1,41 +1,105 @@ package org.folio.rest.impl; +import static io.vertx.core.Future.succeededFuture; + +import java.util.Map; + +import javax.ws.rs.core.Response; + +import org.folio.rest.annotations.Validate; +import org.folio.rest.jaxrs.model.Invoice; +import org.folio.rest.jaxrs.model.InvoiceLine; + import io.vertx.core.AsyncResult; import io.vertx.core.Context; import io.vertx.core.Handler; -import org.folio.rest.jaxrs.model.Invoice; -import org.folio.rest.jaxrs.resource.Invoices; -import javax.ws.rs.core.Response; -import java.util.Map; -import static io.vertx.core.Future.succeededFuture; +public class InvoicesImpl implements org.folio.rest.jaxrs.resource.Invoice { + + private static final String NOT_SUPPORTED = "Not supported"; // To overcome sonarcloud warning + + @Validate + @Override + public void postInvoiceInvoices(String lang, Invoice entity, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(PostInvoiceInvoicesResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } + + @Validate + @Override + public void getInvoiceInvoices(int offset, int limit, String lang, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(GetInvoiceInvoicesResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } + + @Validate + @Override + public void getInvoiceInvoicesById(String id, String lang, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(GetInvoiceInvoicesByIdResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } + + @Validate + @Override + public void putInvoiceInvoicesById(String id, String lang, Invoice entity, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(PutInvoiceInvoicesByIdResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } + + @Validate + @Override + public void deleteInvoiceInvoicesById(String id, String lang, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(DeleteInvoiceInvoicesByIdResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } + @Validate + @Override + public void getInvoiceInvoiceLines(int offset, int limit, String lang, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(GetInvoiceInvoiceLinesResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } -public class InvoicesImpl implements Invoices { + @Validate + @Override + public void postInvoiceInvoiceLines(String lang, InvoiceLine entity, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(PostInvoiceInvoiceLinesResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } - @Override - public void postInvoices(String lang, Invoice entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - asyncResultHandler.handle(succeededFuture(PostInvoicesResponse.respond500WithTextPlain("Not supported"))); - } + @Validate + @Override + public void getInvoiceInvoiceLinesById(String id, String lang, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(GetInvoiceInvoiceLinesByIdResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } - @Override - public void getInvoices(int offset, int limit, String lang, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - asyncResultHandler.handle(succeededFuture(GetInvoicesResponse.respond500WithTextPlain("Not supported"))); - } + @Validate + @Override + public void putInvoiceInvoiceLinesById(String id, String lang, InvoiceLine entity, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(PutInvoiceInvoiceLinesByIdResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } - @Override - public void putInvoicesById(String id, String lang, Invoice entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - asyncResultHandler.handle(succeededFuture(PutInvoicesByIdResponse.respond500WithTextPlain("Not supported"))); - } + @Validate + @Override + public void deleteInvoiceInvoiceLinesById(String id, String lang, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(DeleteInvoiceInvoiceLinesByIdResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } - @Override - public void getInvoicesById(String id, String lang, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - asyncResultHandler.handle(succeededFuture(GetInvoicesByIdResponse.respond500WithTextPlain("Not supported"))); - } + @Validate + @Override + public void getInvoiceInvoiceNumber(String lang, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(GetInvoiceInvoiceNumberResponse.respond500WithTextPlain(NOT_SUPPORTED))); + } - @Override - public void deleteInvoicesById(String id, String lang, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - asyncResultHandler.handle(succeededFuture(PutInvoicesByIdResponse.respond500WithTextPlain("Not supported"))); - } + @Validate + @Override + public void postInvoiceInvoiceNumberValidate(String lang, Object entity, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + asyncResultHandler.handle(succeededFuture(PostInvoiceInvoiceNumberValidateResponse.respond500WithApplicationJson(NOT_SUPPORTED))); + } } diff --git a/src/test/java/org/folio/rest/imp/InvoicesTest.java b/src/test/java/org/folio/rest/imp/InvoicesTest.java index a5fa85c03..e0ffc085e 100644 --- a/src/test/java/org/folio/rest/imp/InvoicesTest.java +++ b/src/test/java/org/folio/rest/imp/InvoicesTest.java @@ -7,28 +7,45 @@ import io.vertx.core.json.JsonObject; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; + +import org.apache.commons.io.IOUtils; import org.folio.rest.RestVerticle; -import org.folio.rest.persist.PostgresClient; +import org.folio.rest.jaxrs.model.Invoice; +import org.folio.rest.jaxrs.model.InvoiceLine; import org.folio.rest.tools.client.test.HttpClientMock2; import org.folio.rest.tools.utils.NetworkUtils; import org.junit.BeforeClass; import org.junit.Test; import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Locale; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; import static io.restassured.RestAssured.given; import static org.folio.rest.RestVerticle.OKAPI_HEADER_TENANT; public class InvoicesTest { private static final Logger logger = LoggerFactory.getLogger(InvoicesTest.class); - public static final String INVOICE_ID_PATH = "/invoices/{id}"; + private static final String INVOICE_ID_PATH = "/invoice/invoices/{id}"; + private static final String INVOICE_LINE_ID_PATH = "/invoice/invoice-lines/{id}"; + private static final String INVOICE_PATH = "/invoice/invoices"; + private static final String INVOICE_LINES_PATH = "/invoice/invoice-lines"; + private static final String INVOICE_NUMBER_PATH = "/invoice/invoice-number"; + private static final String INVOICE_NUMBER_VALIDATE_PATH = "/invoice/invoice-number/validate"; + private static final String INVOICE_SAMPLE_PATH = "invoice.json"; + private static final String INVOICE_LINE_SAMPLE_PATH = "invoice_line.json"; + private static final String ID = "id"; + private static final String UUID = "8d3881f6-dd93-46f0-b29d-1c36bdb5c9f9"; private static Vertx vertx; private static int port = NetworkUtils.nextFreePort(); @@ -77,19 +94,39 @@ public static URL storageUrl(String path) throws MalformedURLException { } @Test - public void getInvoicesTest() throws MalformedURLException { + public void getInvoicingInvoicesTest() throws MalformedURLException { given() .header(TENANT_HEADER) .contentType(ContentType.JSON) - .get(storageUrl("/invoices")) + .get(storageUrl(INVOICE_PATH)) .then() .statusCode(500); } @Test - public void getInvoicesByIdTest() throws MalformedURLException { + public void getInvoicingInvoiceLinesTest() throws MalformedURLException { + given() + .header(TENANT_HEADER) + .contentType(ContentType.JSON) + .get(storageUrl(INVOICE_LINES_PATH)) + .then() + .statusCode(500); + } + + @Test + public void getInvoicingInvoiceNumberTest() throws MalformedURLException { + given() + .header(TENANT_HEADER) + .contentType(ContentType.JSON) + .get(storageUrl(INVOICE_NUMBER_PATH)) + .then() + .statusCode(500); + } + + @Test + public void getInvoicingInvoicesByIdTest() throws MalformedURLException { given() - .pathParam("id", "1") + .pathParam(ID, UUID) .header(TENANT_HEADER) .contentType(ContentType.JSON) .get(storageUrl(INVOICE_ID_PATH)) @@ -98,10 +135,24 @@ public void getInvoicesByIdTest() throws MalformedURLException { } @Test - public void putInvoicesByIdTest() throws MalformedURLException { + public void getInvoicingInvoiceLinesByIdTest() throws MalformedURLException { + given() + .pathParam(ID, UUID) + .header(TENANT_HEADER) + .contentType(ContentType.JSON) + .get(storageUrl(INVOICE_LINE_ID_PATH)) + .then() + .statusCode(500); + } + + @Test + public void putInvoicingInvoicesByIdTest() throws Exception { + Invoice reqData = getMockDraftInvoice().mapTo(Invoice.class); + String jsonBody = JsonObject.mapFrom(reqData).encode(); + given() - .pathParam("id", "1") - .body("{}") + .pathParam(ID, reqData.getId()) + .body(jsonBody) .header(TENANT_HEADER) .contentType(ContentType.JSON) .put(storageUrl(INVOICE_ID_PATH)) @@ -110,9 +161,24 @@ public void putInvoicesByIdTest() throws MalformedURLException { } @Test - public void deleteInvoicesByIdTest() throws MalformedURLException { + public void putInvoicingInvoiceLinesByIdTest() throws Exception { + InvoiceLine reqData = getMockDraftInvoiceLine().mapTo(InvoiceLine.class); + String jsonBody = JsonObject.mapFrom(reqData).encode(); + given() - .pathParam("id", "1") + .pathParam(ID, reqData.getId()) + .body(jsonBody) + .header(TENANT_HEADER) + .contentType(ContentType.JSON) + .put(storageUrl(INVOICE_LINE_ID_PATH)) + .then() + .statusCode(500); + } + + @Test + public void deleteInvoicingInvoicesByIdTest() throws MalformedURLException { + given() + .pathParam(ID, UUID) .header(TENANT_HEADER) .contentType(ContentType.JSON) .delete(storageUrl(INVOICE_ID_PATH)) @@ -121,14 +187,80 @@ public void deleteInvoicesByIdTest() throws MalformedURLException { } @Test - public void postInvoicesTest() throws MalformedURLException { + public void deleteInvoicingInvoiceLinesByIdTest() throws MalformedURLException { + given() + .pathParam(ID, UUID) + .header(TENANT_HEADER) + .contentType(ContentType.JSON) + .delete(storageUrl(INVOICE_LINE_ID_PATH)) + .then() + .statusCode(500); + } + + @Test + public void postInvoicingInvoicesTest() throws Exception { + Invoice reqData = getMockDraftInvoice().mapTo(Invoice.class); + String jsonBody = JsonObject.mapFrom(reqData).encode(); + given() - .body("{}") + .body(jsonBody) .header(TENANT_HEADER) .contentType(ContentType.JSON) - .post(storageUrl("/invoices")) + .post(storageUrl(INVOICE_PATH)) .then() .statusCode(500); } + @Test + public void postInvoicingInvoiceNumberValidateTest() throws Exception { + Invoice reqData = getMockDraftInvoice().mapTo(Invoice.class); + String jsonBody = JsonObject.mapFrom(reqData).encode(); + + given() + .body(jsonBody) + .header(TENANT_HEADER) + .contentType(ContentType.JSON) + .post(storageUrl(INVOICE_NUMBER_VALIDATE_PATH)) + .then() + .statusCode(500); + } + + @Test + public void postInvoicingInvoiceLinesTest() throws Exception { + InvoiceLine reqData = getMockDraftInvoiceLine().mapTo(InvoiceLine.class); + String jsonBody = JsonObject.mapFrom(reqData).encode(); + + given() + .body(jsonBody) + .header(TENANT_HEADER) + .contentType(ContentType.JSON) + .post(storageUrl(INVOICE_LINES_PATH)) + .then() + .statusCode(500); + } + + private JsonObject getMockDraftInvoice() throws Exception { + JsonObject invoice = new JsonObject(getMockData(INVOICE_SAMPLE_PATH)); + return invoice; + } + + private JsonObject getMockDraftInvoiceLine() throws Exception { + JsonObject invoiceLine = new JsonObject(getMockData(INVOICE_LINE_SAMPLE_PATH)); + return invoiceLine; + } + + public static String getMockData(String path) throws IOException { + logger.info("Using mock datafile: {}", path); + try (InputStream resourceAsStream = InvoicesTest.class.getClassLoader().getResourceAsStream(path)) { + if (resourceAsStream != null) { + return IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8); + } else { + StringBuilder sb = new StringBuilder(); + try (Stream lines = Files.lines(Paths.get(path))) { + lines.forEach(sb::append); + } + return sb.toString(); + } + } + } } diff --git a/src/test/resources/invoice.json b/src/test/resources/invoice.json new file mode 100644 index 000000000..10d4e256b --- /dev/null +++ b/src/test/resources/invoice.json @@ -0,0 +1,32 @@ +{ + "id": "c0d08448-347b-418a-8c2f-5fb50248d67e", + "approvedBy": "ab18897b-0e40-4f31-896b-9c9adc979a88", + "approvalDate": "2018-07-29T00:00:00.000+0000", + "chkSubscriptionOverlap": false, + "currency": "USD", + "folioInvoiceNo": "123invoicenumber45", + "invoiceDate": "2018-07-20T00:00:00.000+0000", + "note": "Some note", + "owner": "d79b0bcc-DcAD-1E4E-Abb7-DbFcaD5BB3bb", + "paymentDue": "2018-08-29T00:00:00.000+0000", + "paymentTerms": "Payment in Advance", + "paymentMethod": "EFT", + "prorata": false, + "status": "Open", + "source": "024b6f41-c5c6-4280-858e-33fba452a334", + "totalAmount": 5, + "vendorInvoiceNo": "YK75851", + "disbursementNumber": "58", + "voucherNumber": "478", + "paymentId": "a5065f0d-fb88-4d23-b0c1-57e754fba40e", + "disbursementDate": "2018-08-19T00:00:00.000+0000", + "poNumbers": [ + "AB268758XYZ" + ], + "vendorId": "168f8a63-d612-406e-813f-c7527f241ac3", + "manualPayment": true, + "metadata": { + "createdDate": "2018-07-19T00:00:00.000+0000", + "createdByUserId": "28d1057c-d137-11e8-a8d5-f2801f1b9fd1" + } +} diff --git a/src/test/resources/invoice_line.json b/src/test/resources/invoice_line.json new file mode 100644 index 000000000..384f0fc43 --- /dev/null +++ b/src/test/resources/invoice_line.json @@ -0,0 +1,40 @@ +{ + "id": "e0d08448-343b-118a-8c2f-4fb50248d672", + "description": "Some description", + "poLineIds": [ + "c0d08448-347b-418a-8c2f-5fb50248d67e" + ], + "invoiceLineNumber": "123invoicenumber45-1", + "invoiceLineStatus": "Open", + "vendorRefNo": "1", + "productId": "9780764354113", + "productIdType": "ISBN", + "invoiceLineTax": 11.2, + "comment": "Sample invoice line", + "price": 2.2, + "quantity": 3.0, + "doNotReleaseEncumbrance": true, + "reportTax": 3.5, + "subscriptionInfo": "Subscription information", + "subscriptionStart": "2018-08-01T00:00:00.000+0000", + "subscriptionEnd": "2019-01-01T00:00:00.000+0000", + "pieceIds": [ + "5e317dc2-deeb-4429-b2a1-91e5cd0fd5f7" + ], + "invoiceId": "c0d08448-347b-418a-8c2f-5fb50248d67e", + "fundDistributions": [ + "HIST" + ], + "adjustmentsFieldSet": [ + { + "adjustmentLabel": "Adjustment label", + "adjustmentType": "Percentage", + "adjustmentValue": 10.1, + "proRateAdjustment": true + } + ], + "metadata": { + "createdDate": "2018-07-19T00:00:00.000+0000", + "createdByUserId": "28d1057c-d137-11e8-a8d5-f2801f1b9fd1" + } +}