Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MSEARCH-773]. Return Unified List of Inventory Campuses in a Consortium #611

Merged
merged 4 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Extend response with additional Location fields for Inventory Locations in a Consortium endpoint ([MSEARCH-775](https://folio-org.atlassian.net/browse/MSEARCH-775))
* Implement Indexing of Institutions from Kafka ([MSEARCH-771](https://issues.folio.org/browse/MSEARCH-771))
* Implement Indexing of Libraries from Kafka ([MSEARCH-769](https://issues.folio.org/browse/MSEARCH-769))
* Return Unified List of Inventory Campuses in a Consortium ([MSEARCH-773](https://issues.folio.org/browse/MSEARCH-773))

### Bug fixes
* Do not delete kafka topics if collection topic is enabled ([MSEARCH-725](https://folio-org.atlassian.net/browse/MSEARCH-725))
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,7 @@ Special API that provide consolidated access to records in consortium environmen
| GET | `/search/consortium/holdings` | Returns consolidated holdings |
| GET | `/search/consortium/items` | Returns consolidated items |
| GET | `/search/consortium/locations` | Returns consolidated locations |
| GET | `/search/consortium/campuses` | Returns consolidated campuses |

## Additional Information

Expand Down
17 changes: 17 additions & 0 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,18 @@
"user-tenants.collection.get"
]
},
{
"methods": [
"GET"
],
"pathPattern": "/search/consortium/campuses",
"permissionsRequired": [
"consortium-search.campuses.collection.get"
],
"modulePermissions": [
"user-tenants.collection.get"
]
},
{
"methods": [
"GET"
Expand Down Expand Up @@ -724,6 +736,11 @@
"permissionName": "consortium-search.locations.collection.get",
"displayName": "Consortium Search - fetch locations records",
"description": "Returns location records in consortium"
},
{
"permissionName": "consortium-search.campuses.collection.get",
"displayName": "Consortium Search - fetch campuses records",
"description": "Returns campus records in consortium"
}
],
"launchDescriptor": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.search.domain.dto.BatchIdsDto;
import org.folio.search.domain.dto.ConsortiumCampusCollection;
import org.folio.search.domain.dto.ConsortiumHolding;
import org.folio.search.domain.dto.ConsortiumHoldingCollection;
import org.folio.search.domain.dto.ConsortiumItem;
Expand All @@ -21,6 +22,7 @@
import org.folio.search.model.service.CqlSearchRequest;
import org.folio.search.model.types.ResourceType;
import org.folio.search.rest.resource.SearchConsortiumApi;
import org.folio.search.service.consortium.ConsortiumCampusService;
import org.folio.search.service.consortium.ConsortiumInstanceSearchService;
import org.folio.search.service.consortium.ConsortiumInstanceService;
import org.folio.search.service.consortium.ConsortiumLocationService;
Expand All @@ -45,6 +47,7 @@ public class SearchConsortiumController implements SearchConsortiumApi {
private final ConsortiumInstanceService instanceService;
private final ConsortiumLocationService locationService;
private final ConsortiumInstanceSearchService searchService;
private final ConsortiumCampusService campusService;

@Override
public ResponseEntity<ConsortiumHoldingCollection> getConsortiumHoldings(String tenantHeader, String instanceId,
Expand Down Expand Up @@ -96,6 +99,21 @@ public ResponseEntity<ConsortiumLocationCollection> getConsortiumLocations(Strin
.totalRecords(result.getTotalRecords()));
}

@Override
public ResponseEntity<ConsortiumCampusCollection> getConsortiumCampuses(String tenantHeader,
String tenantId,
Integer limit,
Integer offset,
String sortBy,
SortOrder sortOrder) {
var result = campusService.fetchCampuses(tenantHeader, tenantId, limit, offset, sortBy, sortOrder);

return ResponseEntity.ok(new
ConsortiumCampusCollection()
.campuses(result.getRecords())
.totalRecords(result.getTotalRecords()));
}

@Override
public ResponseEntity<ConsortiumHolding> getConsortiumHolding(UUID id, String tenantHeader) {
var tenant = verifyAndGetTenant(tenantHeader);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.folio.search.repository;

import static org.folio.search.utils.SearchUtils.TENANT_ID_FIELD_NAME;
import static org.folio.search.utils.SearchUtils.performExceptionalOperation;
import static org.opensearch.search.sort.SortOrder.ASC;
import static org.opensearch.search.sort.SortOrder.DESC;

import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.search.domain.dto.ConsortiumCampus;
import org.folio.search.domain.dto.SortOrder;
import org.folio.search.model.SearchResult;
import org.folio.search.service.converter.ElasticsearchDocumentConverter;
import org.jetbrains.annotations.NotNull;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.action.search.SearchResponse;
import org.opensearch.client.RequestOptions;
import org.opensearch.client.RestHighLevelClient;
import org.opensearch.index.query.QueryBuilders;
import org.opensearch.search.builder.SearchSourceBuilder;
import org.opensearch.search.sort.SortBuilders;
import org.springframework.stereotype.Repository;

@Log4j2
@Repository
@RequiredArgsConstructor
public class ConsortiumCampusRepository {

public static final String CAMPUS_INDEX = "campus";
private static final String OPERATION_TYPE = "searchApi";
private final IndexNameProvider indexNameProvider;
private final ElasticsearchDocumentConverter documentConverter;

private final RestHighLevelClient client;

public SearchResult<ConsortiumCampus> fetchCampuses(String tenantHeader,
String tenantId,
Integer limit,
Integer offset,
String sortBy,
SortOrder sortOrder) {

var sourceBuilder = getSearchSourceBuilder(tenantId, limit, offset, sortBy, sortOrder);
var response = search(sourceBuilder, tenantHeader);
return documentConverter.convertToSearchResult(response, ConsortiumCampus.class);
}

@NotNull
private static SearchSourceBuilder getSearchSourceBuilder(String tenantId,
Integer limit,
Integer offset,
String sortBy,
SortOrder sortOrder) {
var sourceBuilder = new SearchSourceBuilder();
Optional.ofNullable(tenantId)
.ifPresent(id -> sourceBuilder
.query(QueryBuilders
.termQuery(TENANT_ID_FIELD_NAME, id)));

return sourceBuilder
.from(offset)
.sort(SortBuilders
.fieldSort(sortBy)
.order(sortOrder == SortOrder.DESC ? DESC : ASC))
.size(limit);
}

private SearchResponse search(SearchSourceBuilder sourceBuilder, String tenantHeader) {
var index = indexNameProvider.getIndexName(CAMPUS_INDEX, tenantHeader);
var searchRequest = new SearchRequest(index);

searchRequest.source(sourceBuilder);

return performExceptionalOperation(() -> client.search(searchRequest,
RequestOptions.DEFAULT), index, OPERATION_TYPE);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.folio.search.service.consortium;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.search.domain.dto.ConsortiumCampus;
import org.folio.search.domain.dto.SortOrder;
import org.folio.search.model.SearchResult;
import org.folio.search.repository.ConsortiumCampusRepository;
import org.springframework.stereotype.Service;

@Log4j2
@Service
@RequiredArgsConstructor
public class ConsortiumCampusService {

public static final String ID = "id";
public static final String NAME = "name";
public static final String TENANT_ID = "tenantId";
private final ConsortiumCampusRepository repository;
private final ConsortiumTenantExecutor executor;

public SearchResult<ConsortiumCampus> fetchCampuses(String tenantHeader,
String tenantId,
Integer limit,
Integer offset,
String sortBy,
SortOrder sortOrder) {
log.info("fetching consortium campuses for tenant: {}, tenantId: {}, sortBy: {}",
tenantHeader,
tenantId,
sortBy);

validateSortByValue(sortBy);

return executor.execute(
tenantHeader,
() -> repository.fetchCampuses(tenantHeader, tenantId, limit, offset, sortBy, sortOrder));
}

private void validateSortByValue(String sortBy) {
if (!(NAME.equals(sortBy) || ID.equals(sortBy) || TENANT_ID.equals(sortBy))) {
azizbekxm marked this conversation as resolved.
Show resolved Hide resolved
throw new IllegalArgumentException("Invalid sortBy value: " + sortBy);
}
}

}
3 changes: 3 additions & 0 deletions src/main/resources/swagger.api/mod-search.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ paths:
/search/consortium/locations:
$ref: 'paths/search-consortium/search-consortium-locations.yaml'

/search/consortium/campuses:
$ref: 'paths/search-consortium/search-consortium-campuses.yaml'

/search/consortium/batch/items:
$ref: 'paths/search-consortium/search-consortium-batch-items.yaml'

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
in: query
name: limit
description: Limit the number of elements returned in the response.
schema:
type: integer
minimum: 0
maximum: 1000
default: 1000
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
in: query
name: sortBy
description: |
Defines a field to sort by.
Possible values:
- id
- tenantId
- institutionId
- name
required: false
schema:
type: string
default: name
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
get:
operationId: getConsortiumCampuses
summary: Get Consortium Campuses
description: Get a list of campuses (only for consortium environment)
tags:
- search-consortium
parameters:
- $ref: '../../parameters/tenant-id-query-param.yaml'
- $ref: '../../parameters/consortium-campuses-limit-param.yaml'
- $ref: '../../parameters/offset-param.yaml'
- $ref: '../../parameters/sort-by-campus-name-param.yaml'
- $ref: '../../parameters/sort-order-param.yaml'
- $ref: '../../parameters/x-okapi-tenant-header.yaml'
responses:
'200':
description: List of campuses
content:
application/json:
schema:
$ref: '../../schemas/entity/consortiumCampusCollection.yaml'
'400':
$ref: '../../responses/badRequestResponse.yaml'
'500':
$ref: '../../responses/internalServerErrorResponse.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type: object
properties:
id:
description: Campus ID
type: string
tenantId:
description: Tenant ID of the Campus
type: string
name:
description: Campus name
type: string
institutionId:
description: The UUID of the institution, the first-level location unit, this (shelf) campus belongs to.
type: string
metadata:
$ref: "../dto/common/metadata.yaml"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type: object
properties:
campuses:
type: array
items:
$ref: './consortiumCampus.yaml'
totalRecords:
type: integer
Loading
Loading