{"action":"created","comment":{"url":"https://api.github.com/repos/folio-org/mod-circulation/pulls/comments/184176310","pull_request_review_id":115317909,"id":184176310,"diff_hunk":"@@ -0,0 +1,377 @@\n+package org.folio.circulation.domain;\n+\n+import io.vertx.core.json.JsonObject;\n+import org.apache.commons.lang3.StringUtils;\n+import org.folio.circulation.support.*;\n+import org.folio.circulation.support.http.client.Response;\n+import org.joda.time.DateTime;\n+\n+import java.util.Collection;\n+import java.util.concurrent.CompletableFuture;\n+import java.util.function.Consumer;\n+import java.util.stream.Collectors;\n+\n+import static org.folio.circulation.domain.RequestStatus.OPEN_AWAITING_PICKUP;\n+\n+public class LoanValidation {\n+  private LoanValidation() { }\n+\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenItemDoesNotExist(\n+    HttpResult<LoanAndRelatedRecords> result) {\n+\n+    return result.next(loan -> {\n+      if(loan.inventoryRecords.getItem() == null) {\n+        final String itemId = loan.loan.getString(\"itemId\");\n+\n+        return HttpResult.failure(new ValidationErrorFailure(\n+          \"Item does not exist\", \"itemId\", itemId));\n+      }\n+      else {\n+        return result;\n+      }\n+    });\n+  }\n+\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenItemBarcodeDoesNotExist(\n+    HttpResult<LoanAndRelatedRecords> result, String barcode) {\n+\n+    return result.next(loanAndRelatedRecords -> {\n+      if(loanAndRelatedRecords.inventoryRecords.getItem() == null) {\n+        return HttpResult.failure(new ValidationErrorFailure(\n+          String.format(\"No item with barcode %s exists\", barcode),\n+          \"itemBarcode\", barcode));\n+      }\n+      else {\n+        return result;\n+      }\n+    });\n+  }\n+\n+  public static void defaultStatusAndAction(JsonObject loan) {\n+    if(!loan.containsKey(\"status\")) {\n+      loan.put(\"status\", new JsonObject().put(\"name\", \"Open\"));\n+\n+      if(!loan.containsKey(\"action\")) {\n+        loan.put(\"action\", \"checkedout\");\n+      }\n+    }\n+  }\n+\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenUserIsNotAwaitingPickup(\n+    HttpResult<LoanAndRelatedRecords> loanAndRelatedRecords) {\n+\n+    return loanAndRelatedRecords.next(loan -> {\n+      final RequestQueue requestQueue = loan.requestQueue;\n+      final JsonObject requestingUser = loan.requestingUser;\n+\n+      if(hasAwaitingPickupRequestForOtherPatron(requestQueue, requestingUser)) {\n+        return HttpResult.failure(new ValidationErrorFailure(\n+          \"User checking out must be requester awaiting pickup\",\n+          \"userId\", loan.loan.getString(\"userId\")));\n+      }\n+      else {\n+        return loanAndRelatedRecords;\n+      }\n+    });\n+  }\n+\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenUserIsNotAwaitingPickup(\n+    HttpResult<LoanAndRelatedRecords> loanAndRelatedRecords, String barcode) {\n+\n+    //TODO: Extract duplication between this and above\n+    return loanAndRelatedRecords.next(loan -> {\n+      final RequestQueue requestQueue = loan.requestQueue;\n+      final JsonObject requestingUser = loan.requestingUser;\n+\n+      if(hasAwaitingPickupRequestForOtherPatron(requestQueue, requestingUser)) {\n+        return HttpResult.failure(new ValidationErrorFailure(\n+          \"User checking out must be requester awaiting pickup\",\n+          \"userBarcode\", barcode));\n+      }\n+      else {\n+        return loanAndRelatedRecords;\n+      }\n+    });\n+  }\n+\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenRequestingUserIsInactive(\n+    HttpResult<LoanAndRelatedRecords> loanAndRelatedRecords, String barcode) {\n+\n+    return loanAndRelatedRecords.next(loan -> {\n+      try {\n+        final User requestingUser = loan.requestingUser;\n+\n+        if (!requestingUser.containsKey(\"active\")) {\n+          return HttpResult.failure(new ValidationErrorFailure(\n+            \"Cannot determine if user is active or not\",\n+            \"userBarcode\", barcode));\n+        }\n+        if (requestingUser.isInactive()) {\n+          return HttpResult.failure(new ValidationErrorFailure(\n+            \"Cannot check out to inactive user\",\n+            \"userBarcode\", barcode));\n+        } else {\n+          return HttpResult.success(loan);\n+        }\n+      } catch (Exception e) {\n+        return HttpResult.failure(new ServerErrorFailure(e));\n+      }\n+    });\n+  }\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenProxyingUserIsInactive(\n+    HttpResult<LoanAndRelatedRecords> loanAndRelatedRecords, String barcode) {\n+\n+    return loanAndRelatedRecords.next(loan -> {\n+      final User proxyingUser = loan.proxyingUser;\n+\n+      if(proxyingUser == null) {\n+        return loanAndRelatedRecords;\n+      }\n+      else if (!proxyingUser.containsKey(\"active\")) {\n+        return HttpResult.failure(new ValidationErrorFailure(\n+          \"Cannot determine if proxying user is active or not\",\n+          \"proxyUserBarcode\", barcode));\n+      }\n+      else if(proxyingUser.isInactive()) {\n+        return HttpResult.failure(new ValidationErrorFailure(\n+          \"Cannot check out via inactive proxying user\",\n+          \"proxyUserBarcode\", barcode));\n+      }\n+      else {\n+        return loanAndRelatedRecords;\n+      }\n+    });\n+  }\n+\n+  private static boolean hasAwaitingPickupRequestForOtherPatron(\n+    RequestQueue requestQueue,\n+    JsonObject requestingUser) {\n+\n+    if(!requestQueue.hasOutstandingFulfillableRequests()) {\n+      return false;\n+    }\n+    else {\n+      final JsonObject highestPriority = requestQueue.getHighestPriorityFulfillableRequest();\n+\n+      return isAwaitingPickup(highestPriority)\n+        && !isFor(highestPriority, requestingUser);\n+    }\n+  }\n+\n+  private static boolean isFor(JsonObject request, JsonObject user) {\n+    return StringUtils.equals(request.getString(\"requesterId\"), user.getString(\"id\"));\n+  }\n+\n+  private static boolean isAwaitingPickup(JsonObject highestPriority) {\n+    return StringUtils.equals(highestPriority.getString(\"status\"), OPEN_AWAITING_PICKUP);\n+  }\n+\n+  public static String determineLocationIdForItem(JsonObject item, JsonObject holding) {\n+    if(item != null && item.containsKey(\"temporaryLocationId\")) {\n+      return item.getString(\"temporaryLocationId\");\n+    }\n+    else if(holding != null && holding.containsKey(\"permanentLocationId\")) {\n+      return holding.getString(\"permanentLocationId\");\n+    }\n+    else if(item != null && item.containsKey(\"permanentLocationId\")) {\n+      return item.getString(\"permanentLocationId\");\n+    }\n+    else {\n+      return null;\n+    }\n+  }\n+\n+  private static void handleProxy(CollectionResourceClient client,\n+                           String query, Consumer<Response> responseHandler){\n+\n+    if(query != null){\n+      client.getMany(query, 1, 0, responseHandler);\n+    }\n+    else{\n+      responseHandler.accept(null);\n+    }\n+  }\n+\n+  public static CompletableFuture<HttpResult<LoanAndRelatedRecords>> refuseWhenProxyRelationshipIsInvalid(\n+    LoanAndRelatedRecords loanAndRelatedRecords,\n+    Clients clients) {\n+\n+    String validProxyQuery = CqlHelper.buildIsValidUserProxyQuery(\n+      loanAndRelatedRecords.loan.getString(\"proxyUserId\"),\n+      loanAndRelatedRecords.loan.getString(\"userId\"));\n+\n+    if(validProxyQuery == null) {\n+      return CompletableFuture.completedFuture(HttpResult.success(loanAndRelatedRecords));\n+    }\n+\n+    CompletableFuture<HttpResult<LoanAndRelatedRecords>> future = new CompletableFuture<>();\n+\n+    handleProxy(clients.userProxies(), validProxyQuery, proxyValidResponse -> {\n+      if (proxyValidResponse != null) {\n+        if (proxyValidResponse.getStatusCode() != 200) {\n+          future.complete(HttpResult.failure(new ForwardOnFailure(proxyValidResponse)));\n+          return;\n+        }\n+\n+        final MultipleRecordsWrapper proxyRelationships = MultipleRecordsWrapper.fromBody(\n+          proxyValidResponse.getBody(), \"proxiesFor\");\n+\n+        final Collection<JsonObject> unExpiredRelationships = proxyRelationships.getRecords()\n+          .stream()\n+          .filter(relationship -> {\n+            if(relationship.containsKey(\"meta\")) {\n+              final JsonObject meta = relationship.getJsonObject(\"meta\");\n+\n+              if(meta.containsKey(\"expirationDate\")) {\n+                final DateTime expirationDate = DateTime.parse(\n+                  meta.getString(\"expirationDate\"));\n+\n+                return expirationDate.isAfter(DateTime.now());\n+              }\n+              else {\n+                return true;\n+              }\n+            }\n+            else {\n+              return true;\n+            }\n+          })\n+          .collect(Collectors.toList());\n+\n+        if (unExpiredRelationships.isEmpty()) { //if empty then we dont have a valid proxy id in the loan\n+          future.complete(HttpResult.failure(new ValidationErrorFailure(\n+            \"proxyUserId is not valid\", \"proxyUserId\",\n+            loanAndRelatedRecords.loan.getString(\"proxyUserId\"))));\n+        }\n+        else {\n+          future.complete(HttpResult.success(loanAndRelatedRecords));\n+        }\n+      }\n+      else {\n+        future.complete(HttpResult.failure(\n+          new ServerErrorFailure(\"No response when requesting proxies\")));\n+      }\n+    });\n+\n+    return future;\n+  }\n+\n+  public static CompletableFuture<HttpResult<LoanAndRelatedRecords>> refuseWhenProxyRelationshipIsInvalid(\n+    LoanAndRelatedRecords loanAndRelatedRecords,\n+    Clients clients,\n+    String proxyUserBarcode) {\n+\n+    //TODO: Remove duplication with above\n+\n+    String validProxyQuery = CqlHelper.buildIsValidUserProxyQuery(\n+      loanAndRelatedRecords.loan.getString(\"proxyUserId\"),\n+      loanAndRelatedRecords.loan.getString(\"userId\"));\n+\n+    if(validProxyQuery == null) {\n+      return CompletableFuture.completedFuture(HttpResult.success(loanAndRelatedRecords));\n+    }\n+\n+    CompletableFuture<HttpResult<LoanAndRelatedRecords>> future = new CompletableFuture<>();\n+\n+    handleProxy(clients.userProxies(), validProxyQuery, proxyValidResponse -> {\n+      if (proxyValidResponse != null) {\n+        if (proxyValidResponse.getStatusCode() != 200) {\n+          future.complete(HttpResult.failure(new ForwardOnFailure(proxyValidResponse)));\n+          return;\n+        }\n+\n+        final MultipleRecordsWrapper proxyRelationships = MultipleRecordsWrapper.fromBody(\n+          proxyValidResponse.getBody(), \"proxiesFor\");\n+\n+        final Collection<JsonObject> unExpiredRelationships = proxyRelationships.getRecords()\n+          .stream()\n+          .filter(relationship -> {\n+            if(relationship.containsKey(\"meta\")) {\n+              final JsonObject meta = relationship.getJsonObject(\"meta\");\n+\n+              if(meta.containsKey(\"expirationDate\")) {\n+                final DateTime expirationDate = DateTime.parse(\n+                  meta.getString(\"expirationDate\"));\n+\n+                return expirationDate.isAfter(DateTime.now());\n+              }\n+              else {\n+                return true;\n+              }\n+            }\n+            else {\n+              return true;\n+            }\n+          })\n+          .collect(Collectors.toList());\n+\n+        if (unExpiredRelationships.isEmpty()) { //if empty then we dont have a valid proxy id in the loan\n+          future.complete(HttpResult.failure(new ValidationErrorFailure(\n+            \"Cannot check out item via proxy when relationship is invalid\", \"proxyUserBarcode\",\n+            proxyUserBarcode)));\n+        }\n+        else {\n+          future.complete(HttpResult.success(loanAndRelatedRecords));\n+        }\n+      }\n+      else {\n+        future.complete(HttpResult.failure(\n+          new ServerErrorFailure(\"No response when requesting proxies\")));\n+      }\n+    });\n+\n+    return future;\n+  }\n+\n+  public static CompletableFuture<HttpResult<LoanAndRelatedRecords>> refuseWhenHasOpenLoan(\n+    LoanAndRelatedRecords loanAndRelatedRecords,\n+    LoanRepository loanRepository,\n+    String barcode) {\n+\n+    final String itemId = loanAndRelatedRecords.loan.getString(\"itemId\");\n+\n+    return loanRepository.hasOpenLoan(itemId)\n+      .thenApply(r -> r.next(openLoan -> {\n+        if(openLoan) {\n+          return HttpResult.failure(new ValidationErrorFailure(\n+            \"Cannot check out item that already has an open loan\", \"itemBarcode\", barcode));\n+        }\n+        else {\n+          return HttpResult.success(loanAndRelatedRecords);\n+        }\n+      }));\n+  }\n+\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenItemIsAlreadyCheckedOut(\n+    HttpResult<LoanAndRelatedRecords> loanAndRelatedRecords) {\n+\n+    return loanAndRelatedRecords.next(loan -> {\n+      final JsonObject item = loan.inventoryRecords.item;\n+\n+      if(ItemStatus.isCheckedOut(item)) {\n+        return HttpResult.failure(new ValidationErrorFailure(\n+          \"Item is already checked out\", \"itemId\", item.getString(\"id\")));\n+      }\n+      else {\n+        return loanAndRelatedRecords;\n+      }\n+    });\n+  }\n+\n+  public static HttpResult<LoanAndRelatedRecords> refuseWhenItemIsAlreadyCheckedOut(\n+    HttpResult<LoanAndRelatedRecords> loanAndRelatedRecords, String barcode) {\n+\n+    //TODO: Extract duplication with above","path":"src/main/java/org/folio/circulation/domain/LoanValidation.java","position":364,"original_position":364,"commit_id":"69ad689d0f03ce312f56ba8c404511123b098f11","original_commit_id":"69ad689d0f03ce312f56ba8c404511123b098f11","user":{"login":"id-jenkins","id":16718781,"avatar_url":"https://avatars0.githubusercontent.com/u/16718781?v=4","gravatar_id":"","url":"https://api.github.com/users/id-jenkins","html_url":"https://github.com/id-jenkins","followers_url":"https://api.github.com/users/id-jenkins/followers","following_url":"https://api.github.com/users/id-jenkins/following{/other_user}","gists_url":"https://api.github.com/users/id-jenkins/gists{/gist_id}","starred_url":"https://api.github.com/users/id-jenkins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/id-jenkins/subscriptions","organizations_url":"https://api.github.com/users/id-jenkins/orgs","repos_url":"https://api.github.com/users/id-jenkins/repos","events_url":"https://api.github.com/users/id-jenkins/events{/privacy}","received_events_url":"https://api.github.com/users/id-jenkins/received_events","type":"User","site_admin":false},"body":"![INFO](https://sonarsource.github.io/sonar-github/severity-info.png 'Severity: INFO') Complete the task associated to this TODO comment. [![rule](https://sonarsource.github.io/sonar-github/rule.png)](https://sonarcloud.io/coding_rules#rule_key=squid%3AS1135)\n","created_at":"2018-04-25T19:15:39Z","updated_at":"2018-04-25T19:15:39Z","html_url":"https://github.com/folio-org/mod-circulation/pull/92#discussion_r184176310","pull_request_url":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/folio-org/mod-circulation/pulls/comments/184176310"},"html":{"href":"https://github.com/folio-org/mod-circulation/pull/92#discussion_r184176310"},"pull_request":{"href":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92"}}},"pull_request":{"url":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92","id":184135516,"html_url":"https://github.com/folio-org/mod-circulation/pull/92","diff_url":"https://github.com/folio-org/mod-circulation/pull/92.diff","patch_url":"https://github.com/folio-org/mod-circulation/pull/92.patch","issue_url":"https://api.github.com/repos/folio-org/mod-circulation/issues/92","number":92,"state":"open","locked":false,"title":"Introduce check out by barcode CIRC-74","user":{"login":"marcjohnson-kint","id":30145808,"avatar_url":"https://avatars0.githubusercontent.com/u/30145808?v=4","gravatar_id":"","url":"https://api.github.com/users/marcjohnson-kint","html_url":"https://github.com/marcjohnson-kint","followers_url":"https://api.github.com/users/marcjohnson-kint/followers","following_url":"https://api.github.com/users/marcjohnson-kint/following{/other_user}","gists_url":"https://api.github.com/users/marcjohnson-kint/gists{/gist_id}","starred_url":"https://api.github.com/users/marcjohnson-kint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcjohnson-kint/subscriptions","organizations_url":"https://api.github.com/users/marcjohnson-kint/orgs","repos_url":"https://api.github.com/users/marcjohnson-kint/repos","events_url":"https://api.github.com/users/marcjohnson-kint/events{/privacy}","received_events_url":"https://api.github.com/users/marcjohnson-kint/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-04-25T19:12:38Z","updated_at":"2018-04-25T19:15:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2bc12b07c286d9410b841281b96ea1cbd5021eba","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92/commits","review_comments_url":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92/comments","review_comment_url":"https://api.github.com/repos/folio-org/mod-circulation/pulls/comments{/number}","comments_url":"https://api.github.com/repos/folio-org/mod-circulation/issues/92/comments","statuses_url":"https://api.github.com/repos/folio-org/mod-circulation/statuses/69ad689d0f03ce312f56ba8c404511123b098f11","head":{"label":"folio-org:CIRC-74-check-out-by-barcode","ref":"CIRC-74-check-out-by-barcode","sha":"69ad689d0f03ce312f56ba8c404511123b098f11","user":{"login":"folio-org","id":16495055,"avatar_url":"https://avatars2.githubusercontent.com/u/16495055?v=4","gravatar_id":"","url":"https://api.github.com/users/folio-org","html_url":"https://github.com/folio-org","followers_url":"https://api.github.com/users/folio-org/followers","following_url":"https://api.github.com/users/folio-org/following{/other_user}","gists_url":"https://api.github.com/users/folio-org/gists{/gist_id}","starred_url":"https://api.github.com/users/folio-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/folio-org/subscriptions","organizations_url":"https://api.github.com/users/folio-org/orgs","repos_url":"https://api.github.com/users/folio-org/repos","events_url":"https://api.github.com/users/folio-org/events{/privacy}","received_events_url":"https://api.github.com/users/folio-org/received_events","type":"Organization","site_admin":false},"repo":{"id":83812902,"name":"mod-circulation","full_name":"folio-org/mod-circulation","owner":{"login":"folio-org","id":16495055,"avatar_url":"https://avatars2.githubusercontent.com/u/16495055?v=4","gravatar_id":"","url":"https://api.github.com/users/folio-org","html_url":"https://github.com/folio-org","followers_url":"https://api.github.com/users/folio-org/followers","following_url":"https://api.github.com/users/folio-org/following{/other_user}","gists_url":"https://api.github.com/users/folio-org/gists{/gist_id}","starred_url":"https://api.github.com/users/folio-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/folio-org/subscriptions","organizations_url":"https://api.github.com/users/folio-org/orgs","repos_url":"https://api.github.com/users/folio-org/repos","events_url":"https://api.github.com/users/folio-org/events{/privacy}","received_events_url":"https://api.github.com/users/folio-org/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/folio-org/mod-circulation","description":"FOLIO mod-circulation","fork":false,"url":"https://api.github.com/repos/folio-org/mod-circulation","forks_url":"https://api.github.com/repos/folio-org/mod-circulation/forks","keys_url":"https://api.github.com/repos/folio-org/mod-circulation/keys{/key_id}","collaborators_url":"https://api.github.com/repos/folio-org/mod-circulation/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/folio-org/mod-circulation/teams","hooks_url":"https://api.github.com/repos/folio-org/mod-circulation/hooks","issue_events_url":"https://api.github.com/repos/folio-org/mod-circulation/issues/events{/number}","events_url":"https://api.github.com/repos/folio-org/mod-circulation/events","assignees_url":"https://api.github.com/repos/folio-org/mod-circulation/assignees{/user}","branches_url":"https://api.github.com/repos/folio-org/mod-circulation/branches{/branch}","tags_url":"https://api.github.com/repos/folio-org/mod-circulation/tags","blobs_url":"https://api.github.com/repos/folio-org/mod-circulation/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/folio-org/mod-circulation/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/folio-org/mod-circulation/git/refs{/sha}","trees_url":"https://api.github.com/repos/folio-org/mod-circulation/git/trees{/sha}","statuses_url":"https://api.github.com/repos/folio-org/mod-circulation/statuses/{sha}","languages_url":"https://api.github.com/repos/folio-org/mod-circulation/languages","stargazers_url":"https://api.github.com/repos/folio-org/mod-circulation/stargazers","contributors_url":"https://api.github.com/repos/folio-org/mod-circulation/contributors","subscribers_url":"https://api.github.com/repos/folio-org/mod-circulation/subscribers","subscription_url":"https://api.github.com/repos/folio-org/mod-circulation/subscription","commits_url":"https://api.github.com/repos/folio-org/mod-circulation/commits{/sha}","git_commits_url":"https://api.github.com/repos/folio-org/mod-circulation/git/commits{/sha}","comments_url":"https://api.github.com/repos/folio-org/mod-circulation/comments{/number}","issue_comment_url":"https://api.github.com/repos/folio-org/mod-circulation/issues/comments{/number}","contents_url":"https://api.github.com/repos/folio-org/mod-circulation/contents/{+path}","compare_url":"https://api.github.com/repos/folio-org/mod-circulation/compare/{base}...{head}","merges_url":"https://api.github.com/repos/folio-org/mod-circulation/merges","archive_url":"https://api.github.com/repos/folio-org/mod-circulation/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/folio-org/mod-circulation/downloads","issues_url":"https://api.github.com/repos/folio-org/mod-circulation/issues{/number}","pulls_url":"https://api.github.com/repos/folio-org/mod-circulation/pulls{/number}","milestones_url":"https://api.github.com/repos/folio-org/mod-circulation/milestones{/number}","notifications_url":"https://api.github.com/repos/folio-org/mod-circulation/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/folio-org/mod-circulation/labels{/name}","releases_url":"https://api.github.com/repos/folio-org/mod-circulation/releases{/id}","deployments_url":"https://api.github.com/repos/folio-org/mod-circulation/deployments","created_at":"2017-03-03T15:30:40Z","updated_at":"2018-04-24T16:40:04Z","pushed_at":"2018-04-25T19:12:38Z","git_url":"git://github.com/folio-org/mod-circulation.git","ssh_url":"git@github.com:folio-org/mod-circulation.git","clone_url":"https://github.com/folio-org/mod-circulation.git","svn_url":"https://github.com/folio-org/mod-circulation","homepage":null,"size":1142,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":2,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"folio-org:master","ref":"master","sha":"65fea43a46848941cac2feb22cf45ed033c51bbf","user":{"login":"folio-org","id":16495055,"avatar_url":"https://avatars2.githubusercontent.com/u/16495055?v=4","gravatar_id":"","url":"https://api.github.com/users/folio-org","html_url":"https://github.com/folio-org","followers_url":"https://api.github.com/users/folio-org/followers","following_url":"https://api.github.com/users/folio-org/following{/other_user}","gists_url":"https://api.github.com/users/folio-org/gists{/gist_id}","starred_url":"https://api.github.com/users/folio-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/folio-org/subscriptions","organizations_url":"https://api.github.com/users/folio-org/orgs","repos_url":"https://api.github.com/users/folio-org/repos","events_url":"https://api.github.com/users/folio-org/events{/privacy}","received_events_url":"https://api.github.com/users/folio-org/received_events","type":"Organization","site_admin":false},"repo":{"id":83812902,"name":"mod-circulation","full_name":"folio-org/mod-circulation","owner":{"login":"folio-org","id":16495055,"avatar_url":"https://avatars2.githubusercontent.com/u/16495055?v=4","gravatar_id":"","url":"https://api.github.com/users/folio-org","html_url":"https://github.com/folio-org","followers_url":"https://api.github.com/users/folio-org/followers","following_url":"https://api.github.com/users/folio-org/following{/other_user}","gists_url":"https://api.github.com/users/folio-org/gists{/gist_id}","starred_url":"https://api.github.com/users/folio-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/folio-org/subscriptions","organizations_url":"https://api.github.com/users/folio-org/orgs","repos_url":"https://api.github.com/users/folio-org/repos","events_url":"https://api.github.com/users/folio-org/events{/privacy}","received_events_url":"https://api.github.com/users/folio-org/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/folio-org/mod-circulation","description":"FOLIO mod-circulation","fork":false,"url":"https://api.github.com/repos/folio-org/mod-circulation","forks_url":"https://api.github.com/repos/folio-org/mod-circulation/forks","keys_url":"https://api.github.com/repos/folio-org/mod-circulation/keys{/key_id}","collaborators_url":"https://api.github.com/repos/folio-org/mod-circulation/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/folio-org/mod-circulation/teams","hooks_url":"https://api.github.com/repos/folio-org/mod-circulation/hooks","issue_events_url":"https://api.github.com/repos/folio-org/mod-circulation/issues/events{/number}","events_url":"https://api.github.com/repos/folio-org/mod-circulation/events","assignees_url":"https://api.github.com/repos/folio-org/mod-circulation/assignees{/user}","branches_url":"https://api.github.com/repos/folio-org/mod-circulation/branches{/branch}","tags_url":"https://api.github.com/repos/folio-org/mod-circulation/tags","blobs_url":"https://api.github.com/repos/folio-org/mod-circulation/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/folio-org/mod-circulation/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/folio-org/mod-circulation/git/refs{/sha}","trees_url":"https://api.github.com/repos/folio-org/mod-circulation/git/trees{/sha}","statuses_url":"https://api.github.com/repos/folio-org/mod-circulation/statuses/{sha}","languages_url":"https://api.github.com/repos/folio-org/mod-circulation/languages","stargazers_url":"https://api.github.com/repos/folio-org/mod-circulation/stargazers","contributors_url":"https://api.github.com/repos/folio-org/mod-circulation/contributors","subscribers_url":"https://api.github.com/repos/folio-org/mod-circulation/subscribers","subscription_url":"https://api.github.com/repos/folio-org/mod-circulation/subscription","commits_url":"https://api.github.com/repos/folio-org/mod-circulation/commits{/sha}","git_commits_url":"https://api.github.com/repos/folio-org/mod-circulation/git/commits{/sha}","comments_url":"https://api.github.com/repos/folio-org/mod-circulation/comments{/number}","issue_comment_url":"https://api.github.com/repos/folio-org/mod-circulation/issues/comments{/number}","contents_url":"https://api.github.com/repos/folio-org/mod-circulation/contents/{+path}","compare_url":"https://api.github.com/repos/folio-org/mod-circulation/compare/{base}...{head}","merges_url":"https://api.github.com/repos/folio-org/mod-circulation/merges","archive_url":"https://api.github.com/repos/folio-org/mod-circulation/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/folio-org/mod-circulation/downloads","issues_url":"https://api.github.com/repos/folio-org/mod-circulation/issues{/number}","pulls_url":"https://api.github.com/repos/folio-org/mod-circulation/pulls{/number}","milestones_url":"https://api.github.com/repos/folio-org/mod-circulation/milestones{/number}","notifications_url":"https://api.github.com/repos/folio-org/mod-circulation/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/folio-org/mod-circulation/labels{/name}","releases_url":"https://api.github.com/repos/folio-org/mod-circulation/releases{/id}","deployments_url":"https://api.github.com/repos/folio-org/mod-circulation/deployments","created_at":"2017-03-03T15:30:40Z","updated_at":"2018-04-24T16:40:04Z","pushed_at":"2018-04-25T19:12:38Z","git_url":"git://github.com/folio-org/mod-circulation.git","ssh_url":"git@github.com:folio-org/mod-circulation.git","clone_url":"https://github.com/folio-org/mod-circulation.git","svn_url":"https://github.com/folio-org/mod-circulation","homepage":null,"size":1142,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":2,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92"},"html":{"href":"https://github.com/folio-org/mod-circulation/pull/92"},"issue":{"href":"https://api.github.com/repos/folio-org/mod-circulation/issues/92"},"comments":{"href":"https://api.github.com/repos/folio-org/mod-circulation/issues/92/comments"},"review_comments":{"href":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92/comments"},"review_comment":{"href":"https://api.github.com/repos/folio-org/mod-circulation/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/folio-org/mod-circulation/pulls/92/commits"},"statuses":{"href":"https://api.github.com/repos/folio-org/mod-circulation/statuses/69ad689d0f03ce312f56ba8c404511123b098f11"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"id-jenkins"}}