Skip to content

Commit

Permalink
Merge pull request #113 from folio-org/EDGEPATRON-131
Browse files Browse the repository at this point in the history
[EDGEPATRON-131]-Added POST edge api for LOC patron
  • Loading branch information
SinghAdes authored Jun 10, 2024
2 parents 09f6f1c + 479bbfe commit 4bc6bac
Show file tree
Hide file tree
Showing 11 changed files with 500 additions and 8 deletions.
2 changes: 1 addition & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"requires": [
{
"id": "patron",
"version": "4.2 5.1"
"version": "4.2 5.2"
},
{
"id": "circulation",
Expand Down
53 changes: 52 additions & 1 deletion ramls/edge-patron.raml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Patron Services
baseUri: https://github.com/folio-org/mod-patron
protocols: [ HTTPS ]
version: v4.3
version: v4.4

documentation:
- title: Patron Services
Expand All @@ -17,6 +17,7 @@ types:
charge: !include charge.json
money: !include money.json
item: !include item.json
external_patron: !include external_patron.json
allowedServicePoints: !include allowed-service-points-response.json
hold-cancellation: !include hold-cancellation.json
errors: !include raml-util/schemas/errors.schema
Expand All @@ -26,6 +27,56 @@ types:
description: |
Services that allow patron empowerment from 3rd party discovery services
/account:
post:
description: |
Creates external patron request
queryParameters:
apikey:
description: "API Key"
type: string
body:
application/json:
type: external_patron
example: !include examples/external_patron.json
responses:
201:
description: |
Returns data for a new created external patron
body:
application/json:
type: external_patron
example: !include examples/external_patron.json
400:
description: Bad request
body:
text/plain:
example: unable to process request
401:
description: Not authorized to perform requested action
body:
text/plain:
example: unable to create request
403:
description: Access Denied
body:
text/plain:
example: Access Denied
409:
description: Conflict
body:
text/plain:
example: Optimistic Locking Conflict
422:
description: Validation error
body:
text/plain:
example: Validation error
500:
description: |
Internal server error, e.g. due to misconfiguration
body:
text/plain:
example: internal server error, contact administrator
/{id}:
displayName: Manage Accounts By Id
description: Service endpoints that manage accounts by an existing Id
Expand Down
31 changes: 31 additions & 0 deletions ramls/examples/external_patron.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"generalInfo": {
"externalSystemId": "ext-123456",
"firstName": "John",
"preferredFirstName": "Johnny",
"middleName": "M",
"lastName": "Doe"
},
"address0": {
"addressLine0": "123 Main St",
"addressLine1": "Apt 4B",
"city": "Metropolis",
"province": "NY",
"zip": "12345",
"country": "USA"
},
"address1": {
"addressLine0": "456 Side St",
"addressLine1": "Suite 500",
"city": "Metropolis",
"province": "NY",
"zip": "12346",
"country": "USA"
},
"contactInfo": {
"phone": "555-1234",
"mobilePhone": "555-5678",
"email": "[email protected]"
},
"preferredEmailCommunication": ["Support", "Programs"]
}
135 changes: 135 additions & 0 deletions ramls/external_patron.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "User Information Schema",
"description": "Schema for user information including general info, addresses, contact info",
"type": "object",
"properties": {
"generalInfo": {
"type": "object",
"description": "General info of patron",
"properties": {
"externalSystemId": {
"type": "string",
"description": "A unique ID that corresponds to an external authority"
},
"firstName": {
"type": "string",
"description": "The user's given name"
},
"preferredFirstName": {
"type": "string",
"description": "The user's preferred name"
},
"middleName": {
"type": "string",
"description": "The user's middle name (if any)"
},
"lastName": {
"type": "string",
"description": "The user's surname"
}
},
"required": ["externalSystemId", "firstName", "lastName"],
"additionalProperties": false
},
"address0": {
"type": "object",
"description": "Primary address info of patron",
"properties": {
"addressLine0": {
"type": "string",
"description": "Address, Line 0"
},
"addressLine1": {
"type": "string",
"description": "Address, Line 1"
},
"city": {
"type": "string",
"description": "City name"
},
"province": {
"type": "string",
"description": "Province"
},
"zip": {
"type": "string",
"description": "Zip Code"
},
"country": {
"type": "string",
"description": "Country"
}
},
"required": ["addressLine0", "city", "province", "zip", "country"],
"additionalProperties": false
},
"address1": {
"type": "object",
"description": "Secondary address info of patron",
"properties": {
"addressLine0": {
"type": "string",
"description": "Address, Line 0"
},
"addressLine1": {
"type": "string",
"description": "Address, Line 1"
},
"city": {
"type": "string",
"description": "City name"
},
"province": {
"type": "string",
"description": "Province"
},
"zip": {
"type": "string",
"description": "Zip Code"
},
"country": {
"type": "string",
"description": "Country"
}
},
"required": ["addressLine0", "city", "province", "zip", "country"],
"additionalProperties": false
},
"contactInfo": {
"type": "object",
"description": "Contact info of patron",
"properties": {
"phone": {
"type": "string",
"description": "The user's primary phone number"
},
"mobilePhone": {
"type": "string",
"description": "The user's mobile phone number"
},
"email": {
"type": "string",
"description": "The user's email address",
"format": "email"
}
},
"required": ["email"],
"additionalProperties": false
},
"preferredEmailCommunication": {
"type": "array",
"description": "Email communication info of patron",
"items": {
"type": "string",
"enum": ["Support", "Programs", "Service"]
},
"minItems": 1,
"maxItems": 3,
"uniqueItems": true,
"description": "Preferred email communication types"
}
},
"required": ["generalInfo", "address0", "contactInfo", "preferredEmailCommunication"],
"additionalProperties": false
}
1 change: 1 addition & 0 deletions src/main/java/org/folio/edge/patron/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class Constants {
public static final String MSG_INTERNAL_SERVER_ERROR = "Internal Server Error";
public static final String MSG_REQUEST_TIMEOUT = "Request to FOLIO timed out";
public static final String MSG_HOLD_NOBODY = "No hold data provided";
public static final String MSG_EXTERNAL_NOBODY = "No external_patron data provided";

public static final String FIELD_EXPIRATION_DATE = "expirationDate";
public static final String FIELD_REQUEST_DATE = "requestDate";
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/folio/edge/patron/MainVerticle.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ public Router defineRoutes() {
router.route(HttpMethod.POST, "/patron/account/:patronId/item/:itemId/hold")
.handler(patronHandler::handlePlaceItemHold);

router.route(HttpMethod.POST, "/patron/account/:patronId")
.handler(patronHandler::handlePatronRequest);

router.route(HttpMethod.POST, "/patron/account/:patronId/instance/:instanceId/hold")
.handler(patronHandler::handlePlaceInstanceHold);

Expand Down
24 changes: 21 additions & 3 deletions src/main/java/org/folio/edge/patron/PatronHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import static org.folio.edge.patron.Constants.FIELD_EXPIRATION_DATE;
import static org.folio.edge.patron.Constants.FIELD_REQUEST_DATE;
import static org.folio.edge.patron.Constants.MSG_ACCESS_DENIED;
import static org.folio.edge.patron.Constants.MSG_EXTERNAL_NOBODY;
import static org.folio.edge.patron.Constants.MSG_HOLD_NOBODY;
import static org.folio.edge.patron.Constants.MSG_INTERNAL_SERVER_ERROR;
import static org.folio.edge.patron.Constants.MSG_REQUEST_TIMEOUT;
import static org.folio.edge.patron.Constants.MSG_HOLD_NOBODY;
import static org.folio.edge.patron.Constants.PARAM_HOLD_ID;
import static org.folio.edge.patron.Constants.PARAM_INCLUDE_CHARGES;
import static org.folio.edge.patron.Constants.PARAM_INCLUDE_HOLDS;
Expand All @@ -32,7 +33,9 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.folio.edge.core.Handler;
Expand Down Expand Up @@ -151,6 +154,21 @@ public void handlePlaceItemHold(RoutingContext ctx) {
t -> handleProxyException(ctx, t)));
}

