FINERACT-1760: Update office by external id

- [x] Add new resource to update
- [x] Integration test
This commit is contained in:
Janos Haber
2023-08-30 09:50:56 +02:00
committed by Arnold Gálovics
parent adcdd1a224
commit 63d6cb38ab
13 changed files with 218 additions and 53 deletions
@@ -32,6 +32,7 @@ import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler
import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.IndexedColors;
@@ -79,7 +80,7 @@ public class OfficeImportHandler implements ImportHandler {
Long parentId = ImportHandlerUtils.readAsLong(OfficeConstants.PARENT_OFFICE_ID_COL, row);
LocalDate openedDate = ImportHandlerUtils.readAsDate(OfficeConstants.OPENED_ON_COL, row);
String externalId = ImportHandlerUtils.readAsString(OfficeConstants.EXTERNAL_ID_COL, row);
OfficeData office = OfficeData.importInstance(officeName, parentId, openedDate, externalId);
OfficeData office = OfficeData.importInstance(officeName, parentId, openedDate, ExternalIdFactory.produce(externalId));
office.setImportFields(row.getRowNum(), locale, dateFormat);
return office;
}
@@ -0,0 +1,38 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.organisation.office.api;
import java.util.Map;
import java.util.Optional;
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.mapstruct.Mapper;
@Mapper(config = MapstructMapperConfig.class)
public interface OfficeSwaggerMapper {
OfficesApiResourceSwagger.PutOfficesOfficeIdResponse toPutOfficesOfficeIdResponse(CommandProcessingResult commandProcessingResult);
default OfficesApiResourceSwagger.PutOfficesOfficeIdResponse.PutOfficesOfficeIdResponseChanges toPutOfficesOfficeIdResponseChanges(
Map<String, Object> changes) {
OfficesApiResourceSwagger.PutOfficesOfficeIdResponse.PutOfficesOfficeIdResponseChanges response = new OfficesApiResourceSwagger.PutOfficesOfficeIdResponse.PutOfficesOfficeIdResponseChanges();
Optional.ofNullable(changes).map(c -> c.get("name")).ifPresent(c -> response.name = String.valueOf(c));
return response;
}
}
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.organisation.office.api;
import com.google.gson.Gson;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
@@ -57,6 +58,8 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.UploadRequest;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.office.data.OfficeData;
@@ -79,6 +82,7 @@ public class OfficesApiResource {
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "OFFICE";
private final OfficeSwaggerMapper officeSwaggerMapper;
private final PlatformSecurityContext context;
private final OfficeReadPlatformService readPlatformService;
private final DefaultToApiJsonSerializer<OfficeData> toApiJsonSerializer;
@@ -87,6 +91,8 @@ public class OfficesApiResource {
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final Gson gson = GoogleGsonSerializerHelper.createSimpleGson();
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@@ -176,6 +182,24 @@ public class OfficesApiResource {
return toApiJsonSerializer.serialize(result);
}
@PUT
@Path("/external-id/{externalId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update Office", description = "")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = OfficesApiResourceSwagger.PutOfficesOfficeIdRequest.class)))
public OfficesApiResourceSwagger.PutOfficesOfficeIdResponse updateOfficeWithExternalId(
@Parameter(description = "externalId") @PathParam("externalId") final String externalId,
final OfficesApiResourceSwagger.PutOfficesOfficeIdRequest apiRequestBody) {
OfficeData office = readPlatformService.retrieveOfficeWithExternalId(ExternalIdFactory.produce(externalId));
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateOffice(office.getId()) //
.withJson(gson.toJson(apiRequestBody)) //
.build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return officeSwaggerMapper.toPutOfficesOfficeIdResponse(result);
}
@GET
@Path("downloadtemplate")
@Produces("application/vnd.ms-excel")
@@ -112,20 +112,21 @@ final class OfficesApiResourceSwagger {
@Schema(example = "Name is updated")
public String name;
@Schema(example = "dd MMMM yyyy")
public String dateFormat;
@Schema(example = "en")
public String locale;
@Schema(example = "01 July 2007", type = "date")
public String openingDate;
@Schema(example = "SYS54-88")
public String externalId;
}
@Schema(description = "PutOfficesOfficeIdResponse")
public static final class PutOfficesOfficeIdResponse {
private PutOfficesOfficeIdResponse() {
}
static final class PutOfficesOfficeIdResponseChanges {
private PutOfficesOfficeIdResponseChanges() {
}
public static final class PutOfficesOfficeIdResponseChanges {
@Schema(example = "Name is updated")
public String name;
@@ -24,8 +24,11 @@ import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -34,9 +37,10 @@ import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.organisation.office.data.OfficeTransactionData;
import org.apache.fineract.organisation.office.domain.OfficeRepository;
import org.apache.fineract.organisation.office.exception.OfficeNotFoundException;
import org.apache.fineract.organisation.office.mapper.OfficeDataMapper;
import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -44,6 +48,7 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService {
private final JdbcTemplate jdbcTemplate;
@@ -51,18 +56,10 @@ public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService
private final PlatformSecurityContext context;
private final CurrencyReadPlatformService currencyReadPlatformService;
private final ColumnValidator columnValidator;
private static final String nameDecoratedBaseOnHierarchy = "concat(substring('........................................', 1, ((LENGTH(o.hierarchy) - LENGTH(REPLACE(o.hierarchy, '.', '')) - 1) * 4)), o.name)";
@Autowired
public OfficeReadPlatformServiceImpl(final PlatformSecurityContext context,
final CurrencyReadPlatformService currencyReadPlatformService, final JdbcTemplate jdbcTemplate,
final ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator) {
this.context = context;
this.currencyReadPlatformService = currencyReadPlatformService;
this.columnValidator = columnValidator;
this.jdbcTemplate = jdbcTemplate;
this.sqlGenerator = sqlGenerator;
}
private final OfficeRepository officeRepository;
private final OfficeDataMapper officeDataMapper;
private static final String nameDecoratedBaseOnHierarchy = "concat(substring('........................................', 1, ((LENGTH(o.hierarchy) - LENGTH(REPLACE(o.hierarchy, '.', '')) - 1) * 4)), o.name)";
private static final class OfficeMapper implements RowMapper<OfficeData> {
@@ -84,7 +81,8 @@ public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService
final Long parentId = JdbcSupport.getLong(rs, "parentId");
final String parentName = rs.getString("parentName");
return new OfficeData(id, name, nameDecorated, externalId, openingDate, hierarchy, parentId, parentName, null);
return new OfficeData(id, name, nameDecorated, ExternalIdFactory.produce(externalId), openingDate, hierarchy, parentId,
parentName, null);
}
}
@@ -210,6 +208,13 @@ public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService
}
}
@Override
public OfficeData retrieveOfficeWithExternalId(ExternalId externalId) {
this.context.authenticatedUser();
return officeRepository.findByExternalId(externalId).map(officeDataMapper::toOfficeData)
.orElseThrow(() -> new OfficeNotFoundException(externalId));
}
@Override
public OfficeData retrieveNewOfficeTemplate() {