FINERACT-1926: Fineract Asset Externalization models

- [x] JPA model changes
This commit is contained in:
Janos Haber
2023-05-17 19:47:30 +02:00
committed by Arnold Gálovics
parent 9fee79ecde
commit debc8e94a4
13 changed files with 113 additions and 92 deletions
@@ -0,0 +1,37 @@
/**
* 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.businessdate.domain;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum BusinessDateType {
BUSINESS_DATE(1, "Business Date"), COB_DATE(2, "Close of Business Date");
private final Integer id;
private final String description;
public String getName() {
return name();
}
}
@@ -0,0 +1,34 @@
/**
* 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.domain;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
@Getter
@AllArgsConstructor
public enum ActionContext {
DEFAULT(0, "Default context", BusinessDateType.BUSINESS_DATE), COB(1, "Close of Business context", BusinessDateType.COB_DATE);
private final int order;
private final String description;
private final BusinessDateType businessDateType;
}
@@ -0,0 +1,34 @@
/**
* 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.domain;
public final class AuditableFieldsConstants {
public static final String CREATED_BY = "createdBy";
public static final String CREATED_DATE = "createdDate";
public static final String LAST_MODIFIED_BY = "lastModifiedBy";
public static final String LAST_MODIFIED_DATE = "lastModifiedDate";
public static final String CREATED_BY_DB_FIELD = "created_by";
public static final String CREATED_DATE_DB_FIELD = "created_on_utc";
public static final String LAST_MODIFIED_BY_DB_FIELD = "last_modified_by";
public static final String LAST_MODIFIED_DATE_DB_FIELD = "last_modified_on_utc";
private AuditableFieldsConstants() {}
}
@@ -0,0 +1,37 @@
/**
* 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.domain;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.HashMap;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
@AllArgsConstructor
@Getter
public class FineractContext implements Serializable {
private final String contextHolder;
private final FineractPlatformTenant tenantContext;
private final String authTokenContext;
private final HashMap<BusinessDateType, LocalDate> businessDateContext;
private final ActionContext actionContext;
}
@@ -0,0 +1,59 @@
/**
* 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.domain;
import java.io.Serializable;
public class FineractPlatformTenant implements Serializable {
private final Long id;
private final String tenantIdentifier;
private final String name;
private final String timezoneId;
private final FineractPlatformTenantConnection connection;
public FineractPlatformTenant(final Long id, final String tenantIdentifier, final String name, final String timezoneId,
final FineractPlatformTenantConnection connection) {
this.id = id;
this.tenantIdentifier = tenantIdentifier;
this.name = name;
this.timezoneId = timezoneId;
this.connection = connection;
}
public Long getId() {
return this.id;
}
public String getTenantIdentifier() {
return this.tenantIdentifier;
}
public String getName() {
return this.name;
}
public String getTimezoneId() {
return this.timezoneId;
}
public FineractPlatformTenantConnection getConnection() {
return connection;
}
}
@@ -0,0 +1,132 @@
/**
* 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.domain;
import java.io.Serializable;
import java.sql.Connection;
import javax.sql.DataSource;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
/**
* Holds Tenant's DB server connection connection details.
*/
@Getter
public class FineractPlatformTenantConnection implements Serializable {
private final Long connectionId;
private final String schemaServer;
private final String schemaServerPort;
private final String schemaConnectionParameters;
private final String schemaUsername;
private final String schemaPassword;
private final String schemaName;
private final String readOnlySchemaServer;
private final String readOnlySchemaServerPort;
private final String readOnlySchemaName;
private final String readOnlySchemaUsername;
private final String readOnlySchemaPassword;
private final String readOnlySchemaConnectionParameters;
private final boolean autoUpdateEnabled;
private final int initialSize;
private final long validationInterval;
private final boolean removeAbandoned;
private final int removeAbandonedTimeout;
private final boolean logAbandoned;
private final int abandonWhenPercentageFull;
private final int maxActive;
private final int minIdle;
private final int maxIdle;
private final int suspectTimeout;
private final int timeBetweenEvictionRunsMillis;
private final int minEvictableIdleTimeMillis;
private final boolean testOnBorrow;
private final String masterPasswordHash;
public FineractPlatformTenantConnection(final Long connectionId, final String schemaName, String schemaServer,
final String schemaServerPort, final String schemaConnectionParameters, final String schemaUsername,
final String schemaPassword, final boolean autoUpdateEnabled, final int initialSize, final long validationInterval,
final boolean removeAbandoned, final int removeAbandonedTimeout, final boolean logAbandoned,
final int abandonWhenPercentageFull, final int maxActive, final int minIdle, final int maxIdle, final int suspectTimeout,
final int timeBetweenEvictionRunsMillis, final int minEvictableIdleTimeMillis, final boolean tesOnBorrow,
final String readOnlySchemaServer, final String readOnlySchemaServerPort, final String readOnlySchemaName,
final String readOnlySchemaUsername, final String readOnlySchemaPassword, final String readOnlySchemaConnectionParameters,
final String masterPasswordHash) {
this.connectionId = connectionId;
this.schemaName = schemaName;
this.schemaServer = schemaServer;
this.schemaServerPort = schemaServerPort;
this.schemaConnectionParameters = schemaConnectionParameters;
this.schemaUsername = schemaUsername;
this.schemaPassword = schemaPassword;
this.autoUpdateEnabled = autoUpdateEnabled;
this.initialSize = initialSize;
this.validationInterval = validationInterval;
this.removeAbandoned = removeAbandoned;
this.removeAbandonedTimeout = removeAbandonedTimeout;
this.logAbandoned = logAbandoned;
this.abandonWhenPercentageFull = abandonWhenPercentageFull;
this.maxActive = maxActive;
this.minIdle = minIdle;
this.maxIdle = maxIdle;
this.suspectTimeout = suspectTimeout;
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
this.testOnBorrow = tesOnBorrow;
this.readOnlySchemaServer = readOnlySchemaServer;
this.readOnlySchemaServerPort = readOnlySchemaServerPort;
this.readOnlySchemaName = readOnlySchemaName;
this.readOnlySchemaUsername = readOnlySchemaUsername;
this.readOnlySchemaPassword = readOnlySchemaPassword;
this.readOnlySchemaConnectionParameters = readOnlySchemaConnectionParameters;
this.masterPasswordHash = masterPasswordHash;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(this.schemaName).append(":").append(this.schemaServer).append(":")
.append(this.schemaServerPort);
if (this.schemaConnectionParameters != null && !this.schemaConnectionParameters.isEmpty()) {
sb.append('?').append(this.schemaConnectionParameters);
}
return sb.toString();
}
public static String toJdbcUrl(String protocol, String host, String port, String db, String parameters) {
StringBuilder sb = new StringBuilder(protocol).append("://").append(host).append(":").append(port).append('/').append(db);
if (!StringUtils.isEmpty(parameters)) {
sb.append('?').append(parameters);
}
return sb.toString();
}
public static String toProtocol(DataSource dataSource) {
try (Connection connection = dataSource.getConnection()) {
String url = connection.getMetaData().getURL();
return url.substring(0, url.indexOf("://"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,89 @@
/**
* 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.service;
import static java.time.temporal.ChronoUnit.DAYS;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoUnit;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
public final class DateUtils {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATETIME_FORMAT = DEFAULT_DATE_FORMAT + " HH:mm:ss";
public static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER = new DateTimeFormatterBuilder().appendPattern(DEFAULT_DATETIME_FORMAT)
.toFormatter();
public static final DateTimeFormatter DEFAULT_DATE_FORMATTER = new DateTimeFormatterBuilder().appendPattern(DEFAULT_DATE_FORMAT)
.toFormatter();
private DateUtils() {
}
public static ZoneId getSystemZoneId() {
return ZoneId.systemDefault();
}
public static ZoneId getDateTimeZoneOfTenant() {
final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
return ZoneId.of(tenant.getTimezoneId());
}
public static LocalDate getLocalDateOfTenant() {
final ZoneId zone = getDateTimeZoneOfTenant();
return LocalDate.now(zone);
}
public static LocalDateTime getLocalDateTimeOfTenant() {
final ZoneId zone = getDateTimeZoneOfTenant();
return LocalDateTime.now(zone).truncatedTo(ChronoUnit.SECONDS);
}
public static OffsetDateTime getOffsetDateTimeOfTenant() {
final ZoneId zone = getDateTimeZoneOfTenant();
return OffsetDateTime.now(zone).truncatedTo(ChronoUnit.SECONDS);
}
public static OffsetDateTime getOffsetDateTimeOfTenantWithMostPrecision() {
final ZoneId zone = getDateTimeZoneOfTenant();
return OffsetDateTime.now(zone);
}
public static LocalDateTime getLocalDateTimeOfSystem() {
return LocalDateTime.now(ZoneId.systemDefault()).truncatedTo(ChronoUnit.SECONDS);
}
public static boolean isDateInTheFuture(final LocalDate localDate) {
return localDate.isAfter(getBusinessLocalDate());
}
public static LocalDate getBusinessLocalDate() {
return ThreadLocalContextUtil.getBusinessDate();
}
public static long getDifferenceInDays(final LocalDate localDateBefore, final LocalDate localDateAfter) {
return DAYS.between(localDateBefore, localDateAfter);
}
}
@@ -0,0 +1,127 @@
/**
* 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.service;
import java.time.LocalDate;
import java.util.HashMap;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.domain.FineractContext;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.springframework.util.Assert;
/**
*
*/
public final class ThreadLocalContextUtil {
public static final String CONTEXT_TENANTS = "tenants";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
private static final ThreadLocal<FineractPlatformTenant> tenantContext = new ThreadLocal<>();
private static final ThreadLocal<String> authTokenContext = new ThreadLocal<>();
private static final ThreadLocal<HashMap<BusinessDateType, LocalDate>> businessDateContext = new ThreadLocal<>();
private static final ThreadLocal<ActionContext> actionContext = new ThreadLocal<>();
private ThreadLocalContextUtil() {}
public static FineractPlatformTenant getTenant() {
return tenantContext.get();
}
public static void setTenant(final FineractPlatformTenant tenant) {
tenantContext.set(tenant);
}
public static void clearTenant() {
tenantContext.remove();
}
public static String getDataSourceContext() {
return contextHolder.get();
}
public static void setDataSourceContext(final String dataSourceContext) {
contextHolder.set(dataSourceContext);
}
public static void clearDataSourceContext() {
contextHolder.remove();
}
public static String getAuthToken() {
return authTokenContext.get();
}
public static void setAuthToken(final String authToken) {
authTokenContext.set(authToken);
}
// Map is not serializable, but Hashmap is
public static HashMap<BusinessDateType, LocalDate> getBusinessDates() {
Assert.notNull(businessDateContext.get(), "Business dates cannot be null!");
return businessDateContext.get();
}
public static void setBusinessDates(HashMap<BusinessDateType, LocalDate> dates) {
Assert.notNull(dates, "Business dates cannot be null!");
businessDateContext.set(dates);
}
public static LocalDate getBusinessDateByType(BusinessDateType businessDateType) {
Assert.notNull(businessDateType, "Business date type cannot be null!");
LocalDate localDate = getBusinessDates().get(businessDateType);
Assert.notNull(localDate, String.format("Business date with type `%s` is not initialised!", businessDateType));
return localDate;
}
public static LocalDate getBusinessDate() {
BusinessDateType businessDateType = getActionContext().getBusinessDateType();
return getBusinessDateByType(businessDateType);
}
public static ActionContext getActionContext() {
return actionContext.get() == null ? ActionContext.DEFAULT : actionContext.get();
}
public static void setActionContext(ActionContext context) {
Assert.notNull(context, "context cannot be null");
actionContext.set(context);
}
public static FineractContext getContext() {
return new FineractContext(getDataSourceContext(), getTenant(), getAuthToken(), getBusinessDates(), getActionContext());
}
public static void init(final FineractContext fineractContext) {
Assert.notNull(fineractContext, "FineractContext cannot be null during synchronisation!");
setDataSourceContext(fineractContext.getContextHolder());
setTenant(fineractContext.getTenantContext());
setAuthToken(fineractContext.getAuthTokenContext());
setBusinessDates(fineractContext.getBusinessDateContext());
setActionContext(fineractContext.getActionContext());
}
public static void reset() {
contextHolder.remove();
tenantContext.remove();
authTokenContext.remove();
businessDateContext.remove();
actionContext.remove();
}
}