diff --git a/src/main/java/org/folio/fqm/resource/MigrationController.java b/src/main/java/org/folio/fqm/resource/MigrationController.java index 633fd597b..6367bd630 100644 --- a/src/main/java/org/folio/fqm/resource/MigrationController.java +++ b/src/main/java/org/folio/fqm/resource/MigrationController.java @@ -1,11 +1,15 @@ package org.folio.fqm.resource; import lombok.RequiredArgsConstructor; +import org.folio.fqm.domain.dto.FqmMigrateRequest; +import org.folio.fqm.domain.dto.FqmMigrateResponse; +import org.folio.fqm.migration.MigratableQueryInformation; import org.folio.fqm.service.MigrationService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; + @RestController @RequiredArgsConstructor public class MigrationController implements FqmVersionApi { @@ -15,4 +19,24 @@ public class MigrationController implements FqmVersionApi { public ResponseEntity getFqmVersion() { return new ResponseEntity<>(migrationService.getLatestVersion(), HttpStatus.OK); } + + @Override + public ResponseEntity fqmMigrate(FqmMigrateRequest fqmMigrateRequest) { + MigratableQueryInformation migratableQueryInformation = new MigratableQueryInformation( + fqmMigrateRequest.getEntityTypeId(), + fqmMigrateRequest.getFqlQuery(), + fqmMigrateRequest.getFields() + ); + + migrationService.migrate(migratableQueryInformation); + + FqmMigrateResponse fqmMigrateResponse = new FqmMigrateResponse() + .entityTypeId(migratableQueryInformation.entityTypeId()) + .fqlQuery(migratableQueryInformation.fqlQuery()) + .fields(migratableQueryInformation.fields()) + .warnings(migratableQueryInformation.warnings().stream() + .map(warning -> warning.getType().toString()) + .toList()); + return new ResponseEntity<>(fqmMigrateResponse, HttpStatus.OK); + } } diff --git a/src/main/resources/swagger.api/mod-fqm-manager.yaml b/src/main/resources/swagger.api/mod-fqm-manager.yaml index 7c44ea66e..df1f04d0f 100644 --- a/src/main/resources/swagger.api/mod-fqm-manager.yaml +++ b/src/main/resources/swagger.api/mod-fqm-manager.yaml @@ -79,6 +79,30 @@ paths: $ref: '#/components/responses/badRequestResponse' '500': $ref: '#/components/responses/internalServerErrorResponse' + /fqm/migrate: + post: + summary: fqm migrate request + operationId: fqmMigrate + tags: + - fqmVersion + requestBody: + description: 'Request for FQM version submitted successfully' + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/fqmMigrateRequest' + responses: + '201': + description: 'FQM version updated successfully' + content: + application/json: + schema: + $ref: '#/components/schemas/fqmMigrateResponse' + '400': + $ref: '#/components/responses/badRequestResponse' + '500': + $ref: '#/components/responses/internalServerErrorResponse' components: parameters: @@ -137,6 +161,10 @@ components: type: array items: type: string + fqmMigrateRequest: + $ref: schemas/FqmMigrateRequest.json + fqmMigrateResponse: + $ref: schemas/FqmMigrateResponse.json responses: badRequestResponse: @@ -159,4 +187,3 @@ components: code: unexpected.error schema: $ref: "#/components/schemas/errorResponse" - diff --git a/src/main/resources/swagger.api/schemas/FqmMigrateRequest.json b/src/main/resources/swagger.api/schemas/FqmMigrateRequest.json new file mode 100644 index 000000000..ac532bf1e --- /dev/null +++ b/src/main/resources/swagger.api/schemas/FqmMigrateRequest.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Entity Upgrade Request", + "description": "Schema for a request to upgrade an entity payload, including an entity type ID, FQL query, and list of fields.", + "type": "object", + "properties": { + "entityTypeId": { + "description": "ID of the entity type to be upgraded", + "type": "string", + "format": "UUID" + }, + "fqlQuery": { + "description": "FQL query string to be used for the upgrade", + "type": "string" + }, + "fields": { + "description": "List of fields to be included in the upgrade", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "entityTypeId" + ] +} diff --git a/src/main/resources/swagger.api/schemas/FqmMigrateResponse.json b/src/main/resources/swagger.api/schemas/FqmMigrateResponse.json new file mode 100644 index 000000000..2a63bd009 --- /dev/null +++ b/src/main/resources/swagger.api/schemas/FqmMigrateResponse.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Entity Upgrade Response", + "description": "Schema for a response to upgrade FQM", + "type": "object", + "properties": { + "entityTypeId": { + "description": "ID of the entity type upgraded successfully", + "type": "string", + "format": "UUID" + }, + "fqlQuery": { + "description": "FQL query string upgraded successfully", + "type": "string" + }, + "fields": { + "description": "List of fields upgraded successfully", + "type": "array", + "items": { + "type": "string" + } + }, + "warnings": { + "description": "List of warnings issued during the upgrade", + "type": "array", + "items": { + "type": "string" + } + } +}, + "required": [ + "entityTypeId" + ] +} diff --git a/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java b/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java index 4b494ae7f..6de8ca2ad 100644 --- a/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java +++ b/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java @@ -1,24 +1,38 @@ package org.folio.fqm.controller; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.folio.fqm.domain.dto.FqmMigrateRequest; +import org.folio.fqm.migration.MigratableQueryInformation; +import org.folio.fqm.migration.warnings.DeprecatedEntityWarning; +import org.folio.fqm.migration.warnings.Warning; import org.folio.fqm.resource.MigrationController; import org.folio.fqm.service.MigrationService; import org.folio.spring.FolioExecutionContext; +import org.folio.spring.integration.XOkapiHeaders; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import java.util.List; +import java.util.UUID; + +import static org.hamcrest.Matchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @WebMvcTest(MigrationController.class) class MigrationControllerTest { private static final String GET_VERSION_URL = "/fqm/version"; + + private static final String POST_FQM_MIGRATE_REQUEST = "/fqm/migrate"; @Autowired private MockMvc mockMvc; @@ -35,10 +49,51 @@ void shouldReturnVersion() throws Exception { when(migrationService.getLatestVersion()).thenReturn("1"); RequestBuilder builder = MockMvcRequestBuilders .get(GET_VERSION_URL) - .accept(MediaType.APPLICATION_JSON); + .accept(APPLICATION_JSON); mockMvc .perform(builder) .andExpect(status().isOk()) .andExpect(content().string("1")); } + +@Test +void shouldMigrateFqmSuccessfully() throws Exception { + String tenantId = "tenant_01"; + UUID entityTypeID = UUID.randomUUID(); + FqmMigrateRequest fqmMigrateRequest = getFqmMigrateRequest(entityTypeID); + + MigratableQueryInformation migratableQueryInformation = mock(MigratableQueryInformation.class); + + Warning deprecatedEntityWarning = new DeprecatedEntityWarning("abc", "def"); + List warningList = List.of(deprecatedEntityWarning); + + when(executionContext.getTenantId()).thenReturn(tenantId); + when(migratableQueryInformation.entityTypeId()).thenReturn(entityTypeID); + when(migratableQueryInformation.fqlQuery()).thenReturn("users.active"); + when(migratableQueryInformation.fields()).thenReturn(List.of("field1", "field2")); + when(migratableQueryInformation.warnings()).thenReturn(warningList); + + when(migrationService.migrate(any(MigratableQueryInformation.class))).thenReturn(migratableQueryInformation); + + RequestBuilder builder = MockMvcRequestBuilders + .post(POST_FQM_MIGRATE_REQUEST) + .header(XOkapiHeaders.TENANT, tenantId) + .contentType(APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(fqmMigrateRequest)); + + mockMvc + .perform(builder) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.entityTypeId", is(entityTypeID.toString()))) + .andExpect(jsonPath("$.fqlQuery", is("users.active"))) + .andExpect(jsonPath("$.fields", is(List.of("field1", "field2")))); +} + @NotNull + private static FqmMigrateRequest getFqmMigrateRequest(UUID entityTypeID) { + FqmMigrateRequest fqmMigrateRequest = new FqmMigrateRequest(); + fqmMigrateRequest.setEntityTypeId(entityTypeID); + fqmMigrateRequest.setFqlQuery("users.active"); + fqmMigrateRequest.setFields(List.of("field1", "field2")); + return fqmMigrateRequest; + } }