Refactor Client to support auditable fields

This commit is contained in:
Adam Saghy
2022-07-26 09:56:30 +02:00
committed by Arnold Gálovics
parent b8f8217148
commit d8f483ab45
9 changed files with 424 additions and 26 deletions
@@ -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.infrastructure.core.api;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
/**
* Serializer for Java Offset Date Time {@link OffsetDateTime} that returns the date in ISO-8601 Offset date time format
*/
public class OffsetDateTimeAdapter implements JsonSerializer<OffsetDateTime> {
@Override
@SuppressWarnings("unused")
public JsonElement serialize(final OffsetDateTime dateTime, final Type typeOfSrc, final JsonSerializationContext context) {
JsonElement object = null;
if (dateTime != null) {
object = new JsonPrimitive(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(dateTime));
}
return object;
}
}
@@ -0,0 +1,87 @@
/**
* 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.portfolio.client.api;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_BY;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_DATE;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
//@Profile("test")
@Component
@Path("/internal/client")
@RequiredArgsConstructor
@Slf4j
public class InternalClientInformationApiResource implements InitializingBean {
private final ClientRepositoryWrapper clientRepositoryWrapper;
private final ToApiJsonSerializer<Map> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
@Override
public void afterPropertiesSet() {
log.warn("------------------------------------------------------------");
log.warn(" ");
log.warn("DO NOT USE THIS IN PRODUCTION!");
log.warn("Internal client services mode is enabled");
log.warn("DO NOT USE THIS IN PRODUCTION!");
log.warn(" ");
log.warn("------------------------------------------------------------");
}
@GET
@Path("{clientId}/audit")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String getClientAuditFields(@Context final UriInfo uriInfo, @PathParam("clientId") Long clientId) {
log.warn("------------------------------------------------------------");
log.warn(" ");
log.warn("Fetching client with {}", clientId);
log.warn(" ");
log.warn("------------------------------------------------------------");
final Client client = clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
Map<String, Object> auditFields = new HashMap<>(
Map.of(CREATED_BY, client.getCreatedBy().orElse(null), CREATED_DATE, client.getCreatedDate().orElse(null), LAST_MODIFIED_BY,
client.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, client.getLastModifiedDate().orElse(null)));
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, auditFields);
}
}
@@ -44,7 +44,7 @@ import org.apache.fineract.infrastructure.codes.domain.CodeValue;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.documentmanagement.domain.Image;
@@ -59,7 +59,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
@Entity
@Table(name = "m_client", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "account_no_UNIQUE"), //
@UniqueConstraint(columnNames = { "mobile_no" }, name = "mobile_no_UNIQUE") })
public final class Client extends AbstractPersistableCustom {
public class Client extends AbstractAuditableWithUTCDateTimeCustom {
@Column(name = "account_no", length = 20, unique = true, nullable = false)
private String accountNumber;
@@ -180,16 +180,14 @@ public final class Client extends AbstractPersistableCustom {
@Column(name = "submittedon_date", nullable = true)
private LocalDate submittedOnDate;
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = "submittedon_userid", nullable = true)
private AppUser submittedBy;
// Deprecated since common Auditable fields were introduced. Columns and data left untouched to help migration.
@Column(name = "updated_on", nullable = true)
private LocalDate updatedOnDate;
// @Column(name = "updated_on", nullable = true)
// private LocalDate updatedOnDate;
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = "updated_by", nullable = true)
private AppUser updatedBy;
// @ManyToOne(optional = true, fetch = FetchType.LAZY)
// @JoinColumn(name = "updated_by", nullable = true)
// private AppUser updatedBy;
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = "activatedon_userid", nullable = true)
@@ -270,9 +268,7 @@ public final class Client extends AbstractPersistableCustom {
savingsAccountId, dataOfBirth, gender, clientType, clientClassification, legalForm, isStaff);
}
Client() {
this.setLegalForm(null);
}
protected Client() {}
private Client(final AppUser currentUser, final ClientStatus status, final Office office, final Group clientParentGroup,
final String accountNo, final String firstname, final String middlename, final String lastname, final String fullname,
@@ -289,7 +285,6 @@ public final class Client extends AbstractPersistableCustom {
}
this.submittedOnDate = submittedOnDate;
this.submittedBy = currentUser;
this.status = status.getValue();
this.office = office;
@@ -969,8 +964,6 @@ public final class Client extends AbstractPersistableCustom {
this.rejectionReason = rejectionReason;
this.rejectionDate = rejectionDate;
this.rejectedBy = currentUser;
this.updatedBy = currentUser;
this.updatedOnDate = rejectionDate;
this.status = ClientStatus.REJECTED.getValue();
}
@@ -979,8 +972,6 @@ public final class Client extends AbstractPersistableCustom {
this.withdrawalReason = withdrawalReason;
this.withdrawalDate = withdrawalDate;
this.withdrawnBy = currentUser;
this.updatedBy = currentUser;
this.updatedOnDate = withdrawalDate;
this.status = ClientStatus.WITHDRAWN.getValue();
}
@@ -990,8 +981,6 @@ public final class Client extends AbstractPersistableCustom {
this.closureReason = null;
this.reactivateDate = reactivateDate;
this.reactivatedBy = currentUser;
this.updatedBy = currentUser;
this.updatedOnDate = reactivateDate;
this.status = ClientStatus.PENDING.getValue();
}
@@ -999,8 +988,6 @@ public final class Client extends AbstractPersistableCustom {
public void reOpened(AppUser currentUser, LocalDate reopenedDate) {
this.reopenedDate = reopenedDate;
this.reopenedBy = currentUser;
this.updatedBy = currentUser;
this.updatedOnDate = reopenedDate;
this.status = ClientStatus.PENDING.getValue();
}
@@ -430,7 +430,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
sqlBuilder.append("left join m_savings_product sp on sp.id = c.default_savings_product ");
sqlBuilder.append("left join m_office transferToOffice on transferToOffice.id = c.transfer_to_office_id ");
sqlBuilder.append("left join m_appuser sbu on sbu.id = c.submittedon_userid ");
sqlBuilder.append("left join m_appuser sbu on sbu.id = c.created_by ");
sqlBuilder.append("left join m_appuser acu on acu.id = c.activatedon_userid ");
sqlBuilder.append("left join m_appuser clu on clu.id = c.closedon_userid ");
sqlBuilder.append("left join m_code_value cv on cv.id = c.gender_cv_id ");
@@ -618,7 +618,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
builder.append("left join m_staff s on s.id = c.staff_id ");
builder.append("left join m_savings_product sp on sp.id = c.default_savings_product ");
builder.append("left join m_office transferToOffice on transferToOffice.id = c.transfer_to_office_id ");
builder.append("left join m_appuser sbu on sbu.id = c.submittedon_userid ");
builder.append("left join m_appuser sbu on sbu.id = c.created_by ");
builder.append("left join m_appuser acu on acu.id = c.activatedon_userid ");
builder.append("left join m_appuser clu on clu.id = c.closedon_userid ");
builder.append("left join m_code_value cv on cv.id = c.gender_cv_id ");