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
@@ -23,6 +23,7 @@ import java.time.LocalDate;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
/** /**
* Immutable data object for office data. * Immutable data object for office data.
@@ -33,7 +34,7 @@ public class OfficeData implements Serializable {
private final Long id; private final Long id;
private final String name; private final String name;
private final String nameDecorated; private final String nameDecorated;
private final String externalId; private final ExternalId externalId;
private final LocalDate openingDate; private final LocalDate openingDate;
private final String hierarchy; private final String hierarchy;
private final Long parentId; private final Long parentId;
@@ -45,7 +46,8 @@ public class OfficeData implements Serializable {
private String locale; private String locale;
private String dateFormat; private String dateFormat;
public static OfficeData importInstance(final String name, final Long parentId, final LocalDate openingDate, final String externalId) { public static OfficeData importInstance(final String name, final Long parentId, final LocalDate openingDate,
final ExternalId externalId) {
return new OfficeData(null, name, null, externalId, openingDate, null, parentId, null, null); return new OfficeData(null, name, null, externalId, openingDate, null, parentId, null, null);
} }
@@ -72,8 +74,9 @@ public class OfficeData implements Serializable {
office.parentId, office.parentName, allowedParents); office.parentId, office.parentName, allowedParents);
} }
public OfficeData(final Long id, final String name, final String nameDecorated, final String externalId, final LocalDate openingDate, public OfficeData(final Long id, final String name, final String nameDecorated, final ExternalId externalId,
final String hierarchy, final Long parentId, final String parentName, final Collection<OfficeData> allowedParents) { final LocalDate openingDate, final String hierarchy, final Long parentId, final String parentName,
final Collection<OfficeData> allowedParents) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.nameDecorated = nameDecorated; this.nameDecorated = nameDecorated;
@@ -32,15 +32,22 @@ import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.organisation.office.exception.CannotUpdateOfficeWithParentOfficeSameAsSelf; import org.apache.fineract.organisation.office.exception.CannotUpdateOfficeWithParentOfficeSameAsSelf;
import org.apache.fineract.organisation.office.exception.RootOfficeParentCannotBeUpdated; import org.apache.fineract.organisation.office.exception.RootOfficeParentCannotBeUpdated;
@Entity @Entity
@Table(name = "m_office", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "name_org"), @Table(name = "m_office", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "name_org"),
@UniqueConstraint(columnNames = { "external_id" }, name = "externalid_org") }) @UniqueConstraint(columnNames = { "external_id" }, name = "externalid_org") })
@Getter
@Setter
public class Office extends AbstractPersistableCustom implements Serializable { public class Office extends AbstractPersistableCustom implements Serializable {
@OneToMany(fetch = FetchType.LAZY) @OneToMany(fetch = FetchType.LAZY)
@@ -60,10 +67,10 @@ public class Office extends AbstractPersistableCustom implements Serializable {
@Column(name = "opening_date", nullable = false) @Column(name = "opening_date", nullable = false)
private LocalDate openingDate; private LocalDate openingDate;
@Column(name = "external_id", length = 100) @Column(name = "external_id", length = 100, unique = true)
private String externalId; private ExternalId externalId;
public static Office headOffice(final String name, final LocalDate openingDate, final String externalId) { public static Office headOffice(final String name, final LocalDate openingDate, final ExternalId externalId) {
return new Office(null, name, openingDate, externalId); return new Office(null, name, openingDate, externalId);
} }
@@ -72,7 +79,7 @@ public class Office extends AbstractPersistableCustom implements Serializable {
final String name = command.stringValueOfParameterNamed("name"); final String name = command.stringValueOfParameterNamed("name");
final LocalDate openingDate = command.localDateValueOfParameterNamed("openingDate"); final LocalDate openingDate = command.localDateValueOfParameterNamed("openingDate");
final String externalId = command.stringValueOfParameterNamed("externalId"); final String externalId = command.stringValueOfParameterNamed("externalId");
return new Office(parentOffice, name, openingDate, externalId); return new Office(parentOffice, name, openingDate, ExternalIdFactory.produce(externalId));
} }
protected Office() { protected Office() {
@@ -82,7 +89,7 @@ public class Office extends AbstractPersistableCustom implements Serializable {
this.externalId = null; this.externalId = null;
} }
private Office(final Office parent, final String name, final LocalDate openingDate, final String externalId) { private Office(final Office parent, final String name, final LocalDate openingDate, final ExternalId externalId) {
this.parent = parent; this.parent = parent;
this.openingDate = openingDate; this.openingDate = openingDate;
if (parent != null) { if (parent != null) {
@@ -94,11 +101,7 @@ public class Office extends AbstractPersistableCustom implements Serializable {
} else { } else {
this.name = null; this.name = null;
} }
if (StringUtils.isNotBlank(externalId)) { this.externalId = externalId;
this.externalId = externalId.trim();
} else {
this.externalId = null;
}
} }
private void addChild(final Office office) { private void addChild(final Office office) {
@@ -141,10 +144,11 @@ public class Office extends AbstractPersistableCustom implements Serializable {
} }
final String externalIdParamName = "externalId"; final String externalIdParamName = "externalId";
if (command.isChangeInStringParameterNamed(externalIdParamName, this.externalId)) { if (command.isChangeInStringParameterNamed(externalIdParamName,
Optional.ofNullable(this.externalId).map(ExternalId::getValue).orElse(null))) {
final String newValue = command.stringValueOfParameterNamed(externalIdParamName); final String newValue = command.stringValueOfParameterNamed(externalIdParamName);
actualChanges.put(externalIdParamName, newValue); actualChanges.put(externalIdParamName, newValue);
this.externalId = StringUtils.defaultIfEmpty(newValue, null); this.externalId = ExternalIdFactory.produce(StringUtils.defaultIfEmpty(newValue, null));
} }
return actualChanges; return actualChanges;
@@ -193,18 +197,6 @@ public class Office extends AbstractPersistableCustom implements Serializable {
return this.hierarchy + id.toString() + "."; return this.hierarchy + id.toString() + ".";
} }
public String getName() {
return this.name;
}
public String getHierarchy() {
return this.hierarchy;
}
public Office getParent() {
return this.parent;
}
public boolean hasParentOf(final Office office) { public boolean hasParentOf(final Office office) {
if (this.parent != null) { if (this.parent != null) {
return this.parent.equals(office); return this.parent.equals(office);
@@ -18,9 +18,12 @@
*/ */
package org.apache.fineract.organisation.office.domain; package org.apache.fineract.organisation.office.domain;
import java.util.Optional;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface OfficeRepository extends JpaRepository<Office, Long>, JpaSpecificationExecutor<Office> { public interface OfficeRepository extends JpaRepository<Office, Long>, JpaSpecificationExecutor<Office> {
// no added behaviour
Optional<Office> findByExternalId(ExternalId externalId);
} }
@@ -18,6 +18,7 @@
*/ */
package org.apache.fineract.organisation.office.exception; package org.apache.fineract.organisation.office.exception;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.EmptyResultDataAccessException;
@@ -33,4 +34,8 @@ public class OfficeNotFoundException extends AbstractPlatformResourceNotFoundExc
public OfficeNotFoundException(Long id, EmptyResultDataAccessException e) { public OfficeNotFoundException(Long id, EmptyResultDataAccessException e) {
super("error.msg.office.id.invalid", "Office with identifier " + id + " does not exist", id, e); super("error.msg.office.id.invalid", "Office with identifier " + id + " does not exist", id, e);
} }
public OfficeNotFoundException(ExternalId externalId) {
super("error.msg.office.external.id.invalid", "Office with external identifier " + externalId + " does not exist", externalId);
}
} }
@@ -0,0 +1,43 @@
/**
* 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.mapper;
import java.util.Optional;
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.organisation.office.domain.Office;
import org.mapstruct.Mapper;
@Mapper(config = MapstructMapperConfig.class)
public interface OfficeDataMapper {
default OfficeData toOfficeData(Office office) {
String hierarchy = office.getHierarchy();
String nameDecorated;
if (hierarchy == null) {
nameDecorated = "";
} else {
nameDecorated = hierarchy.substring(0, (hierarchy.length() - hierarchy.replace(".", "").length() - 1) * 4)
+ Optional.ofNullable(office.getName()).orElse("");
}
return new OfficeData(office.getId(), office.getName(), nameDecorated, office.getExternalId(), office.getOpeningDate(),
office.getHierarchy(), office.getParent() != null ? office.getParent().getId() : null,
office.getParent() != null ? office.getParent().getName() : null, null);
}
}
@@ -19,6 +19,7 @@
package org.apache.fineract.organisation.office.service; package org.apache.fineract.organisation.office.service;
import java.util.Collection; import java.util.Collection;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.service.SearchParameters; import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.organisation.office.data.OfficeData; import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.organisation.office.data.OfficeTransactionData; import org.apache.fineract.organisation.office.data.OfficeTransactionData;
@@ -31,6 +32,8 @@ public interface OfficeReadPlatformService {
OfficeData retrieveOffice(Long officeId); OfficeData retrieveOffice(Long officeId);
OfficeData retrieveOfficeWithExternalId(ExternalId externalId);
OfficeData retrieveNewOfficeTemplate(); OfficeData retrieveNewOfficeTemplate();
Collection<OfficeData> retrieveAllowedParents(Long officeId); Collection<OfficeData> retrieveAllowedParents(Long officeId);
@@ -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.ImportHandlerUtils;
import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer; import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper; 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.fineract.organisation.office.data.OfficeData;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.IndexedColors; 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); Long parentId = ImportHandlerUtils.readAsLong(OfficeConstants.PARENT_OFFICE_ID_COL, row);
LocalDate openedDate = ImportHandlerUtils.readAsDate(OfficeConstants.OPENED_ON_COL, row); LocalDate openedDate = ImportHandlerUtils.readAsDate(OfficeConstants.OPENED_ON_COL, row);
String externalId = ImportHandlerUtils.readAsString(OfficeConstants.EXTERNAL_ID_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); office.setImportFields(row.getRowNum(), locale, dateFormat);
return office; 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; 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.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema; 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.data.UploadRequest;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; 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.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.office.data.OfficeData; 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 static final String RESOURCE_NAME_FOR_PERMISSIONS = "OFFICE";
private final OfficeSwaggerMapper officeSwaggerMapper;
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final OfficeReadPlatformService readPlatformService; private final OfficeReadPlatformService readPlatformService;
private final DefaultToApiJsonSerializer<OfficeData> toApiJsonSerializer; private final DefaultToApiJsonSerializer<OfficeData> toApiJsonSerializer;
@@ -87,6 +91,8 @@ public class OfficesApiResource {
private final BulkImportWorkbookService bulkImportWorkbookService; private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService; private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final Gson gson = GoogleGsonSerializerHelper.createSimpleGson();
@GET @GET
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@@ -176,6 +182,24 @@ public class OfficesApiResource {
return toApiJsonSerializer.serialize(result); 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 @GET
@Path("downloadtemplate") @Path("downloadtemplate")
@Produces("application/vnd.ms-excel") @Produces("application/vnd.ms-excel")
@@ -112,20 +112,21 @@ final class OfficesApiResourceSwagger {
@Schema(example = "Name is updated") @Schema(example = "Name is updated")
public String name; 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") @Schema(description = "PutOfficesOfficeIdResponse")
public static final class PutOfficesOfficeIdResponse { public static final class PutOfficesOfficeIdResponse {
private PutOfficesOfficeIdResponse() { public static final class PutOfficesOfficeIdResponseChanges {
}
static final class PutOfficesOfficeIdResponseChanges {
private PutOfficesOfficeIdResponseChanges() {
}
@Schema(example = "Name is updated") @Schema(example = "Name is updated")
public String name; public String name;
@@ -24,8 +24,11 @@ import java.sql.SQLException;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; 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.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.DateUtils; 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.SearchParameters;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; 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.monetary.service.CurrencyReadPlatformService;
import org.apache.fineract.organisation.office.data.OfficeData; import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.organisation.office.data.OfficeTransactionData; 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.exception.OfficeNotFoundException;
import org.apache.fineract.organisation.office.mapper.OfficeDataMapper;
import org.apache.fineract.useradministration.domain.AppUser; import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
@@ -44,6 +48,7 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@RequiredArgsConstructor
public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService { public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService {
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
@@ -51,18 +56,10 @@ public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final CurrencyReadPlatformService currencyReadPlatformService; private final CurrencyReadPlatformService currencyReadPlatformService;
private final ColumnValidator columnValidator; private final ColumnValidator columnValidator;
private static final String nameDecoratedBaseOnHierarchy = "concat(substring('........................................', 1, ((LENGTH(o.hierarchy) - LENGTH(REPLACE(o.hierarchy, '.', '')) - 1) * 4)), o.name)";
@Autowired private final OfficeRepository officeRepository;
public OfficeReadPlatformServiceImpl(final PlatformSecurityContext context, private final OfficeDataMapper officeDataMapper;
final CurrencyReadPlatformService currencyReadPlatformService, final JdbcTemplate jdbcTemplate, private static final String nameDecoratedBaseOnHierarchy = "concat(substring('........................................', 1, ((LENGTH(o.hierarchy) - LENGTH(REPLACE(o.hierarchy, '.', '')) - 1) * 4)), o.name)";
final ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator) {
this.context = context;
this.currencyReadPlatformService = currencyReadPlatformService;
this.columnValidator = columnValidator;
this.jdbcTemplate = jdbcTemplate;
this.sqlGenerator = sqlGenerator;
}
private static final class OfficeMapper implements RowMapper<OfficeData> { 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 Long parentId = JdbcSupport.getLong(rs, "parentId");
final String parentName = rs.getString("parentName"); 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 @Override
public OfficeData retrieveNewOfficeTemplate() { public OfficeData retrieveNewOfficeTemplate() {
@@ -23,12 +23,16 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification; import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification; import io.restassured.specification.ResponseSpecification;
import java.io.IOException;
import java.util.UUID;
import org.apache.fineract.client.models.PutOfficesOfficeIdResponse;
import org.apache.fineract.integrationtests.common.OfficeDomain; import org.apache.fineract.integrationtests.common.OfficeDomain;
import org.apache.fineract.integrationtests.common.OfficeHelper; import org.apache.fineract.integrationtests.common.OfficeHelper;
import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import retrofit2.Response;
public class OfficeIntegrationTest { public class OfficeIntegrationTest {
@@ -57,4 +61,22 @@ public class OfficeIntegrationTest {
Assertions.assertTrue(name.equals(newOffice.getName())); Assertions.assertTrue(name.equals(newOffice.getName()));
Assertions.assertArrayEquals(dateArr, newOffice.getOpeningDate()); Assertions.assertArrayEquals(dateArr, newOffice.getOpeningDate());
} }
@Test
public void testOfficeModificationWithExternalId() throws IOException {
OfficeHelper oh = new OfficeHelper(requestSpec, responseSpec);
String externalId = UUID.randomUUID().toString();
int officeId = oh.createOfficeWithExternalId(externalId, "01 July 2007");
String date = "02 July 2007";
String name = Utils.uniqueRandomStringGenerator("New_Office_", 4);
String[] dateArr = { "2007", "7", "2" };
Response<PutOfficesOfficeIdResponse> updateResult = oh.updateOfficeUsingExternalId(externalId, name, date);
Assertions.assertTrue(updateResult.isSuccessful());
Assertions.assertEquals(officeId, updateResult.body().getOfficeId());
OfficeDomain newOffice = oh.retrieveOfficeByID(officeId);
Assertions.assertTrue(name.equals(newOffice.getName()));
Assertions.assertArrayEquals(dateArr, newOffice.getOpeningDate());
}
} }
@@ -30,13 +30,17 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap; import java.util.HashMap;
import org.apache.fineract.client.models.GetOfficesResponse; import org.apache.fineract.client.models.GetOfficesResponse;
import org.apache.fineract.client.models.PutOfficesOfficeIdRequest;
import org.apache.fineract.client.models.PutOfficesOfficeIdResponse;
import org.apache.fineract.client.util.JSON; import org.apache.fineract.client.util.JSON;
import org.apache.fineract.integrationtests.client.IntegrationTest;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import retrofit2.Response;
public class OfficeHelper { public class OfficeHelper extends IntegrationTest {
public static final long HEAD_OFFICE_ID = 1L; // The ID is hardcoded in the initial Liquibase migration script public static final long HEAD_OFFICE_ID = 1L; // The ID is hardcoded in the initial Liquibase migration script
@@ -69,6 +73,12 @@ public class OfficeHelper {
CommonConstants.RESPONSE_RESOURCE_ID); CommonConstants.RESPONSE_RESOURCE_ID);
} }
public Integer createOfficeWithExternalId(String externalId, final String openingDate) {
String json = getAsJSON(externalId, openingDate);
return Utils.performServerPost(this.requestSpec, this.responseSpec, OFFICE_URL + "?" + Utils.TENANT_IDENTIFIER, json,
CommonConstants.RESPONSE_RESOURCE_ID);
}
public Integer updateOffice(int id, String name, String openingDate) { public Integer updateOffice(int id, String name, String openingDate) {
final HashMap<String, String> map = new HashMap<String, String>(); final HashMap<String, String> map = new HashMap<String, String>();
map.put("name", name); map.put("name", name);
@@ -82,13 +92,28 @@ public class OfficeHelper {
new Gson().toJson(map), "resourceId"); new Gson().toJson(map), "resourceId");
} }
public Response<PutOfficesOfficeIdResponse> updateOfficeUsingExternalId(String externalId, String name, String openingDate)
throws IOException {
return fineract().offices
.updateOfficeWithExternalId(externalId,
new PutOfficesOfficeIdRequest().name(name).openingDate(openingDate).dateFormat("dd MMMM yyyy").locale("en"))
.execute();
}
public static String getAsJSON(final String openingDate) { public static String getAsJSON(final String openingDate) {
return getAsJSON(null, openingDate);
}
public static String getAsJSON(String externalId, final String openingDate) {
final HashMap<String, String> map = new HashMap<>(); final HashMap<String, String> map = new HashMap<>();
map.put("parentId", "1"); map.put("parentId", "1");
map.put("name", Utils.uniqueRandomStringGenerator("Office_", 4)); map.put("name", Utils.uniqueRandomStringGenerator("Office_", 4));
map.put("dateFormat", "dd MMMM yyyy"); map.put("dateFormat", "dd MMMM yyyy");
map.put("locale", "en"); map.put("locale", "en");
map.put("openingDate", openingDate); map.put("openingDate", openingDate);
if (externalId != null) {
map.put("externalId", externalId);
}
LOG.info("map : {}", map); LOG.info("map : {}", map);
return new Gson().toJson(map); return new Gson().toJson(map);
} }