public void handlePatronRequest(RoutingContext ctx) {
if (ctx.body().asJsonObject() == null) {
badRequest(ctx, MSG_EXTERNAL_NOBODY);
return;
}
final String body = String.valueOf(ctx.body().asJsonObject());
handleCommon(ctx,
new String[] {},
new String[] {},
(client, params) -> ((PatronOkapiClient) client).postPatron(
body,
resp -> handleProxyResponse(ctx, resp),
t -> handleProxyException(ctx, t)));
}

public void handleCancelHold(RoutingContext ctx) {
String validationResult = validateCancelHoldRequest(ctx.body().asJsonObject());
if ( validationResult != null) {
Expand Down Expand Up @@ -259,13 +277,13 @@ protected void handleProxyResponse(RoutingContext ctx, HttpResponse<Buffer> resp
serverResponse.setStatusCode(statusCode);

String respBody = resp.bodyAsString();
if (logger.isDebugEnabled()) {
if (logger.isDebugEnabled() ) {
logger.debug("response: " + respBody);
}

String contentType = resp.getHeader(HttpHeaders.CONTENT_TYPE.toString());

if (resp.statusCode() < 400){
if (resp.statusCode() < 400 && Objects.nonNull(respBody)){
setContentType(serverResponse, contentType);
serverResponse.end(respBody); //not an error case, pass on the response body as received
}
Expand Down
Loading

0 comments on commit 4bc6bac

Please sign in to comment.