FINERACT-1670: Rework command source to store dates in UTC
This commit is contained in:
committed by
Arnold Gálovics
parent
d5ca6baab3
commit
629b9f6d7c
+21
-14
@@ -18,8 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.commands.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
@@ -72,16 +71,24 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
@JoinColumn(name = "maker_id", nullable = false)
|
||||
private AppUser maker;
|
||||
|
||||
@Column(name = "made_on_date", nullable = false)
|
||||
private LocalDateTime madeOnDate;
|
||||
/*
|
||||
* Deprecated: Columns and data left untouched to help migration.
|
||||
*
|
||||
* @Column(name = "made_on_date", nullable = false) private LocalDateTime madeOnDate;
|
||||
*
|
||||
* @Column(name = "checked_on_date", nullable = true) private LocalDateTime checkedOnDate;
|
||||
*/
|
||||
|
||||
@Column(name = "made_on_date_utc", nullable = false)
|
||||
private OffsetDateTime madeOnDate;
|
||||
|
||||
@Column(name = "checked_on_date_utc")
|
||||
private OffsetDateTime checkedOnDate;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "checker_id", nullable = true)
|
||||
private AppUser checker;
|
||||
|
||||
@Column(name = "checked_on_date", nullable = true)
|
||||
private LocalDateTime checkedOnDate;
|
||||
|
||||
@Column(name = "processing_result_enum", nullable = false)
|
||||
private Integer processingResult;
|
||||
|
||||
@@ -99,7 +106,7 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
|
||||
public static CommandSource fullEntryFrom(final CommandWrapper wrapper, final JsonCommand command, final AppUser maker) {
|
||||
return new CommandSource(wrapper.actionName(), wrapper.entityName(), wrapper.getHref(), command.entityId(), command.subentityId(),
|
||||
command.json(), maker, ZonedDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
|
||||
command.json(), maker);
|
||||
}
|
||||
|
||||
protected CommandSource() {
|
||||
@@ -107,7 +114,7 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private CommandSource(final String actionName, final String entityName, final String href, final Long resourceId,
|
||||
final Long subresourceId, final String commandSerializedAsJson, final AppUser maker, final ZonedDateTime madeOnDateTime) {
|
||||
final Long subresourceId, final String commandSerializedAsJson, final AppUser maker) {
|
||||
this.actionName = actionName;
|
||||
this.entityName = entityName;
|
||||
this.resourceGetUrl = href;
|
||||
@@ -115,7 +122,7 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
this.subresourceId = subresourceId;
|
||||
this.commandAsJson = commandSerializedAsJson;
|
||||
this.maker = maker;
|
||||
this.madeOnDate = madeOnDateTime != null ? madeOnDateTime.toLocalDateTime() : null;
|
||||
this.madeOnDate = DateUtils.getOffsetDateTimeOfTenant();
|
||||
this.processingResult = CommandProcessingResultType.PROCESSED.getValue();
|
||||
}
|
||||
|
||||
@@ -135,15 +142,15 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
this.organisationCreditBureauId = organisationCreditBureauId;
|
||||
}
|
||||
|
||||
public void markAsChecked(final AppUser checker, final ZonedDateTime checkedOnDate) {
|
||||
public void markAsChecked(final AppUser checker) {
|
||||
this.checker = checker;
|
||||
this.checkedOnDate = checkedOnDate != null ? checkedOnDate.toLocalDateTime() : null;
|
||||
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenant();
|
||||
this.processingResult = CommandProcessingResultType.PROCESSED.getValue();
|
||||
}
|
||||
|
||||
public void markAsRejected(final AppUser checker, final ZonedDateTime checkedOnDate) {
|
||||
public void markAsRejected(final AppUser checker) {
|
||||
this.checker = checker;
|
||||
this.checkedOnDate = checkedOnDate != null ? checkedOnDate.toLocalDateTime() : null;
|
||||
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenant();
|
||||
this.processingResult = CommandProcessingResultType.REJECTED.getValue();
|
||||
}
|
||||
|
||||
|
||||
+10
-4
@@ -24,6 +24,7 @@ import com.google.gson.JsonObject;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -105,8 +106,8 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
|
||||
|
||||
String partSql = " aud.id as id, aud.action_name as actionName, aud.entity_name as entityName,"
|
||||
+ " aud.resource_id as resourceId, aud.subresource_id as subresourceId,aud.client_id as clientId, aud.loan_id as loanId,"
|
||||
+ " mk.username as maker, aud.made_on_date as madeOnDate, " + " aud.api_get_url as resourceGetUrl, "
|
||||
+ "ck.username as checker, aud.checked_on_date as checkedOnDate, ev.enum_message_property as processingResult "
|
||||
+ " mk.username as maker, aud.made_on_date as madeOnDate, aud.made_on_date_utc as madeOnDateUTC, aud.api_get_url as resourceGetUrl, "
|
||||
+ "ck.username as checker, aud.checked_on_date as checkedOnDate, aud.checked_on_date_utc as checkedOnDateUTC, ev.enum_message_property as processingResult "
|
||||
+ commandAsJsonString + ", "
|
||||
+ " o.name as officeName, gl.level_name as groupLevelName, g.display_name as groupName, c.display_name as clientName, "
|
||||
+ " l.account_no as loanAccountNo, s.account_no as savingsAccountNo " + " from m_portfolio_command_source aud "
|
||||
@@ -136,9 +137,11 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
|
||||
final Long loanId = JdbcSupport.getLong(rs, "loanId");
|
||||
final Long subresourceId = JdbcSupport.getLong(rs, "subresourceId");
|
||||
final String maker = rs.getString("maker");
|
||||
final ZonedDateTime madeOnDate = JdbcSupport.getDateTime(rs, "madeOnDate");
|
||||
final ZonedDateTime madeOnDateTenant = JdbcSupport.getDateTime(rs, "madeOnDate");
|
||||
final OffsetDateTime madeOnDateUTC = JdbcSupport.getOffsetDateTime(rs, "madeOnDateUTC");
|
||||
final String checker = rs.getString("checker");
|
||||
final ZonedDateTime checkedOnDate = JdbcSupport.getDateTime(rs, "checkedOnDate");
|
||||
final ZonedDateTime checkedOnDateTenant = JdbcSupport.getDateTime(rs, "checkedOnDate");
|
||||
final OffsetDateTime checkedOnDateUTC = JdbcSupport.getOffsetDateTime(rs, "checkedOnDateUTC");
|
||||
final String processingResult = rs.getString("processingResult");
|
||||
final String resourceGetUrl = rs.getString("resourceGetUrl");
|
||||
String commandAsJson;
|
||||
@@ -156,6 +159,9 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
|
||||
final String loanAccountNo = rs.getString("loanAccountNo");
|
||||
final String savingsAccountNo = rs.getString("savingsAccountNo");
|
||||
|
||||
ZonedDateTime madeOnDate = madeOnDateUTC != null ? madeOnDateUTC.toZonedDateTime() : madeOnDateTenant;
|
||||
ZonedDateTime checkedOnDate = checkedOnDateUTC != null ? checkedOnDateUTC.toZonedDateTime() : checkedOnDateTenant;
|
||||
|
||||
return new AuditData(id, actionName, entityName, resourceId, subresourceId, maker, madeOnDate, checker, checkedOnDate,
|
||||
processingResult, commandAsJson, officeName, groupLevelName, groupName, clientName, loanAccountNo, savingsAccountNo,
|
||||
clientId, loanId, resourceGetUrl);
|
||||
|
||||
+1
-3
@@ -21,7 +21,6 @@ package org.apache.fineract.commands.service;
|
||||
import com.google.gson.JsonElement;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.security.SecureRandom;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.commands.domain.CommandSource;
|
||||
@@ -33,7 +32,6 @@ import org.apache.fineract.commands.exception.RollbackTransactionAsCommandIsNotA
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.infrastructure.jobs.service.SchedulerJobRunnerReadService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
@@ -180,7 +178,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
|
||||
final CommandSource commandSourceInput = validateMakerCheckerTransaction(makerCheckerId);
|
||||
validateIsUpdateAllowed();
|
||||
final AppUser maker = this.context.authenticatedUser();
|
||||
commandSourceInput.markAsRejected(maker, ZonedDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
|
||||
commandSourceInput.markAsRejected(maker);
|
||||
this.commandSourceRepository.save(commandSourceInput);
|
||||
return makerCheckerId;
|
||||
}
|
||||
|
||||
+9
-11
@@ -22,7 +22,6 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -32,6 +31,7 @@ import org.apache.fineract.batch.exception.ErrorInfo;
|
||||
import org.apache.fineract.commands.domain.CommandSource;
|
||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.exception.CommandNotFoundException;
|
||||
import org.apache.fineract.commands.exception.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
|
||||
import org.apache.fineract.commands.exception.UnsupportedCommandException;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
@@ -41,7 +41,6 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.infrastructure.hooks.event.HookEvent;
|
||||
import org.apache.fineract.infrastructure.hooks.event.HookEventSource;
|
||||
@@ -84,10 +83,11 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
|
||||
final AppUser maker = this.context.authenticatedUser(wrapper);
|
||||
|
||||
CommandSource commandSourceResult = null;
|
||||
CommandSource commandSourceResult;
|
||||
if (command.commandId() != null) {
|
||||
commandSourceResult = this.commandSourceRepository.findById(command.commandId()).orElse(null);
|
||||
commandSourceResult.markAsChecked(maker, ZonedDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
|
||||
commandSourceResult = this.commandSourceRepository.findById(command.commandId())
|
||||
.orElseThrow(() -> new CommandNotFoundException(command.commandId()));
|
||||
commandSourceResult.markAsChecked(maker);
|
||||
} else {
|
||||
commandSourceResult = CommandSource.fullEntryFrom(wrapper, command, maker);
|
||||
}
|
||||
@@ -95,7 +95,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
commandSourceResult.updateForAudit(result.getOfficeId(), result.getGroupId(), result.getClientId(), result.getLoanId(),
|
||||
result.getSavingsId(), result.getProductId(), result.getTransactionId());
|
||||
|
||||
String changesOnlyJson = null;
|
||||
String changesOnlyJson;
|
||||
boolean rollBack = (rollbackTransaction || result.isRollbackTransaction()) && !isApprovedByChecker;
|
||||
if (result.hasChanges() && !rollBack) {
|
||||
changesOnlyJson = this.toApiJsonSerializer.serializeResult(result.getChanges());
|
||||
@@ -142,7 +142,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
}
|
||||
|
||||
private NewCommandSourceHandler findCommandHandler(final CommandWrapper wrapper) {
|
||||
NewCommandSourceHandler handler = null;
|
||||
NewCommandSourceHandler handler;
|
||||
|
||||
if (wrapper.isDatatableResource()) {
|
||||
if (wrapper.isCreateDatatable()) {
|
||||
@@ -209,8 +209,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
private void publishErrorEvent(CommandWrapper wrapper, JsonCommand command, Throwable t) {
|
||||
|
||||
ErrorInfo ex;
|
||||
if (t instanceof RuntimeException) {
|
||||
final RuntimeException e = (RuntimeException) t;
|
||||
if (t instanceof final RuntimeException e) {
|
||||
ex = ErrorHandler.handler(e);
|
||||
} else {
|
||||
ex = new ErrorInfo(500, 9999, "{\"Exception\": " + t.toString() + "}");
|
||||
@@ -249,8 +248,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
reqmap.put("clientId", resultCopy.getClientId());
|
||||
resultCopy.setOfficeId(null);
|
||||
reqmap.put("response", resultCopy);
|
||||
} else if (result instanceof ErrorInfo) {
|
||||
ErrorInfo ex = (ErrorInfo) result;
|
||||
} else if (result instanceof ErrorInfo ex) {
|
||||
reqmap.put("status", "Exception");
|
||||
|
||||
Map<String, Object> errorMap = gson.fromJson(ex.getMessage(), type);
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public final class JdbcSupport {
|
||||
ZonedDateTime dateTime = null;
|
||||
final Timestamp dateValue = rs.getTimestamp(columnName);
|
||||
if (dateValue != null) {
|
||||
dateTime = ZonedDateTime.ofInstant(dateValue.toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||
dateTime = ZonedDateTime.of(dateValue.toLocalDateTime(), DateUtils.getDateTimeZoneOfTenant());
|
||||
}
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
@@ -55,4 +55,5 @@
|
||||
<include file="parts/0033_add_audit_entries_to_loan_repayment_schedule_installment.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0034_add_audit_entries_to_note.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0035_add_audit_entries_to_calendar.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0036_add_audit_entries_and_rework_command_source_datetime_fields.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
|
||||
<changeSet author="fineract" id="portfolio_command_source-1" context="mysql">
|
||||
<addColumn tableName="m_portfolio_command_source">
|
||||
<column name="made_on_date_utc" type="DATETIME"/>
|
||||
<column name="checked_on_date_utc" type="DATETIME"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="portfolio_command_source-1" context="postgresql">
|
||||
<addColumn tableName="m_portfolio_command_source">
|
||||
<column name="made_on_date_utc" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="checked_on_date_utc" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
<changeSet id="portfolio_command_source-2" author="fineract">
|
||||
<dropNotNullConstraint tableName="m_portfolio_command_source" columnName="made_on_date" columnDataType="datetime"/>
|
||||
</changeSet>
|
||||
<changeSet id="portfolio_command_source-3" author="fineract" context="mysql">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">select count(*) from m_portfolio_command_source</sqlCheck>
|
||||
</preConditions>
|
||||
<addNotNullConstraint tableName="m_portfolio_command_source" columnName="made_on_date_utc" columnDataType="DATETIME"/>
|
||||
</changeSet>
|
||||
<changeSet id="portfolio_command_source-3" author="fineract" context="postgresql">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">select count(*) from m_portfolio_command_source</sqlCheck>
|
||||
</preConditions>
|
||||
<addNotNullConstraint tableName="m_portfolio_command_source" columnName="made_on_date_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user