FINERACT-1932: Add loan module (WIP)
This commit is contained in:
Executable
+116
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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.accounting.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountUsage;
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioProductType;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public final class AccountingEnumerations {
|
||||
|
||||
private AccountingEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData gLAccountType(final int id) {
|
||||
return gLAccountType(GLAccountType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData gLAccountType(final GLAccountType accountType) {
|
||||
final EnumOptionData optionData = new EnumOptionData(accountType.getValue().longValue(), accountType.getCode(),
|
||||
accountType.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> gLAccountType(final GLAccountType[] accountTypes) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final GLAccountType accountType : accountTypes) {
|
||||
optionDatas.add(gLAccountType(accountType));
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData gLAccountUsage(final int id) {
|
||||
return gLAccountUsage(GLAccountUsage.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData gLAccountUsage(final GLAccountUsage accountUsage) {
|
||||
final EnumOptionData optionData = new EnumOptionData(accountUsage.getValue().longValue(), accountUsage.getCode(),
|
||||
accountUsage.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> gLAccountUsage(final GLAccountUsage[] accountUsages) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final GLAccountUsage accountUsage : accountUsages) {
|
||||
optionDatas.add(gLAccountUsage(accountUsage));
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData journalEntryType(final int id) {
|
||||
return journalEntryType(JournalEntryType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData journalEntryType(final JournalEntryType journalEntryType) {
|
||||
final EnumOptionData optionData = new EnumOptionData(journalEntryType.getValue().longValue(), journalEntryType.getCode(),
|
||||
journalEntryType.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> journalEntryTypes(final JournalEntryType[] journalEntryTypes) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final JournalEntryType journalEntryType : journalEntryTypes) {
|
||||
optionDatas.add(journalEntryType(journalEntryType));
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData portfolioProductType(final int id) {
|
||||
return portfolioProductType(PortfolioProductType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData portfolioProductType(final PortfolioProductType portfolioProductType) {
|
||||
final EnumOptionData optionData = new EnumOptionData(portfolioProductType.getValue().longValue(), portfolioProductType.getCode(),
|
||||
portfolioProductType.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData accountingRuleType(final int id) {
|
||||
return accountingRuleType(AccountingRuleType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData accountingRuleType(final AccountingRuleType type) {
|
||||
final EnumOptionData optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), type.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> accountingRuleTypes(final AccountingRuleType[] accountingRuleTypes) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final AccountingRuleType accountingRuleType : accountingRuleTypes) {
|
||||
optionDatas.add(accountingRuleType(accountingRuleType));
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.accounting.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum AccountingRuleType {
|
||||
|
||||
NONE(1, "accountingRuleType.none"), //
|
||||
CASH_BASED(2, "accountingRuleType.cash"), //
|
||||
ACCRUAL_PERIODIC(3, "accountingRuleType.accrual.periodic"), //
|
||||
ACCRUAL_UPFRONT(4, "accountingRuleType.accrual.upfront"); //
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private static final Map<Integer, AccountingRuleType> intToEnumMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (final AccountingRuleType type : AccountingRuleType.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static AccountingRuleType fromInt(final Integer ruleTypeValue) {
|
||||
final AccountingRuleType type = intToEnumMap.get(ruleTypeValue);
|
||||
return type;
|
||||
}
|
||||
|
||||
AccountingRuleType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 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.accounting.glaccount.api;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/***
|
||||
* Enum of all parameters passed in while creating/updating a GL Account
|
||||
***/
|
||||
public enum GLAccountJsonInputParams {
|
||||
|
||||
ID("id"), NAME("name"), PARENT_ID("parentId"), GL_CODE("glCode"), DISABLED("disabled"), MANUAL_ENTRIES_ALLOWED(
|
||||
"manualEntriesAllowed"), TYPE("type"), USAGE("usage"), DESCRIPTION("description"), TAGID("tagId");
|
||||
|
||||
private final String value;
|
||||
|
||||
GLAccountJsonInputParams(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
|
||||
static {
|
||||
for (final GLAccountJsonInputParams type : GLAccountJsonInputParams.values()) {
|
||||
values.add(type.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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.accounting.glaccount.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.accounting.common.AccountingEnumerations;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountUsage;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
/**
|
||||
* Immutable object representing a General Ledger Account
|
||||
*
|
||||
* Note: no getter/setters required as google-gson will produce json from fields of object.
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class GLAccountData implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long parentId;
|
||||
private String glCode;
|
||||
private Boolean disabled;
|
||||
private Boolean manualEntriesAllowed;
|
||||
private EnumOptionData type;
|
||||
private EnumOptionData usage;
|
||||
private String description;
|
||||
private String nameDecorated;
|
||||
private CodeValueData tagId;
|
||||
private Long organizationRunningBalance;
|
||||
|
||||
// templates
|
||||
private List<EnumOptionData> accountTypeOptions;
|
||||
private List<EnumOptionData> usageOptions;
|
||||
private List<GLAccountData> assetHeaderAccountOptions;
|
||||
private List<GLAccountData> liabilityHeaderAccountOptions;
|
||||
private List<GLAccountData> equityHeaderAccountOptions;
|
||||
private List<GLAccountData> incomeHeaderAccountOptions;
|
||||
private List<GLAccountData> expenseHeaderAccountOptions;
|
||||
private Collection<CodeValueData> allowedAssetsTagOptions;
|
||||
private Collection<CodeValueData> allowedLiabilitiesTagOptions;
|
||||
private Collection<CodeValueData> allowedEquityTagOptions;
|
||||
private Collection<CodeValueData> allowedIncomeTagOptions;
|
||||
private Collection<CodeValueData> allowedExpensesTagOptions;
|
||||
|
||||
// import fields
|
||||
private transient Integer rowIndex;
|
||||
|
||||
public static GLAccountData importInstance(String name, Long parentId, String glCode, Boolean manualEntriesAllowed, EnumOptionData type,
|
||||
EnumOptionData usage, String description, CodeValueData tagId, Integer rowIndex) {
|
||||
return new GLAccountData().setName(name).setParentId(parentId).setGlCode(glCode).setManualEntriesAllowed(manualEntriesAllowed)
|
||||
.setType(type).setUsage(usage).setDescription(description).setTagId(tagId).setRowIndex(rowIndex);
|
||||
}
|
||||
|
||||
public static GLAccountData createFrom(final Long id) {
|
||||
|
||||
return new GLAccountData().setId(id);
|
||||
}
|
||||
|
||||
public static GLAccountData sensibleDefaultsForNewGLAccountCreation(final Integer glAccType) {
|
||||
final boolean disabled = false;
|
||||
final boolean manualEntriesAllowed = true;
|
||||
final EnumOptionData type;
|
||||
if (glAccType != null && glAccType >= GLAccountType.getMinValue() && glAccType <= GLAccountType.getMaxValue()) {
|
||||
type = AccountingEnumerations.gLAccountType(glAccType);
|
||||
} else {
|
||||
type = AccountingEnumerations.gLAccountType(GLAccountType.ASSET);
|
||||
}
|
||||
final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(GLAccountUsage.DETAIL);
|
||||
|
||||
return new GLAccountData().setDisabled(disabled).setManualEntriesAllowed(manualEntriesAllowed).setType(type).setUsage(usage);
|
||||
}
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* 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.accounting.glaccount.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.accounting.glaccount.api.GLAccountJsonInputParams;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "acc_gl_account", uniqueConstraints = { @UniqueConstraint(columnNames = { "gl_code" }, name = "acc_gl_code") })
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class GLAccount extends AbstractPersistableCustom {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "parent_id")
|
||||
private GLAccount parent;
|
||||
|
||||
@Column(name = "hierarchy", nullable = true, length = 50)
|
||||
private String hierarchy;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "parent_id")
|
||||
private List<GLAccount> children = new ArrayList<>();
|
||||
|
||||
@Column(name = "name", nullable = false, length = 45)
|
||||
private String name;
|
||||
|
||||
@Column(name = "gl_code", nullable = false, length = 100)
|
||||
private String glCode;
|
||||
|
||||
@Column(name = "disabled", nullable = false)
|
||||
private boolean disabled;
|
||||
|
||||
@Column(name = "manual_journal_entries_allowed", nullable = false)
|
||||
private boolean manualEntriesAllowed = true;
|
||||
|
||||
@Column(name = "classification_enum", nullable = false)
|
||||
private Integer type;
|
||||
|
||||
@Column(name = "account_usage", nullable = false)
|
||||
private Integer usage;
|
||||
|
||||
@Column(name = "description", nullable = true, length = 500)
|
||||
private String description;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "tag_id")
|
||||
private CodeValue tagId;
|
||||
|
||||
public static GLAccount fromJson(final GLAccount parent, final JsonCommand command, final CodeValue glAccountTagType) {
|
||||
final String name = command.stringValueOfParameterNamed(GLAccountJsonInputParams.NAME.getValue());
|
||||
final String glCode = command.stringValueOfParameterNamed(GLAccountJsonInputParams.GL_CODE.getValue());
|
||||
final boolean disabled = command.booleanPrimitiveValueOfParameterNamed(GLAccountJsonInputParams.DISABLED.getValue());
|
||||
final boolean manualEntriesAllowed = command
|
||||
.booleanPrimitiveValueOfParameterNamed(GLAccountJsonInputParams.MANUAL_ENTRIES_ALLOWED.getValue());
|
||||
final Integer usage = command.integerValueSansLocaleOfParameterNamed(GLAccountJsonInputParams.USAGE.getValue());
|
||||
final Integer type = command.integerValueSansLocaleOfParameterNamed(GLAccountJsonInputParams.TYPE.getValue());
|
||||
final String description = command.stringValueOfParameterNamed(GLAccountJsonInputParams.DESCRIPTION.getValue());
|
||||
return new GLAccount().setParent(parent).setName(name).setGlCode(glCode).setDisabled(disabled)
|
||||
.setManualEntriesAllowed(manualEntriesAllowed).setType(type).setUsage(usage).setDescription(description)
|
||||
.setTagId(glAccountTagType);
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(15);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.DESCRIPTION.getValue(), this.description);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.DISABLED.getValue(), this.disabled);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.GL_CODE.getValue(), this.glCode);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.MANUAL_ENTRIES_ALLOWED.getValue(), this.manualEntriesAllowed);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.NAME.getValue(), this.name);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.PARENT_ID.getValue(), 0L);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.TYPE.getValue(), this.type, true);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.USAGE.getValue(), this.usage, true);
|
||||
handlePropertyUpdate(command, actualChanges, GLAccountJsonInputParams.TAGID.getValue(),
|
||||
this.tagId == null ? 0L : this.tagId.getId());
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
|
||||
final Integer propertyToBeUpdated, final boolean sansLocale) {
|
||||
boolean changeDetected = false;
|
||||
if (sansLocale) {
|
||||
changeDetected = command.isChangeInIntegerSansLocaleParameterNamed(paramName, propertyToBeUpdated);
|
||||
} else {
|
||||
changeDetected = command.isChangeInIntegerParameterNamed(paramName, propertyToBeUpdated);
|
||||
}
|
||||
if (changeDetected) {
|
||||
Integer newValue = null;
|
||||
if (sansLocale) {
|
||||
newValue = command.integerValueSansLocaleOfParameterNamed(paramName);
|
||||
} else {
|
||||
newValue = command.integerValueOfParameterNamed(paramName);
|
||||
}
|
||||
actualChanges.put(paramName, newValue);
|
||||
// now update actual property
|
||||
if (paramName.equals(GLAccountJsonInputParams.TYPE.getValue())) {
|
||||
this.type = newValue;
|
||||
} else if (paramName.equals(GLAccountJsonInputParams.USAGE.getValue())) {
|
||||
this.usage = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
|
||||
final String propertyToBeUpdated) {
|
||||
if (command.isChangeInStringParameterNamed(paramName, propertyToBeUpdated)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(paramName);
|
||||
actualChanges.put(paramName, newValue);
|
||||
// now update actual property
|
||||
if (paramName.equals(GLAccountJsonInputParams.DESCRIPTION.getValue())) {
|
||||
this.description = newValue;
|
||||
} else if (paramName.equals(GLAccountJsonInputParams.GL_CODE.getValue())) {
|
||||
this.glCode = newValue;
|
||||
} else if (paramName.equals(GLAccountJsonInputParams.NAME.getValue())) {
|
||||
this.name = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
|
||||
final Long propertyToBeUpdated) {
|
||||
if (command.isChangeInLongParameterNamed(paramName, propertyToBeUpdated)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(paramName);
|
||||
actualChanges.put(paramName, newValue);
|
||||
// now update actual property
|
||||
if (paramName.equals(GLAccountJsonInputParams.PARENT_ID.getValue())) {
|
||||
// do nothing as this is a nested property
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
|
||||
final boolean propertyToBeUpdated) {
|
||||
if (command.isChangeInBooleanParameterNamed(paramName, propertyToBeUpdated)) {
|
||||
final Boolean newValue = command.booleanObjectValueOfParameterNamed(paramName);
|
||||
actualChanges.put(paramName, newValue);
|
||||
// now update actual property
|
||||
if (paramName.equals(GLAccountJsonInputParams.MANUAL_ENTRIES_ALLOWED.getValue())) {
|
||||
this.manualEntriesAllowed = newValue;
|
||||
} else if (paramName.equals(GLAccountJsonInputParams.DISABLED.getValue())) {
|
||||
this.disabled = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHeaderAccount() {
|
||||
return GLAccountUsage.HEADER.getValue().equals(this.usage);
|
||||
}
|
||||
|
||||
public void generateHierarchy() {
|
||||
|
||||
if (this.parent != null) {
|
||||
this.hierarchy = this.parent.hierarchyOf(getId());
|
||||
} else {
|
||||
this.hierarchy = ".";
|
||||
}
|
||||
}
|
||||
|
||||
private String hierarchyOf(final Long id) {
|
||||
return this.hierarchy + id.toString() + ".";
|
||||
}
|
||||
|
||||
public boolean isDetailAccount() {
|
||||
return GLAccountUsage.DETAIL.getValue().equals(this.usage);
|
||||
}
|
||||
}
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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.accounting.glaccount.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum GLAccountUsage {
|
||||
|
||||
DETAIL(1, "accountUsage.detail"), HEADER(2, "accountUsage.header");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
GLAccountUsage(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, GLAccountUsage> intToEnumMap = new HashMap<>();
|
||||
private static int minValue;
|
||||
private static int maxValue;
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
for (final GLAccountUsage type : GLAccountUsage.values()) {
|
||||
if (i == 0) {
|
||||
minValue = type.value;
|
||||
}
|
||||
intToEnumMap.put(type.value, type);
|
||||
if (minValue >= type.value) {
|
||||
minValue = type.value;
|
||||
}
|
||||
if (maxValue < type.value) {
|
||||
maxValue = type.value;
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static GLAccountUsage fromInt(final int i) {
|
||||
final GLAccountUsage type = intToEnumMap.get(Integer.valueOf(i));
|
||||
return type;
|
||||
}
|
||||
|
||||
public static int getMinValue() {
|
||||
return minValue;
|
||||
}
|
||||
|
||||
public static int getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
}
|
||||
fineract-core/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryType.java
Executable
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.accounting.journalentry.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum JournalEntryType {
|
||||
|
||||
CREDIT(1, "journalEntryType.credit"), DEBIT(2, "journalEntrytType.debit");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
JournalEntryType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, JournalEntryType> intToEnumMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (final JournalEntryType type : JournalEntryType.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static JournalEntryType fromInt(final int i) {
|
||||
return intToEnumMap.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name();
|
||||
}
|
||||
|
||||
public boolean isDebitType() {
|
||||
return this.value.equals(JournalEntryType.DEBIT.getValue());
|
||||
}
|
||||
|
||||
public boolean isCreditType() {
|
||||
return this.value.equals(JournalEntryType.CREDIT.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -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.accounting.producttoaccountmapping.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
public class ChargeToGLAccountMapper implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private ChargeData charge;
|
||||
private GLAccountData incomeAccount;
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.accounting.producttoaccountmapping.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class PaymentTypeToGLAccountMapper implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private PaymentTypeData paymentType;
|
||||
private GLAccountData fundSourceAccount;
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.accounting.producttoaccountmapping.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum PortfolioProductType {
|
||||
|
||||
LOAN(1, "productType.loan"), SAVING(2, "productType.saving"), CLIENT(5, "productType.client"), PROVISIONING(3,
|
||||
"productType.provisioning"), SHARES(4, "productType.shares");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
PortfolioProductType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, PortfolioProductType> intToEnumMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (final PortfolioProductType type : PortfolioProductType.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static PortfolioProductType fromInt(final int i) {
|
||||
final PortfolioProductType type = intToEnumMap.get(Integer.valueOf(i));
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isSavingProduct() {
|
||||
return this.value.equals(PortfolioProductType.SAVING.getValue());
|
||||
}
|
||||
|
||||
public boolean isLoanProduct() {
|
||||
return this.value.equals(PortfolioProductType.LOAN.getValue());
|
||||
}
|
||||
|
||||
public boolean isClient() {
|
||||
return this.value.equals(PortfolioProductType.CLIENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isShareProduct() {
|
||||
return this.value.equals(PortfolioProductType.SHARES.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.cob;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
public interface COBBusinessStep<T extends AbstractPersistableCustom> {
|
||||
|
||||
T execute(T input);
|
||||
|
||||
String getEnumStyledName();
|
||||
|
||||
String getHumanReadableName();
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.codes;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class CodeConstants {
|
||||
|
||||
/***
|
||||
* Enum of all parameters passed in while creating/updating a code and code value
|
||||
***/
|
||||
public enum CodevalueJSONinputParams {
|
||||
|
||||
CODEVALUE_ID("id"), NAME("name"), POSITION("position"), DESCRIPTION("description"), IS_ACTIVE("isActive"), IS_MANDATORY(
|
||||
"isMandatory");
|
||||
|
||||
private final String value;
|
||||
|
||||
CodevalueJSONinputParams(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
|
||||
static {
|
||||
for (final CodevalueJSONinputParams type : CodevalueJSONinputParams.values()) {
|
||||
values.add(type.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.codes.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* Immutable data object represent code-value data in system.
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class CodeValueData implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private Integer position;
|
||||
private String description;
|
||||
private boolean active;
|
||||
private boolean mandatory;
|
||||
|
||||
public static CodeValueData instance(final Long id, final String name, final Integer position, final boolean isActive,
|
||||
final boolean mandatory) {
|
||||
String description = null;
|
||||
return new CodeValueData().setId(id).setName(name).setPosition(position).setDescription(description).setActive(isActive)
|
||||
.setMandatory(mandatory);
|
||||
}
|
||||
|
||||
public static CodeValueData instance(final Long id, final String name, final String description, final boolean isActive,
|
||||
final boolean mandatory) {
|
||||
Integer position = null;
|
||||
return new CodeValueData().setId(id).setName(name).setPosition(position).setDescription(description).setActive(isActive)
|
||||
.setMandatory(mandatory);
|
||||
}
|
||||
|
||||
public static CodeValueData instance(final Long id, final String name, final String description, final boolean isActive) {
|
||||
Integer position = null;
|
||||
boolean mandatory = false;
|
||||
|
||||
return new CodeValueData().setId(id).setName(name).setPosition(position).setDescription(description).setActive(isActive)
|
||||
.setMandatory(mandatory);
|
||||
}
|
||||
|
||||
public static CodeValueData instance(final Long id, final String name) {
|
||||
String description = null;
|
||||
Integer position = null;
|
||||
boolean isActive = false;
|
||||
boolean mandatory = false;
|
||||
|
||||
return new CodeValueData().setId(id).setName(name).setPosition(position).setDescription(description).setActive(isActive)
|
||||
.setMandatory(mandatory);
|
||||
}
|
||||
|
||||
public static CodeValueData instance(final Long id, final String name, final Integer position, final String description,
|
||||
final boolean isActive, final boolean mandatory) {
|
||||
return new CodeValueData().setId(id).setName(name).setPosition(position).setDescription(description).setActive(isActive)
|
||||
.setMandatory(mandatory);
|
||||
}
|
||||
}
|
||||
@@ -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.infrastructure.codes.domain;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.codes.exception.SystemDefinedCodeCannotBeChangedException;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_code", uniqueConstraints = { @UniqueConstraint(columnNames = { "code_name" }, name = "code_name") })
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class Code extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "code_name", length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "is_system_defined")
|
||||
private boolean systemDefined;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "code", orphanRemoval = true)
|
||||
private Set<CodeValue> values;
|
||||
|
||||
public static Code fromJson(final JsonCommand command) {
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
return new Code().setName(name);
|
||||
}
|
||||
|
||||
public static Code createNew(final String name) {
|
||||
return new Code().setName(name);
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
if (this.systemDefined) {
|
||||
throw new SystemDefinedCodeCannotBeChangedException();
|
||||
}
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(1);
|
||||
|
||||
final String firstnameParamName = "name";
|
||||
if (command.isChangeInStringParameterNamed(firstnameParamName, this.name)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(firstnameParamName);
|
||||
actualChanges.put(firstnameParamName, newValue);
|
||||
this.name = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean remove(final CodeValue codeValueToDelete) {
|
||||
return this.values.remove(codeValueToDelete);
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* 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.codes.domain;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.codes.CodeConstants.CodevalueJSONinputParams;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_code_value", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "code_id", "code_value" }, name = "code_value_duplicate") })
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class CodeValue extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "code_value", length = 100)
|
||||
private String label;
|
||||
|
||||
@Column(name = "order_position")
|
||||
private int position;
|
||||
|
||||
@Column(name = "code_description")
|
||||
private String description;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "code_id", nullable = false)
|
||||
private Code code;
|
||||
|
||||
@Column(name = "is_active")
|
||||
private boolean isActive;
|
||||
|
||||
@Column(name = "is_mandatory")
|
||||
private boolean mandatory;
|
||||
|
||||
public static CodeValue createNew(final Code code, final String label, final int position, final String description,
|
||||
final boolean isActive, final boolean mandatory) {
|
||||
return new CodeValue().setCode(code).setLabel(StringUtils.defaultIfEmpty(label, null)).setPosition(position)
|
||||
.setDescription(description).setActive(isActive).setMandatory(mandatory);
|
||||
}
|
||||
|
||||
public static CodeValue fromJson(final Code code, final JsonCommand command) {
|
||||
|
||||
final String label = command.stringValueOfParameterNamed(CodevalueJSONinputParams.NAME.getValue());
|
||||
Integer position = command.integerValueSansLocaleOfParameterNamed(CodevalueJSONinputParams.POSITION.getValue());
|
||||
String description = command.stringValueOfParameterNamed(CodevalueJSONinputParams.DESCRIPTION.getValue());
|
||||
Boolean isActiveObj = command.booleanObjectValueOfParameterNamed(CodevalueJSONinputParams.IS_ACTIVE.getValue());
|
||||
boolean isActive = true;
|
||||
if (isActiveObj != null) {
|
||||
isActive = isActiveObj;
|
||||
}
|
||||
if (position == null) {
|
||||
position = 0;
|
||||
}
|
||||
|
||||
Boolean mandatory = command.booleanPrimitiveValueOfParameterNamed(CodevalueJSONinputParams.IS_MANDATORY.getValue());
|
||||
|
||||
return new CodeValue().setCode(code).setLabel(StringUtils.defaultIfEmpty(label, null)).setPosition(position)
|
||||
.setDescription(description).setActive(isActive).setMandatory(mandatory);
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(2);
|
||||
|
||||
final String labelParamName = CodevalueJSONinputParams.NAME.getValue();
|
||||
if (command.isChangeInStringParameterNamed(labelParamName, this.label)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(labelParamName);
|
||||
actualChanges.put(labelParamName, newValue);
|
||||
this.label = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
final String decriptionParamName = CodevalueJSONinputParams.DESCRIPTION.getValue();
|
||||
if (command.isChangeInStringParameterNamed(decriptionParamName, this.description)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(decriptionParamName);
|
||||
actualChanges.put(decriptionParamName, newValue);
|
||||
this.description = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
final String positionParamName = CodevalueJSONinputParams.POSITION.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(positionParamName, this.position)) {
|
||||
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(positionParamName);
|
||||
actualChanges.put(positionParamName, newValue);
|
||||
this.position = newValue;
|
||||
}
|
||||
|
||||
final String isActiveParamName = CodevalueJSONinputParams.IS_ACTIVE.getValue();
|
||||
if (command.isChangeInBooleanParameterNamed(isActiveParamName, this.isActive)) {
|
||||
final Boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isActiveParamName);
|
||||
actualChanges.put(isActiveParamName, newValue);
|
||||
this.isActive = newValue;
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public CodeValueData toData() {
|
||||
return CodeValueData.instance(getId(), this.label, this.position, this.isActive, this.mandatory);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.codes.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* A {@link AbstractPlatformDomainRuleException} thrown when someone attempts to update or delete a system defined code.
|
||||
*/
|
||||
public class SystemDefinedCodeCannotBeChangedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public SystemDefinedCodeCannotBeChangedException() {
|
||||
super("error.msg.code.systemdefined", "This code is system defined and cannot be modified or deleted.");
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.configuration.service;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Temporary (static) configuration service container.
|
||||
*
|
||||
* Provide static access to the configuration service TODO: To be deleted when the code cleanup / refactor finished (of
|
||||
* Loan.java) and we dont need this workaround anymore
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class TemporaryConfigurationServiceContainer implements InitializingBean {
|
||||
|
||||
private static volatile ConfigurationDomainService STATIC_REF_CONFIGURATION_SERVICE;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
// To avoid any abuse of this temporary solution, only the `isExternalIdAutoGenerationEnabled()` is exposed
|
||||
public static boolean isExternalIdAutoGenerationEnabled() {
|
||||
return TemporaryConfigurationServiceContainer.STATIC_REF_CONFIGURATION_SERVICE.isExternalIdAutoGenerationEnabled();
|
||||
}
|
||||
|
||||
public static String getAccrualDateConfigForCharge() {
|
||||
return TemporaryConfigurationServiceContainer.STATIC_REF_CONFIGURATION_SERVICE.getAccrualDateConfigForCharge();
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
TemporaryConfigurationServiceContainer.STATIC_REF_CONFIGURATION_SERVICE = configurationDomainService;
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import org.springframework.data.domain.Auditable;
|
||||
import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
|
||||
/**
|
||||
* Make sure to modify the same class in the modules (fineract-investor, etc)
|
||||
*
|
||||
* A custom copy of {@link AbstractAuditable} to override the column names used on database. It also uses Instant
|
||||
* instead of LocalDateTime for created and modified.
|
||||
*
|
||||
* Abstract base class for auditable entities. Stores the audit values in persistent fields.
|
||||
*
|
||||
* @param <U>
|
||||
* the auditing type. Typically some kind of user.
|
||||
* @param <PK>
|
||||
* the type of the auditing type's identifier
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractAuditableCustom extends AbstractPersistableCustom implements Auditable<Long, Long, LocalDateTime> {
|
||||
|
||||
private static final long serialVersionUID = 141481953116476081L;
|
||||
|
||||
@Column(name = "createdby_id")
|
||||
private Long createdBy;
|
||||
|
||||
@Column(name = "created_date")
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
@Column(name = "lastmodifiedby_id")
|
||||
private Long lastModifiedBy;
|
||||
|
||||
@Column(name = "lastmodified_date")
|
||||
private LocalDateTime lastModifiedDate;
|
||||
|
||||
@Override
|
||||
public Optional<Long> getCreatedBy() {
|
||||
return Optional.ofNullable(this.createdBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreatedBy(final Long createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LocalDateTime> getCreatedDate() {
|
||||
return null == this.createdDate ? Optional.empty() : Optional.of(this.createdDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreatedDate(final LocalDateTime createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Long> getLastModifiedBy() {
|
||||
return Optional.ofNullable(this.lastModifiedBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastModifiedBy(final Long lastModifiedBy) {
|
||||
this.lastModifiedBy = lastModifiedBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LocalDateTime> getLastModifiedDate() {
|
||||
return null == this.lastModifiedDate ? Optional.empty() : Optional.of(this.lastModifiedDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastModifiedDate(final LocalDateTime lastModifiedDate) {
|
||||
this.lastModifiedDate = lastModifiedDate;
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 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 static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY_DB_FIELD;
|
||||
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE_DB_FIELD;
|
||||
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_BY_DB_FIELD;
|
||||
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_DATE_DB_FIELD;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.springframework.data.domain.Auditable;
|
||||
import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
|
||||
/**
|
||||
* A custom copy of {@link AbstractAuditable} to override the column names used on database. It also uses OffsetDateTime
|
||||
* for created and modified. The datetimes will be converted from tenant TZ to UTC before storing (automatically
|
||||
* happens) and converted from System TZ to tenant TZ after fetching from DB
|
||||
*
|
||||
* Abstract base class for auditable entities. Stores the audit values in persistent fields.
|
||||
*/
|
||||
@MappedSuperclass
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public abstract class AbstractAuditableWithUTCDateTimeCustom extends AbstractPersistableCustom
|
||||
implements Auditable<Long, Long, OffsetDateTime> {
|
||||
|
||||
private static final long serialVersionUID = 141481953116476081L;
|
||||
|
||||
@Column(name = CREATED_BY_DB_FIELD, nullable = false)
|
||||
@Setter(onMethod = @__(@Override))
|
||||
private Long createdBy;
|
||||
|
||||
@Column(name = CREATED_DATE_DB_FIELD, nullable = false)
|
||||
@Setter(onMethod = @__(@Override))
|
||||
private OffsetDateTime createdDate;
|
||||
|
||||
@Column(name = LAST_MODIFIED_BY_DB_FIELD, nullable = false)
|
||||
@Setter(onMethod = @__(@Override))
|
||||
private Long lastModifiedBy;
|
||||
|
||||
@Column(name = LAST_MODIFIED_DATE_DB_FIELD, nullable = false)
|
||||
@Setter(onMethod = @__(@Override))
|
||||
private OffsetDateTime lastModifiedDate;
|
||||
|
||||
@Override
|
||||
public Optional<Long> getCreatedBy() {
|
||||
return Optional.ofNullable(this.createdBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<OffsetDateTime> getCreatedDate() {
|
||||
if (this.createdDate == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(this.createdDate
|
||||
.withOffsetSameInstant(DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(this.createdDate.toInstant())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Long> getLastModifiedBy() {
|
||||
return Optional.ofNullable(this.lastModifiedBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<OffsetDateTime> getLastModifiedDate() {
|
||||
if (this.lastModifiedDate == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(this.lastModifiedDate
|
||||
.withOffsetSameInstant(DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(this.lastModifiedDate.toInstant())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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 javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.PrePersist;
|
||||
import javax.persistence.Transient;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
|
||||
/**
|
||||
* Make sure to modify the same class in the modules (fineract-investor, etc)
|
||||
*
|
||||
* Abstract base class for entities.
|
||||
*
|
||||
* Inspired by {@link org.springframework.data.jpa.domain.AbstractPersistable}, but Id is always Long (and this class
|
||||
* thus does not require generic parameterization), and auto-generation is of strategy
|
||||
* {@link javax.persistence.GenerationType#IDENTITY}.
|
||||
*
|
||||
* The {@link #equals(Object)} and {@link #hashCode()} methods are NOT implemented here, which is untypical for JPA
|
||||
* (it's usually implemented based on the Id), because "we end up with issues on OpenJPA" (TODO clarify this).
|
||||
*/
|
||||
@MappedSuperclass
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public abstract class AbstractPersistableCustom implements Persistable<Long>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 9181640245194392646L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private Long id;
|
||||
|
||||
@Transient
|
||||
@Setter(value = AccessLevel.NONE)
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private boolean isNew = true;
|
||||
|
||||
@PrePersist
|
||||
@PostLoad
|
||||
void markNotNew() {
|
||||
this.isNew = false;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class LocalDateInterval {
|
||||
|
||||
private final LocalDate startDate;
|
||||
private final LocalDate endDate;
|
||||
|
||||
public static LocalDateInterval create(final LocalDate startDate, final LocalDate endDate) {
|
||||
return new LocalDateInterval(startDate, endDate);
|
||||
}
|
||||
|
||||
public LocalDateInterval(final LocalDate startDate, final LocalDate endDate) {
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public LocalDate startDate() {
|
||||
return this.startDate;
|
||||
}
|
||||
|
||||
public LocalDate endDate() {
|
||||
return this.endDate;
|
||||
}
|
||||
|
||||
public Integer daysInPeriodInclusiveOfEndDate() {
|
||||
return daysBetween() + 1;
|
||||
}
|
||||
|
||||
private Integer daysBetween() {
|
||||
return Math.toIntExact(ChronoUnit.DAYS.between(this.startDate, this.endDate));
|
||||
}
|
||||
|
||||
public boolean containsPortionOf(final LocalDateInterval interval) {
|
||||
return contains(interval.startDate) || contains(interval.endDate);
|
||||
}
|
||||
|
||||
public boolean contains(final LocalDateInterval interval) {
|
||||
return contains(interval.startDate) && contains(interval.endDate);
|
||||
}
|
||||
|
||||
public boolean contains(final LocalDate target) {
|
||||
return isBetweenInclusive(this.startDate, this.endDate, target);
|
||||
}
|
||||
|
||||
private boolean isBetweenInclusive(final LocalDate start, final LocalDate end, final LocalDate target) {
|
||||
return !target.isBefore(start) && !target.isAfter(end);
|
||||
}
|
||||
|
||||
public boolean fallsBefore(final LocalDate dateToCheck) {
|
||||
return this.endDate.isBefore(dateToCheck);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when a valid API request ends up violating some domain rule.
|
||||
*/
|
||||
public abstract class AbstractPlatformDomainRuleException extends AbstractPlatformException {
|
||||
|
||||
protected AbstractPlatformDomainRuleException(String globalisationMessageCode, String defaultUserMessage,
|
||||
Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when resources that are queried for are not found.
|
||||
*/
|
||||
public abstract class AbstractPlatformResourceNotFoundException extends AbstractPlatformException {
|
||||
|
||||
protected AbstractPlatformResourceNotFoundException(final String globalisationMessageCode, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when valid api request end up violating some domain rule.
|
||||
*/
|
||||
public final class GeneralPlatformDomainRuleException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public GeneralPlatformDomainRuleException(String globalisationMessageCode, String defaultUserMessage,
|
||||
Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+43
@@ -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.exception;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when data integrity problems happen due to state modifying actions.
|
||||
*/
|
||||
public class PlatformDataIntegrityException extends AbstractPlatformException {
|
||||
|
||||
private final String parameterName;
|
||||
|
||||
public PlatformDataIntegrityException(final String globalisationMessageCode, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
this.parameterName = null;
|
||||
}
|
||||
|
||||
public PlatformDataIntegrityException(final String globalisationMessageCode, final String defaultUserMessage,
|
||||
final String parameterName, final Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
this.parameterName = parameterName;
|
||||
}
|
||||
|
||||
public String getParameterName() {
|
||||
return this.parameterName;
|
||||
}
|
||||
}
|
||||
+572
@@ -0,0 +1,572 @@
|
||||
/**
|
||||
* 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 org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public final class SearchParameters {
|
||||
|
||||
private final String sqlSearch;
|
||||
private final Long officeId;
|
||||
private final String externalId;
|
||||
private final String name;
|
||||
private final String hierarchy;
|
||||
private final String firstname;
|
||||
private final String lastname;
|
||||
private final String status;
|
||||
private final Integer offset;
|
||||
private final Integer limit;
|
||||
private final String orderBy;
|
||||
private final String sortOrder;
|
||||
private final String accountNo;
|
||||
private final String currencyCode;
|
||||
|
||||
private final Long staffId;
|
||||
|
||||
private final Long loanId;
|
||||
|
||||
private final Long savingsId;
|
||||
private final Boolean orphansOnly;
|
||||
|
||||
// Provisning Entries Search Params
|
||||
private final Long provisioningEntryId;
|
||||
private final Long productId;
|
||||
private final Long categoryId;
|
||||
private final boolean isSelfUser;
|
||||
|
||||
public static SearchParameters from(final String sqlSearch, final Long officeId, final String externalId, final String name,
|
||||
final String hierarchy) {
|
||||
final Long staffId = null;
|
||||
final String accountNo = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
return new SearchParameters(sqlSearch, officeId, externalId, name, hierarchy, null, null, null, null, null, null, staffId,
|
||||
accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forClients(final String sqlSearch, final Long officeId, final String externalId,
|
||||
final String displayName, final String firstname, final String lastname, final String status, final String hierarchy,
|
||||
final Integer offset, final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly,
|
||||
final boolean isSelfUser) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final String accountNo = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
|
||||
return new SearchParameters(sqlSearch, officeId, externalId, displayName, hierarchy, firstname, lastname, status, offset,
|
||||
maxLimitAllowed, orderBy, sortOrder, staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forGroups(final Long officeId, final Long staffId, final String externalId, final String name,
|
||||
final String hierarchy, final Integer offset, final Integer limit, final String orderBy, final String sortOrder,
|
||||
final Boolean orphansOnly) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final String accountNo = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(officeId, externalId, name, hierarchy, null, null, offset, maxLimitAllowed, orderBy, sortOrder, staffId,
|
||||
accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forOffices(final String orderBy, final String sortOrder) {
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
return new SearchParameters(null, null, null, null, null, null, null, null, null, orderBy, sortOrder, null, null, null, null,
|
||||
orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forLoans(final String sqlSearch, final String externalId, final Integer offset, final Integer limit,
|
||||
final String orderBy, final String sortOrder, final String accountNo) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(sqlSearch, null, externalId, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder,
|
||||
staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forJournalEntries(final Long officeId, final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder, final Long loanId, final Long savingsId) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(null, officeId, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, staffId,
|
||||
null, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forJournalEntries(final Long officeId, final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder, final Long loanId, final Long savingsId, final String currencyCode) {
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
|
||||
return new SearchParameters(null, officeId, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, staffId,
|
||||
null, loanId, savingsId, orphansOnly, currencyCode);
|
||||
}
|
||||
|
||||
public static SearchParameters forPagination(final Integer offset, final Integer limit, final String orderBy, final String sortOrder) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, staffId, null,
|
||||
loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forPaginationAndAccountNumberSearch(final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder, final String accountNumber) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, staffId,
|
||||
accountNumber, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forPagination(final Integer offset, final Integer limit) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final String orderBy = null;
|
||||
final String sortOrder = null;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, staffId, null,
|
||||
loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forProvisioningEntries(final Long provisioningEntryId, final Long officeId, final Long productId,
|
||||
final Long categoryId, final Integer offset, final Integer limit) {
|
||||
return new SearchParameters(provisioningEntryId, officeId, productId, categoryId, offset, limit);
|
||||
}
|
||||
|
||||
public static SearchParameters forSavings(final String sqlSearch, final String externalId, final Integer offset, final Integer limit,
|
||||
final String orderBy, final String sortOrder) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final String accountNo = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(sqlSearch, null, externalId, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder,
|
||||
staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forAccountTransfer(final String sqlSearch, final String externalId, final Integer offset,
|
||||
final Integer limit, final String orderBy, final String sortOrder) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final String accountNo = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(sqlSearch, null, externalId, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder,
|
||||
staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forSMSCampaign(final String sqlSearch, final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder) {
|
||||
|
||||
final String externalId = null;
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final String accountNo = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(sqlSearch, null, externalId, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder,
|
||||
staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forEmailCampaign(final String sqlSearch, final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder) {
|
||||
|
||||
final String externalId = null;
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final String accountNo = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(sqlSearch, null, externalId, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder,
|
||||
staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
private SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name,
|
||||
final String hierarchy, final String firstname, final String lastname, final Integer offset, final Integer limit,
|
||||
final String orderBy, final String sortOrder, final Long staffId, final String accountNo, final Long loanId,
|
||||
final Long savingsId, final Boolean orphansOnly, boolean isSelfUser) {
|
||||
this.sqlSearch = sqlSearch;
|
||||
this.officeId = officeId;
|
||||
this.externalId = externalId;
|
||||
this.name = name;
|
||||
this.hierarchy = hierarchy;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.offset = offset;
|
||||
this.limit = limit;
|
||||
this.orderBy = orderBy;
|
||||
this.sortOrder = sortOrder;
|
||||
this.staffId = staffId;
|
||||
this.accountNo = accountNo;
|
||||
this.loanId = loanId;
|
||||
this.savingsId = savingsId;
|
||||
this.orphansOnly = orphansOnly;
|
||||
this.currencyCode = null;
|
||||
this.provisioningEntryId = null;
|
||||
this.productId = null;
|
||||
this.categoryId = null;
|
||||
this.isSelfUser = isSelfUser;
|
||||
this.status = null;
|
||||
|
||||
}
|
||||
|
||||
private SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name,
|
||||
final String hierarchy, final String firstname, final String lastname, final String status, final Integer offset,
|
||||
final Integer limit, final String orderBy, final String sortOrder, final Long staffId, final String accountNo,
|
||||
final Long loanId, final Long savingsId, final Boolean orphansOnly, boolean isSelfUser) {
|
||||
this.sqlSearch = sqlSearch;
|
||||
this.officeId = officeId;
|
||||
this.externalId = externalId;
|
||||
this.name = name;
|
||||
this.hierarchy = hierarchy;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.offset = offset;
|
||||
this.limit = limit;
|
||||
this.orderBy = orderBy;
|
||||
this.sortOrder = sortOrder;
|
||||
this.staffId = staffId;
|
||||
this.accountNo = accountNo;
|
||||
this.loanId = loanId;
|
||||
this.savingsId = savingsId;
|
||||
this.orphansOnly = orphansOnly;
|
||||
this.currencyCode = null;
|
||||
this.provisioningEntryId = null;
|
||||
this.productId = null;
|
||||
this.categoryId = null;
|
||||
this.isSelfUser = isSelfUser;
|
||||
this.status = status;
|
||||
|
||||
}
|
||||
|
||||
private SearchParameters(final Long officeId, final String externalId, final String name, final String hierarchy,
|
||||
final String firstname, final String lastname, final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder, final Long staffId, final String accountNo, final Long loanId, final Long savingsId,
|
||||
final Boolean orphansOnly, boolean isSelfUser) {
|
||||
this.sqlSearch = null;
|
||||
this.officeId = officeId;
|
||||
this.externalId = externalId;
|
||||
this.name = name;
|
||||
this.hierarchy = hierarchy;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.offset = offset;
|
||||
this.limit = limit;
|
||||
this.orderBy = orderBy;
|
||||
this.sortOrder = sortOrder;
|
||||
this.staffId = staffId;
|
||||
this.accountNo = accountNo;
|
||||
this.loanId = loanId;
|
||||
this.savingsId = savingsId;
|
||||
this.orphansOnly = orphansOnly;
|
||||
this.currencyCode = null;
|
||||
this.provisioningEntryId = null;
|
||||
this.productId = null;
|
||||
this.categoryId = null;
|
||||
this.isSelfUser = isSelfUser;
|
||||
this.status = null;
|
||||
}
|
||||
|
||||
private SearchParameters(final Long provisioningEntryId, final Long officeId, final Long productId, final Long categoryId,
|
||||
final Integer offset, final Integer limit) {
|
||||
this.sqlSearch = null;
|
||||
this.externalId = null;
|
||||
this.name = null;
|
||||
this.hierarchy = null;
|
||||
this.firstname = null;
|
||||
this.lastname = null;
|
||||
this.orderBy = null;
|
||||
this.sortOrder = null;
|
||||
this.staffId = null;
|
||||
this.accountNo = null;
|
||||
this.loanId = null;
|
||||
this.savingsId = null;
|
||||
this.orphansOnly = null;
|
||||
this.currencyCode = null;
|
||||
this.officeId = officeId;
|
||||
this.offset = offset;
|
||||
this.limit = limit;
|
||||
this.provisioningEntryId = provisioningEntryId;
|
||||
this.productId = productId;
|
||||
this.categoryId = categoryId;
|
||||
this.isSelfUser = false;
|
||||
this.status = null;
|
||||
|
||||
}
|
||||
|
||||
public SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, final String hierarchy,
|
||||
final String firstname, final String lastname, final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder, final Long staffId, final String accountNo, final Long loanId, final Long savingsId,
|
||||
final Boolean orphansOnly, final String currencyCode) {
|
||||
this.sqlSearch = sqlSearch;
|
||||
this.officeId = officeId;
|
||||
this.externalId = externalId;
|
||||
this.name = name;
|
||||
this.hierarchy = hierarchy;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.offset = offset;
|
||||
this.limit = limit;
|
||||
this.orderBy = orderBy;
|
||||
this.sortOrder = sortOrder;
|
||||
this.staffId = staffId;
|
||||
this.accountNo = accountNo;
|
||||
this.loanId = loanId;
|
||||
this.savingsId = savingsId;
|
||||
this.orphansOnly = orphansOnly;
|
||||
this.currencyCode = currencyCode;
|
||||
this.provisioningEntryId = null;
|
||||
this.productId = null;
|
||||
this.categoryId = null;
|
||||
this.isSelfUser = false;
|
||||
this.status = null;
|
||||
|
||||
}
|
||||
|
||||
public boolean isOrderByRequested() {
|
||||
return StringUtils.isNotBlank(this.orderBy);
|
||||
}
|
||||
|
||||
public boolean isSortOrderProvided() {
|
||||
return StringUtils.isNotBlank(this.sortOrder);
|
||||
}
|
||||
|
||||
public static Integer getCheckedLimit(final Integer limit) {
|
||||
|
||||
final Integer maxLimitAllowed = 200;
|
||||
// default to max limit first off
|
||||
Integer checkedLimit = maxLimitAllowed;
|
||||
|
||||
if (limit != null && limit > 0) {
|
||||
checkedLimit = limit;
|
||||
} else if (limit != null) {
|
||||
// unlimited case: limit provided and 0 or less
|
||||
checkedLimit = null;
|
||||
}
|
||||
|
||||
return checkedLimit;
|
||||
}
|
||||
|
||||
public boolean isOfficeIdPassed() {
|
||||
return this.officeId != null && this.officeId != 0;
|
||||
}
|
||||
|
||||
public boolean isCurrencyCodePassed() {
|
||||
return this.currencyCode != null;
|
||||
}
|
||||
|
||||
public boolean isLimited() {
|
||||
return this.limit != null && this.limit.intValue() > 0;
|
||||
}
|
||||
|
||||
public boolean isOffset() {
|
||||
return this.offset != null;
|
||||
}
|
||||
|
||||
public boolean isScopedByOfficeHierarchy() {
|
||||
return StringUtils.isNotBlank(this.hierarchy);
|
||||
}
|
||||
|
||||
public String getSqlSearch() {
|
||||
return this.sqlSearch;
|
||||
}
|
||||
|
||||
public Long getOfficeId() {
|
||||
return this.officeId;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return this.currencyCode;
|
||||
}
|
||||
|
||||
public String getExternalId() {
|
||||
return this.externalId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getHierarchy() {
|
||||
return this.hierarchy;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return this.firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return this.lastname;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public Integer getOffset() {
|
||||
return this.offset;
|
||||
}
|
||||
|
||||
public Integer getLimit() {
|
||||
return this.limit;
|
||||
}
|
||||
|
||||
public String getOrderBy() {
|
||||
return this.orderBy;
|
||||
}
|
||||
|
||||
public String getSortOrder() {
|
||||
return this.sortOrder;
|
||||
}
|
||||
|
||||
public boolean isStaffIdPassed() {
|
||||
return this.staffId != null && this.staffId != 0;
|
||||
}
|
||||
|
||||
public Long getStaffId() {
|
||||
return this.staffId;
|
||||
}
|
||||
|
||||
public String getAccountNo() {
|
||||
return this.accountNo;
|
||||
}
|
||||
|
||||
public boolean isLoanIdPassed() {
|
||||
return this.loanId != null && this.loanId != 0;
|
||||
}
|
||||
|
||||
public boolean isSavingsIdPassed() {
|
||||
return this.savingsId != null && this.savingsId != 0;
|
||||
}
|
||||
|
||||
public Long getLoanId() {
|
||||
return this.loanId;
|
||||
}
|
||||
|
||||
public Long getSavingsId() {
|
||||
return this.savingsId;
|
||||
}
|
||||
|
||||
public Boolean isOrphansOnly() {
|
||||
if (this.orphansOnly != null) {
|
||||
return this.orphansOnly;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Long getProvisioningEntryId() {
|
||||
return this.provisioningEntryId;
|
||||
}
|
||||
|
||||
public boolean isProvisioningEntryIdPassed() {
|
||||
return this.provisioningEntryId != null && this.provisioningEntryId != 0;
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return this.productId;
|
||||
}
|
||||
|
||||
public boolean isProductIdPassed() {
|
||||
return this.productId != null && this.productId != 0;
|
||||
}
|
||||
|
||||
public Long getCategoryId() {
|
||||
return this.categoryId;
|
||||
}
|
||||
|
||||
public boolean isCategoryIdPassed() {
|
||||
return this.categoryId != null && this.categoryId != 0;
|
||||
}
|
||||
|
||||
public boolean isSelfUser() {
|
||||
return this.isSelfUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an instance of the SearchParameters from a request for the report mailing job run history
|
||||
*
|
||||
* @return SearchParameters object
|
||||
**/
|
||||
public static SearchParameters fromReportMailingJobRunHistory(final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder) {
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
|
||||
return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, null, null, null,
|
||||
null, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an instance of the {@link SearchParameters} from a request for the report mailing job
|
||||
*
|
||||
* @return {@link SearchParameters} object
|
||||
*/
|
||||
public static SearchParameters fromReportMailingJob(final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder) {
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
|
||||
return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, null, null, null,
|
||||
null, null, false);
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.dataqueries.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Immutable data object representing datatable data.
|
||||
*/
|
||||
public final class DatatableData implements Serializable {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final String applicationTableName;
|
||||
@SuppressWarnings("unused")
|
||||
private final String registeredTableName;
|
||||
@SuppressWarnings("unused")
|
||||
private final String entitySubType;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<ResultsetColumnHeaderData> columnHeaderData;
|
||||
|
||||
public static DatatableData create(final String applicationTableName, final String registeredTableName, final String entitySubType,
|
||||
final List<ResultsetColumnHeaderData> columnHeaderData) {
|
||||
return new DatatableData(applicationTableName, registeredTableName, entitySubType, columnHeaderData);
|
||||
}
|
||||
|
||||
private DatatableData(final String applicationTableName, final String registeredTableName, final String entitySubType,
|
||||
final List<ResultsetColumnHeaderData> columnHeaderData) {
|
||||
this.applicationTableName = applicationTableName;
|
||||
this.registeredTableName = registeredTableName;
|
||||
this.entitySubType = entitySubType;
|
||||
this.columnHeaderData = columnHeaderData;
|
||||
|
||||
}
|
||||
|
||||
public boolean hasColumn(final String columnName) {
|
||||
|
||||
for (ResultsetColumnHeaderData c : this.columnHeaderData) {
|
||||
|
||||
if (c.getColumnName().equals(columnName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getRegisteredTableName() {
|
||||
return registeredTableName;
|
||||
}
|
||||
|
||||
}
|
||||
+352
@@ -0,0 +1,352 @@
|
||||
/**
|
||||
* 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.dataqueries.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a resultset column.
|
||||
*/
|
||||
public final class ResultsetColumnHeaderData implements Serializable {
|
||||
|
||||
private final String columnName;
|
||||
private String columnType;
|
||||
private final Long columnLength;
|
||||
private final String columnDisplayType;
|
||||
private final boolean isColumnNullable;
|
||||
private final boolean isColumnPrimaryKey;
|
||||
private final boolean isColumnUnique;
|
||||
private final boolean isColumnIndexed;
|
||||
|
||||
private final List<ResultsetColumnValueData> columnValues;
|
||||
private final String columnCode;
|
||||
|
||||
public static ResultsetColumnHeaderData basic(final String columnName, final String columnType) {
|
||||
|
||||
final Long columnLength = null;
|
||||
final boolean columnNullable = false;
|
||||
final boolean columnIsPrimaryKey = false;
|
||||
final List<ResultsetColumnValueData> columnValues = new ArrayList<>();
|
||||
final String columnCode = null;
|
||||
final boolean columnIsUnique = false;
|
||||
final boolean columnIsIndexed = false;
|
||||
return new ResultsetColumnHeaderData(columnName, columnType, columnLength, columnNullable, columnIsPrimaryKey, columnValues,
|
||||
columnCode, columnIsUnique, columnIsIndexed);
|
||||
}
|
||||
|
||||
public static ResultsetColumnHeaderData detailed(final String columnName, final String columnType, final Long columnLength,
|
||||
final boolean columnNullable, final boolean columnIsPrimaryKey, final List<ResultsetColumnValueData> columnValues,
|
||||
final String columnCode, final boolean columnIsUnique, final boolean columnIsIndexed) {
|
||||
return new ResultsetColumnHeaderData(columnName, columnType, columnLength, columnNullable, columnIsPrimaryKey, columnValues,
|
||||
columnCode, columnIsUnique, columnIsIndexed);
|
||||
}
|
||||
|
||||
private ResultsetColumnHeaderData(final String columnName, final String columnType, final Long columnLength,
|
||||
final boolean columnNullable, final boolean columnIsPrimaryKey, final List<ResultsetColumnValueData> columnValues,
|
||||
final String columnCode, final boolean columnIsUnique, final boolean columnIsIndexed) {
|
||||
this.columnName = columnName;
|
||||
this.columnType = columnType;
|
||||
this.columnLength = columnLength;
|
||||
this.isColumnNullable = columnNullable;
|
||||
this.isColumnPrimaryKey = columnIsPrimaryKey;
|
||||
this.columnValues = columnValues;
|
||||
this.columnCode = columnCode;
|
||||
this.isColumnUnique = columnIsUnique;
|
||||
this.isColumnIndexed = columnIsIndexed;
|
||||
|
||||
// Refer org.drizzle.jdbc.internal.mysql.MySQLType.java
|
||||
adjustColumnTypes();
|
||||
|
||||
String displayType = null;
|
||||
if (this.columnCode == null) {
|
||||
if (isString()) {
|
||||
displayType = "STRING";
|
||||
} else if (isAnyInteger()) {
|
||||
if (isInteger()) {
|
||||
this.columnType = this.columnType.toUpperCase();
|
||||
}
|
||||
displayType = "INTEGER";
|
||||
} else if (isDate()) {
|
||||
displayType = "DATE";
|
||||
} else if (isDateTime()) {
|
||||
displayType = "DATETIME";
|
||||
} else if (isDecimal()) {
|
||||
displayType = "DECIMAL";
|
||||
} else if (isAnyText()) {
|
||||
displayType = "TEXT";
|
||||
} else if (isBit() || isBoolean()) {
|
||||
displayType = "BOOLEAN";
|
||||
} else {
|
||||
throw new PlatformDataIntegrityException("error.msg.invalid.lookup.type",
|
||||
"Invalid Lookup Type:" + this.columnType + " - Column Name: " + this.columnName);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (isInt() || isInteger()) {
|
||||
displayType = "CODELOOKUP";
|
||||
} else if (isVarchar()) {
|
||||
displayType = "CODEVALUE";
|
||||
} else {
|
||||
throw new PlatformDataIntegrityException("error.msg.invalid.lookup.type",
|
||||
"Invalid Lookup Type:" + this.columnType + " - Column Name: " + this.columnName);
|
||||
}
|
||||
}
|
||||
|
||||
this.columnDisplayType = displayType;
|
||||
}
|
||||
|
||||
private void adjustColumnTypes() {
|
||||
switch (this.columnType) {
|
||||
case "NEWDECIMAL":
|
||||
this.columnType = "DECIMAL";
|
||||
break;
|
||||
case "CLOB":
|
||||
case "ENUM":
|
||||
case "SET":
|
||||
this.columnType = "varchar";
|
||||
break;
|
||||
case "LONGLONG":
|
||||
this.columnType = "bigint";
|
||||
break;
|
||||
case "SHORT":
|
||||
this.columnType = "smallint";
|
||||
break;
|
||||
case "TINY":
|
||||
this.columnType = "tinyint";
|
||||
break;
|
||||
case "INT24":
|
||||
this.columnType = "int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNamed(final String columnName) {
|
||||
return this.columnName.equalsIgnoreCase(columnName);
|
||||
}
|
||||
|
||||
private boolean isAnyText() {
|
||||
return isText() || isTinyText() || isMediumText() || isLongText();
|
||||
}
|
||||
|
||||
private boolean isText() {
|
||||
return "text".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isTinyText() {
|
||||
return "tinytext".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isMediumText() {
|
||||
return "mediumtext".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isLongText() {
|
||||
return "longtext".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isDecimal() {
|
||||
return "decimal".equalsIgnoreCase(this.columnType) || "NEWDECIMAL".equalsIgnoreCase(this.columnType)
|
||||
|| "numeric".equalsIgnoreCase(this.columnType);
|
||||
// Refer org.drizzle.jdbc.internal.mysql.MySQLType.java
|
||||
}
|
||||
|
||||
private boolean isDate() {
|
||||
return "date".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isDateTime() {
|
||||
return "datetime".equalsIgnoreCase(this.columnType) || "timestamp".equalsIgnoreCase(this.columnType)
|
||||
|| "timestamp without time zone".equalsIgnoreCase(this.columnType) || "timestamptz".equalsIgnoreCase(this.columnType)
|
||||
|| "timestamp with time zone".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
public boolean isString() {
|
||||
return isVarchar() || isChar();
|
||||
}
|
||||
|
||||
private boolean isChar() {
|
||||
return "char".equalsIgnoreCase(this.columnType) || "CHARACTER VARYING".equalsIgnoreCase(this.columnType)
|
||||
|| "bpchar".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isVarchar() {
|
||||
return "varchar".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isAnyInteger() {
|
||||
return isInt() || isInteger() || isSmallInt() || isTinyInt() || isMediumInt() || isBigInt() || isLong() || isSerial();
|
||||
}
|
||||
|
||||
private boolean isSerial() {
|
||||
return "SERIAL".equalsIgnoreCase(this.columnType) || "SERIAL4".equalsIgnoreCase(this.columnType)
|
||||
|| "SERIAL8".equalsIgnoreCase(this.columnType) || "SMALLSERIAL".equalsIgnoreCase(this.columnType)
|
||||
|| "BIGSERIAL".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isInt() {
|
||||
return "int".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isInteger() {
|
||||
return "integer".equalsIgnoreCase(this.columnType) || "int2".equalsIgnoreCase(this.columnType)
|
||||
|| "int4".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isSmallInt() {
|
||||
return "smallint".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isTinyInt() {
|
||||
return "tinyint".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isMediumInt() {
|
||||
return "mediumint".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isBigInt() {
|
||||
return "bigint".equalsIgnoreCase(this.columnType) || "int8".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isLong() {
|
||||
return "LONG".equalsIgnoreCase(this.columnType) || "LONGLONG".equalsIgnoreCase(this.columnType);
|
||||
// Refer org.drizzle.jdbc.internal.mysql.MySQLType.java
|
||||
}
|
||||
|
||||
private boolean isBit() {
|
||||
return "bit".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
private boolean isBoolean() {
|
||||
return "boolean".equalsIgnoreCase(this.columnType) || "bool".equalsIgnoreCase(this.columnType);
|
||||
}
|
||||
|
||||
public String getColumnName() {
|
||||
return this.columnName;
|
||||
}
|
||||
|
||||
public String getColumnType() {
|
||||
return this.columnType;
|
||||
}
|
||||
|
||||
public Long getColumnLength() {
|
||||
return this.columnLength;
|
||||
}
|
||||
|
||||
public boolean getIsColumnNullable() {
|
||||
return isColumnNullable;
|
||||
}
|
||||
|
||||
public boolean getIsColumnPrimaryKey() {
|
||||
return isColumnPrimaryKey;
|
||||
}
|
||||
|
||||
public boolean getIsColumnUnique() {
|
||||
return isColumnUnique;
|
||||
}
|
||||
|
||||
public boolean getIsColumnIndexed() {
|
||||
return isColumnIndexed;
|
||||
}
|
||||
|
||||
public String getColumnDisplayType() {
|
||||
return this.columnDisplayType;
|
||||
}
|
||||
|
||||
public boolean isDateDisplayType() {
|
||||
return "DATE".equalsIgnoreCase(this.columnDisplayType);
|
||||
}
|
||||
|
||||
public boolean isDateTimeDisplayType() {
|
||||
return "DATETIME".equalsIgnoreCase(this.columnDisplayType);
|
||||
}
|
||||
|
||||
public boolean isIntegerDisplayType() {
|
||||
return "INTEGER".equalsIgnoreCase(this.columnDisplayType);
|
||||
}
|
||||
|
||||
public boolean isDecimalDisplayType() {
|
||||
return "DECIMAL".equalsIgnoreCase(this.columnDisplayType);
|
||||
}
|
||||
|
||||
public boolean isBooleanDisplayType() {
|
||||
return "BOOLEAN".equalsIgnoreCase(this.columnDisplayType);
|
||||
}
|
||||
|
||||
public boolean isCodeValueDisplayType() {
|
||||
return "CODEVALUE".equalsIgnoreCase(this.columnDisplayType);
|
||||
}
|
||||
|
||||
public boolean isCodeLookupDisplayType() {
|
||||
return "CODELOOKUP".equalsIgnoreCase(this.columnDisplayType);
|
||||
}
|
||||
|
||||
public boolean isMandatory() {
|
||||
return !isOptional();
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return this.isColumnNullable;
|
||||
}
|
||||
|
||||
public boolean hasColumnValues() {
|
||||
return !this.columnValues.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isColumnValueAllowed(final String match) {
|
||||
boolean allowed = false;
|
||||
for (final ResultsetColumnValueData allowedValue : this.columnValues) {
|
||||
if (allowedValue.matches(match)) {
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public boolean isColumnValueNotAllowed(final String match) {
|
||||
return !isColumnValueAllowed(match);
|
||||
}
|
||||
|
||||
public boolean isColumnCodeNotAllowed(final Integer match) {
|
||||
return !isColumnCodeAllowed(match);
|
||||
}
|
||||
|
||||
public boolean isColumnCodeAllowed(final Integer match) {
|
||||
boolean allowed = false;
|
||||
for (final ResultsetColumnValueData allowedValue : this.columnValues) {
|
||||
if (allowedValue.codeMatches(match)) {
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public String getColumnCode() {
|
||||
return this.columnCode;
|
||||
}
|
||||
|
||||
public List<ResultsetColumnValueData> getColumnValues() {
|
||||
return this.columnValues;
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.dataqueries.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a possible value for a given resultset column.
|
||||
*/
|
||||
public class ResultsetColumnValueData implements Serializable {
|
||||
|
||||
private final int id;
|
||||
private final String value;
|
||||
@SuppressWarnings("unused")
|
||||
private final Integer score;
|
||||
|
||||
public ResultsetColumnValueData(final int id, final String value) {
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
this.score = null;
|
||||
}
|
||||
|
||||
public ResultsetColumnValueData(final int id, final String value, final int score) {
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public boolean matches(final String match) {
|
||||
return match.equalsIgnoreCase(this.value);
|
||||
}
|
||||
|
||||
public boolean codeMatches(final Integer match) {
|
||||
return match.intValue() == this.id;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.documentmanagement.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_image")
|
||||
public final class Image extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "location", length = 500)
|
||||
private String location;
|
||||
|
||||
@Column(name = "storage_type_enum")
|
||||
private Integer storageType;
|
||||
|
||||
public Image(final String location, final StorageType storageType) {
|
||||
this.location = location;
|
||||
this.storageType = storageType.getValue();
|
||||
}
|
||||
|
||||
Image() {
|
||||
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public Integer getStorageType() {
|
||||
return this.storageType;
|
||||
}
|
||||
|
||||
public void setLocation(final String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public void setStorageType(final Integer storageType) {
|
||||
this.storageType = storageType;
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.documentmanagement.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum StorageType {
|
||||
|
||||
FILE_SYSTEM(1), S3(2);
|
||||
|
||||
private final Integer value;
|
||||
|
||||
StorageType(final Integer value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
private static final Map<Integer, StorageType> intToEnumMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (final StorageType type : StorageType.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static StorageType fromInt(final int i) {
|
||||
final StorageType type = intToEnumMap.get(Integer.valueOf(i));
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.security.exception;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} that is thrown in the case where a user does not have sufficient authorization to execute
|
||||
* operation on platform.
|
||||
*/
|
||||
public class NoAuthorizationException extends RuntimeException {
|
||||
|
||||
public NoAuthorizationException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.security.service;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class RandomPasswordGenerator {
|
||||
|
||||
private final int numberOfCharactersInPassword;
|
||||
private static final SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
public RandomPasswordGenerator(final int numberOfCharactersInPassword) {
|
||||
this.numberOfCharactersInPassword = numberOfCharactersInPassword;
|
||||
}
|
||||
|
||||
public String generate() {
|
||||
|
||||
final StringBuilder passwordBuilder = new StringBuilder(this.numberOfCharactersInPassword);
|
||||
for (int i = 0; i < this.numberOfCharactersInPassword; i++) {
|
||||
passwordBuilder.append((char) ((int) (secureRandom.nextDouble() * 26) + 97));
|
||||
}
|
||||
return passwordBuilder.toString();
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.holiday.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class HolidayApiConstants {
|
||||
|
||||
private HolidayApiConstants() {
|
||||
|
||||
}
|
||||
|
||||
public static final String HOLIDAY_RESOURCE_NAME = "holiday";
|
||||
|
||||
// general
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
|
||||
// request parameters
|
||||
public static final String idParamName = "id";
|
||||
public static final String nameParamName = "name";
|
||||
public static final String fromDateParamName = "fromDate";
|
||||
public static final String toDateParamName = "toDate";
|
||||
public static final String descriptionParamName = "description";
|
||||
public static final String officesParamName = "offices";
|
||||
public static final String officeIdParamName = "officeId";
|
||||
public static final String repaymentsRescheduledToParamName = "repaymentsRescheduledTo";
|
||||
public static final String processed = "processed";
|
||||
public static final String status = "status";
|
||||
public static final String reschedulingType = "reschedulingType";
|
||||
|
||||
static final Set<String> HOLIDAY_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, nameParamName, fromDateParamName,
|
||||
descriptionParamName, toDateParamName, repaymentsRescheduledToParamName, localeParamName, dateFormatParamName, status));
|
||||
}
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
/**
|
||||
* 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.holiday.domain;
|
||||
|
||||
import static org.apache.fineract.organisation.holiday.api.HolidayApiConstants.descriptionParamName;
|
||||
import static org.apache.fineract.organisation.holiday.api.HolidayApiConstants.fromDateParamName;
|
||||
import static org.apache.fineract.organisation.holiday.api.HolidayApiConstants.nameParamName;
|
||||
import static org.apache.fineract.organisation.holiday.api.HolidayApiConstants.officesParamName;
|
||||
import static org.apache.fineract.organisation.holiday.api.HolidayApiConstants.repaymentsRescheduledToParamName;
|
||||
import static org.apache.fineract.organisation.holiday.api.HolidayApiConstants.toDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dateFormatParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.organisation.holiday.api.HolidayApiConstants;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_holiday", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "holiday_name") })
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class Holiday extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "name", unique = true, nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "from_date", nullable = false)
|
||||
private LocalDate fromDate;
|
||||
|
||||
@Column(name = "to_date", nullable = false)
|
||||
private LocalDate toDate;
|
||||
|
||||
@Column(name = "repayments_rescheduled_to", nullable = true)
|
||||
private LocalDate repaymentsRescheduledTo;
|
||||
|
||||
@Column(name = "rescheduling_type", nullable = false)
|
||||
private int reschedulingType;
|
||||
|
||||
@Column(name = "status_enum", nullable = false)
|
||||
private Integer status;
|
||||
|
||||
@Column(name = "processed", nullable = false)
|
||||
private boolean processed;
|
||||
|
||||
@Column(name = "description", length = 100)
|
||||
private String description;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "m_holiday_office", joinColumns = @JoinColumn(name = "holiday_id"), inverseJoinColumns = @JoinColumn(name = "office_id"))
|
||||
private Set<Office> offices;
|
||||
|
||||
public static Holiday createNew(final Set<Office> offices, final JsonCommand command) {
|
||||
final String name = command.stringValueOfParameterNamed(HolidayApiConstants.nameParamName);
|
||||
final LocalDate fromDate = command.localDateValueOfParameterNamed(HolidayApiConstants.fromDateParamName);
|
||||
final LocalDate toDate = command.localDateValueOfParameterNamed(HolidayApiConstants.toDateParamName);
|
||||
Integer reschedulingType = null;
|
||||
if (command.parameterExists(HolidayApiConstants.reschedulingType)) {
|
||||
reschedulingType = command.integerValueOfParameterNamed(HolidayApiConstants.reschedulingType);
|
||||
}
|
||||
LocalDate repaymentsRescheduledTo = null;
|
||||
if (reschedulingType == null || reschedulingType.equals(RescheduleType.RESCHEDULETOSPECIFICDATE.getValue())) {
|
||||
repaymentsRescheduledTo = command.localDateValueOfParameterNamed(HolidayApiConstants.repaymentsRescheduledToParamName);
|
||||
}
|
||||
final Integer status = HolidayStatusType.PENDING_FOR_ACTIVATION.getValue();
|
||||
final boolean processed = false;// default it to false. Only batch job
|
||||
// should update this field.
|
||||
final String description = command.stringValueOfParameterNamed(HolidayApiConstants.descriptionParamName);
|
||||
|
||||
return new Holiday().setName(StringUtils.trim(name)).setFromDate(fromDate).setToDate(toDate)
|
||||
.setRepaymentsRescheduledTo(repaymentsRescheduledTo).setStatus(status).setProcessed(processed)
|
||||
.setDescription(StringUtils.trim(description)).setOffices(offices).setReschedulingType(reschedulingType);
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("holiday" + ".update");
|
||||
|
||||
final HolidayStatusType currentStatus = HolidayStatusType.fromInt(this.status);
|
||||
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(nameParamName);
|
||||
actualChanges.put(nameParamName, newValue);
|
||||
this.name = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
|
||||
actualChanges.put(descriptionParamName, newValue);
|
||||
this.description = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(HolidayApiConstants.reschedulingType, this.reschedulingType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(HolidayApiConstants.reschedulingType);
|
||||
actualChanges.put(HolidayApiConstants.reschedulingType, newValue);
|
||||
this.reschedulingType = RescheduleType.fromInt(newValue).getValue();
|
||||
if (newValue.equals(RescheduleType.RESCHEDULETONEXTREPAYMENTDATE.getValue())) {
|
||||
this.repaymentsRescheduledTo = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentStatus.isPendingActivation()) {
|
||||
if (command.isChangeInLocalDateParameterNamed(fromDateParamName, getFromDate())) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(fromDateParamName);
|
||||
actualChanges.put(fromDateParamName, valueAsInput);
|
||||
actualChanges.put(dateFormatParamName, dateFormatAsInput);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.fromDate = command.localDateValueOfParameterNamed(fromDateParamName);
|
||||
}
|
||||
|
||||
if (command.isChangeInLocalDateParameterNamed(toDateParamName, getToDate())) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(toDateParamName);
|
||||
actualChanges.put(toDateParamName, valueAsInput);
|
||||
actualChanges.put(dateFormatParamName, dateFormatAsInput);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
|
||||
this.toDate = command.localDateValueOfParameterNamed(toDateParamName);
|
||||
}
|
||||
|
||||
if (command.isChangeInLocalDateParameterNamed(repaymentsRescheduledToParamName, getRepaymentsRescheduledTo())) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(repaymentsRescheduledToParamName);
|
||||
actualChanges.put(repaymentsRescheduledToParamName, valueAsInput);
|
||||
actualChanges.put(dateFormatParamName, dateFormatAsInput);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
|
||||
this.repaymentsRescheduledTo = command.localDateValueOfParameterNamed(repaymentsRescheduledToParamName);
|
||||
}
|
||||
|
||||
if (command.hasParameter(officesParamName)) {
|
||||
final JsonArray jsonArray = command.arrayOfParameterNamed(officesParamName);
|
||||
if (jsonArray != null) {
|
||||
actualChanges.put(officesParamName, command.jsonFragment(officesParamName));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (command.isChangeInLocalDateParameterNamed(fromDateParamName, getFromDate())) {
|
||||
baseDataValidator.reset().parameter(fromDateParamName).failWithCode("cannot.edit.holiday.in.active.state");
|
||||
}
|
||||
|
||||
if (command.isChangeInLocalDateParameterNamed(toDateParamName, getToDate())) {
|
||||
baseDataValidator.reset().parameter(toDateParamName).failWithCode("cannot.edit.holiday.in.active.state");
|
||||
}
|
||||
|
||||
if (command.isChangeInLocalDateParameterNamed(repaymentsRescheduledToParamName, getRepaymentsRescheduledTo())) {
|
||||
baseDataValidator.reset().parameter(repaymentsRescheduledToParamName).failWithCode("cannot.edit.holiday.in.active.state");
|
||||
}
|
||||
|
||||
if (command.hasParameter(officesParamName)) {
|
||||
baseDataValidator.reset().parameter(repaymentsRescheduledToParamName).failWithCode("cannot.edit.holiday.in.active.state");
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean update(final Set<Office> newOffices) {
|
||||
if (newOffices == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean updated = false;
|
||||
if (this.offices != null) {
|
||||
final Set<Office> currentSetOfOffices = new HashSet<>(this.offices);
|
||||
final Set<Office> newSetOfOffices = new HashSet<>(newOffices);
|
||||
|
||||
if (!currentSetOfOffices.equals(newSetOfOffices)) {
|
||||
updated = true;
|
||||
this.offices = newOffices;
|
||||
}
|
||||
} else {
|
||||
updated = true;
|
||||
this.offices = newOffices;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
public void activate() {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("holiday" + ".activate");
|
||||
|
||||
final HolidayStatusType currentStatus = HolidayStatusType.fromInt(this.status);
|
||||
if (!currentStatus.isPendingActivation()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.in.pending.for.activation.state");
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
this.status = HolidayStatusType.ACTIVE.getValue();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("holiday" + ".delete");
|
||||
|
||||
final HolidayStatusType currentStatus = HolidayStatusType.fromInt(this.status);
|
||||
if (currentStatus.isDeleted()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("already.in.deleted.state");
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
this.status = HolidayStatusType.DELETED.getValue();
|
||||
}
|
||||
|
||||
public RescheduleType getReScheduleType() {
|
||||
return RescheduleType.fromInt(this.reschedulingType);
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.holiday.domain;
|
||||
|
||||
/**
|
||||
* Enum representation of {@link Holiday} status states.
|
||||
*/
|
||||
public enum HolidayStatusType {
|
||||
|
||||
INVALID(0, "holidayStatusType.invalid"), //
|
||||
PENDING_FOR_ACTIVATION(100, "holidayStatusType.pending.for.activation"), //
|
||||
ACTIVE(300, "holidayStatusType.active"), //
|
||||
DELETED(600, "savingsAccountStatusType.transfer.in.progress");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
public static HolidayStatusType fromInt(final Integer type) {
|
||||
HolidayStatusType enumeration = HolidayStatusType.INVALID;
|
||||
switch (type) {
|
||||
case 100:
|
||||
enumeration = HolidayStatusType.PENDING_FOR_ACTIVATION;
|
||||
break;
|
||||
case 300:
|
||||
enumeration = HolidayStatusType.ACTIVE;
|
||||
break;
|
||||
case 600:
|
||||
enumeration = HolidayStatusType.DELETED;
|
||||
break;
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
HolidayStatusType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public boolean hasStateOf(final HolidayStatusType state) {
|
||||
return this.value.equals(state.getValue());
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public boolean isPendingActivation() {
|
||||
return this.value.equals(HolidayStatusType.PENDING_FOR_ACTIVATION.getValue());
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.value.equals(HolidayStatusType.ACTIVE.getValue());
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return this.value.equals(HolidayStatusType.DELETED.getValue());
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.holiday.domain;
|
||||
|
||||
public enum RescheduleType {
|
||||
|
||||
INVALID(0, "rescheduletype.invalid"), RESCHEDULETOSPECIFICDATE(2, "rescheduletype.rescheduletospecificdate"), //
|
||||
RESCHEDULETONEXTREPAYMENTDATE(1, "rescheduletype.rescheduletonextrepaymentdate");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
RescheduleType(Integer value, String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static RescheduleType fromInt(int rescheduleTypeValue) {
|
||||
RescheduleType enumerration = RescheduleType.INVALID;
|
||||
switch (rescheduleTypeValue) {
|
||||
case 1:
|
||||
enumerration = RescheduleType.RESCHEDULETONEXTREPAYMENTDATE;
|
||||
break;
|
||||
case 2:
|
||||
enumerration = RescheduleType.RESCHEDULETOSPECIFICDATE;
|
||||
break;
|
||||
}
|
||||
return enumerration;
|
||||
}
|
||||
|
||||
public boolean isRescheduleToSpecificDate() {
|
||||
return this.value.equals(RescheduleType.RESCHEDULETOSPECIFICDATE.getValue());
|
||||
}
|
||||
|
||||
public boolean isResheduleToNextRepaymentDate() {
|
||||
return this.value.equals(RescheduleType.RESCHEDULETONEXTREPAYMENTDATE.getValue());
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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.holiday.service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
|
||||
|
||||
public final class HolidayUtil {
|
||||
|
||||
private HolidayUtil() {
|
||||
|
||||
}
|
||||
|
||||
public static LocalDate getRepaymentRescheduleDateToIfHoliday(LocalDate repaymentDate, final List<Holiday> holidays) {
|
||||
|
||||
for (final Holiday holiday : holidays) {
|
||||
if (repaymentDate.equals(holiday.getFromDate()) || repaymentDate.equals(holiday.getToDate())
|
||||
|| (repaymentDate.isAfter(holiday.getFromDate()) && repaymentDate.isBefore(holiday.getToDate()))) {
|
||||
repaymentDate = getRepaymentRescheduleDateIfHoliday(repaymentDate, holidays);
|
||||
}
|
||||
}
|
||||
return repaymentDate;
|
||||
}
|
||||
|
||||
private static LocalDate getRepaymentRescheduleDateIfHoliday(final LocalDate repaymentDate, final List<Holiday> holidays) {
|
||||
|
||||
for (final Holiday holiday : holidays) {
|
||||
if (repaymentDate.equals(holiday.getFromDate()) || repaymentDate.equals(holiday.getToDate())
|
||||
|| (repaymentDate.isAfter(holiday.getFromDate()) && repaymentDate.isBefore(holiday.getToDate()))) {
|
||||
// should be take from holiday
|
||||
return holiday.getRepaymentsRescheduledTo();
|
||||
}
|
||||
}
|
||||
return repaymentDate;
|
||||
}
|
||||
|
||||
public static boolean isHoliday(final LocalDate date, final List<Holiday> holidays) {
|
||||
for (final Holiday holiday : holidays) {
|
||||
if (date.isEqual(holiday.getFromDate()) || date.isEqual(holiday.getToDate())
|
||||
|| (date.isAfter(holiday.getFromDate()) && date.isBefore(holiday.getToDate()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Holiday getApplicableHoliday(final LocalDate repaymentDate, final List<Holiday> holidays) {
|
||||
Holiday referedHoliday = null;
|
||||
for (final Holiday holiday : holidays) {
|
||||
if (!repaymentDate.isBefore(holiday.getFromDate()) && !repaymentDate.isAfter(holiday.getToDate())) {
|
||||
referedHoliday = holiday;
|
||||
}
|
||||
}
|
||||
return referedHoliday;
|
||||
}
|
||||
|
||||
public static void updateRepaymentRescheduleDateToWorkingDayIfItIsHoliday(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
|
||||
final Holiday holiday) {
|
||||
if (holiday.getReScheduleType().isRescheduleToSpecificDate()) {
|
||||
adjustedDateDetailsDTO.setChangedScheduleDate(holiday.getRepaymentsRescheduledTo());
|
||||
}
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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.monetary.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Immutable data object representing currency.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
public class CurrencyData implements Serializable {
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
private final int decimalPlaces;
|
||||
private final Integer inMultiplesOf;
|
||||
private final String displaySymbol;
|
||||
private final String nameCode;
|
||||
private final String displayLabel;
|
||||
|
||||
public static CurrencyData blank() {
|
||||
return new CurrencyData("", "", 0, 0, "", "");
|
||||
}
|
||||
|
||||
public CurrencyData(String code) {
|
||||
this.code = code;
|
||||
this.name = null;
|
||||
this.decimalPlaces = 0;
|
||||
this.inMultiplesOf = null;
|
||||
this.displaySymbol = null;
|
||||
this.nameCode = null;
|
||||
this.displayLabel = null;
|
||||
}
|
||||
|
||||
public CurrencyData(final String code, final String name, final int decimalPlaces, final Integer inMultiplesOf,
|
||||
final String displaySymbol, final String nameCode) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.decimalPlaces = decimalPlaces;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
this.displaySymbol = displaySymbol;
|
||||
this.nameCode = nameCode;
|
||||
this.displayLabel = generateDisplayLabel();
|
||||
}
|
||||
|
||||
public CurrencyData(final String code, final int decimalPlaces, final Integer inMultiplesOf) {
|
||||
this.code = code;
|
||||
this.name = null;
|
||||
this.decimalPlaces = decimalPlaces;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
this.displaySymbol = null;
|
||||
this.nameCode = null;
|
||||
this.displayLabel = null;
|
||||
}
|
||||
|
||||
private String generateDisplayLabel() {
|
||||
|
||||
final StringBuilder builder = new StringBuilder(20);
|
||||
if (this.name != null) {
|
||||
builder.append(this.name).append(' ');
|
||||
}
|
||||
|
||||
if (this.displaySymbol != null && !"".equalsIgnoreCase(this.displaySymbol.trim())) {
|
||||
builder.append('(').append(this.displaySymbol).append(')');
|
||||
} else {
|
||||
builder.append('[').append(this.code).append(']');
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* 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.monetary.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.office.domain.OrganisationCurrency;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_currency")
|
||||
public class ApplicationCurrency extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "code", nullable = false, length = 3)
|
||||
private String code;
|
||||
|
||||
@Column(name = "decimal_places", nullable = false)
|
||||
private Integer decimalPlaces;
|
||||
|
||||
@Column(name = "currency_multiplesof")
|
||||
private Integer inMultiplesOf;
|
||||
|
||||
@Column(name = "name", nullable = false, length = 50)
|
||||
private String name;
|
||||
|
||||
@Column(name = "internationalized_name_code", nullable = false, length = 50)
|
||||
private String nameCode;
|
||||
|
||||
@Column(name = "display_symbol", nullable = true, length = 10)
|
||||
private String displaySymbol;
|
||||
|
||||
protected ApplicationCurrency() {
|
||||
this.code = null;
|
||||
this.name = null;
|
||||
this.decimalPlaces = null;
|
||||
this.inMultiplesOf = null;
|
||||
this.nameCode = null;
|
||||
this.displaySymbol = null;
|
||||
}
|
||||
|
||||
public static ApplicationCurrency from(final ApplicationCurrency currency, final int decimalPlaces, final Integer inMultiplesOf) {
|
||||
return new ApplicationCurrency(currency.code, currency.name, decimalPlaces, inMultiplesOf, currency.nameCode,
|
||||
currency.displaySymbol);
|
||||
}
|
||||
|
||||
private ApplicationCurrency(final String code, final String name, final int decimalPlaces, final Integer inMultiplesOf,
|
||||
final String nameCode, final String displaySymbol) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.decimalPlaces = decimalPlaces;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
this.nameCode = nameCode;
|
||||
this.displaySymbol = displaySymbol;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Integer getDecimalPlaces() {
|
||||
return this.decimalPlaces;
|
||||
}
|
||||
|
||||
public Integer getCurrencyInMultiplesOf() {
|
||||
return this.inMultiplesOf;
|
||||
}
|
||||
|
||||
public String getNameCode() {
|
||||
return this.nameCode;
|
||||
}
|
||||
|
||||
public String getDisplaySymbol() {
|
||||
return this.displaySymbol;
|
||||
}
|
||||
|
||||
public CurrencyData toData() {
|
||||
return new CurrencyData(this.code, this.name, this.decimalPlaces, this.inMultiplesOf, this.displaySymbol, this.nameCode);
|
||||
}
|
||||
|
||||
public CurrencyData toData(final int digitsAfterDecimalSupported, final Integer inMultiplesOf) {
|
||||
return new CurrencyData(this.code, this.name, digitsAfterDecimalSupported, inMultiplesOf, this.displaySymbol, this.nameCode);
|
||||
}
|
||||
|
||||
public OrganisationCurrency toOrganisationCurrency() {
|
||||
return new OrganisationCurrency(this.code, this.name, this.decimalPlaces, this.inMultiplesOf, this.nameCode, this.displaySymbol);
|
||||
}
|
||||
|
||||
public void setCode(final String code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 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.monetary.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
|
||||
@Embeddable
|
||||
public class MonetaryCurrency {
|
||||
|
||||
@Column(name = "currency_code", length = 3, nullable = false)
|
||||
private String code;
|
||||
|
||||
@Column(name = "currency_digits", nullable = false)
|
||||
private int digitsAfterDecimal;
|
||||
|
||||
@Column(name = "currency_multiplesof")
|
||||
private Integer inMultiplesOf;
|
||||
|
||||
protected MonetaryCurrency() {
|
||||
this.code = null;
|
||||
this.digitsAfterDecimal = 0;
|
||||
this.inMultiplesOf = 0;
|
||||
}
|
||||
|
||||
public MonetaryCurrency(final String code, final int digitsAfterDecimal, final Integer inMultiplesOf) {
|
||||
this.code = code;
|
||||
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
}
|
||||
|
||||
public MonetaryCurrency copy() {
|
||||
return new MonetaryCurrency(this.code, this.digitsAfterDecimal, this.inMultiplesOf);
|
||||
}
|
||||
|
||||
public static MonetaryCurrency fromApplicationCurrency(ApplicationCurrency applicationCurrency) {
|
||||
return new MonetaryCurrency(applicationCurrency.getCode(), applicationCurrency.getDecimalPlaces(),
|
||||
applicationCurrency.getCurrencyInMultiplesOf());
|
||||
}
|
||||
|
||||
public static MonetaryCurrency fromCurrencyData(final CurrencyData currencyData) {
|
||||
return new MonetaryCurrency(currencyData.getCode(), currencyData.getDecimalPlaces(), currencyData.getInMultiplesOf());
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public int getDigitsAfterDecimal() {
|
||||
return this.digitsAfterDecimal;
|
||||
}
|
||||
|
||||
public Integer getCurrencyInMultiplesOf() {
|
||||
return this.inMultiplesOf;
|
||||
}
|
||||
|
||||
}
|
||||
+388
@@ -0,0 +1,388 @@
|
||||
/**
|
||||
* 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.monetary.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Iterator;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
|
||||
@Embeddable
|
||||
public class Money implements Comparable<Money> {
|
||||
|
||||
@Column(name = "currency_code", length = 3)
|
||||
private String currencyCode;
|
||||
|
||||
@Column(name = "currency_digits")
|
||||
private int currencyDigitsAfterDecimal;
|
||||
|
||||
@Column(name = "currency_multiplesof")
|
||||
private Integer inMultiplesOf;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19)
|
||||
private BigDecimal amount;
|
||||
|
||||
public static Money total(final Money... monies) {
|
||||
if (monies.length == 0) {
|
||||
throw new IllegalArgumentException("Money array must not be empty");
|
||||
}
|
||||
Money total = monies[0];
|
||||
for (int i = 1; i < monies.length; i++) {
|
||||
total = total.plus(monies[i]);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static Money total(final Iterable<? extends Money> monies) {
|
||||
final Iterator<? extends Money> it = monies.iterator();
|
||||
if (it.hasNext() == false) {
|
||||
throw new IllegalArgumentException("Money iterator must not be empty");
|
||||
}
|
||||
Money total = it.next();
|
||||
while (it.hasNext()) {
|
||||
total = total.plus(it.next());
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static Money of(final MonetaryCurrency currency, final BigDecimal newAmount) {
|
||||
return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), defaultToZeroIfNull(newAmount),
|
||||
currency.getCurrencyInMultiplesOf());
|
||||
}
|
||||
|
||||
public static Money of(final CurrencyData currency, final BigDecimal newAmount) {
|
||||
return new Money(currency.getCode(), currency.getDecimalPlaces(), defaultToZeroIfNull(newAmount), currency.getInMultiplesOf());
|
||||
}
|
||||
|
||||
public static Money zero(final MonetaryCurrency currency) {
|
||||
return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), BigDecimal.ZERO, currency.getCurrencyInMultiplesOf());
|
||||
}
|
||||
|
||||
public static Money zero(final CurrencyData currency) {
|
||||
return new Money(currency.getCode(), currency.getDecimalPlaces(), BigDecimal.ZERO, currency.getInMultiplesOf());
|
||||
}
|
||||
|
||||
protected Money() {
|
||||
this.currencyCode = null;
|
||||
this.currencyDigitsAfterDecimal = 0;
|
||||
this.inMultiplesOf = 0;
|
||||
this.amount = null;
|
||||
}
|
||||
|
||||
private Money(final String currencyCode, final int digitsAfterDecimal, final BigDecimal amount, final Integer inMultiplesOf) {
|
||||
this.currencyCode = currencyCode;
|
||||
this.currencyDigitsAfterDecimal = digitsAfterDecimal;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
|
||||
final BigDecimal amountZeroed = defaultToZeroIfNull(amount);
|
||||
final BigDecimal amountStripped = amountZeroed.stripTrailingZeros();
|
||||
BigDecimal amountScaled = amountStripped;
|
||||
|
||||
// round monetary amounts into multiplesof say 20/50.
|
||||
if (inMultiplesOf != null && this.currencyDigitsAfterDecimal == 0 && inMultiplesOf > 0 && amountScaled.doubleValue() > 0) {
|
||||
final double existingVal = amountScaled.doubleValue();
|
||||
amountScaled = BigDecimal.valueOf(roundToMultiplesOf(existingVal, inMultiplesOf));
|
||||
}
|
||||
this.amount = amountScaled.setScale(this.currencyDigitsAfterDecimal, MoneyHelper.getRoundingMode());
|
||||
}
|
||||
|
||||
public static double roundToMultiplesOf(final double existingVal, final Integer inMultiplesOf) {
|
||||
double amountScaled = existingVal;
|
||||
final double ceilingOfValue = ceiling(existingVal, inMultiplesOf);
|
||||
final double floorOfValue = floor(existingVal, inMultiplesOf);
|
||||
|
||||
final double floorDiff = existingVal - floorOfValue;
|
||||
final double ceilDiff = ceilingOfValue - existingVal;
|
||||
|
||||
if (ceilDiff > floorDiff) {
|
||||
amountScaled = floorOfValue;
|
||||
} else {
|
||||
amountScaled = ceilingOfValue;
|
||||
}
|
||||
return amountScaled;
|
||||
}
|
||||
|
||||
public static double ceiling(final double n, final double s) {
|
||||
double c;
|
||||
|
||||
if ((n < 0 && s > 0) || (n > 0 && s < 0)) {
|
||||
c = Double.NaN;
|
||||
} else {
|
||||
c = (n == 0 || s == 0) ? 0 : Math.ceil(n / s) * s;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public static double floor(final double n, final double s) {
|
||||
double f;
|
||||
|
||||
if ((n < 0 && s > 0) || (n > 0 && s < 0) || (s == 0 && n != 0)) {
|
||||
f = Double.NaN;
|
||||
} else {
|
||||
f = (n == 0 || s == 0) ? 0 : Math.floor(n / s) * s;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private static BigDecimal defaultToZeroIfNull(final BigDecimal value) {
|
||||
BigDecimal result = BigDecimal.ZERO;
|
||||
if (value != null) {
|
||||
result = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Money copy() {
|
||||
return new Money(this.currencyCode, this.currencyDigitsAfterDecimal, this.amount.stripTrailingZeros(), this.inMultiplesOf);
|
||||
}
|
||||
|
||||
public Money plus(final Iterable<? extends Money> moniesToAdd) {
|
||||
BigDecimal total = this.amount;
|
||||
for (final Money moneyProvider : moniesToAdd) {
|
||||
final Money money = checkCurrencyEqual(moneyProvider);
|
||||
total = total.add(money.amount);
|
||||
}
|
||||
return Money.of(monetaryCurrency(), total);
|
||||
}
|
||||
|
||||
public Money plus(final Money moneyToAdd) {
|
||||
final Money toAdd = checkCurrencyEqual(moneyToAdd);
|
||||
return this.plus(toAdd.getAmount());
|
||||
}
|
||||
|
||||
public Money plus(final BigDecimal amountToAdd) {
|
||||
if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.add(amountToAdd);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money plus(final double amountToAdd) {
|
||||
if (amountToAdd == 0) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.add(BigDecimal.valueOf(amountToAdd));
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money minus(final Money moneyToSubtract) {
|
||||
final Money toSubtract = checkCurrencyEqual(moneyToSubtract);
|
||||
return this.minus(toSubtract.getAmount());
|
||||
}
|
||||
|
||||
public Money add(final Money moneyToAdd) {
|
||||
final Money toAdd = checkCurrencyEqual(moneyToAdd);
|
||||
return this.add(toAdd.getAmount());
|
||||
}
|
||||
|
||||
public Money add(final BigDecimal amountToAdd) {
|
||||
if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.add(amountToAdd);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money minus(final BigDecimal amountToSubtract) {
|
||||
if (amountToSubtract == null || amountToSubtract.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.subtract(amountToSubtract);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
private Money checkCurrencyEqual(final Money money) {
|
||||
if (isSameCurrency(money) == false) {
|
||||
throw new UnsupportedOperationException("currencies are different.");
|
||||
}
|
||||
return money;
|
||||
}
|
||||
|
||||
public boolean isSameCurrency(final Money money) {
|
||||
return this.currencyCode.equals(money.getCurrencyCode());
|
||||
}
|
||||
|
||||
public Money dividedBy(final BigDecimal valueToDivideBy, final RoundingMode roundingMode) {
|
||||
if (valueToDivideBy.compareTo(BigDecimal.ONE) == 0) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.divide(valueToDivideBy, roundingMode);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money dividedBy(final double valueToDivideBy, final RoundingMode roundingMode) {
|
||||
if (valueToDivideBy == 1) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.divide(BigDecimal.valueOf(valueToDivideBy), roundingMode);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money dividedBy(final long valueToDivideBy, final RoundingMode roundingMode) {
|
||||
if (valueToDivideBy == 1) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.divide(BigDecimal.valueOf(valueToDivideBy), roundingMode);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money multipliedBy(final BigDecimal valueToMultiplyBy) {
|
||||
if (valueToMultiplyBy.compareTo(BigDecimal.ONE) == 0) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.multiply(valueToMultiplyBy);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money multipliedBy(final double valueToMultiplyBy) {
|
||||
if (valueToMultiplyBy == 1) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.multiply(BigDecimal.valueOf(valueToMultiplyBy));
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money multipliedBy(final long valueToMultiplyBy) {
|
||||
if (valueToMultiplyBy == 1) {
|
||||
return this;
|
||||
}
|
||||
final BigDecimal newAmount = this.amount.multiply(BigDecimal.valueOf(valueToMultiplyBy));
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money multiplyRetainScale(final BigDecimal valueToMultiplyBy, final RoundingMode roundingMode) {
|
||||
if (valueToMultiplyBy.compareTo(BigDecimal.ONE) == 0) {
|
||||
return this;
|
||||
}
|
||||
BigDecimal newAmount = this.amount.multiply(valueToMultiplyBy);
|
||||
newAmount = newAmount.setScale(this.currencyDigitsAfterDecimal, roundingMode);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
public Money multiplyRetainScale(final double valueToMultiplyBy, final RoundingMode roundingMode) {
|
||||
return this.multiplyRetainScale(BigDecimal.valueOf(valueToMultiplyBy), roundingMode);
|
||||
}
|
||||
|
||||
public Money percentageOf(BigDecimal percentage, final RoundingMode roundingMode) {
|
||||
final BigDecimal newAmount = this.amount.multiply(percentage).divide(BigDecimal.valueOf(100), roundingMode);
|
||||
return Money.of(monetaryCurrency(), newAmount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Money other) {
|
||||
final Money otherMoney = other;
|
||||
if (this.currencyCode.equals(otherMoney.currencyCode) == false) {
|
||||
throw new UnsupportedOperationException("currencies arent different");
|
||||
}
|
||||
return this.amount.compareTo(otherMoney.amount);
|
||||
}
|
||||
|
||||
public boolean isZero() {
|
||||
return isEqualTo(Money.zero(getCurrency()));
|
||||
}
|
||||
|
||||
public boolean isEqualTo(final Money other) {
|
||||
return compareTo(other) == 0;
|
||||
}
|
||||
|
||||
public boolean isNotEqualTo(final Money other) {
|
||||
return !isEqualTo(other);
|
||||
}
|
||||
|
||||
public boolean isGreaterThanOrEqualTo(final Money other) {
|
||||
return isGreaterThan(other) || isEqualTo(other);
|
||||
}
|
||||
|
||||
public boolean isGreaterThan(final Money other) {
|
||||
return compareTo(other) > 0;
|
||||
}
|
||||
|
||||
public boolean isGreaterThanZero() {
|
||||
return isGreaterThan(Money.zero(getCurrency()));
|
||||
}
|
||||
|
||||
public boolean isLessThan(final Money other) {
|
||||
return compareTo(other) < 0;
|
||||
}
|
||||
|
||||
public boolean isLessThanZero() {
|
||||
return isLessThan(Money.zero(getCurrency()));
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return this.currencyCode;
|
||||
}
|
||||
|
||||
public int getCurrencyDigitsAfterDecimal() {
|
||||
return this.currencyDigitsAfterDecimal;
|
||||
}
|
||||
|
||||
public Integer getCurrencyInMultiplesOf() {
|
||||
return this.inMultiplesOf;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public BigDecimal getAmountDefaultedToNullIfZero() {
|
||||
return defaultToNullIfZero(this.amount);
|
||||
}
|
||||
|
||||
private static BigDecimal defaultToNullIfZero(final BigDecimal value) {
|
||||
BigDecimal result = value;
|
||||
if (value != null && BigDecimal.ZERO.compareTo(value) == 0) {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder().append(this.currencyCode).append(' ').append(this.amount.toPlainString()).toString();
|
||||
}
|
||||
|
||||
public Money negated() {
|
||||
if (isZero()) {
|
||||
return this;
|
||||
}
|
||||
return Money.of(monetaryCurrency(), this.amount.negate());
|
||||
}
|
||||
|
||||
public Money abs() {
|
||||
return isLessThanZero() ? negated() : this;
|
||||
}
|
||||
|
||||
public MonetaryCurrency getCurrency() {
|
||||
return monetaryCurrency();
|
||||
}
|
||||
|
||||
private MonetaryCurrency monetaryCurrency() {
|
||||
return new MonetaryCurrency(this.currencyCode, this.currencyDigitsAfterDecimal, this.inMultiplesOf);
|
||||
}
|
||||
|
||||
public Money zero() {
|
||||
return Money.zero(getCurrency());
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.monetary.domain;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import javax.annotation.PostConstruct;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class MoneyHelper {
|
||||
|
||||
private static RoundingMode roundingMode = null;
|
||||
private static MathContext mathContext;
|
||||
private static final int PRECISION = 12;
|
||||
|
||||
private static ConfigurationDomainService staticConfigurationDomainService;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@PostConstruct
|
||||
// This is a hack, but fixing this is not trivial, because some @Entity
|
||||
// domain classes use this helper
|
||||
@SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
|
||||
public void someFunction() {
|
||||
staticConfigurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
public static RoundingMode getRoundingMode() {
|
||||
if (roundingMode == null) {
|
||||
roundingMode = RoundingMode.valueOf(staticConfigurationDomainService.getRoundingMode());
|
||||
}
|
||||
return roundingMode;
|
||||
}
|
||||
|
||||
public static MathContext getMathContext() {
|
||||
if (mathContext == null) {
|
||||
mathContext = new MathContext(PRECISION, getRoundingMode());
|
||||
}
|
||||
return mathContext;
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Immutable data object for office data.
|
||||
*/
|
||||
@Getter
|
||||
public class OfficeData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final String name;
|
||||
private final String nameDecorated;
|
||||
private final String externalId;
|
||||
private final LocalDate openingDate;
|
||||
private final String hierarchy;
|
||||
private final Long parentId;
|
||||
private final String parentName;
|
||||
private final Collection<OfficeData> allowedParents;
|
||||
|
||||
// import fields
|
||||
private transient Integer rowIndex;
|
||||
private String locale;
|
||||
private String dateFormat;
|
||||
|
||||
public static OfficeData importInstance(final String name, final Long parentId, final LocalDate openingDate, final String externalId) {
|
||||
return new OfficeData(null, name, null, externalId, openingDate, null, parentId, null, null);
|
||||
}
|
||||
|
||||
public void setImportFields(final Integer rowIndex, final String locale, final String dateFormat) {
|
||||
this.rowIndex = rowIndex;
|
||||
this.locale = locale;
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
public static OfficeData testInstance(final Long id, final String name) {
|
||||
return new OfficeData(id, name, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static OfficeData dropdown(final Long id, final String name, final String nameDecorated) {
|
||||
return new OfficeData(id, name, nameDecorated, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static OfficeData template(final List<OfficeData> parentLookups, final LocalDate defaultOpeningDate) {
|
||||
return new OfficeData(null, null, null, null, defaultOpeningDate, null, null, null, parentLookups);
|
||||
}
|
||||
|
||||
public static OfficeData appendedTemplate(final OfficeData office, final Collection<OfficeData> allowedParents) {
|
||||
return new OfficeData(office.id, office.name, office.nameDecorated, office.externalId, office.openingDate, office.hierarchy,
|
||||
office.parentId, office.parentName, allowedParents);
|
||||
}
|
||||
|
||||
public OfficeData(final Long id, final String name, final String nameDecorated, final String externalId, final LocalDate openingDate,
|
||||
final String hierarchy, final Long parentId, final String parentName, final Collection<OfficeData> allowedParents) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.nameDecorated = nameDecorated;
|
||||
this.externalId = externalId;
|
||||
this.openingDate = openingDate;
|
||||
this.hierarchy = hierarchy;
|
||||
this.parentName = parentName;
|
||||
this.parentId = parentId;
|
||||
this.allowedParents = allowedParents;
|
||||
}
|
||||
|
||||
public boolean hasIdentifyOf(final Long officeId) {
|
||||
return this.id.equals(officeId);
|
||||
}
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.office.exception.CannotUpdateOfficeWithParentOfficeSameAsSelf;
|
||||
import org.apache.fineract.organisation.office.exception.RootOfficeParentCannotBeUpdated;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_office", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "name_org"),
|
||||
@UniqueConstraint(columnNames = { "external_id" }, name = "externalid_org") })
|
||||
public class Office extends AbstractPersistableCustom implements Serializable {
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "parent_id")
|
||||
private List<Office> children = new ArrayList<>();
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "parent_id")
|
||||
private Office parent;
|
||||
|
||||
@Column(name = "name", nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "hierarchy", length = 50)
|
||||
private String hierarchy;
|
||||
|
||||
@Column(name = "opening_date", nullable = false)
|
||||
private LocalDate openingDate;
|
||||
|
||||
@Column(name = "external_id", length = 100)
|
||||
private String externalId;
|
||||
|
||||
public static Office headOffice(final String name, final LocalDate openingDate, final String externalId) {
|
||||
return new Office(null, name, openingDate, externalId);
|
||||
}
|
||||
|
||||
public static Office fromJson(final Office parentOffice, final JsonCommand command) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
final LocalDate openingDate = command.localDateValueOfParameterNamed("openingDate");
|
||||
final String externalId = command.stringValueOfParameterNamed("externalId");
|
||||
return new Office(parentOffice, name, openingDate, externalId);
|
||||
}
|
||||
|
||||
protected Office() {
|
||||
this.openingDate = null;
|
||||
this.parent = null;
|
||||
this.name = null;
|
||||
this.externalId = null;
|
||||
}
|
||||
|
||||
private Office(final Office parent, final String name, final LocalDate openingDate, final String externalId) {
|
||||
this.parent = parent;
|
||||
this.openingDate = openingDate;
|
||||
if (parent != null) {
|
||||
this.parent.addChild(this);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
this.name = name.trim();
|
||||
} else {
|
||||
this.name = null;
|
||||
}
|
||||
if (StringUtils.isNotBlank(externalId)) {
|
||||
this.externalId = externalId.trim();
|
||||
} else {
|
||||
this.externalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void addChild(final Office office) {
|
||||
this.children.add(office);
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
final String parentIdParamName = "parentId";
|
||||
|
||||
if (command.parameterExists(parentIdParamName) && this.parent == null) {
|
||||
throw new RootOfficeParentCannotBeUpdated();
|
||||
}
|
||||
|
||||
if (this.parent != null && command.isChangeInLongParameterNamed(parentIdParamName, this.parent.getId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(parentIdParamName);
|
||||
actualChanges.put(parentIdParamName, newValue);
|
||||
}
|
||||
|
||||
final String openingDateParamName = "openingDate";
|
||||
if (command.isChangeInLocalDateParameterNamed(openingDateParamName, getOpeningLocalDate())) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(openingDateParamName);
|
||||
actualChanges.put(openingDateParamName, valueAsInput);
|
||||
actualChanges.put("dateFormat", dateFormatAsInput);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
|
||||
this.openingDate = command.localDateValueOfParameterNamed(openingDateParamName);
|
||||
}
|
||||
|
||||
final String nameParamName = "name";
|
||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(nameParamName);
|
||||
actualChanges.put(nameParamName, newValue);
|
||||
this.name = newValue;
|
||||
}
|
||||
|
||||
final String externalIdParamName = "externalId";
|
||||
if (command.isChangeInStringParameterNamed(externalIdParamName, this.externalId)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(externalIdParamName);
|
||||
actualChanges.put(externalIdParamName, newValue);
|
||||
this.externalId = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean isOpeningDateBefore(final LocalDate baseDate) {
|
||||
return getOpeningLocalDate().isBefore(baseDate);
|
||||
}
|
||||
|
||||
public boolean isOpeningDateAfter(final LocalDate activationLocalDate) {
|
||||
return getOpeningLocalDate().isAfter(activationLocalDate);
|
||||
}
|
||||
|
||||
public LocalDate getOpeningLocalDate() {
|
||||
return this.openingDate;
|
||||
}
|
||||
|
||||
public void update(final Office newParent) {
|
||||
|
||||
if (this.parent == null) {
|
||||
throw new RootOfficeParentCannotBeUpdated();
|
||||
}
|
||||
|
||||
if (identifiedBy(newParent.getId())) {
|
||||
throw new CannotUpdateOfficeWithParentOfficeSameAsSelf(getId(), newParent.getId());
|
||||
}
|
||||
|
||||
this.parent = newParent;
|
||||
generateHierarchy();
|
||||
}
|
||||
|
||||
public boolean identifiedBy(final Long id) {
|
||||
return getId().equals(id);
|
||||
}
|
||||
|
||||
public void generateHierarchy() {
|
||||
|
||||
if (this.parent != null) {
|
||||
this.hierarchy = this.parent.hierarchyOf(getId());
|
||||
} else {
|
||||
this.hierarchy = ".";
|
||||
}
|
||||
}
|
||||
|
||||
private String hierarchyOf(final Long id) {
|
||||
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) {
|
||||
if (this.parent != null) {
|
||||
return this.parent.equals(office);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean doesNotHaveAnOfficeInHierarchyWithId(final Long officeId) {
|
||||
return !hasAnOfficeInHierarchyWithId(officeId);
|
||||
}
|
||||
|
||||
private boolean hasAnOfficeInHierarchyWithId(final Long officeId) {
|
||||
|
||||
boolean match = false;
|
||||
|
||||
if (identifiedBy(officeId)) {
|
||||
match = true;
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
for (final Office child : this.children) {
|
||||
final boolean result = child.hasAnOfficeInHierarchyWithId(officeId);
|
||||
|
||||
if (result) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
public void loadLazyCollections() {
|
||||
this.children.size();
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
|
||||
/**
|
||||
* Represents currencies allowed for this MFI/organisation.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "m_organisation_currency")
|
||||
public class OrganisationCurrency extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "code", nullable = false, length = 3)
|
||||
private String code;
|
||||
|
||||
@Column(name = "decimal_places", nullable = false)
|
||||
private Integer decimalPlaces;
|
||||
|
||||
@Column(name = "currency_multiplesof")
|
||||
private Integer inMultiplesOf;
|
||||
|
||||
@Column(name = "name", nullable = false, length = 50)
|
||||
private String name;
|
||||
|
||||
@Column(name = "internationalized_name_code", nullable = false, length = 50)
|
||||
private String nameCode;
|
||||
|
||||
@Column(name = "display_symbol", nullable = true, length = 10)
|
||||
private String displaySymbol;
|
||||
|
||||
protected OrganisationCurrency() {
|
||||
this.code = null;
|
||||
this.name = null;
|
||||
this.decimalPlaces = null;
|
||||
this.inMultiplesOf = null;
|
||||
this.nameCode = null;
|
||||
this.displaySymbol = null;
|
||||
}
|
||||
|
||||
public OrganisationCurrency(final String code, final String name, final int decimalPlaces, final Integer inMultiplesOf,
|
||||
final String nameCode, final String displaySymbol) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.decimalPlaces = decimalPlaces;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
this.nameCode = nameCode;
|
||||
this.displaySymbol = displaySymbol;
|
||||
}
|
||||
|
||||
public final String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public final MonetaryCurrency toMonetaryCurrency() {
|
||||
return new MonetaryCurrency(this.code, this.decimalPlaces, this.inMultiplesOf);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* Exception thrown when an attempt is made update the parent of a root office.
|
||||
*/
|
||||
public class CannotUpdateOfficeWithParentOfficeSameAsSelf extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public CannotUpdateOfficeWithParentOfficeSameAsSelf(final Long officeId, final Long parentId) {
|
||||
super("error.msg.office.parentId.same.as.id", "Cannot update office with parent same as self.", officeId, parentId);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* Exception thrown when an attempt is made update the parent of a root office.
|
||||
*/
|
||||
public class RootOfficeParentCannotBeUpdated extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public RootOfficeParentCannotBeUpdated() {
|
||||
super("error.msg.office.cannot.update.parent.office.of.root.office", "The root office must not be set with a parent office.");
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* 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.staff.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.organisation.office.data.OfficeData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing staff data.
|
||||
*/
|
||||
public final class StaffData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final String externalId;
|
||||
private final String firstname;
|
||||
private final String lastname;
|
||||
private final String displayName;
|
||||
private final String mobileNo;
|
||||
private final Long officeId;
|
||||
private final String officeName;
|
||||
private final Boolean isLoanOfficer;
|
||||
private final Boolean isActive;
|
||||
private final LocalDate joiningDate;
|
||||
|
||||
// import fields
|
||||
private transient Integer rowIndex;
|
||||
private String dateFormat;
|
||||
private String locale;
|
||||
|
||||
public static StaffData importInstance(String externalId, String firstname, String lastname, String mobileNo, Long officeId,
|
||||
Boolean isLoanOfficer, Boolean isActive, LocalDate joinedOnDate, Integer rowIndex, String locale, String dateFormat) {
|
||||
return new StaffData(externalId, firstname, lastname, mobileNo, officeId, isLoanOfficer, isActive, joinedOnDate, rowIndex, locale,
|
||||
dateFormat);
|
||||
|
||||
}
|
||||
|
||||
private StaffData(String externalId, String firstname, String lastname, String mobileNo, Long officeId, Boolean isLoanOfficer,
|
||||
Boolean isActive, LocalDate joiningDate, Integer rowIndex, String locale, String dateFormat) {
|
||||
|
||||
this.externalId = externalId;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.mobileNo = mobileNo;
|
||||
this.officeId = officeId;
|
||||
this.isLoanOfficer = isLoanOfficer;
|
||||
this.isActive = isActive;
|
||||
this.joiningDate = joiningDate;
|
||||
this.rowIndex = rowIndex;
|
||||
this.dateFormat = dateFormat;
|
||||
this.locale = locale;
|
||||
this.allowedOffices = null;
|
||||
this.id = null;
|
||||
this.officeName = null;
|
||||
this.displayName = null;
|
||||
}
|
||||
|
||||
public Integer getRowIndex() {
|
||||
return rowIndex;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<OfficeData> allowedOffices;
|
||||
|
||||
public static StaffData templateData(final StaffData staff, final Collection<OfficeData> allowedOffices) {
|
||||
return new StaffData(staff.id, staff.firstname, staff.lastname, staff.displayName, staff.officeId, staff.officeName,
|
||||
staff.isLoanOfficer, staff.externalId, staff.mobileNo, allowedOffices, staff.isActive, staff.joiningDate);
|
||||
}
|
||||
|
||||
public static StaffData lookup(final Long id, final String displayName) {
|
||||
return new StaffData(id, null, null, displayName, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static StaffData instance(final Long id, final String firstname, final String lastname, final String displayName,
|
||||
final Long officeId, final String officeName, final Boolean isLoanOfficer, final String externalId, final String mobileNo,
|
||||
final boolean isActive, final LocalDate joiningDate) {
|
||||
return new StaffData(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer, externalId, mobileNo, null,
|
||||
isActive, joiningDate);
|
||||
}
|
||||
|
||||
private StaffData(final Long id, final String firstname, final String lastname, final String displayName, final Long officeId,
|
||||
final String officeName, final Boolean isLoanOfficer, final String externalId, final String mobileNo,
|
||||
final Collection<OfficeData> allowedOffices, final Boolean isActive, final LocalDate joiningDate) {
|
||||
this.id = id;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.displayName = displayName;
|
||||
this.officeName = officeName;
|
||||
this.isLoanOfficer = isLoanOfficer;
|
||||
this.externalId = externalId;
|
||||
this.officeId = officeId;
|
||||
this.mobileNo = mobileNo;
|
||||
this.allowedOffices = allowedOffices;
|
||||
this.isActive = isActive;
|
||||
this.joiningDate = joiningDate;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return this.firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return this.lastname;
|
||||
}
|
||||
|
||||
public String getOfficeName() {
|
||||
return this.officeName;
|
||||
}
|
||||
|
||||
public LocalDate getJoiningDate() {
|
||||
return this.joiningDate;
|
||||
}
|
||||
|
||||
public Long getOfficeId() {
|
||||
return this.officeId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* 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.staff.domain;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.documentmanagement.domain.Image;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
@Table(name = "m_staff", uniqueConstraints = { @UniqueConstraint(columnNames = { "display_name" }, name = "display_name"),
|
||||
@UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE"),
|
||||
@UniqueConstraint(columnNames = { "mobile_no" }, name = "mobile_no_UNIQUE") })
|
||||
public class Staff extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "firstname", length = 50)
|
||||
private String firstname;
|
||||
|
||||
@Column(name = "lastname", length = 50)
|
||||
private String lastname;
|
||||
|
||||
@Column(name = "display_name", length = 100)
|
||||
private String displayName;
|
||||
|
||||
@Column(name = "mobile_no", length = 50, nullable = false, unique = true)
|
||||
private String mobileNo;
|
||||
|
||||
@Column(name = "external_id", length = 100, unique = true)
|
||||
private String externalId;
|
||||
|
||||
@Column(name = "email_address", length = 50, unique = true)
|
||||
private String emailAddress;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "office_id", nullable = false)
|
||||
private Office office;
|
||||
|
||||
@Column(name = "is_loan_officer", nullable = false)
|
||||
private boolean loanOfficer;
|
||||
|
||||
@Column(name = "organisational_role_enum")
|
||||
private Integer organisationalRoleType;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private boolean active;
|
||||
|
||||
@Column(name = "joining_date")
|
||||
private LocalDate joiningDate;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "organisational_role_parent_staff_id")
|
||||
private Staff organisationalRoleParentStaff;
|
||||
|
||||
@OneToOne(optional = true)
|
||||
@JoinColumn(name = "image_id")
|
||||
private Image image;
|
||||
|
||||
public static Staff fromJson(final Office staffOffice, final JsonCommand command) {
|
||||
|
||||
final String firstnameParamName = "firstname";
|
||||
final String firstname = command.stringValueOfParameterNamed(firstnameParamName);
|
||||
|
||||
final String lastnameParamName = "lastname";
|
||||
final String lastname = command.stringValueOfParameterNamed(lastnameParamName);
|
||||
|
||||
final String externalIdParamName = "externalId";
|
||||
final String externalId = command.stringValueOfParameterNamedAllowingNull(externalIdParamName);
|
||||
|
||||
final String mobileNoParamName = "mobileNo";
|
||||
final String mobileNo = command.stringValueOfParameterNamedAllowingNull(mobileNoParamName);
|
||||
|
||||
final String isLoanOfficerParamName = "isLoanOfficer";
|
||||
final boolean isLoanOfficer = command.booleanPrimitiveValueOfParameterNamed(isLoanOfficerParamName);
|
||||
|
||||
final String isActiveParamName = "isActive";
|
||||
final Boolean isActive = command.booleanObjectValueOfParameterNamed(isActiveParamName);
|
||||
|
||||
LocalDate joiningDate = null;
|
||||
|
||||
final String joiningDateParamName = "joiningDate";
|
||||
if (command.hasParameter(joiningDateParamName)) {
|
||||
joiningDate = command.localDateValueOfParameterNamed(joiningDateParamName);
|
||||
}
|
||||
|
||||
return new Staff(staffOffice, firstname, lastname, externalId, mobileNo, isLoanOfficer, isActive, joiningDate);
|
||||
}
|
||||
|
||||
protected Staff() {
|
||||
//
|
||||
}
|
||||
|
||||
private Staff(final Office staffOffice, final String firstname, final String lastname, final String externalId, final String mobileNo,
|
||||
final boolean isLoanOfficer, final Boolean isActive, final LocalDate joiningDate) {
|
||||
this.office = staffOffice;
|
||||
this.firstname = StringUtils.defaultIfEmpty(firstname, null);
|
||||
this.lastname = StringUtils.defaultIfEmpty(lastname, null);
|
||||
this.externalId = StringUtils.defaultIfEmpty(externalId, null);
|
||||
this.mobileNo = StringUtils.defaultIfEmpty(mobileNo, null);
|
||||
this.loanOfficer = isLoanOfficer;
|
||||
this.active = isActive == null ? true : isActive;
|
||||
deriveDisplayName(firstname);
|
||||
this.joiningDate = joiningDate;
|
||||
}
|
||||
|
||||
public EnumOptionData organisationalRoleData() {
|
||||
EnumOptionData organisationalRole = null;
|
||||
if (this.organisationalRoleType != null) {
|
||||
organisationalRole = StaffEnumerations.organisationalRole(this.organisationalRoleType);
|
||||
}
|
||||
return organisationalRole;
|
||||
}
|
||||
|
||||
public void changeOffice(final Office newOffice) {
|
||||
this.office = newOffice;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
final String officeIdParamName = "officeId";
|
||||
if (command.isChangeInLongParameterNamed(officeIdParamName, this.office.getId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(officeIdParamName);
|
||||
actualChanges.put(officeIdParamName, newValue);
|
||||
}
|
||||
|
||||
boolean firstnameChanged = false;
|
||||
final String firstnameParamName = "firstname";
|
||||
if (command.isChangeInStringParameterNamed(firstnameParamName, this.firstname)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(firstnameParamName);
|
||||
actualChanges.put(firstnameParamName, newValue);
|
||||
this.firstname = newValue;
|
||||
firstnameChanged = true;
|
||||
}
|
||||
|
||||
boolean lastnameChanged = false;
|
||||
final String lastnameParamName = "lastname";
|
||||
if (command.isChangeInStringParameterNamed(lastnameParamName, this.lastname)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(lastnameParamName);
|
||||
actualChanges.put(lastnameParamName, newValue);
|
||||
this.lastname = newValue;
|
||||
lastnameChanged = true;
|
||||
}
|
||||
|
||||
if (firstnameChanged || lastnameChanged) {
|
||||
deriveDisplayName(this.firstname);
|
||||
}
|
||||
|
||||
final String externalIdParamName = "externalId";
|
||||
if (command.isChangeInStringParameterNamed(externalIdParamName, this.externalId)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(externalIdParamName);
|
||||
actualChanges.put(externalIdParamName, newValue);
|
||||
this.externalId = newValue;
|
||||
}
|
||||
|
||||
final String mobileNoParamName = "mobileNo";
|
||||
if (command.isChangeInStringParameterNamed(mobileNoParamName, this.mobileNo)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(mobileNoParamName);
|
||||
actualChanges.put(mobileNoParamName, newValue);
|
||||
this.mobileNo = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
final String isLoanOfficerParamName = "isLoanOfficer";
|
||||
if (command.isChangeInBooleanParameterNamed(isLoanOfficerParamName, this.loanOfficer)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isLoanOfficerParamName);
|
||||
actualChanges.put(isLoanOfficerParamName, newValue);
|
||||
this.loanOfficer = newValue;
|
||||
}
|
||||
|
||||
final String isActiveParamName = "isActive";
|
||||
if (command.isChangeInBooleanParameterNamed(isActiveParamName, this.active)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isActiveParamName);
|
||||
actualChanges.put(isActiveParamName, newValue);
|
||||
this.active = newValue;
|
||||
}
|
||||
|
||||
final String joiningDateParamName = "joiningDate";
|
||||
if (command.isChangeInDateParameterNamed(joiningDateParamName, this.joiningDate)) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(joiningDateParamName);
|
||||
actualChanges.put(joiningDateParamName, valueAsInput);
|
||||
this.joiningDate = command.localDateValueOfParameterNamed(joiningDateParamName);
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean isNotLoanOfficer() {
|
||||
return !isLoanOfficer();
|
||||
}
|
||||
|
||||
public boolean isLoanOfficer() {
|
||||
return this.loanOfficer;
|
||||
}
|
||||
|
||||
public boolean isNotActive() {
|
||||
return !isActive();
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
private void deriveDisplayName(final String firstname) {
|
||||
if (!StringUtils.isBlank(firstname)) {
|
||||
this.displayName = this.lastname + ", " + this.firstname;
|
||||
} else {
|
||||
this.displayName = this.lastname;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean identifiedBy(final Staff staff) {
|
||||
return getId().equals(staff.getId());
|
||||
}
|
||||
|
||||
public String emailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public Long officeId() {
|
||||
return this.office.getId();
|
||||
}
|
||||
|
||||
public String displayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
public String mobileNo() {
|
||||
return this.mobileNo;
|
||||
}
|
||||
|
||||
public Office office() {
|
||||
return this.office;
|
||||
}
|
||||
|
||||
public void setImage(Image image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.staff.domain;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public final class StaffEnumerations {
|
||||
|
||||
private StaffEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData organisationalRole(final Integer id) {
|
||||
return organisationalRole(StaffOrganisationalRoleType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData organisationalRole(final StaffOrganisationalRoleType type) {
|
||||
EnumOptionData optionData = new EnumOptionData(StaffOrganisationalRoleType.INVALID.getValue().longValue(),
|
||||
StaffOrganisationalRoleType.INVALID.getCode(), "Invalid");
|
||||
switch (type) {
|
||||
case PROGRAM_DIRECTOR:
|
||||
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Program Director");
|
||||
break;
|
||||
case BRANCH_MANAGER:
|
||||
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Branch Manager");
|
||||
break;
|
||||
case FIELD_OFFICER_COORDINATOR:
|
||||
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Field Officer Coordinator");
|
||||
break;
|
||||
case FIELD_OFFICER:
|
||||
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Field Officer");
|
||||
break;
|
||||
case INVALID:
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.staff.domain;
|
||||
|
||||
public enum StaffOrganisationalRoleType {
|
||||
|
||||
INVALID(0, "staffOrganisationalRoleType.invalid"), //
|
||||
PROGRAM_DIRECTOR(100, "staffOrganisationalRoleType.programDirector"), //
|
||||
BRANCH_MANAGER(200, "staffOrganisationalRoleType.branchManager"), //
|
||||
FIELD_OFFICER_COORDINATOR(300, "staffOrganisationalRoleType.coordinator"), //
|
||||
FIELD_OFFICER(400, "staffOrganisationalRoleType.fieldAgent");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
StaffOrganisationalRoleType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static StaffOrganisationalRoleType fromInt(final Integer chargeCalculation) {
|
||||
StaffOrganisationalRoleType chargeCalculationType = StaffOrganisationalRoleType.INVALID;
|
||||
switch (chargeCalculation) {
|
||||
case 100:
|
||||
chargeCalculationType = PROGRAM_DIRECTOR;
|
||||
break;
|
||||
case 200:
|
||||
chargeCalculationType = BRANCH_MANAGER;
|
||||
break;
|
||||
case 300:
|
||||
chargeCalculationType = FIELD_OFFICER_COORDINATOR;
|
||||
break;
|
||||
case 400:
|
||||
chargeCalculationType = FIELD_OFFICER;
|
||||
break;
|
||||
}
|
||||
return chargeCalculationType;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.workingdays.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class WorkingDaysApiConstants {
|
||||
|
||||
private WorkingDaysApiConstants() {
|
||||
|
||||
}
|
||||
|
||||
public static final String WORKING_DAYS_RESOURCE_NAME = "workingdays";
|
||||
|
||||
// request parameters
|
||||
public static final String recurrence = "recurrence";
|
||||
|
||||
public static final String repayment_rescheduling_enum = "repaymentRescheduleType";
|
||||
|
||||
public static final String idParamName = "id";
|
||||
|
||||
public static final String rescheduleRepaymentTemplate = "rescheduleRepaymentTemplate";
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String extendTermForDailyRepayments = "extendTermForDailyRepayments";
|
||||
public static final String extendTermForRepaymentsOnHolidays = "extendTermForRepaymentsOnHolidays";
|
||||
|
||||
static final Set<String> WORKING_DAYS_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, recurrence,
|
||||
repayment_rescheduling_enum, extendTermForDailyRepayments, extendTermForRepaymentsOnHolidays));
|
||||
|
||||
static final Set<String> WORKING_DAYS_TEMPLATE_PARAMETERS = new HashSet<>(Arrays.asList(rescheduleRepaymentTemplate));
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.workingdays.data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class AdjustedDateDetailsDTO {
|
||||
|
||||
/**
|
||||
* Variable tracks the current schedule date that has been changed
|
||||
*/
|
||||
LocalDate changedScheduleDate;
|
||||
/**
|
||||
* Variable tracks If the meeting has been changed , i.e future schedule also changes along with the current
|
||||
* repayments date.
|
||||
*/
|
||||
LocalDate changedActualRepaymentDate;
|
||||
|
||||
/**
|
||||
* Variable tracks the next repayment period due date
|
||||
*/
|
||||
LocalDate nextRepaymentPeriodDueDate;
|
||||
|
||||
public AdjustedDateDetailsDTO(final LocalDate changedScheduleDate, final LocalDate changedActualRepaymentDate) {
|
||||
this.changedScheduleDate = changedScheduleDate;
|
||||
this.changedActualRepaymentDate = changedActualRepaymentDate;
|
||||
}
|
||||
|
||||
public AdjustedDateDetailsDTO(final LocalDate changedScheduleDate, final LocalDate changedActualRepaymentDate,
|
||||
final LocalDate nextRepaymentPeriodDueDate) {
|
||||
this.changedScheduleDate = changedScheduleDate;
|
||||
this.changedActualRepaymentDate = changedActualRepaymentDate;
|
||||
this.nextRepaymentPeriodDueDate = nextRepaymentPeriodDueDate;
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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.workingdays.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum RepaymentRescheduleType {
|
||||
|
||||
INVALID(0, "RepaymentRescheduleType.invalid"), SAME_DAY(1, "RepaymentRescheduleType.same.day"), MOVE_TO_NEXT_WORKING_DAY(2,
|
||||
"RepaymentRescheduleType.move.to.next.working.day"), MOVE_TO_NEXT_REPAYMENT_MEETING_DAY(3,
|
||||
"RepaymentRescheduleType.move.to.next.repayment.meeting.day"), MOVE_TO_PREVIOUS_WORKING_DAY(4,
|
||||
"RepaymentRescheduleType.move.to.previous.working.day"), MOVE_TO_NEXT_MEETING_DAY(5,
|
||||
"RepaymentRescheduleType.move.to.next.meeting.day");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
RepaymentRescheduleType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public boolean isMoveToNextRepaymentDay() {
|
||||
return this.value.equals(RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY.getValue());
|
||||
}
|
||||
|
||||
private static final Map<Integer, RepaymentRescheduleType> intToEnumMap = new HashMap<>();
|
||||
private static int minValue;
|
||||
private static int maxValue;
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
for (final RepaymentRescheduleType entityType : RepaymentRescheduleType.values()) {
|
||||
if (i == 0) {
|
||||
minValue = entityType.value;
|
||||
}
|
||||
intToEnumMap.put(entityType.value, entityType);
|
||||
if (minValue >= entityType.value) {
|
||||
minValue = entityType.value;
|
||||
}
|
||||
if (maxValue < entityType.value) {
|
||||
maxValue = entityType.value;
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static RepaymentRescheduleType fromInt(final int i) {
|
||||
final RepaymentRescheduleType repaymentRescheduleType = intToEnumMap.get(Integer.valueOf(i));
|
||||
return repaymentRescheduleType;
|
||||
}
|
||||
|
||||
public static int getMinValue() {
|
||||
return minValue;
|
||||
}
|
||||
|
||||
public static int getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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.workingdays.domain;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.workingdays.api.WorkingDaysApiConstants;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
@Table(name = "m_working_days")
|
||||
public class WorkingDays extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "recurrence", length = 100, nullable = true)
|
||||
private String recurrence;
|
||||
|
||||
@Setter
|
||||
@Column(name = "repayment_rescheduling_enum", nullable = false)
|
||||
private Integer repaymentReschedulingType;
|
||||
|
||||
@Column(name = "extend_term_daily_repayments", nullable = false)
|
||||
private Boolean extendTermForDailyRepayments;
|
||||
|
||||
@Column(name = "extend_term_holiday_repayment", nullable = false)
|
||||
private Boolean extendTermForRepaymentsOnHolidays;
|
||||
|
||||
protected WorkingDays() {
|
||||
|
||||
}
|
||||
|
||||
protected WorkingDays(final String recurrence, final Integer repaymentReschedulingType, final Boolean extendTermForDailyRepayments,
|
||||
final Boolean extendTermForRepaymentsOnHolidays) {
|
||||
this.recurrence = recurrence;
|
||||
this.repaymentReschedulingType = repaymentReschedulingType;
|
||||
this.extendTermForDailyRepayments = extendTermForDailyRepayments;
|
||||
this.extendTermForRepaymentsOnHolidays = extendTermForRepaymentsOnHolidays;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
final String recurrenceParamName = "recurrence";
|
||||
if (command.isChangeInStringParameterNamed(recurrenceParamName, this.recurrence)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(recurrenceParamName);
|
||||
actualChanges.put(recurrenceParamName, newValue);
|
||||
this.recurrence = newValue;
|
||||
}
|
||||
|
||||
final String repaymentRescheduleTypeParamName = "repaymentRescheduleType";
|
||||
if (command.isChangeInIntegerParameterNamed(repaymentRescheduleTypeParamName, this.repaymentReschedulingType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(repaymentRescheduleTypeParamName);
|
||||
actualChanges.put(repaymentRescheduleTypeParamName, WorkingDaysEnumerations.workingDaysStatusType(newValue));
|
||||
this.repaymentReschedulingType = RepaymentRescheduleType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(WorkingDaysApiConstants.extendTermForDailyRepayments,
|
||||
this.extendTermForDailyRepayments)) {
|
||||
final Boolean newValue = command.booleanPrimitiveValueOfParameterNamed(WorkingDaysApiConstants.extendTermForDailyRepayments);
|
||||
actualChanges.put(WorkingDaysApiConstants.extendTermForDailyRepayments, newValue);
|
||||
this.extendTermForDailyRepayments = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(WorkingDaysApiConstants.extendTermForRepaymentsOnHolidays,
|
||||
this.extendTermForRepaymentsOnHolidays)) {
|
||||
final Boolean newValue = command
|
||||
.booleanPrimitiveValueOfParameterNamed(WorkingDaysApiConstants.extendTermForRepaymentsOnHolidays);
|
||||
actualChanges.put(WorkingDaysApiConstants.extendTermForRepaymentsOnHolidays, newValue);
|
||||
this.extendTermForRepaymentsOnHolidays = newValue;
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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.workingdays.domain;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public final class WorkingDaysEnumerations {
|
||||
|
||||
private WorkingDaysEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData workingDaysStatusType(final int id) {
|
||||
return repaymentRescheduleType(RepaymentRescheduleType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData repaymentRescheduleType(final RepaymentRescheduleType type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
optionData = new EnumOptionData(RepaymentRescheduleType.INVALID.getValue().longValue(),
|
||||
RepaymentRescheduleType.INVALID.getCode(), "invalid");
|
||||
break;
|
||||
|
||||
case SAME_DAY:
|
||||
optionData = new EnumOptionData(RepaymentRescheduleType.SAME_DAY.getValue().longValue(),
|
||||
RepaymentRescheduleType.SAME_DAY.getCode(), "same day");
|
||||
|
||||
break;
|
||||
case MOVE_TO_NEXT_WORKING_DAY:
|
||||
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_NEXT_WORKING_DAY.getValue().longValue(),
|
||||
RepaymentRescheduleType.MOVE_TO_NEXT_WORKING_DAY.getCode(), "move to next working day");
|
||||
break;
|
||||
|
||||
case MOVE_TO_NEXT_REPAYMENT_MEETING_DAY:
|
||||
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY.getValue().longValue(),
|
||||
RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY.getCode(), "move to next repayment meeting day");
|
||||
break;
|
||||
case MOVE_TO_PREVIOUS_WORKING_DAY:
|
||||
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_PREVIOUS_WORKING_DAY.getValue().longValue(),
|
||||
RepaymentRescheduleType.MOVE_TO_PREVIOUS_WORKING_DAY.getCode(), "move to previous working day");
|
||||
break;
|
||||
case MOVE_TO_NEXT_MEETING_DAY:
|
||||
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_NEXT_MEETING_DAY.getValue().longValue(),
|
||||
RepaymentRescheduleType.MOVE_TO_NEXT_MEETING_DAY.getCode(), "move to next meeting day");
|
||||
break;
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.workingdays.service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
|
||||
import org.apache.fineract.organisation.workingdays.domain.RepaymentRescheduleType;
|
||||
import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||
|
||||
public final class WorkingDaysUtil {
|
||||
|
||||
private WorkingDaysUtil() {
|
||||
|
||||
}
|
||||
|
||||
public static LocalDate getOffSetDateIfNonWorkingDay(final LocalDate date, final LocalDate nextMeetingDate,
|
||||
final WorkingDays workingDays) {
|
||||
|
||||
// If date is not a non working day then return date.
|
||||
if (isWorkingDay(workingDays, date)) {
|
||||
return date;
|
||||
}
|
||||
|
||||
final RepaymentRescheduleType rescheduleType = RepaymentRescheduleType.fromInt(workingDays.getRepaymentReschedulingType());
|
||||
|
||||
switch (rescheduleType) {
|
||||
case INVALID:
|
||||
return date;
|
||||
case SAME_DAY:
|
||||
return date;
|
||||
case MOVE_TO_NEXT_WORKING_DAY:
|
||||
return getOffSetDateIfNonWorkingDay(date.plusDays(1), nextMeetingDate, workingDays);
|
||||
case MOVE_TO_NEXT_REPAYMENT_MEETING_DAY:
|
||||
return nextMeetingDate;
|
||||
case MOVE_TO_PREVIOUS_WORKING_DAY:
|
||||
return getOffSetDateIfNonWorkingDay(date.minusDays(1), nextMeetingDate, workingDays);
|
||||
default:
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isWorkingDay(final WorkingDays workingDays, final LocalDate date) {
|
||||
return CalendarUtils.isValidRedurringDate(workingDays.getRecurrence(), date, date);
|
||||
}
|
||||
|
||||
public static boolean isNonWorkingDay(final WorkingDays workingDays, final LocalDate date) {
|
||||
return !isWorkingDay(workingDays, date);
|
||||
}
|
||||
|
||||
public static void updateWorkingDayIfRepaymentDateIsNonWorkingDay(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
|
||||
final WorkingDays workingDays) {
|
||||
final LocalDate changedScheduleDate = getOffSetDateIfNonWorkingDay(adjustedDateDetailsDTO.getChangedScheduleDate(),
|
||||
adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate(), workingDays);
|
||||
adjustedDateDetailsDTO.setChangedScheduleDate(changedScheduleDate);
|
||||
}
|
||||
|
||||
public static RepaymentRescheduleType getRepaymentRescheduleType(final WorkingDays workingDays, final LocalDate date) {
|
||||
RepaymentRescheduleType rescheduleType = RepaymentRescheduleType.fromInt(workingDays.getRepaymentReschedulingType());
|
||||
return rescheduleType;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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.account;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public enum PortfolioAccountType {
|
||||
|
||||
INVALID(0, "accountType.invalid"), //
|
||||
LOAN(1, "accountType.loan"), //
|
||||
SAVINGS(2, "accountType.savings");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
PortfolioAccountType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] integerValues() {
|
||||
final List<Integer> values = new ArrayList<>();
|
||||
for (final PortfolioAccountType enumType : values()) {
|
||||
if (enumType.getValue() > 0) {
|
||||
values.add(enumType.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return values.toArray();
|
||||
}
|
||||
|
||||
public static PortfolioAccountType fromInt(final Integer type) {
|
||||
|
||||
PortfolioAccountType enumType = PortfolioAccountType.INVALID;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case 1:
|
||||
enumType = LOAN;
|
||||
break;
|
||||
case 2:
|
||||
enumType = SAVINGS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return enumType;
|
||||
}
|
||||
|
||||
public boolean isSavingsAccount() {
|
||||
return this.value.equals(2);
|
||||
}
|
||||
|
||||
public boolean isLoanAccount() {
|
||||
return this.value.equals(1);
|
||||
}
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.office.data.OfficeData;
|
||||
import org.apache.fineract.portfolio.client.data.ClientData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a savings account.
|
||||
*/
|
||||
@Getter
|
||||
public final class AccountTransferData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final Boolean reversed;
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal transferAmount;
|
||||
private final LocalDate transferDate;
|
||||
private final String transferDescription;
|
||||
private final OfficeData fromOffice;
|
||||
private final ClientData fromClient;
|
||||
private final EnumOptionData fromAccountType;
|
||||
private final PortfolioAccountData fromAccount;
|
||||
private final OfficeData toOffice;
|
||||
private final ClientData toClient;
|
||||
private final EnumOptionData toAccountType;
|
||||
private final PortfolioAccountData toAccount;
|
||||
|
||||
// template
|
||||
private final Collection<OfficeData> fromOfficeOptions;
|
||||
private final Collection<ClientData> fromClientOptions;
|
||||
private final Collection<EnumOptionData> fromAccountTypeOptions;
|
||||
private final Collection<PortfolioAccountData> fromAccountOptions;
|
||||
private final Collection<OfficeData> toOfficeOptions;
|
||||
private final Collection<ClientData> toClientOptions;
|
||||
private final Collection<EnumOptionData> toAccountTypeOptions;
|
||||
private final Collection<PortfolioAccountData> toAccountOptions;
|
||||
|
||||
public static AccountTransferData template(final OfficeData fromOffice, final ClientData fromClient,
|
||||
final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount, final LocalDate transferDate,
|
||||
final OfficeData toOffice, final ClientData toClient, final EnumOptionData toAccountType, final PortfolioAccountData toAccount,
|
||||
final Collection<OfficeData> fromOfficeOptions, final Collection<ClientData> fromClientOptions,
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions, final Collection<PortfolioAccountData> fromAccountOptions,
|
||||
final Collection<OfficeData> toOfficeOptions, final Collection<ClientData> toClientOptions,
|
||||
final Collection<EnumOptionData> toAccountTypeOptions, final Collection<PortfolioAccountData> toAccountOptions) {
|
||||
final Long id = null;
|
||||
CurrencyData currency = null;
|
||||
BigDecimal transferAmount = BigDecimal.ZERO;
|
||||
if (fromAccount != null) {
|
||||
currency = fromAccount.getCurrency();
|
||||
if (fromAccount.getAmtForTransfer() != null) {
|
||||
transferAmount = fromAccount.getAmtForTransfer();
|
||||
}
|
||||
}
|
||||
final String transferDescription = null;
|
||||
final Boolean reversed = null;
|
||||
return new AccountTransferData(id, reversed, fromOffice, fromClient, fromAccountType, fromAccount, currency, transferAmount,
|
||||
transferDate, transferDescription, toOffice, toClient, toAccountType, toAccount, fromOfficeOptions, fromClientOptions,
|
||||
fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions);
|
||||
}
|
||||
|
||||
public static AccountTransferData instance(final Long id, final Boolean reversed, final LocalDate transferDate,
|
||||
final CurrencyData currency, final BigDecimal transferAmount, final String transferDescription, final OfficeData fromOffice,
|
||||
final OfficeData toOffice, final ClientData fromClient, final ClientData toClient, final EnumOptionData fromAccountType,
|
||||
final PortfolioAccountData fromAccount, final EnumOptionData toAccountType, final PortfolioAccountData toAccount) {
|
||||
|
||||
return new AccountTransferData(id, reversed, fromOffice, fromClient, fromAccountType, fromAccount, currency, transferAmount,
|
||||
transferDate, transferDescription, toOffice, toClient, toAccountType, toAccount, null, null, null, null, null, null, null,
|
||||
null);
|
||||
}
|
||||
|
||||
public static AccountTransferData transferBasicDetails(final Long id, final CurrencyData currency, final BigDecimal transferAmount,
|
||||
final LocalDate transferDate, final String description, final Boolean reversed) {
|
||||
|
||||
final EnumOptionData fromAccountType = null;
|
||||
final EnumOptionData toAccountType = null;
|
||||
|
||||
return new AccountTransferData(id, reversed, null, null, fromAccountType, null, currency, transferAmount, transferDate, description,
|
||||
null, null, toAccountType, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
private AccountTransferData(final Long id, final Boolean reversed, final OfficeData fromOffice, final ClientData fromClient,
|
||||
final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount, final CurrencyData currency,
|
||||
final BigDecimal transferAmount, final LocalDate transferDate, final String transferDescription, final OfficeData toOffice,
|
||||
final ClientData toClient, final EnumOptionData toAccountType, final PortfolioAccountData toAccount,
|
||||
final Collection<OfficeData> fromOfficeOptions, final Collection<ClientData> fromClientOptions,
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions, final Collection<PortfolioAccountData> fromAccountOptions,
|
||||
final Collection<OfficeData> toOfficeOptions, final Collection<ClientData> toClientOptions,
|
||||
final Collection<EnumOptionData> toAccountTypeOptions, final Collection<PortfolioAccountData> toAccountOptions) {
|
||||
this.id = id;
|
||||
this.reversed = reversed;
|
||||
this.fromOffice = fromOffice;
|
||||
this.fromClient = fromClient;
|
||||
this.fromAccountType = fromAccountType;
|
||||
this.fromAccount = fromAccount;
|
||||
this.toOffice = toOffice;
|
||||
this.toClient = toClient;
|
||||
this.toAccountType = toAccountType;
|
||||
this.toAccount = toAccount;
|
||||
|
||||
this.currency = currency;
|
||||
this.transferAmount = transferAmount;
|
||||
this.transferDate = transferDate;
|
||||
this.transferDescription = transferDescription;
|
||||
|
||||
this.fromOfficeOptions = fromOfficeOptions;
|
||||
this.fromClientOptions = fromClientOptions;
|
||||
this.fromAccountTypeOptions = fromAccountTypeOptions;
|
||||
this.fromAccountOptions = fromAccountOptions;
|
||||
this.toOfficeOptions = toOfficeOptions;
|
||||
this.toClientOptions = toClientOptions;
|
||||
this.toAccountTypeOptions = toAccountTypeOptions;
|
||||
this.toAccountOptions = toAccountOptions;
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a savings account.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor
|
||||
public class PortfolioAccountData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final String accountNo;
|
||||
private final String externalId;
|
||||
private final Long groupId;
|
||||
private final String groupName;
|
||||
private final Long clientId;
|
||||
private final String clientName;
|
||||
private final Long productId;
|
||||
private final String productName;
|
||||
private final Long fieldOfficerId;
|
||||
private final String fieldOfficerName;
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal amtForTransfer;
|
||||
|
||||
public static PortfolioAccountData lookup(final Long accountId, final String accountNo) {
|
||||
return new PortfolioAccountData(accountId, accountNo, null, null, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public PortfolioAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, final String groupName,
|
||||
final Long clientId, final String clientName, final Long productId, final String productName, final Long fieldOfficerId,
|
||||
final String fieldOfficerName, final CurrencyData currency) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
this.groupId = groupId;
|
||||
this.groupName = groupName;
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
this.fieldOfficerId = fieldOfficerId;
|
||||
this.fieldOfficerName = fieldOfficerName;
|
||||
this.currency = currency;
|
||||
this.amtForTransfer = null;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return this.currency.getCode();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferData;
|
||||
|
||||
public interface AccountTransfersReadPlatformService {
|
||||
|
||||
AccountTransferData retrieveTemplate(Long fromOfficeId, Long fromClientId, Long fromAccountId, Integer fromAccountType, Long toOfficeId,
|
||||
Long toClientId, Long toAccountId, Integer toAccountType);
|
||||
|
||||
Page<AccountTransferData> retrieveAll(SearchParameters searchParameters, Long accountDetailId);
|
||||
|
||||
AccountTransferData retrieveOne(Long transferId);
|
||||
|
||||
boolean isAccountTransfer(Long transactionId, PortfolioAccountType accountType);
|
||||
|
||||
Page<AccountTransferData> retrieveByStandingInstruction(Long id, SearchParameters searchParameters);
|
||||
|
||||
Collection<Long> fetchPostInterestTransactionIds(Long accountId);
|
||||
|
||||
Collection<Long> fetchPostInterestTransactionIdsWithPivotDate(Long accountId, LocalDate pivotDate);
|
||||
|
||||
AccountTransferData retrieveRefundByTransferTemplate(Long fromOfficeId, Long fromClientId, Long fromAccountId, Integer fromAccountType,
|
||||
Long toOfficeId, Long toClientId, Long toAccountId, Integer toAccountType);
|
||||
|
||||
BigDecimal getTotalTransactionAmount(Long accountId, Integer accountType, LocalDate transactionDate);
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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.accountdetails.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
|
||||
|
||||
/**
|
||||
* Immutable data object for savings accounts.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class SavingsAccountSummaryData {
|
||||
|
||||
private final Long id;
|
||||
private final String accountNo;
|
||||
private final String externalId;
|
||||
private final Long productId;
|
||||
private final String productName;
|
||||
private final String shortProductName;
|
||||
private final SavingsAccountStatusEnumData status;
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal accountBalance;
|
||||
// differentiate Individual, JLG or Group account
|
||||
private final EnumOptionData accountType;
|
||||
private final SavingsAccountApplicationTimelineData timeline;
|
||||
private final SavingsAccountSubStatusEnumData subStatus;
|
||||
private final LocalDate lastActiveTransactionDate;
|
||||
|
||||
// differentiate deposit accounts Savings, FD and RD accounts
|
||||
private final EnumOptionData depositType;
|
||||
|
||||
public SavingsAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
|
||||
final String productName, final String shortProductName, final SavingsAccountStatusEnumData status, final CurrencyData currency,
|
||||
final BigDecimal accountBalance, final EnumOptionData accountType, final SavingsAccountApplicationTimelineData timeline,
|
||||
final EnumOptionData depositType, final SavingsAccountSubStatusEnumData subStatus, final LocalDate lastActiveTransactionDate) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
this.shortProductName = shortProductName;
|
||||
this.status = status;
|
||||
this.currency = currency;
|
||||
this.accountBalance = accountBalance;
|
||||
this.accountType = accountType;
|
||||
this.timeline = timeline;
|
||||
this.depositType = depositType;
|
||||
this.subStatus = subStatus;
|
||||
this.lastActiveTransactionDate = lastActiveTransactionDate;
|
||||
}
|
||||
|
||||
public String getAccountNo() {
|
||||
return accountNo;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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.accountdetails.domain;
|
||||
|
||||
/**
|
||||
* Enum representation of account types .
|
||||
*/
|
||||
public enum AccountType {
|
||||
|
||||
INVALID(0, "accountType.invalid"), //
|
||||
INDIVIDUAL(1, "accountType.individual"), //
|
||||
GROUP(2, "accountType.group"), //
|
||||
JLG(3, "accountType.jlg"), // JLG account given in group context
|
||||
GLIM(4, "accountType.glim"), GSIM(5, "accountType.gsim");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
AccountType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static AccountType fromInt(final Integer accountTypeValue) {
|
||||
|
||||
AccountType enumeration = AccountType.INVALID;
|
||||
switch (accountTypeValue) {
|
||||
case 1:
|
||||
enumeration = AccountType.INDIVIDUAL;
|
||||
break;
|
||||
case 2:
|
||||
enumeration = AccountType.GROUP;
|
||||
break;
|
||||
case 3:
|
||||
enumeration = AccountType.JLG;
|
||||
break;
|
||||
case 4:
|
||||
enumeration = AccountType.GLIM;
|
||||
break;
|
||||
case 5:
|
||||
enumeration = AccountType.GSIM;
|
||||
break;
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
public static AccountType fromName(final String name) {
|
||||
AccountType accountType = AccountType.INVALID;
|
||||
for (final AccountType type : AccountType.values()) {
|
||||
if (type.getName().equals(name)) {
|
||||
accountType = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return accountType;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return this.value.equals(AccountType.INVALID.getValue());
|
||||
}
|
||||
|
||||
public boolean isIndividualAccount() {
|
||||
return this.value.equals(AccountType.INDIVIDUAL.getValue());
|
||||
}
|
||||
|
||||
public boolean isGroupAccount() {
|
||||
return this.value.equals(AccountType.GROUP.getValue());
|
||||
}
|
||||
|
||||
public boolean isJLGAccount() {
|
||||
return this.value.equals(AccountType.JLG.getValue());
|
||||
}
|
||||
|
||||
public boolean isGLIMAccount() {
|
||||
return this.value.equals(AccountType.GLIM.getValue());
|
||||
}
|
||||
|
||||
public boolean isGSIMAccount() {
|
||||
return this.value.equals(AccountType.GSIM.getValue());
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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.accountdetails.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
|
||||
|
||||
public final class AccountEnumerations {
|
||||
|
||||
private AccountEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData loanType(final Integer loanTypeId) {
|
||||
return loanType(AccountType.fromInt(loanTypeId));
|
||||
}
|
||||
|
||||
public static EnumOptionData loanType(final String name) {
|
||||
return loanType(AccountType.fromName(name));
|
||||
}
|
||||
|
||||
public static EnumOptionData loanType(final AccountType type) {
|
||||
EnumOptionData optionData = new EnumOptionData(AccountType.INVALID.getValue().longValue(), AccountType.INVALID.getCode(),
|
||||
"Invalid");
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
optionData = new EnumOptionData(AccountType.INVALID.getValue().longValue(), AccountType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
case INDIVIDUAL:
|
||||
optionData = new EnumOptionData(AccountType.INDIVIDUAL.getValue().longValue(), AccountType.INDIVIDUAL.getCode(),
|
||||
"Individual");
|
||||
break;
|
||||
case GROUP:
|
||||
optionData = new EnumOptionData(AccountType.GROUP.getValue().longValue(), AccountType.GROUP.getCode(), "Group");
|
||||
break;
|
||||
case JLG:
|
||||
optionData = new EnumOptionData(AccountType.JLG.getValue().longValue(), AccountType.JLG.getCode(), "JLG");
|
||||
break;
|
||||
case GLIM:
|
||||
optionData = new EnumOptionData(AccountType.GLIM.getValue().longValue(), AccountType.GLIM.getCode(), "GLIM");
|
||||
break;
|
||||
case GSIM:
|
||||
optionData = new EnumOptionData(AccountType.GSIM.getValue().longValue(), AccountType.GSIM.getCode(), "GSIM");
|
||||
break;
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* 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.address.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class AddressData implements Serializable {
|
||||
|
||||
private final Long clientID;
|
||||
|
||||
private final String addressType;
|
||||
|
||||
private final Long addressId;
|
||||
|
||||
private final Long addressTypeId;
|
||||
|
||||
private final Boolean isActive;
|
||||
|
||||
private final String street;
|
||||
|
||||
private final String addressLine1;
|
||||
|
||||
private final String addressLine2;
|
||||
|
||||
private final String addressLine3;
|
||||
|
||||
private final String townVillage;
|
||||
|
||||
private final String city;
|
||||
|
||||
private final String countyDistrict;
|
||||
|
||||
private final Long stateProvinceId;
|
||||
|
||||
private final String countryName;
|
||||
|
||||
private final String stateName;
|
||||
|
||||
private final Long countryId;
|
||||
|
||||
private final String postalCode;
|
||||
|
||||
private final BigDecimal latitude;
|
||||
|
||||
private final BigDecimal longitude;
|
||||
|
||||
private final String createdBy;
|
||||
|
||||
private final LocalDate createdOn;
|
||||
|
||||
private final String updatedBy;
|
||||
|
||||
private final LocalDate updatedOn;
|
||||
|
||||
// template holder
|
||||
private final Collection<CodeValueData> countryIdOptions;
|
||||
private final Collection<CodeValueData> stateProvinceIdOptions;
|
||||
private final Collection<CodeValueData> addressTypeIdOptions;
|
||||
|
||||
public AddressData(Long addressTypeId, String street, String addressLine1, String addressLine2, String addressLine3, String city,
|
||||
String postalCode, Boolean isActive, Long stateProvinceId, Long countryId) {
|
||||
|
||||
this.addressTypeId = addressTypeId;
|
||||
this.isActive = isActive;
|
||||
this.street = street;
|
||||
this.addressLine1 = addressLine1;
|
||||
this.addressLine2 = addressLine2;
|
||||
this.addressLine3 = addressLine3;
|
||||
this.countryId = countryId;
|
||||
this.postalCode = postalCode;
|
||||
this.stateProvinceId = stateProvinceId;
|
||||
this.city = city;
|
||||
this.townVillage = null;
|
||||
this.clientID = null;
|
||||
this.addressType = null;
|
||||
this.addressId = null;
|
||||
this.countyDistrict = null;
|
||||
this.countryName = null;
|
||||
this.stateName = null;
|
||||
this.latitude = null;
|
||||
this.longitude = null;
|
||||
this.createdBy = null;
|
||||
this.createdOn = null;
|
||||
this.updatedBy = null;
|
||||
this.updatedOn = null;
|
||||
this.countryIdOptions = null;
|
||||
this.stateProvinceIdOptions = null;
|
||||
this.addressTypeIdOptions = null;
|
||||
}
|
||||
|
||||
private AddressData(final String addressType, final Long clientID, final Long addressId, final Long addressTypeId,
|
||||
final Boolean is_active, final String street, final String addressLine1, final String addressLine2, final String addressLine3,
|
||||
final String townVillage, final String city, final String countyDistrict, final Long stateProvinceId, final Long countryId,
|
||||
final String stateName, final String countryName, final String postalCode, final BigDecimal latitude,
|
||||
final BigDecimal longitude, final String createdBy, final LocalDate createdOn, final String updatedBy,
|
||||
final LocalDate updatedOn, final Collection<CodeValueData> countryIdOptions,
|
||||
final Collection<CodeValueData> stateProvinceIdOptions, final Collection<CodeValueData> addressTypeIdOptions) {
|
||||
this.addressType = addressType;
|
||||
this.clientID = clientID;
|
||||
this.addressId = addressId;
|
||||
this.addressTypeId = addressTypeId;
|
||||
this.isActive = is_active;
|
||||
this.street = street;
|
||||
this.addressLine1 = addressLine1;
|
||||
this.addressLine2 = addressLine2;
|
||||
this.addressLine3 = addressLine3;
|
||||
this.townVillage = townVillage;
|
||||
this.city = city;
|
||||
this.countyDistrict = countyDistrict;
|
||||
this.stateProvinceId = stateProvinceId;
|
||||
this.countryId = countryId;
|
||||
this.stateName = stateName;
|
||||
this.countryName = countryName;
|
||||
this.postalCode = postalCode;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
this.createdBy = createdBy;
|
||||
this.createdOn = createdOn;
|
||||
this.updatedBy = updatedBy;
|
||||
this.updatedOn = updatedOn;
|
||||
this.countryIdOptions = countryIdOptions;
|
||||
this.stateProvinceIdOptions = stateProvinceIdOptions;
|
||||
this.addressTypeIdOptions = addressTypeIdOptions;
|
||||
}
|
||||
|
||||
public static AddressData instance(final String addressType, final Long clientID, final Long addressId, final Long addressTypeId,
|
||||
final Boolean is_active, final String street, final String addressLine1, final String addressLine2, final String addressLine3,
|
||||
final String townVillage, final String city, final String countyDistrict, final Long stateProvinceId, final Long countryId,
|
||||
final String stateName, final String countryName, final String postalCode, final BigDecimal latitude,
|
||||
final BigDecimal longitude, final String createdBy, final LocalDate createdOn, final String updatedBy,
|
||||
final LocalDate updatedOn) {
|
||||
|
||||
return new AddressData(addressType, clientID, addressId, addressTypeId, is_active, street, addressLine1, addressLine2, addressLine3,
|
||||
townVillage, city, countyDistrict, stateProvinceId, countryId, stateName, countryName, postalCode, latitude, longitude,
|
||||
createdBy, createdOn, updatedBy, updatedOn, null, null, null);
|
||||
}
|
||||
|
||||
public static AddressData instance1(final Long addressId, final String street, final String addressLine1, final String addressLine2,
|
||||
final String addressLine3, final String townVillage, final String city, final String countyDistrict, final Long stateProvinceId,
|
||||
final Long countryId, final String postalCode, final BigDecimal latitude, final BigDecimal longitude, final String createdBy,
|
||||
final LocalDate createdOn, final String updatedBy, final LocalDate updatedOn) {
|
||||
return new AddressData(null, null, addressId, null, false, street, addressLine1, addressLine2, addressLine3, townVillage, city,
|
||||
countyDistrict, stateProvinceId, countryId, null, null, postalCode, latitude, longitude, createdBy, createdOn, updatedBy,
|
||||
updatedOn, null, null, null);
|
||||
}
|
||||
|
||||
public static AddressData template(final Collection<CodeValueData> countryIdOptions,
|
||||
final Collection<CodeValueData> stateProvinceIdOptions, final Collection<CodeValueData> addressTypeIdOptions) {
|
||||
final Long client_idtemp = null;
|
||||
|
||||
final Long addressIdtemp = null;
|
||||
|
||||
final Long addressTypeIdtemp = null;
|
||||
|
||||
final Boolean is_activetemp = null;
|
||||
|
||||
final String streettemp = null;
|
||||
|
||||
final String addressLine1temp = null;
|
||||
|
||||
final String addressLine2temp = null;
|
||||
|
||||
final String addressLine3temp = null;
|
||||
|
||||
final String townVillagetemp = null;
|
||||
|
||||
final String citytemp = null;
|
||||
|
||||
final String countyDistricttemp = null;
|
||||
|
||||
final Long stateProvinceIdtemp = null;
|
||||
|
||||
final Long countryIdtemp = null;
|
||||
|
||||
final String postalCodetemp = null;
|
||||
|
||||
final BigDecimal latitudetemp = null;
|
||||
|
||||
final BigDecimal longitudetemp = null;
|
||||
|
||||
final String createdBytemp = null;
|
||||
|
||||
final LocalDate createdOntemp = null;
|
||||
|
||||
final String updatedBytemp = null;
|
||||
|
||||
final LocalDate updatedOntemp = null;
|
||||
|
||||
return new AddressData(null, client_idtemp, addressIdtemp, addressTypeIdtemp, is_activetemp, streettemp, addressLine1temp,
|
||||
addressLine2temp, addressLine3temp, townVillagetemp, citytemp, countyDistricttemp, stateProvinceIdtemp, countryIdtemp, null,
|
||||
null, postalCodetemp, latitudetemp, longitudetemp, createdBytemp, createdOntemp, updatedBytemp, updatedOntemp,
|
||||
countryIdOptions, stateProvinceIdOptions, addressTypeIdOptions);
|
||||
}
|
||||
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 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.calendar;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class CalendarConstants {
|
||||
|
||||
private CalendarConstants() {
|
||||
|
||||
}
|
||||
|
||||
public static final String CALENDAR_RESOURCE_NAME = "calendar";
|
||||
|
||||
public enum CalendarSupportedParameters {
|
||||
|
||||
CALENDAR_ID("id"), ENTITY_TYPE("entityType"), ENTITY_ID("entityId"), TITLE("title"), DESCRIPTION("description"), LOCATION(
|
||||
"location"), START_DATE("startDate"), END_DATE("endDate"), CREATED_DATE("createdDate"), DURATION("duration"), TYPE_ID(
|
||||
"typeId"), REPEATING("repeating"), REMIND_BY_ID("remindById"), FIRST_REMINDER("firstReminder"), SECOND_REMINDER(
|
||||
"secondReminder"), LOCALE("locale"), DATE_FORMAT("dateFormat"), FREQUENCY("frequency"), INTERVAL(
|
||||
"interval"), REPEATS_ON_DAY("repeatsOnDay"), RESCHEDULE_BASED_ON_MEETING_DATES(
|
||||
"reschedulebasedOnMeetingDates"), PRESENT_MEETING_DATE(
|
||||
"presentMeetingDate"), NEW_MEETING_DATE("newMeetingDate"), MEETING_TIME(
|
||||
"meetingtime"), Time_Format("timeFormat"), REPEATS_ON_NTH_DAY_OF_MONTH(
|
||||
"repeatsOnNthDayOfMonth"), REPEATS_ON_LAST_WEEKDAY_OF_MONTH(
|
||||
"repeatsOnLastWeekdayOfMonth"), REPEATS_ON_DAY_OF_MONTH(
|
||||
"repeatsOnDayOfMonth");
|
||||
|
||||
private final String value;
|
||||
|
||||
CalendarSupportedParameters(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
|
||||
static {
|
||||
for (final CalendarSupportedParameters param : CalendarSupportedParameters.values()) {
|
||||
values.add(param.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+413
@@ -0,0 +1,413 @@
|
||||
/**
|
||||
* 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.calendar.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarWeekDaysType;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarEnumerations;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||
import org.apache.fineract.portfolio.common.domain.NthDayType;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public final class CalendarData implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private Long calendarInstanceId;
|
||||
private Long entityId;
|
||||
private EnumOptionData entityType;
|
||||
private String title;
|
||||
private String description;
|
||||
private String location;
|
||||
private LocalDate startDate;
|
||||
private LocalDate endDate;
|
||||
private LocalTime meetingTime;
|
||||
private Integer duration;
|
||||
private EnumOptionData type;
|
||||
private boolean repeating;
|
||||
private String recurrence;
|
||||
private EnumOptionData frequency;
|
||||
private Integer interval;
|
||||
private EnumOptionData repeatsOnDay;
|
||||
private EnumOptionData repeatsOnNthDayOfMonth;
|
||||
private EnumOptionData remindBy;
|
||||
private Integer firstReminder;
|
||||
private Integer secondReminder;
|
||||
private Collection<LocalDate> recurringDates;
|
||||
private Collection<LocalDate> nextTenRecurringDates;
|
||||
private String humanReadable;
|
||||
private LocalDate recentEligibleMeetingDate;
|
||||
|
||||
private OffsetDateTime createdDate;
|
||||
private OffsetDateTime lastUpdatedDate;
|
||||
private Long createdByUserId;
|
||||
private String createdByUsername;
|
||||
private Long lastUpdatedByUserId;
|
||||
private String lastUpdatedByUsername;
|
||||
private Integer repeatsOnDayOfMonth;
|
||||
|
||||
// template related
|
||||
private List<EnumOptionData> entityTypeOptions;
|
||||
private List<EnumOptionData> calendarTypeOptions;
|
||||
private List<EnumOptionData> remindByOptions;
|
||||
private List<EnumOptionData> frequencyOptions;
|
||||
private List<EnumOptionData> repeatsOnDayOptions;
|
||||
private List<EnumOptionData> frequencyNthDayTypeOptions;
|
||||
|
||||
// import fields
|
||||
private Integer rowIndex;
|
||||
private String dateFormat;
|
||||
private String locale;
|
||||
private String centerId;
|
||||
private String typeId;
|
||||
|
||||
public static CalendarData importInstanceNoRepeatsOnDay(LocalDate startDate, boolean repeating, EnumOptionData frequency,
|
||||
Integer interval, Integer rowIndex, String locale, String dateFormat) {
|
||||
return new CalendarData(startDate, repeating, frequency, interval, rowIndex, locale, dateFormat);
|
||||
|
||||
}
|
||||
|
||||
public static CalendarData importInstanceWithRepeatsOnDay(LocalDate startDate, boolean repeating, EnumOptionData frequency,
|
||||
Integer interval, EnumOptionData repeatsOnDay, Integer rowIndex, String locale, String dateFormat) {
|
||||
return new CalendarData(startDate, repeating, frequency, interval, repeatsOnDay, rowIndex, locale, dateFormat);
|
||||
}
|
||||
|
||||
private CalendarData(LocalDate startDate, boolean repeating, EnumOptionData frequency, Integer interval, Integer rowIndex,
|
||||
String locale, String dateFormat) {
|
||||
this.startDate = startDate;
|
||||
this.repeating = repeating;
|
||||
this.frequency = frequency;
|
||||
this.interval = interval;
|
||||
this.rowIndex = rowIndex;
|
||||
this.dateFormat = dateFormat;
|
||||
this.locale = locale;
|
||||
this.description = "";
|
||||
this.typeId = "1";
|
||||
this.id = null;
|
||||
this.calendarInstanceId = null;
|
||||
this.entityId = null;
|
||||
this.entityType = null;
|
||||
this.title = null;
|
||||
this.location = null;
|
||||
this.endDate = null;
|
||||
this.meetingTime = null;
|
||||
this.type = null;
|
||||
this.recurrence = null;
|
||||
this.repeatsOnDay = null;
|
||||
this.repeatsOnNthDayOfMonth = null;
|
||||
this.remindBy = null;
|
||||
this.firstReminder = null;
|
||||
this.secondReminder = null;
|
||||
this.recurringDates = null;
|
||||
this.nextTenRecurringDates = null;
|
||||
this.humanReadable = null;
|
||||
this.recentEligibleMeetingDate = null;
|
||||
this.createdDate = null;
|
||||
this.lastUpdatedDate = null;
|
||||
this.createdByUserId = null;
|
||||
this.createdByUsername = null;
|
||||
this.lastUpdatedByUserId = null;
|
||||
this.lastUpdatedByUsername = null;
|
||||
this.repeatsOnDayOfMonth = null;
|
||||
this.entityTypeOptions = null;
|
||||
this.calendarTypeOptions = null;
|
||||
this.remindByOptions = null;
|
||||
this.frequencyOptions = null;
|
||||
this.repeatsOnDayOptions = null;
|
||||
this.frequencyNthDayTypeOptions = null;
|
||||
this.duration = null;
|
||||
}
|
||||
|
||||
private CalendarData(LocalDate startDate, boolean repeating, EnumOptionData frequency, Integer interval, EnumOptionData repeatsOnDay,
|
||||
Integer rowIndex, String locale, String dateFormat) {
|
||||
this.startDate = startDate;
|
||||
this.repeating = repeating;
|
||||
this.frequency = frequency;
|
||||
this.interval = interval;
|
||||
this.repeatsOnDay = repeatsOnDay;
|
||||
this.rowIndex = rowIndex;
|
||||
this.dateFormat = dateFormat;
|
||||
this.locale = locale;
|
||||
this.description = "";
|
||||
this.typeId = "1";
|
||||
this.id = null;
|
||||
this.calendarInstanceId = null;
|
||||
this.entityId = null;
|
||||
this.entityType = null;
|
||||
this.title = null;
|
||||
this.location = null;
|
||||
this.endDate = null;
|
||||
this.meetingTime = null;
|
||||
this.type = null;
|
||||
this.recurrence = null;
|
||||
this.repeatsOnNthDayOfMonth = null;
|
||||
this.remindBy = null;
|
||||
this.firstReminder = null;
|
||||
this.secondReminder = null;
|
||||
this.recurringDates = null;
|
||||
this.nextTenRecurringDates = null;
|
||||
this.humanReadable = null;
|
||||
this.recentEligibleMeetingDate = null;
|
||||
this.createdDate = null;
|
||||
this.lastUpdatedDate = null;
|
||||
this.createdByUserId = null;
|
||||
this.createdByUsername = null;
|
||||
this.lastUpdatedByUserId = null;
|
||||
this.lastUpdatedByUsername = null;
|
||||
this.repeatsOnDayOfMonth = null;
|
||||
this.entityTypeOptions = null;
|
||||
this.calendarTypeOptions = null;
|
||||
this.remindByOptions = null;
|
||||
this.frequencyOptions = null;
|
||||
this.repeatsOnDayOptions = null;
|
||||
this.frequencyNthDayTypeOptions = null;
|
||||
this.duration = null;
|
||||
}
|
||||
|
||||
public void setCenterId(String centerId) {
|
||||
this.centerId = centerId;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public static CalendarData instance(final Long id, final Long calendarInstanceId, final Long entityId, final EnumOptionData entityType,
|
||||
final String title, final String description, final String location, final LocalDate startDate, final LocalDate endDate,
|
||||
final Integer duration, final EnumOptionData type, final boolean repeating, final String recurrence,
|
||||
final EnumOptionData frequency, final Integer interval, final EnumOptionData repeatsOnDay,
|
||||
final EnumOptionData repeatsOnNthDayOfMonth, final EnumOptionData remindBy, final Integer firstReminder,
|
||||
final Integer secondReminder, final String humanReadable, final OffsetDateTime createdDate,
|
||||
final OffsetDateTime lastUpdatedDate, final Long createdByUserId, final String createdByUsername,
|
||||
final Long lastUpdatedByUserId, final String lastUpdatedByUsername, final LocalTime meetingTime,
|
||||
final Integer repeatsOnDayOfMonth) {
|
||||
|
||||
final Collection<LocalDate> recurringDates = null;
|
||||
final Collection<LocalDate> nextTenRecurringDates = null;
|
||||
final LocalDate recentEligibleMeetingDate = null;
|
||||
|
||||
final List<EnumOptionData> entityTypeOptions = null;
|
||||
final List<EnumOptionData> calendarTypeOptions = null;
|
||||
final List<EnumOptionData> remindByOptions = null;
|
||||
final List<EnumOptionData> frequencyOptions = null;
|
||||
final List<EnumOptionData> repeatsOnDayOptions = null;
|
||||
final List<EnumOptionData> frequencyNthDayTypeOptions = null;
|
||||
|
||||
return new CalendarData(id, calendarInstanceId, entityId, entityType, title, description, location, startDate, endDate, duration,
|
||||
type, repeating, recurrence, frequency, interval, repeatsOnDay, repeatsOnNthDayOfMonth, remindBy, firstReminder,
|
||||
secondReminder, recurringDates, nextTenRecurringDates, humanReadable, recentEligibleMeetingDate, createdDate,
|
||||
lastUpdatedDate, createdByUserId, createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername, repeatsOnDayOfMonth,
|
||||
entityTypeOptions, calendarTypeOptions, remindByOptions, frequencyOptions, repeatsOnDayOptions, meetingTime,
|
||||
frequencyNthDayTypeOptions);
|
||||
}
|
||||
|
||||
public static CalendarData withRecurringDates(final CalendarData calendarData, final Collection<LocalDate> recurringDates,
|
||||
final Collection<LocalDate> nextTenRecurringDates, final LocalDate recentEligibleMeetingDate) {
|
||||
return new CalendarData(calendarData.id, calendarData.calendarInstanceId, calendarData.entityId, calendarData.entityType,
|
||||
calendarData.title, calendarData.description, calendarData.location, calendarData.startDate, calendarData.endDate,
|
||||
calendarData.duration, calendarData.type, calendarData.repeating, calendarData.recurrence, calendarData.frequency,
|
||||
calendarData.interval, calendarData.repeatsOnDay, calendarData.repeatsOnNthDayOfMonth, calendarData.remindBy,
|
||||
calendarData.firstReminder, calendarData.secondReminder, recurringDates, nextTenRecurringDates, calendarData.humanReadable,
|
||||
recentEligibleMeetingDate, calendarData.createdDate, calendarData.lastUpdatedDate, calendarData.createdByUserId,
|
||||
calendarData.createdByUsername, calendarData.lastUpdatedByUserId, calendarData.lastUpdatedByUsername,
|
||||
calendarData.repeatsOnDayOfMonth, calendarData.entityTypeOptions, calendarData.calendarTypeOptions,
|
||||
calendarData.remindByOptions, calendarData.frequencyOptions, calendarData.repeatsOnDayOptions, calendarData.meetingTime,
|
||||
calendarData.frequencyNthDayTypeOptions);
|
||||
}
|
||||
|
||||
public static CalendarData withRecentEligibleMeetingDate(final CalendarData calendarData, final LocalDate recentEligibleMeetingDate) {
|
||||
return new CalendarData(calendarData.id, calendarData.calendarInstanceId, calendarData.entityId, calendarData.entityType,
|
||||
calendarData.title, calendarData.description, calendarData.location, calendarData.startDate, calendarData.endDate,
|
||||
calendarData.duration, calendarData.type, calendarData.repeating, calendarData.recurrence, calendarData.frequency,
|
||||
calendarData.interval, calendarData.repeatsOnDay, calendarData.repeatsOnNthDayOfMonth, calendarData.remindBy,
|
||||
calendarData.firstReminder, calendarData.secondReminder, calendarData.recurringDates, calendarData.nextTenRecurringDates,
|
||||
calendarData.humanReadable, recentEligibleMeetingDate, calendarData.createdDate, calendarData.lastUpdatedDate,
|
||||
calendarData.createdByUserId, calendarData.createdByUsername, calendarData.lastUpdatedByUserId,
|
||||
calendarData.lastUpdatedByUsername, calendarData.repeatsOnDayOfMonth, calendarData.entityTypeOptions,
|
||||
calendarData.calendarTypeOptions, calendarData.remindByOptions, calendarData.frequencyOptions,
|
||||
calendarData.repeatsOnDayOptions, calendarData.meetingTime, calendarData.frequencyNthDayTypeOptions);
|
||||
}
|
||||
|
||||
public static CalendarData sensibleDefaultsForNewCalendarCreation() {
|
||||
final Long id = null;
|
||||
final Long calendarInstanceId = null;
|
||||
final Long entityId = null;
|
||||
final EnumOptionData entityType = null;
|
||||
final String title = null;
|
||||
final String description = null;
|
||||
final String location = null;
|
||||
final LocalDate startDate = null;
|
||||
final LocalDate endDate = null;
|
||||
final Integer duration = 0;
|
||||
final EnumOptionData type = CalendarEnumerations.calendarType(CalendarType.COLLECTION);
|
||||
final boolean repeating = false;
|
||||
final String recurrence = null;
|
||||
final EnumOptionData frequency = CalendarEnumerations.calendarFrequencyType(CalendarFrequencyType.DAILY);
|
||||
final Integer interval = 1;
|
||||
final EnumOptionData repeatsOnDay = CalendarEnumerations.calendarWeekDaysType(CalendarWeekDaysType.MO);
|
||||
final EnumOptionData repeatsOnNthDayOfMonth = CalendarEnumerations.calendarFrequencyNthDayType(NthDayType.ONE);
|
||||
final EnumOptionData remindBy = CalendarEnumerations.calendarRemindBy(CalendarRemindBy.EMAIL);
|
||||
final Integer firstReminder = 0;
|
||||
final Integer secondReminder = 0;
|
||||
final String humanReadable = null;
|
||||
final Collection<LocalDate> recurringDates = null;
|
||||
final Collection<LocalDate> nextTenRecurringDates = null;
|
||||
final LocalDate recentEligibleMeetingDate = null;
|
||||
|
||||
final List<EnumOptionData> entityTypeOptions = null;
|
||||
final List<EnumOptionData> calendarTypeOptions = null;
|
||||
final List<EnumOptionData> remindByOptions = null;
|
||||
final List<EnumOptionData> frequencyOptions = null;
|
||||
final List<EnumOptionData> repeatsOnDayOptions = null;
|
||||
final List<EnumOptionData> frequencyNthDayTypeOptions = null;
|
||||
|
||||
final OffsetDateTime createdDate = null;
|
||||
final OffsetDateTime lastUpdatedDate = null;
|
||||
final Long createdByUserId = null;
|
||||
final String createdByUsername = null;
|
||||
final Long lastUpdatedByUserId = null;
|
||||
final String lastUpdatedByUsername = null;
|
||||
final LocalTime meetingTime = null;
|
||||
final Integer repeatsOnDayOfMonth = null;
|
||||
|
||||
return new CalendarData(id, calendarInstanceId, entityId, entityType, title, description, location, startDate, endDate, duration,
|
||||
type, repeating, recurrence, frequency, interval, repeatsOnDay, repeatsOnNthDayOfMonth, remindBy, firstReminder,
|
||||
secondReminder, recurringDates, nextTenRecurringDates, humanReadable, recentEligibleMeetingDate, createdDate,
|
||||
lastUpdatedDate, createdByUserId, createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername, repeatsOnDayOfMonth,
|
||||
entityTypeOptions, calendarTypeOptions, remindByOptions, frequencyOptions, repeatsOnDayOptions, meetingTime,
|
||||
frequencyNthDayTypeOptions);
|
||||
}
|
||||
|
||||
public static CalendarData withTemplateOptions(final CalendarData calendarData, final List<EnumOptionData> entityTypeOptions,
|
||||
final List<EnumOptionData> calendarTypeOptions, final List<EnumOptionData> remindByOptions,
|
||||
final List<EnumOptionData> repeatsOptions, final List<EnumOptionData> repeatsOnDayOptions,
|
||||
final List<EnumOptionData> frequencyNthDayTypeOptions) {
|
||||
|
||||
return new CalendarData(calendarData.id, calendarData.calendarInstanceId, calendarData.entityId, calendarData.entityType,
|
||||
calendarData.title, calendarData.description, calendarData.location, calendarData.startDate, calendarData.endDate,
|
||||
calendarData.duration, calendarData.type, calendarData.repeating, calendarData.recurrence, calendarData.frequency,
|
||||
calendarData.interval, calendarData.repeatsOnDay, calendarData.repeatsOnNthDayOfMonth, calendarData.remindBy,
|
||||
calendarData.firstReminder, calendarData.secondReminder, calendarData.recurringDates, calendarData.nextTenRecurringDates,
|
||||
calendarData.humanReadable, calendarData.recentEligibleMeetingDate, calendarData.createdDate, calendarData.lastUpdatedDate,
|
||||
calendarData.createdByUserId, calendarData.createdByUsername, calendarData.lastUpdatedByUserId,
|
||||
calendarData.lastUpdatedByUsername, calendarData.repeatsOnDayOfMonth, entityTypeOptions, calendarTypeOptions,
|
||||
remindByOptions, repeatsOptions, repeatsOnDayOptions, calendarData.meetingTime, frequencyNthDayTypeOptions);
|
||||
}
|
||||
|
||||
private CalendarData(final Long id, final Long calendarInstanceId, final Long entityId, final EnumOptionData entityType,
|
||||
final String title, final String description, final String location, final LocalDate startDate, final LocalDate endDate,
|
||||
final Integer duration, final EnumOptionData type, final boolean repeating, final String recurrence,
|
||||
final EnumOptionData frequency, final Integer interval, final EnumOptionData repeatsOnDay,
|
||||
final EnumOptionData repeatsOnNthDayOfMonth, final EnumOptionData remindBy, final Integer firstReminder,
|
||||
final Integer secondReminder, final Collection<LocalDate> recurringDates, final Collection<LocalDate> nextTenRecurringDates,
|
||||
final String humanReadable, final LocalDate recentEligibleMeetingDate, final OffsetDateTime createdDate,
|
||||
final OffsetDateTime lastUpdatedDate, final Long createdByUserId, final String createdByUsername,
|
||||
final Long lastUpdatedByUserId, final String lastUpdatedByUsername, final Integer repeatsOnDayOfMonth,
|
||||
final List<EnumOptionData> entityTypeOptions, final List<EnumOptionData> calendarTypeOptions,
|
||||
final List<EnumOptionData> remindByOptions, final List<EnumOptionData> repeatsOptions,
|
||||
final List<EnumOptionData> repeatsOnDayOptions, final LocalTime meetingTime,
|
||||
final List<EnumOptionData> frequencyNthDayTypeOptions) {
|
||||
this.id = id;
|
||||
this.calendarInstanceId = calendarInstanceId;
|
||||
this.entityId = entityId;
|
||||
this.entityType = entityType;
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.location = location;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.duration = duration;
|
||||
this.type = type;
|
||||
this.repeating = repeating;
|
||||
this.recurrence = recurrence;
|
||||
this.frequency = frequency;
|
||||
this.interval = interval;
|
||||
this.repeatsOnDay = repeatsOnDay;
|
||||
this.repeatsOnNthDayOfMonth = repeatsOnNthDayOfMonth;
|
||||
this.remindBy = remindBy;
|
||||
this.firstReminder = firstReminder;
|
||||
this.secondReminder = secondReminder;
|
||||
this.recurringDates = recurringDates;
|
||||
this.nextTenRecurringDates = nextTenRecurringDates;
|
||||
this.humanReadable = humanReadable;
|
||||
this.recentEligibleMeetingDate = recentEligibleMeetingDate;
|
||||
this.createdDate = createdDate;
|
||||
this.lastUpdatedDate = lastUpdatedDate;
|
||||
this.createdByUserId = createdByUserId;
|
||||
this.createdByUsername = createdByUsername;
|
||||
this.lastUpdatedByUserId = lastUpdatedByUserId;
|
||||
this.lastUpdatedByUsername = lastUpdatedByUsername;
|
||||
this.repeatsOnDayOfMonth = repeatsOnDayOfMonth;
|
||||
this.entityTypeOptions = entityTypeOptions;
|
||||
this.calendarTypeOptions = calendarTypeOptions;
|
||||
this.remindByOptions = remindByOptions;
|
||||
this.frequencyOptions = repeatsOptions;
|
||||
this.repeatsOnDayOptions = repeatsOnDayOptions;
|
||||
this.meetingTime = meetingTime;
|
||||
this.frequencyNthDayTypeOptions = frequencyNthDayTypeOptions;
|
||||
}
|
||||
|
||||
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
||||
if (this.startDate != null && compareDate != null) {
|
||||
if (this.startDate.isBefore(compareDate) || this.startDate.equals(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
||||
if (this.endDate != null && compareDate != null) {
|
||||
if (this.endDate.isAfter(compareDate) || this.endDate.isEqual(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
||||
if (isStartDateBeforeOrEqual(compareDate)) {
|
||||
if (this.endDate == null || isEndDateAfterOrEqual(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isValidRecurringDate(final LocalDate compareDate, final Boolean isSkipMeetingOnFirstDay, final Integer numberOfDays) {
|
||||
if (isBetweenStartAndEndDate(compareDate)) {
|
||||
return CalendarUtils.isValidRedurringDate(this.getRecurrence(), this.getStartDate(), compareDate, isSkipMeetingOnFirstDay,
|
||||
numberOfDays);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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.calendar.data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarHistory;
|
||||
|
||||
public class CalendarHistoryDataWrapper {
|
||||
|
||||
private final List<CalendarHistory> calendarHistoryList;
|
||||
|
||||
public CalendarHistoryDataWrapper(final Set<CalendarHistory> calendarHistoryList) {
|
||||
this.calendarHistoryList = new ArrayList<>();
|
||||
this.calendarHistoryList.addAll(calendarHistoryList);
|
||||
final Comparator<CalendarHistory> orderByDate = new Comparator<CalendarHistory>() {
|
||||
|
||||
@Override
|
||||
public int compare(CalendarHistory calendarHistory1, CalendarHistory calendarHistory2) {
|
||||
return calendarHistory1.getEndDateLocalDate().compareTo(calendarHistory2.getEndDateLocalDate());
|
||||
}
|
||||
};
|
||||
Collections.sort(this.calendarHistoryList, orderByDate);
|
||||
}
|
||||
|
||||
public CalendarHistory getCalendarHistory(final LocalDate dueRepaymentPeriodDate) {
|
||||
CalendarHistory calendarHistory = null;
|
||||
for (CalendarHistory history : this.calendarHistoryList) {
|
||||
if (history.getEndDateLocalDate().isAfter(dueRepaymentPeriodDate)) {
|
||||
calendarHistory = history;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return calendarHistory;
|
||||
}
|
||||
|
||||
public List<CalendarHistory> getCalendarHistoryList() {
|
||||
return this.calendarHistoryList;
|
||||
}
|
||||
}
|
||||
+652
@@ -0,0 +1,652 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.calendar.CalendarConstants.CALENDAR_RESOURCE_NAME;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.calendar.CalendarConstants.CalendarSupportedParameters;
|
||||
import org.apache.fineract.portfolio.calendar.exception.CalendarDateException;
|
||||
import org.apache.fineract.portfolio.calendar.exception.CalendarParameterUpdateNotSupportedException;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||
import org.apache.fineract.portfolio.common.domain.NthDayType;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_calendar")
|
||||
public class Calendar extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
@Column(name = "title", length = 50, nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(name = "description", length = 100, nullable = true)
|
||||
private String description;
|
||||
|
||||
@Column(name = "location", length = 100, nullable = true)
|
||||
private String location;
|
||||
|
||||
@Column(name = "start_date", nullable = false)
|
||||
private LocalDate startDate;
|
||||
|
||||
@Column(name = "end_date", nullable = true)
|
||||
private LocalDate endDate;
|
||||
|
||||
@Column(name = "duration", nullable = true)
|
||||
private Integer duration;
|
||||
|
||||
@Column(name = "calendar_type_enum", nullable = false)
|
||||
private Integer typeId;
|
||||
|
||||
@Column(name = "repeating", nullable = false)
|
||||
private boolean repeating = false;
|
||||
|
||||
@Column(name = "recurrence", length = 100, nullable = true)
|
||||
private String recurrence;
|
||||
|
||||
@Column(name = "remind_by_enum", nullable = true)
|
||||
private Integer remindById;
|
||||
|
||||
@Column(name = "first_reminder", nullable = true)
|
||||
private Integer firstReminder;
|
||||
|
||||
@Column(name = "second_reminder", nullable = true)
|
||||
private Integer secondReminder;
|
||||
|
||||
@Column(name = "meeting_time", nullable = true)
|
||||
private LocalTime meetingtime;
|
||||
|
||||
@OneToMany(mappedBy = "calendar", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
private Set<CalendarHistory> calendarHistory = new HashSet<>();
|
||||
|
||||
protected Calendar() {
|
||||
|
||||
}
|
||||
|
||||
public Calendar(final String title, final String description, final String location, final LocalDate startDate, final LocalDate endDate,
|
||||
final Integer duration, final Integer typeId, final boolean repeating, final String recurrence, final Integer remindById,
|
||||
final Integer firstReminder, final Integer secondReminder, final LocalTime meetingtime) {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(CALENDAR_RESOURCE_NAME);
|
||||
|
||||
final CalendarType calendarType = CalendarType.fromInt(typeId);
|
||||
if (calendarType.isCollection() && !repeating) {
|
||||
baseDataValidator.reset().parameter(CalendarSupportedParameters.REPEATING.getValue())
|
||||
.failWithCodeNoParameterAddedToErrorCode("must.repeat.for.collection.calendar");
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
this.title = StringUtils.defaultIfEmpty(title, null);
|
||||
this.description = StringUtils.defaultIfEmpty(description, null);
|
||||
this.location = StringUtils.defaultIfEmpty(location, null);
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.duration = duration;
|
||||
this.typeId = typeId;
|
||||
this.repeating = repeating;
|
||||
this.recurrence = StringUtils.defaultIfEmpty(recurrence, null);
|
||||
this.remindById = remindById;
|
||||
this.firstReminder = firstReminder;
|
||||
this.secondReminder = secondReminder;
|
||||
this.meetingtime = meetingtime;
|
||||
}
|
||||
|
||||
public static Calendar createRepeatingCalendar(final String title, final LocalDate startDate, final Integer typeId,
|
||||
final CalendarFrequencyType frequencyType, final Integer interval, final Integer repeatsOnDay,
|
||||
final Integer repeatsOnNthDayOfMonth) {
|
||||
final String recurrence = constructRecurrence(frequencyType, interval, repeatsOnDay, repeatsOnNthDayOfMonth);
|
||||
return createRepeatingCalendar(title, startDate, typeId, recurrence);
|
||||
}
|
||||
|
||||
public static Calendar createRepeatingCalendar(final String title, final LocalDate startDate, final Integer typeId,
|
||||
final String recurrence) {
|
||||
final String description = null;
|
||||
final String location = null;
|
||||
final LocalDate endDate = null;
|
||||
final Integer duration = null;
|
||||
final boolean repeating = true;
|
||||
final Integer remindById = null;
|
||||
final Integer firstReminder = null;
|
||||
final Integer secondReminder = null;
|
||||
final LocalTime meetingtime = null;
|
||||
return new Calendar(title, description, location, startDate, endDate, duration, typeId, repeating, recurrence, remindById,
|
||||
firstReminder, secondReminder, meetingtime);
|
||||
}
|
||||
|
||||
public static Calendar fromJson(final JsonCommand command) {
|
||||
|
||||
// final Long entityId = command.getSupportedEntityId();
|
||||
// final Integer entityTypeId =
|
||||
// CalendarEntityType.valueOf(command.getSupportedEntityType().toUpperCase()).getValue();
|
||||
LocalTime meetingtime = null;
|
||||
final String title = command.stringValueOfParameterNamed(CalendarSupportedParameters.TITLE.getValue());
|
||||
final String description = command.stringValueOfParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue());
|
||||
final String location = command.stringValueOfParameterNamed(CalendarSupportedParameters.LOCATION.getValue());
|
||||
final LocalDate startDate = command.localDateValueOfParameterNamed(CalendarSupportedParameters.START_DATE.getValue());
|
||||
final LocalDate endDate = command.localDateValueOfParameterNamed(CalendarSupportedParameters.END_DATE.getValue());
|
||||
final Integer duration = command.integerValueSansLocaleOfParameterNamed(CalendarSupportedParameters.DURATION.getValue());
|
||||
final Integer typeId = command.integerValueSansLocaleOfParameterNamed(CalendarSupportedParameters.TYPE_ID.getValue());
|
||||
final boolean repeating = command.booleanPrimitiveValueOfParameterNamed(CalendarSupportedParameters.REPEATING.getValue());
|
||||
final Integer remindById = command.integerValueSansLocaleOfParameterNamed(CalendarSupportedParameters.REMIND_BY_ID.getValue());
|
||||
final Integer firstReminder = command.integerValueSansLocaleOfParameterNamed(CalendarSupportedParameters.FIRST_REMINDER.getValue());
|
||||
final Integer secondReminder = command
|
||||
.integerValueSansLocaleOfParameterNamed(CalendarSupportedParameters.SECOND_REMINDER.getValue());
|
||||
meetingtime = command.localTimeValueOfParameterNamed(CalendarSupportedParameters.MEETING_TIME.getValue());
|
||||
|
||||
final String recurrence = Calendar.constructRecurrence(command, null);
|
||||
|
||||
return new Calendar(title, description, location, startDate, endDate, duration, typeId, repeating, recurrence, remindById,
|
||||
firstReminder, secondReminder, meetingtime);
|
||||
}
|
||||
|
||||
public Map<String, Object> updateStartDateAndDerivedFeilds(final LocalDate newMeetingStartDate) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||
|
||||
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||
|
||||
if (newMeetingStartDate.isBefore(currentDate)) {
|
||||
final String defaultUserMessage = "New meeting effective from date cannot be in past";
|
||||
throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newMeetingStartDate,
|
||||
getStartDateLocalDate());
|
||||
} else if (isStartDateAfter(newMeetingStartDate) && isStartDateBeforeOrEqual(currentDate)) {
|
||||
// new meeting date should be on or after start date or current
|
||||
// date
|
||||
final String defaultUserMessage = "New meeting effective from date cannot be a date before existing meeting start date";
|
||||
throw new CalendarDateException("new.start.date.before.existing.date", defaultUserMessage, newMeetingStartDate,
|
||||
getStartDateLocalDate());
|
||||
} else {
|
||||
|
||||
actualChanges.put(CalendarSupportedParameters.START_DATE.getValue(), newMeetingStartDate.toString());
|
||||
this.startDate = newMeetingStartDate;
|
||||
|
||||
/*
|
||||
* If meeting start date is changed then there is possibilities of recurring day may change, so derive the
|
||||
* recurring day and update it if it is changed. For weekly type is weekday and for monthly type it is day
|
||||
* of the month
|
||||
*/
|
||||
|
||||
CalendarFrequencyType calendarFrequencyType = CalendarUtils.getFrequency(this.recurrence);
|
||||
Integer interval = CalendarUtils.getInterval(this.recurrence);
|
||||
Integer repeatsOnDay = null;
|
||||
|
||||
/*
|
||||
* Repeats on day, need to derive based on the start date
|
||||
*/
|
||||
|
||||
if (calendarFrequencyType.isWeekly()) {
|
||||
repeatsOnDay = newMeetingStartDate.get(ChronoField.DAY_OF_WEEK);
|
||||
} else if (calendarFrequencyType.isMonthly()) {
|
||||
repeatsOnDay = newMeetingStartDate.getDayOfMonth();
|
||||
}
|
||||
|
||||
// TODO cover other recurrence also
|
||||
|
||||
this.recurrence = constructRecurrence(calendarFrequencyType, interval, repeatsOnDay, null);
|
||||
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command, final Boolean areActiveEntitiesSynced) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||
|
||||
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.TITLE.getValue(), this.title)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.TITLE.getValue());
|
||||
actualChanges.put(CalendarSupportedParameters.TITLE.getValue(), newValue);
|
||||
this.title = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue(), this.description)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.DESCRIPTION.getValue());
|
||||
actualChanges.put(CalendarSupportedParameters.DESCRIPTION.getValue(), newValue);
|
||||
this.description = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
if (command.isChangeInStringParameterNamed(CalendarSupportedParameters.LOCATION.getValue(), this.location)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.LOCATION.getValue());
|
||||
actualChanges.put(CalendarSupportedParameters.LOCATION.getValue(), newValue);
|
||||
this.location = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
final String startDateParamName = CalendarSupportedParameters.START_DATE.getValue();
|
||||
if (command.isChangeInLocalDateParameterNamed(startDateParamName, getStartDateLocalDate())) {
|
||||
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName);
|
||||
final LocalDate newValue = command.localDateValueOfParameterNamed(startDateParamName);
|
||||
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||
|
||||
if (newValue.isBefore(currentDate)) {
|
||||
final String defaultUserMessage = "New meeting effective from date cannot be in past";
|
||||
throw new CalendarDateException("new.start.date.cannot.be.in.past", defaultUserMessage, newValue, getStartDateLocalDate());
|
||||
} else if (isStartDateAfter(newValue) && isStartDateBeforeOrEqual(currentDate)) {
|
||||
// new meeting date should be on or after start date or current
|
||||
// date
|
||||
final String defaultUserMessage = "New meeting effective from date cannot be a date before existing meeting start date";
|
||||
throw new CalendarDateException("new.start.date.before.existing.date", defaultUserMessage, newValue,
|
||||
getStartDateLocalDate());
|
||||
} else {
|
||||
actualChanges.put(startDateParamName, valueAsInput);
|
||||
actualChanges.put("dateFormat", dateFormatAsInput);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.startDate = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
final String endDateParamName = CalendarSupportedParameters.END_DATE.getValue();
|
||||
if (command.isChangeInLocalDateParameterNamed(endDateParamName, getEndDateLocalDate())) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(endDateParamName);
|
||||
actualChanges.put(endDateParamName, valueAsInput);
|
||||
actualChanges.put("dateFormat", dateFormatAsInput);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
|
||||
this.endDate = command.localDateValueOfParameterNamed(endDateParamName);
|
||||
}
|
||||
|
||||
final String durationParamName = CalendarSupportedParameters.DURATION.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(durationParamName, this.duration)) {
|
||||
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(durationParamName);
|
||||
actualChanges.put(durationParamName, newValue);
|
||||
this.duration = newValue;
|
||||
}
|
||||
|
||||
// Do not allow to change calendar type
|
||||
// TODO: AA Instead of throwing an exception, do not allow meeting
|
||||
// calendar type to update.
|
||||
final String typeParamName = CalendarSupportedParameters.TYPE_ID.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(typeParamName, this.typeId)) {
|
||||
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(typeParamName);
|
||||
final String defaultUserMessage = "Meeting calendar type update is not supported";
|
||||
final String oldMeeingType = CalendarType.fromInt(this.typeId).name();
|
||||
final String newMeetingType = CalendarType.fromInt(newValue).name();
|
||||
|
||||
throw new CalendarParameterUpdateNotSupportedException("meeting.type", defaultUserMessage, newMeetingType, oldMeeingType);
|
||||
/*
|
||||
* final Integer newValue = command.integerValueSansLocaleOfParameterNamed(typeParamName);
|
||||
* actualChanges.put(typeParamName, newValue); this.typeId = newValue;
|
||||
*/
|
||||
}
|
||||
|
||||
final String repeatingParamName = CalendarSupportedParameters.REPEATING.getValue();
|
||||
if (command.isChangeInBooleanParameterNamed(repeatingParamName, this.repeating)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(repeatingParamName);
|
||||
actualChanges.put(repeatingParamName, newValue);
|
||||
this.repeating = newValue;
|
||||
}
|
||||
|
||||
// if repeating is false then update recurrence to NULL
|
||||
if (!this.repeating) {
|
||||
this.recurrence = null;
|
||||
}
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(CALENDAR_RESOURCE_NAME);
|
||||
|
||||
final CalendarType calendarType = CalendarType.fromInt(this.typeId);
|
||||
if (calendarType.isCollection() && !this.repeating) {
|
||||
baseDataValidator.reset().parameter(CalendarSupportedParameters.REPEATING.getValue())
|
||||
.failWithCodeNoParameterAddedToErrorCode("must.repeat.for.collection.calendar");
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
final String newRecurrence = Calendar.constructRecurrence(command, this);
|
||||
if (!StringUtils.isBlank(this.recurrence) && !newRecurrence.equalsIgnoreCase(this.recurrence)) {
|
||||
/*
|
||||
* If active entities like JLG loan or RD accounts are synced to the calendar then do not allow to change
|
||||
* meeting frequency
|
||||
*/
|
||||
|
||||
if (areActiveEntitiesSynced && !CalendarUtils.isFrequencySame(this.recurrence, newRecurrence)) {
|
||||
final String defaultUserMessage = "Update of meeting frequency is not supported";
|
||||
throw new CalendarParameterUpdateNotSupportedException("meeting.frequency", defaultUserMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* If active entities like JLG loan or RD accounts are synced to the calendar then do not allow to change
|
||||
* meeting interval
|
||||
*/
|
||||
|
||||
if (areActiveEntitiesSynced && !CalendarUtils.isIntervalSame(this.recurrence, newRecurrence)) {
|
||||
final String defaultUserMessage = "Update of meeting interval is not supported";
|
||||
throw new CalendarParameterUpdateNotSupportedException("meeting.interval", defaultUserMessage);
|
||||
}
|
||||
|
||||
actualChanges.put("recurrence", newRecurrence);
|
||||
this.recurrence = StringUtils.defaultIfEmpty(newRecurrence, null);
|
||||
}
|
||||
|
||||
final String remindByParamName = CalendarSupportedParameters.REMIND_BY_ID.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(remindByParamName, this.remindById)) {
|
||||
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(remindByParamName);
|
||||
actualChanges.put(remindByParamName, newValue);
|
||||
this.remindById = newValue;
|
||||
}
|
||||
|
||||
final String firstRemindarParamName = CalendarSupportedParameters.FIRST_REMINDER.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(firstRemindarParamName, this.firstReminder)) {
|
||||
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(firstRemindarParamName);
|
||||
actualChanges.put(firstRemindarParamName, newValue);
|
||||
this.firstReminder = newValue;
|
||||
}
|
||||
|
||||
final String secondRemindarParamName = CalendarSupportedParameters.SECOND_REMINDER.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(secondRemindarParamName, this.secondReminder)) {
|
||||
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(secondRemindarParamName);
|
||||
actualChanges.put(secondRemindarParamName, newValue);
|
||||
this.secondReminder = newValue;
|
||||
}
|
||||
|
||||
final String timeFormat = command.stringValueOfParameterNamed(CalendarSupportedParameters.Time_Format.getValue());
|
||||
final String time = CalendarSupportedParameters.MEETING_TIME.getValue();
|
||||
if (command.isChangeInTimeParameterNamed(CalendarSupportedParameters.MEETING_TIME.getValue(), this.meetingtime, timeFormat)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(CalendarSupportedParameters.MEETING_TIME.getValue());
|
||||
actualChanges.put(CalendarSupportedParameters.MEETING_TIME.getValue(), newValue);
|
||||
LocalTime timeInLocalDateTimeFormat = command.localTimeValueOfParameterNamed(time);
|
||||
if (timeInLocalDateTimeFormat != null) {
|
||||
this.meetingtime = timeInLocalDateTimeFormat;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public Map<String, Object> updateRepeatingCalendar(final LocalDate calendarStartDate, final CalendarFrequencyType frequencyType,
|
||||
final Integer interval, final Integer repeatsOnDay, final Integer repeatsOnNthDay) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
|
||||
|
||||
if (calendarStartDate != null && this.startDate != null) {
|
||||
if (!calendarStartDate.equals(this.getStartDateLocalDate())) {
|
||||
actualChanges.put("startDate", calendarStartDate);
|
||||
this.startDate = calendarStartDate;
|
||||
}
|
||||
}
|
||||
|
||||
final String newRecurrence = Calendar.constructRecurrence(frequencyType, interval, repeatsOnDay, repeatsOnNthDay);
|
||||
if (!StringUtils.isBlank(this.recurrence) && !newRecurrence.equalsIgnoreCase(this.recurrence)) {
|
||||
actualChanges.put("recurrence", newRecurrence);
|
||||
this.recurrence = newRecurrence;
|
||||
}
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return this.startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return this.endDate;
|
||||
}
|
||||
|
||||
public Integer getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
public Integer getTypeId() {
|
||||
return this.typeId;
|
||||
}
|
||||
|
||||
public boolean isRepeating() {
|
||||
return this.repeating;
|
||||
}
|
||||
|
||||
public String getRecurrence() {
|
||||
return this.recurrence;
|
||||
}
|
||||
|
||||
public Integer getRemindById() {
|
||||
return this.remindById;
|
||||
}
|
||||
|
||||
public Integer getFirstReminder() {
|
||||
return this.firstReminder;
|
||||
}
|
||||
|
||||
public Integer getSecondReminder() {
|
||||
return this.secondReminder;
|
||||
}
|
||||
|
||||
public LocalTime getMeetingTime() {
|
||||
return this.meetingtime;
|
||||
}
|
||||
|
||||
public LocalDate getStartDateLocalDate() {
|
||||
return this.startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDateLocalDate() {
|
||||
return this.endDate;
|
||||
}
|
||||
|
||||
public Set<CalendarHistory> history() {
|
||||
return this.calendarHistory;
|
||||
}
|
||||
|
||||
public boolean isStartDateBefore(final LocalDate compareDate) {
|
||||
if (this.startDate != null && compareDate != null && getStartDateLocalDate().isBefore(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
||||
if (this.startDate != null && compareDate != null) {
|
||||
if (getStartDateLocalDate().isBefore(compareDate) || getStartDateLocalDate().equals(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStartDateAfter(final LocalDate compareDate) {
|
||||
if (this.startDate != null && compareDate != null && getStartDateLocalDate().isAfter(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStartDateAfterOrEqual(final LocalDate compareDate) {
|
||||
if (this.startDate != null && compareDate != null) {
|
||||
if (getStartDateLocalDate().isAfter(compareDate) || getStartDateLocalDate().isEqual(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
||||
if (this.endDate != null && compareDate != null) {
|
||||
if (getEndDateLocalDate().isAfter(compareDate) || getEndDateLocalDate().isEqual(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
||||
if (isStartDateBeforeOrEqual(compareDate)) {
|
||||
if (getEndDateLocalDate() == null || isEndDateAfterOrEqual(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String constructRecurrence(final JsonCommand command, final Calendar calendar) {
|
||||
final boolean repeating;
|
||||
if (command.parameterExists(CalendarSupportedParameters.REPEATING.getValue())) {
|
||||
repeating = command.booleanPrimitiveValueOfParameterNamed(CalendarSupportedParameters.REPEATING.getValue());
|
||||
} else if (calendar != null) {
|
||||
repeating = calendar.isRepeating();
|
||||
} else {
|
||||
repeating = false;
|
||||
}
|
||||
|
||||
if (repeating) {
|
||||
final Integer frequency = command.integerValueOfParameterNamed(CalendarSupportedParameters.FREQUENCY.getValue());
|
||||
final CalendarFrequencyType frequencyType = CalendarFrequencyType.fromInt(frequency);
|
||||
final Integer interval = command.integerValueOfParameterNamed(CalendarSupportedParameters.INTERVAL.getValue());
|
||||
Integer repeatsOnDay = null;
|
||||
if (frequencyType.isWeekly()) {
|
||||
repeatsOnDay = command.integerValueOfParameterNamed(CalendarSupportedParameters.REPEATS_ON_DAY.getValue());
|
||||
}
|
||||
Integer repeatsOnNthDayOfMonth = null;
|
||||
if (frequencyType.isMonthly()) {
|
||||
repeatsOnNthDayOfMonth = command
|
||||
.integerValueOfParameterNamed(CalendarSupportedParameters.REPEATS_ON_NTH_DAY_OF_MONTH.getValue());
|
||||
final NthDayType nthDay = NthDayType.fromInt(repeatsOnNthDayOfMonth);
|
||||
repeatsOnDay = command
|
||||
.integerValueOfParameterNamed(CalendarSupportedParameters.REPEATS_ON_LAST_WEEKDAY_OF_MONTH.getValue());
|
||||
if (nthDay.isOnDay()) {
|
||||
repeatsOnNthDayOfMonth = command
|
||||
.integerValueOfParameterNamed(CalendarSupportedParameters.REPEATS_ON_DAY_OF_MONTH.getValue());
|
||||
repeatsOnDay = null;
|
||||
}
|
||||
}
|
||||
|
||||
return constructRecurrence(frequencyType, interval, repeatsOnDay, repeatsOnNthDayOfMonth);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String constructRecurrence(final CalendarFrequencyType frequencyType, final Integer interval, final Integer repeatsOnDay,
|
||||
final Integer repeatsOnNthDayOfMonth) {
|
||||
final StringBuilder recurrenceBuilder = new StringBuilder(200);
|
||||
|
||||
recurrenceBuilder.append("FREQ=");
|
||||
recurrenceBuilder.append(frequencyType.toString().toUpperCase());
|
||||
if (interval > 1) {
|
||||
recurrenceBuilder.append(";INTERVAL=");
|
||||
recurrenceBuilder.append(interval);
|
||||
}
|
||||
if (frequencyType.isWeekly()) {
|
||||
if (repeatsOnDay != null) {
|
||||
final CalendarWeekDaysType weekDays = CalendarWeekDaysType.fromInt(repeatsOnDay);
|
||||
if (!weekDays.isInvalid()) {
|
||||
recurrenceBuilder.append(";BYDAY=");
|
||||
recurrenceBuilder.append(weekDays.toString().toUpperCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (frequencyType.isMonthly()) {
|
||||
if (repeatsOnNthDayOfMonth != null && (repeatsOnDay == null || repeatsOnDay.equals(CalendarWeekDaysType.INVALID.getValue()))) {
|
||||
if (repeatsOnNthDayOfMonth >= -1 && repeatsOnNthDayOfMonth <= 28) {
|
||||
recurrenceBuilder.append(";BYMONTHDAY=");
|
||||
recurrenceBuilder.append(repeatsOnNthDayOfMonth);
|
||||
}
|
||||
} else if (repeatsOnNthDayOfMonth != null && repeatsOnDay != null
|
||||
&& !repeatsOnDay.equals(CalendarWeekDaysType.INVALID.getValue())) {
|
||||
final NthDayType nthDay = NthDayType.fromInt(repeatsOnNthDayOfMonth);
|
||||
if (!nthDay.isInvalid()) {
|
||||
recurrenceBuilder.append(";BYSETPOS=");
|
||||
recurrenceBuilder.append(nthDay.getValue());
|
||||
}
|
||||
final CalendarWeekDaysType weekday = CalendarWeekDaysType.fromInt(repeatsOnDay);
|
||||
if (!weekday.isInvalid()) {
|
||||
recurrenceBuilder.append(";BYDAY=");
|
||||
recurrenceBuilder.append(weekday.toString().toUpperCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
return recurrenceBuilder.toString();
|
||||
}
|
||||
|
||||
public boolean isValidRecurringDate(final LocalDate compareDate, Boolean isSkipRepaymentOnFirstMonth, Integer numberOfDays) {
|
||||
|
||||
if (isBetweenStartAndEndDate(compareDate)) {
|
||||
return CalendarUtils.isValidRedurringDate(getRecurrence(), getStartDateLocalDate(), compareDate, isSkipRepaymentOnFirstMonth,
|
||||
numberOfDays);
|
||||
}
|
||||
|
||||
// validate with history details.
|
||||
for (CalendarHistory history : history()) {
|
||||
if (history.isBetweenStartAndEndDate(compareDate)) {
|
||||
return CalendarUtils.isValidRedurringDate(history.getRecurrence(), history.getStartDateLocalDate(), compareDate,
|
||||
isSkipRepaymentOnFirstMonth, numberOfDays);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateStartAndEndDate(final LocalDate startDate, final LocalDate endDate) {
|
||||
|
||||
final CalendarFrequencyType frequencyType = CalendarUtils.getFrequency(this.recurrence);
|
||||
final Integer interval = Integer.valueOf(CalendarUtils.getInterval(this.recurrence));
|
||||
final String newRecurrence = Calendar.constructRecurrence(frequencyType, interval, startDate.get(ChronoField.DAY_OF_WEEK), null);
|
||||
|
||||
this.recurrence = newRecurrence;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public Set<CalendarHistory> getCalendarHistory() {
|
||||
return this.calendarHistory;
|
||||
}
|
||||
|
||||
public void updateCalendarHistory(final Set<CalendarHistory> calendarHistory) {
|
||||
this.calendarHistory = calendarHistory;
|
||||
}
|
||||
|
||||
public void setRecurrence(String recurrence) {
|
||||
this.recurrence = recurrence;
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum CalendarEntityType {
|
||||
|
||||
INVALID(0, "calendarEntityType.invalid"), //
|
||||
CLIENTS(1, "calendarEntityType.clients"), //
|
||||
GROUPS(2, "calendarEntityType.groups"), //
|
||||
LOANS(3, "calendarEntityType.loans"), //
|
||||
CENTERS(4, "calendarEntityType.centers"), //
|
||||
SAVINGS(5, "calendarEntityType.savings"), //
|
||||
LOAN_RECALCULATION_REST_DETAIL(6, "calendarEntityType.loan.recalculation.rest.detail"), //
|
||||
LOAN_RECALCULATION_COMPOUNDING_DETAIL(7, "calendarEntityType.loan.recalculation.compounding.detail");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
CalendarEntityType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, CalendarEntityType> intToEnumMap = new HashMap<>();
|
||||
private static int minValue;
|
||||
private static int maxValue;
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
for (final CalendarEntityType entityType : CalendarEntityType.values()) {
|
||||
if (i == 0) {
|
||||
minValue = entityType.value;
|
||||
}
|
||||
intToEnumMap.put(entityType.value, entityType);
|
||||
if (minValue >= entityType.value) {
|
||||
minValue = entityType.value;
|
||||
}
|
||||
if (maxValue < entityType.value) {
|
||||
maxValue = entityType.value;
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static CalendarEntityType fromInt(final int i) {
|
||||
final CalendarEntityType entityType = intToEnumMap.get(Integer.valueOf(i));
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public static int getMinValue() {
|
||||
return minValue;
|
||||
}
|
||||
|
||||
public static int getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public static boolean isGroup(final Integer value) {
|
||||
return CalendarEntityType.GROUPS.value.equals(value) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isGroup(final String name) {
|
||||
return CalendarEntityType.GROUPS.name().equalsIgnoreCase(name) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isCenter(final Integer value) {
|
||||
return CalendarEntityType.CENTERS.value.equals(value) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isCenter(final String name) {
|
||||
return CalendarEntityType.CENTERS.name().equalsIgnoreCase(name) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isLoan(final Integer value) {
|
||||
return CalendarEntityType.LOANS.value.equals(value) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isLoan(final String name) {
|
||||
return CalendarEntityType.LOANS.name().equalsIgnoreCase(name) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isClient(final Integer value) {
|
||||
return CalendarEntityType.CLIENTS.value.equals(value) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isClient(final String name) {
|
||||
return CalendarEntityType.CLIENTS.name().equalsIgnoreCase(name) ? true : false;
|
||||
}
|
||||
|
||||
public boolean isCenter() {
|
||||
return this.value.equals(CalendarEntityType.CENTERS.getValue());
|
||||
}
|
||||
|
||||
public boolean isGroup() {
|
||||
return this.value.equals(CalendarEntityType.GROUPS.getValue());
|
||||
}
|
||||
|
||||
public boolean isLoan() {
|
||||
return this.value.equals(CalendarEntityType.LOANS.getValue());
|
||||
}
|
||||
|
||||
public boolean isClient() {
|
||||
return this.value.equals(CalendarEntityType.CLIENTS.getValue());
|
||||
}
|
||||
|
||||
private static final Map<String, CalendarEntityType> entityNameToEnumMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (final CalendarEntityType entityType : CalendarEntityType.values()) {
|
||||
entityNameToEnumMap.put(entityType.name().toLowerCase(), entityType);
|
||||
}
|
||||
}
|
||||
|
||||
public static CalendarEntityType getEntityType(String entityType) {
|
||||
return entityNameToEnumMap.get(entityType.toLowerCase());
|
||||
}
|
||||
|
||||
public static boolean isSavings(final Integer value) {
|
||||
return CalendarEntityType.SAVINGS.value.equals(value) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isSavings(final String name) {
|
||||
return CalendarEntityType.SAVINGS.name().equalsIgnoreCase(name) ? true : false;
|
||||
}
|
||||
|
||||
public boolean isSavings() {
|
||||
return this.value.equals(CalendarEntityType.SAVINGS.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public enum CalendarFrequencyType {
|
||||
|
||||
INVALID(0, "calendarFrequencyType.invalid"), DAILY(1, "calendarFrequencyType.daily"), WEEKLY(2,
|
||||
"calendarFrequencyType.weekly"), MONTHLY(3, "calendarFrequencyType.monthly"), YEARLY(4, "calendarFrequencyType.yearly");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
CalendarFrequencyType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, CalendarFrequencyType> intToEnumMap = new HashMap<>();
|
||||
private static int minValue = CalendarFrequencyType.DAILY.value;
|
||||
private static int maxValue = CalendarFrequencyType.YEARLY.value;
|
||||
|
||||
static {
|
||||
for (final CalendarFrequencyType type : CalendarFrequencyType.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static CalendarFrequencyType fromInt(final int i) {
|
||||
final CalendarFrequencyType type = intToEnumMap.get(Integer.valueOf(i));
|
||||
return type;
|
||||
}
|
||||
|
||||
public static CalendarFrequencyType fromString(final String frequencyString) {
|
||||
CalendarFrequencyType frequency = CalendarFrequencyType.INVALID;
|
||||
|
||||
if (!StringUtils.hasText(frequencyString)) {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.DAILY.toString())) {
|
||||
frequency = CalendarFrequencyType.DAILY;
|
||||
} else if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.WEEKLY.toString())) {
|
||||
frequency = CalendarFrequencyType.WEEKLY;
|
||||
} else if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.MONTHLY.toString())) {
|
||||
frequency = CalendarFrequencyType.MONTHLY;
|
||||
} else if (frequencyString.equalsIgnoreCase(CalendarFrequencyType.YEARLY.toString())) {
|
||||
frequency = CalendarFrequencyType.YEARLY;
|
||||
}
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public static int getMinValue() {
|
||||
return minValue;
|
||||
}
|
||||
|
||||
public static int getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public boolean isWeekly() {
|
||||
return this.value.equals(CalendarFrequencyType.WEEKLY.value);
|
||||
}
|
||||
|
||||
public boolean isMonthly() {
|
||||
return this.value.equals(CalendarFrequencyType.MONTHLY.value);
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return this.value.equals(CalendarFrequencyType.INVALID.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* To convert from period frequency type tp calendar frequency type. This method requires code refactoring.
|
||||
*
|
||||
* @param periodFrequencyType
|
||||
* periodFrequencyType
|
||||
* @return CalendarFrequencyType
|
||||
*/
|
||||
public static CalendarFrequencyType from(final PeriodFrequencyType periodFrequencyType) {
|
||||
switch (periodFrequencyType) {
|
||||
case DAYS:
|
||||
return CalendarFrequencyType.DAILY;
|
||||
case WEEKS:
|
||||
return CalendarFrequencyType.WEEKLY;
|
||||
case MONTHS:
|
||||
return CalendarFrequencyType.MONTHLY;
|
||||
case YEARS:
|
||||
return CalendarFrequencyType.YEARLY;
|
||||
default:
|
||||
return CalendarFrequencyType.INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To convert from period frequency type tp calendar frequency type. This method requires code refactoring.
|
||||
*
|
||||
* @param frequencyType
|
||||
* @return
|
||||
*/
|
||||
public static PeriodFrequencyType from(final CalendarFrequencyType frequencyType) {
|
||||
switch (frequencyType) {
|
||||
case DAILY:
|
||||
return PeriodFrequencyType.DAYS;
|
||||
case WEEKLY:
|
||||
return PeriodFrequencyType.WEEKS;
|
||||
case MONTHLY:
|
||||
return PeriodFrequencyType.MONTHS;
|
||||
case YEARLY:
|
||||
return PeriodFrequencyType.YEARS;
|
||||
default:
|
||||
return PeriodFrequencyType.INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_calendar_history")
|
||||
public class CalendarHistory extends AbstractPersistableCustom {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "calendar_id", referencedColumnName = "id", nullable = false)
|
||||
private Calendar calendar;
|
||||
|
||||
@Column(name = "title", length = 50, nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(name = "description", length = 100, nullable = true)
|
||||
private String description;
|
||||
|
||||
@Column(name = "location", length = 100, nullable = true)
|
||||
private String location;
|
||||
|
||||
@Column(name = "start_date", nullable = false)
|
||||
private LocalDate startDate;
|
||||
|
||||
@Column(name = "end_date", nullable = true)
|
||||
private LocalDate endDate;
|
||||
|
||||
@Column(name = "duration", nullable = true)
|
||||
private Integer duration;
|
||||
|
||||
@Column(name = "calendar_type_enum", nullable = false)
|
||||
private Integer typeId;
|
||||
|
||||
@Column(name = "repeating", nullable = false)
|
||||
private boolean repeating = false;
|
||||
|
||||
@Column(name = "recurrence", length = 100, nullable = true)
|
||||
private String recurrence;
|
||||
|
||||
@Column(name = "remind_by_enum", nullable = true)
|
||||
private Integer remindById;
|
||||
|
||||
@Column(name = "first_reminder", nullable = true)
|
||||
private Integer firstReminder;
|
||||
|
||||
@Column(name = "second_reminder", nullable = true)
|
||||
private Integer secondReminder;
|
||||
|
||||
protected CalendarHistory() {
|
||||
|
||||
}
|
||||
|
||||
public CalendarHistory(Calendar calendar, LocalDate startDate) {
|
||||
this.calendar = calendar;
|
||||
this.title = calendar.getTitle();
|
||||
this.description = calendar.getDescription();
|
||||
this.location = calendar.getLocation();
|
||||
this.startDate = startDate;
|
||||
this.endDate = calendar.getStartDate();// Calendar start date become end
|
||||
// date for history data.
|
||||
this.duration = calendar.getDuration();
|
||||
this.typeId = calendar.getTypeId();
|
||||
this.repeating = calendar.isRepeating();
|
||||
this.recurrence = calendar.getRecurrence();
|
||||
this.remindById = calendar.getRemindById();
|
||||
this.firstReminder = calendar.getFirstReminder();
|
||||
this.secondReminder = calendar.getSecondReminder();
|
||||
}
|
||||
|
||||
public String getRecurrence() {
|
||||
return this.recurrence;
|
||||
}
|
||||
|
||||
public LocalDate getStartDateLocalDate() {
|
||||
return this.startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDateLocalDate() {
|
||||
return this.endDate;
|
||||
}
|
||||
|
||||
public boolean isEndDateAfterOrEqual(final LocalDate compareDate) {
|
||||
if (this.endDate != null && compareDate != null) {
|
||||
if (getEndDateLocalDate().isAfter(compareDate) || getEndDateLocalDate().isEqual(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStartDateBeforeOrEqual(final LocalDate compareDate) {
|
||||
if (this.startDate != null && compareDate != null) {
|
||||
if (getStartDateLocalDate().isBefore(compareDate) || getStartDateLocalDate().equals(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isBetweenStartAndEndDate(final LocalDate compareDate) {
|
||||
if (isStartDateBeforeOrEqual(compareDate)) {
|
||||
if (getEndDateLocalDate() == null || isEndDateAfterOrEqual(compareDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateEndDate(LocalDate historyCalEndDate) {
|
||||
this.endDate = historyCalEndDate;
|
||||
}
|
||||
|
||||
public Calendar getCalendar() {
|
||||
return this.calendar;
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_calendar_instance")
|
||||
public class CalendarInstance extends AbstractPersistableCustom {
|
||||
|
||||
@ManyToOne(cascade = CascadeType.PERSIST)
|
||||
@JoinColumn(name = "calendar_id", nullable = false)
|
||||
private Calendar calendar;
|
||||
|
||||
@Column(name = "entity_id", nullable = false)
|
||||
private Long entityId;
|
||||
|
||||
@Column(name = "entity_type_enum", nullable = false)
|
||||
private Integer entityTypeId;
|
||||
|
||||
public CalendarInstance(final Calendar calendar, final Long entityId, final Integer entityTypeId) {
|
||||
this.calendar = calendar;
|
||||
this.entityId = entityId;
|
||||
this.entityTypeId = entityTypeId;
|
||||
}
|
||||
|
||||
protected CalendarInstance() {
|
||||
|
||||
}
|
||||
|
||||
public static CalendarInstance from(final Calendar calendar, final Long entityId, final Integer entityTypeId) {
|
||||
return new CalendarInstance(calendar, entityId, entityTypeId);
|
||||
}
|
||||
|
||||
public void updateCalendar(final Calendar calendar) {
|
||||
this.calendar = calendar;
|
||||
}
|
||||
|
||||
public Calendar getCalendar() {
|
||||
return this.calendar;
|
||||
}
|
||||
|
||||
public Long getEntityId() {
|
||||
return this.entityId;
|
||||
}
|
||||
|
||||
public Integer getEntityTypeId() {
|
||||
return this.entityTypeId;
|
||||
}
|
||||
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum CalendarRemindBy {
|
||||
|
||||
SMS(1, "calendarRemindBy.sms"), EMAIL(2, "calendarRemindBy.email"), SYSTEMALERT(3, "calendarRemindBy.systemalert");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
CalendarRemindBy(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, CalendarRemindBy> intToEnumMap = new HashMap<>();
|
||||
private static int minValue;
|
||||
private static int maxValue;
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
for (final CalendarRemindBy remindBy : CalendarRemindBy.values()) {
|
||||
if (i == 0) {
|
||||
minValue = remindBy.value;
|
||||
}
|
||||
intToEnumMap.put(remindBy.value, remindBy);
|
||||
if (minValue >= remindBy.value) {
|
||||
minValue = remindBy.value;
|
||||
}
|
||||
if (maxValue < remindBy.value) {
|
||||
maxValue = remindBy.value;
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static CalendarRemindBy fromInt(final int i) {
|
||||
final CalendarRemindBy remindBy = intToEnumMap.get(Integer.valueOf(i));
|
||||
return remindBy;
|
||||
}
|
||||
|
||||
public static int getMinValue() {
|
||||
return minValue;
|
||||
}
|
||||
|
||||
public static int getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
}
|
||||
+87
@@ -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.calendar.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum CalendarType {
|
||||
|
||||
COLLECTION(1, "calendarType.collection"), TRAINING(2, "calendarType.training"), AUDIT(3, "calendarType.audit"), GENERAL(4,
|
||||
"calendarType.general");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
CalendarType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, CalendarType> intToEnumMap = new HashMap<>();
|
||||
private static int minValue;
|
||||
private static int maxValue;
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
for (final CalendarType type : CalendarType.values()) {
|
||||
if (i == 0) {
|
||||
minValue = type.value;
|
||||
}
|
||||
intToEnumMap.put(type.value, type);
|
||||
if (minValue >= type.value) {
|
||||
minValue = type.value;
|
||||
}
|
||||
if (maxValue < type.value) {
|
||||
maxValue = type.value;
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static CalendarType fromInt(final int i) {
|
||||
final CalendarType type = intToEnumMap.get(Integer.valueOf(i));
|
||||
return type;
|
||||
}
|
||||
|
||||
public static int getMinValue() {
|
||||
return minValue;
|
||||
}
|
||||
|
||||
public static int getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public boolean isCollection() {
|
||||
return this.value.equals(CalendarType.COLLECTION.value);
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public enum CalendarWeekDaysType {
|
||||
|
||||
INVALID(0, "calendarWeekDaysType.invalid"), MO(1, "calendarWeekDaysType.monday"), TU(2, "calendarWeekDaysType.tuesday"), WE(3,
|
||||
"calendarWeekDaysType.wednesday"), TH(4, "calendarWeekDaysType.thursday"), FR(5,
|
||||
"calendarWeekDaysType.friday"), SA(6, "calendarWeekDaysType.saturday"), SU(7, "calendarWeekDaysType.sunday");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
CalendarWeekDaysType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
private static final Map<Integer, CalendarWeekDaysType> intToEnumMap = new HashMap<>();
|
||||
private static int minValue = CalendarWeekDaysType.MO.value;
|
||||
private static int maxValue = CalendarWeekDaysType.SU.value;
|
||||
|
||||
static {
|
||||
for (final CalendarWeekDaysType type : CalendarWeekDaysType.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static CalendarWeekDaysType fromInt(final int i) {
|
||||
final CalendarWeekDaysType type = intToEnumMap.get(Integer.valueOf(i));
|
||||
return type;
|
||||
}
|
||||
|
||||
public static int getMinValue() {
|
||||
return minValue;
|
||||
}
|
||||
|
||||
public static int getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return this.value.equals(CalendarWeekDaysType.INVALID.value);
|
||||
}
|
||||
|
||||
public static CalendarWeekDaysType fromString(final String weekDayString) {
|
||||
CalendarWeekDaysType weekDay = CalendarWeekDaysType.INVALID;
|
||||
|
||||
if (!StringUtils.hasText(weekDayString)) {
|
||||
return weekDay;
|
||||
}
|
||||
|
||||
if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.MO.toString())) {
|
||||
weekDay = CalendarWeekDaysType.MO;
|
||||
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.TU.toString())) {
|
||||
weekDay = CalendarWeekDaysType.TU;
|
||||
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.WE.toString())) {
|
||||
weekDay = CalendarWeekDaysType.WE;
|
||||
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.TH.toString())) {
|
||||
weekDay = CalendarWeekDaysType.TH;
|
||||
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.FR.toString())) {
|
||||
weekDay = CalendarWeekDaysType.FR;
|
||||
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.SA.toString())) {
|
||||
weekDay = CalendarWeekDaysType.SA;
|
||||
} else if (weekDayString.equalsIgnoreCase(CalendarWeekDaysType.SU.toString())) {
|
||||
weekDay = CalendarWeekDaysType.SU;
|
||||
}
|
||||
|
||||
return weekDay;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.calendar.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when Calendar resources are not found.
|
||||
*/
|
||||
public class CalendarDateException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public CalendarDateException(final String postFix, final String defaultUserMessage, final Object... defaultUserMessageArgs) {
|
||||
super("error.msg.calendar." + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.calendar.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when Calendar resources are not found.
|
||||
*/
|
||||
public class CalendarParameterUpdateNotSupportedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public CalendarParameterUpdateNotSupportedException(final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg.calendar.update.of." + postFix + ".is.not.supported", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* 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.calendar.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarWeekDaysType;
|
||||
import org.apache.fineract.portfolio.common.domain.NthDayType;
|
||||
|
||||
public final class CalendarEnumerations {
|
||||
|
||||
private CalendarEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarEntityType(final int id) {
|
||||
return calendarEntityType(CalendarEntityType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarEntityType(final CalendarEntityType entityType) {
|
||||
final EnumOptionData optionData = new EnumOptionData(entityType.getValue().longValue(), entityType.getCode(),
|
||||
entityType.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> calendarEntityType(final CalendarEntityType[] entityTypes) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final CalendarEntityType entityType : entityTypes) {
|
||||
optionDatas.add(calendarEntityType(entityType));
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarType(final int id) {
|
||||
return calendarType(CalendarType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarType(final CalendarType type) {
|
||||
final EnumOptionData optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), type.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> calendarType(final CalendarType[] types) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final CalendarType type : types) {
|
||||
optionDatas.add(calendarType(type));
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarRemindBy(final int id) {
|
||||
return calendarRemindBy(CalendarRemindBy.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarRemindBy(final CalendarRemindBy remindBy) {
|
||||
final EnumOptionData optionData = new EnumOptionData(remindBy.getValue().longValue(), remindBy.getCode(), remindBy.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> calendarRemindBy(final CalendarRemindBy[] remindBys) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final CalendarRemindBy remindBy : remindBys) {
|
||||
optionDatas.add(calendarRemindBy(remindBy));
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarFrequencyType(final int id) {
|
||||
return calendarFrequencyType(CalendarFrequencyType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarFrequencyType(final CalendarFrequencyType calendarFrequencyType) {
|
||||
EnumOptionData optionData = null;
|
||||
if (!calendarFrequencyType.isInvalid()) {
|
||||
optionData = new EnumOptionData(calendarFrequencyType.getValue().longValue(), calendarFrequencyType.getCode(),
|
||||
calendarFrequencyType.toString());
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> calendarFrequencyType(final CalendarFrequencyType[] calendarFrequencyTypes) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final CalendarFrequencyType calendarFrequencyType : calendarFrequencyTypes) {
|
||||
if (!calendarFrequencyType.isInvalid()) {
|
||||
optionDatas.add(calendarFrequencyType(calendarFrequencyType));
|
||||
}
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarWeekDaysType(final int id) {
|
||||
return calendarWeekDaysType(CalendarWeekDaysType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarWeekDaysType(final CalendarWeekDaysType calendarWeekDaysType) {
|
||||
EnumOptionData optionData = null;
|
||||
if (!calendarWeekDaysType.isInvalid()) {
|
||||
optionData = new EnumOptionData(calendarWeekDaysType.getValue().longValue(), calendarWeekDaysType.getCode(),
|
||||
calendarWeekDaysType.toString());
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> calendarWeekDaysType(final CalendarWeekDaysType[] calendarWeekDaysTypes) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final CalendarWeekDaysType calendarWeekDaysType : calendarWeekDaysTypes) {
|
||||
if (!calendarWeekDaysType.isInvalid()) {
|
||||
optionDatas.add(calendarWeekDaysType(calendarWeekDaysType));
|
||||
}
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarFrequencyNthDayType(final int id) {
|
||||
return calendarFrequencyNthDayType(NthDayType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData calendarFrequencyNthDayType(final NthDayType calendarFrequencyNthDayType) {
|
||||
final EnumOptionData optionData = new EnumOptionData(calendarFrequencyNthDayType.getValue().longValue(),
|
||||
calendarFrequencyNthDayType.getCode(), calendarFrequencyNthDayType.toString());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> calendarFrequencyNthDayType() {
|
||||
final List<EnumOptionData> optionDatas = Arrays.asList(calendarFrequencyNthDayType(NthDayType.ONE),
|
||||
calendarFrequencyNthDayType(NthDayType.TWO), calendarFrequencyNthDayType(NthDayType.THREE),
|
||||
calendarFrequencyNthDayType(NthDayType.FOUR), calendarFrequencyNthDayType(NthDayType.LAST),
|
||||
calendarFrequencyNthDayType(NthDayType.ONDAY));
|
||||
return optionDatas;
|
||||
}
|
||||
}
|
||||
+888
@@ -0,0 +1,888 @@
|
||||
/**
|
||||
* 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.calendar.service;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import java.text.ParseException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.YearMonth;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import net.fortuna.ical4j.model.Date;
|
||||
import net.fortuna.ical4j.model.DateList;
|
||||
import net.fortuna.ical4j.model.DateTime;
|
||||
import net.fortuna.ical4j.model.NumberList;
|
||||
import net.fortuna.ical4j.model.Recur;
|
||||
import net.fortuna.ical4j.model.WeekDay;
|
||||
import net.fortuna.ical4j.model.WeekDayList;
|
||||
import net.fortuna.ical4j.model.parameter.Value;
|
||||
import net.fortuna.ical4j.model.property.RRule;
|
||||
import net.fortuna.ical4j.validate.ValidationException;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
|
||||
import org.apache.fineract.organisation.workingdays.service.WorkingDaysUtil;
|
||||
import org.apache.fineract.portfolio.calendar.domain.Calendar;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarWeekDaysType;
|
||||
import org.apache.fineract.portfolio.common.domain.NthDayType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class CalendarUtils {
|
||||
|
||||
private CalendarUtils() {
|
||||
|
||||
}
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CalendarUtils.class);
|
||||
|
||||
static {
|
||||
System.setProperty("net.fortuna.ical4j.timezone.date.floating", "true");
|
||||
}
|
||||
|
||||
public static LocalDateTime getNextRecurringDate(final String recurringRule, final LocalDateTime seedDate,
|
||||
final LocalDateTime startDate) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
LocalDateTime nextDate = getNextRecurringDate(recur, seedDate, startDate);
|
||||
nextDate = (LocalDateTime) adjustDate(nextDate, seedDate, getMeetingPeriodFrequencyType(recurringRule));
|
||||
return nextDate;
|
||||
}
|
||||
|
||||
public static LocalDate getNextRecurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate startDate) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
LocalDate nextDate = getNextRecurringDate(recur, seedDate, startDate);
|
||||
nextDate = (LocalDate) adjustDate(nextDate, seedDate, getMeetingPeriodFrequencyType(recurringRule));
|
||||
return nextDate;
|
||||
}
|
||||
|
||||
public static Temporal adjustDate(final Temporal date, final Temporal seedDate, final PeriodFrequencyType frequencyType) {
|
||||
if (frequencyType.isMonthly() && seedDate.get(ChronoField.DAY_OF_MONTH) > 28 && date.get(ChronoField.DAY_OF_MONTH) >= 28) {
|
||||
int noOfDaysInCurrentMonth = YearMonth.from(date).lengthOfMonth();
|
||||
int seedDay = seedDate.get(ChronoField.DAY_OF_MONTH);
|
||||
int adjustedDay = Math.min(noOfDaysInCurrentMonth, seedDay);
|
||||
return date.with(ChronoField.DAY_OF_MONTH, adjustedDay);
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
private static LocalDateTime getNextRecurringDate(final Recur recur, final LocalDateTime seedDate, final LocalDateTime startDate) {
|
||||
final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()));
|
||||
final Date seed = convertToiCal4JCompatibleDate(seedDate);
|
||||
final Date nextRecDate = recur.getNextDate(seed, periodStart);
|
||||
return nextRecDate == null ? null : LocalDateTime.ofInstant(nextRecDate.toInstant(), DateUtils.getSystemZoneId());
|
||||
}
|
||||
|
||||
private static LocalDate getNextRecurringDate(final Recur recur, final LocalDate seedDate, final LocalDate startDate) {
|
||||
final DateTime periodStart = new DateTime(java.util.Date.from(startDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
|
||||
final Date seed = convertToiCal4JCompatibleDate(seedDate.atStartOfDay());
|
||||
final Date nextRecDate = recur.getNextDate(seed, periodStart);
|
||||
return nextRecDate == null ? null : LocalDate.ofInstant(nextRecDate.toInstant(), DateUtils.getSystemZoneId());
|
||||
}
|
||||
|
||||
private static Date convertToiCal4JCompatibleDate(final LocalDateTime inputDate) {
|
||||
Date formattedDate = null;
|
||||
final String seedDateStr = DateUtils.DEFAULT_DATETIME_FORMATTER.format(inputDate);
|
||||
try {
|
||||
formattedDate = new Date(seedDateStr, DateUtils.DEFAULT_DATETIME_FORMAT);
|
||||
} catch (final ParseException e) {
|
||||
LOG.error("Invalid date: {}", seedDateStr, e);
|
||||
}
|
||||
return formattedDate;
|
||||
}
|
||||
|
||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate, final LocalDate endDate) {
|
||||
|
||||
final LocalDate periodStartDate = DateUtils.getLocalDateOfTenant();
|
||||
final LocalDate periodEndDate = (endDate == null) ? DateUtils.getLocalDateOfTenant().plusYears(5) : endDate;
|
||||
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate);
|
||||
}
|
||||
|
||||
public static Collection<LocalDate> getRecurringDatesFrom(final String recurringRule, final LocalDate seedDate,
|
||||
final LocalDate startDate) {
|
||||
final LocalDate periodStartDate = (startDate == null) ? DateUtils.getLocalDateOfTenant() : startDate;
|
||||
final LocalDate periodEndDate = DateUtils.getLocalDateOfTenant().plusYears(5);
|
||||
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate);
|
||||
}
|
||||
|
||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate,
|
||||
final LocalDate periodStartDate, final LocalDate periodEndDate) {
|
||||
final int maxCount = 10;// Default number of recurring dates
|
||||
boolean isSkipRepaymentOnFirstdayofMonth = false;
|
||||
final Integer numberofDays = 0;
|
||||
return getRecurringDates(recurringRule, seedDate, periodStartDate, periodEndDate, maxCount, isSkipRepaymentOnFirstdayofMonth,
|
||||
numberofDays);
|
||||
}
|
||||
|
||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate,
|
||||
final LocalDate periodStartDate, final LocalDate periodEndDate, final int maxCount, boolean isSkippMeetingOnFirstDay,
|
||||
final Integer numberOfDays) {
|
||||
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
|
||||
return getRecurringDates(recur, seedDate, periodStartDate, periodEndDate, maxCount, isSkippMeetingOnFirstDay, numberOfDays);
|
||||
}
|
||||
|
||||
private static Collection<LocalDate> getRecurringDates(final Recur recur, final LocalDate seedDate, final LocalDate periodStartDate,
|
||||
final LocalDate periodEndDate, final int maxCount, boolean isSkippMeetingOnFirstDay, final Integer numberOfDays) {
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
final Date seed = convertToiCal4JCompatibleDate(seedDate.atStartOfDay());
|
||||
final DateTime periodStart = new DateTime(java.util.Date.from(periodStartDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
|
||||
final DateTime periodEnd = new DateTime(java.util.Date.from(periodEndDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
|
||||
|
||||
final Value value = new Value(Value.DATE.getValue());
|
||||
final DateList recurringDates = recur.getDates(seed, periodStart, periodEnd, value, maxCount);
|
||||
return convertToLocalDateList(recurringDates, seedDate, getMeetingPeriodFrequencyType(recur), isSkippMeetingOnFirstDay,
|
||||
numberOfDays);
|
||||
}
|
||||
|
||||
private static Collection<LocalDate> convertToLocalDateList(final DateList dates, final LocalDate seedDate,
|
||||
final PeriodFrequencyType frequencyType, boolean isSkippMeetingOnFirstDay, final Integer numberOfDays) {
|
||||
|
||||
final Collection<LocalDate> recurringDates = new ArrayList<>();
|
||||
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = dates.iterator(); iterator.hasNext();) {
|
||||
final Date date = (Date) iterator.next();
|
||||
recurringDates.add((LocalDate) adjustDate(LocalDate.ofInstant(date.toInstant(), DateUtils.getDateTimeZoneOfTenant()), seedDate,
|
||||
frequencyType));
|
||||
}
|
||||
|
||||
if (isSkippMeetingOnFirstDay) {
|
||||
return skipMeetingOnFirstdayOfMonth(recurringDates, numberOfDays);
|
||||
}
|
||||
|
||||
return recurringDates;
|
||||
}
|
||||
|
||||
private static Collection<LocalDate> skipMeetingOnFirstdayOfMonth(final Collection<LocalDate> recurringDates,
|
||||
final Integer numberOfDays) {
|
||||
final Collection<LocalDate> adjustedRecurringDates = new ArrayList<>();
|
||||
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = recurringDates.iterator(); iterator.hasNext();) {
|
||||
LocalDate recuringDate = (LocalDate) iterator.next();
|
||||
adjustedRecurringDates.add(adjustRecurringDate(recuringDate, numberOfDays));
|
||||
}
|
||||
return adjustedRecurringDates;
|
||||
}
|
||||
|
||||
public static LocalDate adjustRecurringDate(final LocalDate recuringDate, final Integer numberOfDays) {
|
||||
if (recuringDate.getDayOfMonth() == 1) {
|
||||
LocalDate adjustedRecurringDate = recuringDate.plusDays(numberOfDays);
|
||||
return adjustedRecurringDate;
|
||||
}
|
||||
return recuringDate;
|
||||
}
|
||||
|
||||
public static Recur getICalRecur(final String recurringRule) {
|
||||
|
||||
// Construct RRule
|
||||
try {
|
||||
final RRule rrule = new RRule(recurringRule);
|
||||
rrule.validate();
|
||||
|
||||
final Recur recur = rrule.getRecur();
|
||||
|
||||
return recur;
|
||||
} catch (final ParseException e) {
|
||||
// TODO Auto-generated catch block
|
||||
LOG.error("Problem occurred in getICalRecur function", e);
|
||||
} catch (final ValidationException e) {
|
||||
// TODO Auto-generated catch block
|
||||
LOG.error("Problem occurred in getICalRecur function", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getRRuleReadable(final LocalDate startDate, final String recurringRule) {
|
||||
|
||||
String humanReadable = "";
|
||||
|
||||
RRule rrule;
|
||||
Recur recur = null;
|
||||
try {
|
||||
rrule = new RRule(recurringRule);
|
||||
rrule.validate();
|
||||
recur = rrule.getRecur();
|
||||
} catch (final ValidationException e) {
|
||||
throw new PlatformDataIntegrityException("error.msg.invalid.recurring.rule",
|
||||
"The Recurring Rule value: " + recurringRule + " is not valid.", "recurrence", recurringRule, e);
|
||||
} catch (final ParseException e) {
|
||||
throw new PlatformDataIntegrityException("error.msg.recurring.rule.parsing.error",
|
||||
"Error in pasring the Recurring Rule value: " + recurringRule, "recurrence", recurringRule, e);
|
||||
}
|
||||
|
||||
if (recur == null) {
|
||||
return humanReadable;
|
||||
}
|
||||
|
||||
if (recur.getFrequency().equals(Recur.Frequency.DAILY)) {
|
||||
if (recur.getInterval() == 1) {
|
||||
humanReadable = "Daily";
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " days";
|
||||
}
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.WEEKLY)) {
|
||||
if (recur.getInterval() == 1 || recur.getInterval() == -1) {
|
||||
humanReadable = "Weekly";
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " weeks";
|
||||
}
|
||||
|
||||
humanReadable += " on ";
|
||||
final WeekDayList weekDayList = recur.getDayList();
|
||||
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = weekDayList.iterator(); iterator.hasNext();) {
|
||||
final WeekDay weekDay = (WeekDay) iterator.next();
|
||||
humanReadable += DayNameEnum.from(weekDay.getDay().name()).getCode();
|
||||
}
|
||||
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.MONTHLY)) {
|
||||
NumberList nthDays = recur.getSetPosList();
|
||||
Integer nthDay = null;
|
||||
if (!nthDays.isEmpty()) {
|
||||
nthDay = nthDays.get(0);
|
||||
}
|
||||
NumberList monthDays = recur.getMonthDayList();
|
||||
Integer monthDay = null;
|
||||
if (!monthDays.isEmpty()) {
|
||||
monthDay = monthDays.get(0);
|
||||
}
|
||||
WeekDayList weekdays = recur.getDayList();
|
||||
WeekDay weekDay = null;
|
||||
if (!weekdays.isEmpty()) {
|
||||
weekDay = weekdays.get(0);
|
||||
}
|
||||
if (nthDay != null && weekDay != null) {
|
||||
NthDayType nthDayType = NthDayType.fromInt(nthDay);
|
||||
NthDayNameEnum nthDayName = NthDayNameEnum.from(nthDayType.toString());
|
||||
DayNameEnum weekdayType = DayNameEnum.from(weekDay.getDay().name());
|
||||
if (recur.getInterval() == 1 || recur.getInterval() == -1) {
|
||||
humanReadable = "Monthly on " + nthDayName.getCode().toLowerCase() + " " + weekdayType.getCode().toLowerCase();
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " months on " + nthDayName.getCode().toLowerCase() + " "
|
||||
+ weekdayType.getCode().toLowerCase();
|
||||
}
|
||||
} else if (monthDay != null) {
|
||||
if (monthDay == -1) {
|
||||
if (recur.getInterval() == 1 || recur.getInterval() == -1) {
|
||||
humanReadable = "Monthly on last day";
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " months on last day";
|
||||
}
|
||||
} else {
|
||||
if (recur.getInterval() == 1 || recur.getInterval() == -1) {
|
||||
humanReadable = "Monthly on day " + monthDay;
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " months on day " + monthDay;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (recur.getInterval() == 1 || recur.getInterval() == -1) {
|
||||
humanReadable = "Monthly on day " + startDate.getDayOfMonth();
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " months on day " + startDate.getDayOfMonth();
|
||||
}
|
||||
}
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.YEARLY)) {
|
||||
if (recur.getInterval() == 1) {
|
||||
humanReadable = "Annually on " + startDate.format(DateTimeFormatter.ofPattern("MMM")) + " " + startDate.getDayOfMonth();
|
||||
} else {
|
||||
humanReadable = "Every " + recur.getInterval() + " years on " + startDate.format(DateTimeFormatter.ofPattern("MMM")) + " "
|
||||
+ startDate.getDayOfMonth();
|
||||
}
|
||||
}
|
||||
|
||||
if (recur.getCount() > 0) {
|
||||
if (recur.getCount() == 1) {
|
||||
humanReadable = "Once";
|
||||
}
|
||||
humanReadable += ", " + recur.getCount() + " times";
|
||||
}
|
||||
|
||||
final Date endDate = recur.getUntil();
|
||||
if (endDate != null) {
|
||||
final LocalDate date = LocalDate.ofInstant(endDate.toInstant(), DateUtils.getDateTimeZoneOfTenant());
|
||||
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd MMMM yy");
|
||||
final String formattedDate = date.format(fmt);
|
||||
humanReadable += ", until " + formattedDate;
|
||||
}
|
||||
|
||||
return humanReadable;
|
||||
}
|
||||
|
||||
public static boolean isValidRedurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate date) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return false;
|
||||
}
|
||||
final boolean isSkipRepaymentonFirstDayOfMonth = false;
|
||||
final int numberOfDays = 0;
|
||||
return isValidRecurringDate(recur, seedDate, date, isSkipRepaymentonFirstDayOfMonth, numberOfDays);
|
||||
}
|
||||
|
||||
public static boolean isValidRedurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate date,
|
||||
boolean isSkipRepaymentonFirstDayOfMonth, final Integer numberOfDays) {
|
||||
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValidRecurringDate(recur, seedDate, date, isSkipRepaymentonFirstDayOfMonth, numberOfDays);
|
||||
}
|
||||
|
||||
public static boolean isValidRecurringDate(final Recur recur, final LocalDate seedDate, final LocalDate date,
|
||||
boolean isSkipRepaymentonFirstDayOfMonth, final int numberOfDays) {
|
||||
LocalDate startDate = date;
|
||||
if (isSkipRepaymentonFirstDayOfMonth && date.getDayOfMonth() == (numberOfDays + 1)) {
|
||||
startDate = startDate.minusDays(numberOfDays);
|
||||
}
|
||||
final Collection<LocalDate> recurDate = getRecurringDates(recur, seedDate, startDate, date.plusDays(1), 1,
|
||||
isSkipRepaymentonFirstDayOfMonth, numberOfDays);
|
||||
|
||||
return (recurDate == null || recurDate.isEmpty()) ? false : recurDate.contains(date);
|
||||
}
|
||||
|
||||
public enum DayNameEnum {
|
||||
|
||||
MO(1, "Monday"), TU(2, "Tuesday"), WE(3, "Wednesday"), TH(4, "Thursday"), FR(5, "Friday"), SA(6, "Saturday"), SU(7, "Sunday");
|
||||
|
||||
private final String code;
|
||||
private final Integer value;
|
||||
|
||||
DayNameEnum(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static DayNameEnum from(final String name) {
|
||||
for (final DayNameEnum dayName : DayNameEnum.values()) {
|
||||
if (dayName.toString().equals(name)) {
|
||||
return dayName;
|
||||
}
|
||||
}
|
||||
return DayNameEnum.MO;// Default it to Monday
|
||||
}
|
||||
}
|
||||
|
||||
public enum NthDayNameEnum {
|
||||
|
||||
ONE(1, "First"), TWO(2, "Second"), THREE(3, "Third"), FOUR(4, "Fourth"), FIVE(5, "Fifth"), LAST(-1, "Last"), INVALID(0, "Invalid");
|
||||
|
||||
private final String code;
|
||||
private final Integer value;
|
||||
|
||||
NthDayNameEnum(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static NthDayNameEnum from(final String name) {
|
||||
for (final NthDayNameEnum nthDayName : NthDayNameEnum.values()) {
|
||||
if (nthDayName.toString().equals(name)) {
|
||||
return nthDayName;
|
||||
}
|
||||
}
|
||||
return NthDayNameEnum.INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
public static PeriodFrequencyType getMeetingPeriodFrequencyType(final String recurringRule) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
return getMeetingPeriodFrequencyType(recur);
|
||||
}
|
||||
|
||||
private static PeriodFrequencyType getMeetingPeriodFrequencyType(final Recur recur) {
|
||||
PeriodFrequencyType meetingFrequencyType = PeriodFrequencyType.INVALID;
|
||||
if (recur.getFrequency().equals(Recur.Frequency.DAILY)) {
|
||||
meetingFrequencyType = PeriodFrequencyType.DAYS;
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.WEEKLY)) {
|
||||
meetingFrequencyType = PeriodFrequencyType.WEEKS;
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.MONTHLY)) {
|
||||
meetingFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.YEARLY)) {
|
||||
meetingFrequencyType = PeriodFrequencyType.YEARS;
|
||||
}
|
||||
return meetingFrequencyType;
|
||||
}
|
||||
|
||||
public static String getMeetingFrequencyFromPeriodFrequencyType(final PeriodFrequencyType periodFrequency) {
|
||||
String frequency = null;
|
||||
if (periodFrequency.equals(PeriodFrequencyType.DAYS)) {
|
||||
frequency = Recur.Frequency.DAILY.name();
|
||||
} else if (periodFrequency.equals(PeriodFrequencyType.WEEKS)) {
|
||||
frequency = Recur.Frequency.WEEKLY.name();
|
||||
} else if (periodFrequency.equals(PeriodFrequencyType.MONTHS)) {
|
||||
frequency = Recur.Frequency.MONTHLY.name();
|
||||
} else if (periodFrequency.equals(PeriodFrequencyType.YEARS)) {
|
||||
frequency = Recur.Frequency.YEARLY.name();
|
||||
}
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public static int getInterval(final String recurringRule) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
return recur.getInterval();
|
||||
}
|
||||
|
||||
public static CalendarFrequencyType getFrequency(final String recurringRule) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
return CalendarFrequencyType.fromString(recur.getFrequency().name());
|
||||
}
|
||||
|
||||
public static CalendarWeekDaysType getRepeatsOnDay(final String recurringRule) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
final WeekDayList weekDays = recur.getDayList();
|
||||
if (weekDays.isEmpty()) {
|
||||
return CalendarWeekDaysType.INVALID;
|
||||
}
|
||||
// supports only one day
|
||||
WeekDay weekDay = weekDays.get(0);
|
||||
return CalendarWeekDaysType.fromString(weekDay.getDay().name());
|
||||
}
|
||||
|
||||
public static NthDayType getRepeatsOnNthDayOfMonth(final String recurringRule) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
NumberList monthDays = null;
|
||||
if (recur.getDayList().isEmpty()) {
|
||||
monthDays = recur.getMonthDayList();
|
||||
} else {
|
||||
monthDays = recur.getSetPosList();
|
||||
}
|
||||
if (monthDays.isEmpty()) {
|
||||
return NthDayType.INVALID;
|
||||
}
|
||||
if (!recur.getMonthDayList().isEmpty() && recur.getSetPosList().isEmpty()) {
|
||||
return NthDayType.ONDAY;
|
||||
}
|
||||
Integer monthDay = monthDays.get(0);
|
||||
return NthDayType.fromInt(monthDay);
|
||||
}
|
||||
|
||||
public static LocalDate getFirstRepaymentMeetingDate(final Calendar calendar, final LocalDate disbursementDate,
|
||||
final Integer loanRepaymentInterval, final String frequency, boolean isSkipRepaymentOnFirstDayOfMonth,
|
||||
final Integer numberOfDays) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(calendar.getRecurrence());
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
LocalDate startDate = disbursementDate;
|
||||
final LocalDate seedDate = calendar.getStartDateLocalDate();
|
||||
if (isValidRedurringDate(calendar.getRecurrence(), seedDate, startDate, isSkipRepaymentOnFirstDayOfMonth, numberOfDays)
|
||||
&& !frequency.equals(Recur.Frequency.DAILY.name())) {
|
||||
startDate = startDate.plusDays(1);
|
||||
}
|
||||
// Recurring dates should follow loanRepaymentInterval.
|
||||
// e.g.
|
||||
// for weekly meeting interval is 1
|
||||
// where as for loan product with fortnightly frequency interval is 2
|
||||
// to generate currect set of meeting dates reset interval same as loan
|
||||
// repayment interval.
|
||||
|
||||
Recur.Builder recurBuilder = getRecurBuilder(recur);
|
||||
recurBuilder = recurBuilder.interval(loanRepaymentInterval);
|
||||
|
||||
// Recurring dates should follow loanRepayment frequency.
|
||||
// e.g.
|
||||
// daily meeting frequency should support all loan products with any
|
||||
// frequency type.
|
||||
// to generate currect set of meeting dates reset frequency same as loan
|
||||
// repayment frequency.
|
||||
|
||||
if (recur.getFrequency().equals(Recur.Frequency.DAILY)) {
|
||||
recurBuilder = recurBuilder.frequency(Recur.Frequency.valueOf(frequency));
|
||||
}
|
||||
|
||||
Recur modifiedRecur = recurBuilder.build();
|
||||
final LocalDate firstRepaymentDate = getNextRecurringDate(modifiedRecur, seedDate, startDate);
|
||||
if (isSkipRepaymentOnFirstDayOfMonth && firstRepaymentDate.getDayOfMonth() == 1) {
|
||||
return adjustRecurringDate(firstRepaymentDate, numberOfDays);
|
||||
}
|
||||
|
||||
return firstRepaymentDate;
|
||||
}
|
||||
|
||||
public static LocalDate getNewRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate,
|
||||
final LocalDate oldRepaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays,
|
||||
final boolean isSkipRepaymentOnFirstDayOfMonth, final Integer numberOfDays) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
if (isValidRecurringDate(recur, seedDate, oldRepaymentDate, isSkipRepaymentOnFirstDayOfMonth, numberOfDays)) {
|
||||
return oldRepaymentDate;
|
||||
}
|
||||
LocalDate nextRepaymentDate = getNextRepaymentMeetingDate(recurringRule, seedDate, oldRepaymentDate, loanRepaymentInterval,
|
||||
frequency, workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays);
|
||||
|
||||
return nextRepaymentDate;
|
||||
}
|
||||
|
||||
public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate repaymentDate,
|
||||
final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays,
|
||||
boolean isSkipRepaymentOnFirstDayOfMonth, final Integer numberOfDays) {
|
||||
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
LocalDate tmpDate = repaymentDate;
|
||||
if (isValidRecurringDate(recur, seedDate, repaymentDate, isSkipRepaymentOnFirstDayOfMonth, numberOfDays)) {
|
||||
tmpDate = repaymentDate.plusDays(1);
|
||||
}
|
||||
/*
|
||||
* Recurring dates should follow loanRepaymentInterval.
|
||||
*
|
||||
* e.g. The weekly meeting will have interval of 1, if the loan product with fortnightly frequency will have
|
||||
* interval of 2, to generate right set of meeting dates reset interval same as loan repayment interval.
|
||||
*/
|
||||
|
||||
Recur.Builder recurBuilder = getRecurBuilder(recur);
|
||||
|
||||
recurBuilder = recurBuilder.interval(loanRepaymentInterval);
|
||||
|
||||
/*
|
||||
* Recurring dates should follow loanRepayment frequency. //e.g. daily meeting frequency should support all loan
|
||||
* products with any type of frequency. to generate right set of meeting dates reset frequency same as loan
|
||||
* repayment frequency.
|
||||
*/
|
||||
|
||||
if (recur.getFrequency().equals(Recur.Frequency.DAILY)) {
|
||||
recurBuilder = recurBuilder.frequency(Recur.Frequency.valueOf(frequency));
|
||||
}
|
||||
|
||||
Recur modifiedRecur = recurBuilder.build();
|
||||
|
||||
LocalDate newRepaymentDate = getNextRecurringDate(modifiedRecur, seedDate, tmpDate);
|
||||
final LocalDate nextRepaymentDate = getNextRecurringDate(modifiedRecur, seedDate, newRepaymentDate);
|
||||
|
||||
newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDate, nextRepaymentDate, workingDays);
|
||||
if (isSkipRepaymentOnFirstDayOfMonth) {
|
||||
LocalDate newRepaymentDateTemp = adjustRecurringDate(newRepaymentDate, numberOfDays);
|
||||
return WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDateTemp, nextRepaymentDate, workingDays);
|
||||
}
|
||||
|
||||
return newRepaymentDate;
|
||||
}
|
||||
|
||||
public static boolean isFrequencySame(final String oldRRule, final String newRRule) {
|
||||
final Recur oldRecur = getICalRecur(oldRRule);
|
||||
final Recur newRecur = getICalRecur(newRRule);
|
||||
|
||||
if (oldRecur == null || oldRecur.getFrequency() == null || newRecur == null || newRecur.getFrequency() == null) {
|
||||
return false;
|
||||
}
|
||||
return oldRecur.getFrequency().equals(newRecur.getFrequency());
|
||||
}
|
||||
|
||||
public static boolean isIntervalSame(final String oldRRule, final String newRRule) {
|
||||
final Recur oldRecur = getICalRecur(oldRRule);
|
||||
final Recur newRecur = getICalRecur(newRRule);
|
||||
|
||||
if (oldRecur == null || oldRecur.getFrequency() == null || newRecur == null || newRecur.getFrequency() == null) {
|
||||
return false;
|
||||
}
|
||||
return (oldRecur.getInterval() == newRecur.getInterval());
|
||||
}
|
||||
|
||||
public static List<Integer> createIntegerListFromQueryParameter(final String calendarTypeQuery) {
|
||||
final List<Integer> calendarTypeOptions = new ArrayList<>();
|
||||
// adding all calendar Types if query parameter is "all"
|
||||
if (calendarTypeQuery.equalsIgnoreCase("all")) {
|
||||
calendarTypeOptions.add(1);
|
||||
calendarTypeOptions.add(2);
|
||||
calendarTypeOptions.add(3);
|
||||
calendarTypeOptions.add(4);
|
||||
return calendarTypeOptions;
|
||||
}
|
||||
// creating a list of calendar type options from the comma separated
|
||||
// query parameter.
|
||||
final List<String> calendarTypeOptionsInQuery = new ArrayList<>();
|
||||
final StringTokenizer st = new StringTokenizer(calendarTypeQuery, ",");
|
||||
while (st.hasMoreElements()) {
|
||||
calendarTypeOptionsInQuery.add(st.nextElement().toString());
|
||||
}
|
||||
|
||||
for (final String calType : calendarTypeOptionsInQuery) {
|
||||
if (calType.equalsIgnoreCase("collection")) {
|
||||
calendarTypeOptions.add(1);
|
||||
} else if (calType.equalsIgnoreCase("training")) {
|
||||
calendarTypeOptions.add(2);
|
||||
} else if (calType.equalsIgnoreCase("audit")) {
|
||||
calendarTypeOptions.add(3);
|
||||
} else if (calType.equalsIgnoreCase("general")) {
|
||||
calendarTypeOptions.add(4);
|
||||
}
|
||||
}
|
||||
|
||||
return calendarTypeOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* function returns a comma separated list of calendar_type_enum values ex. 1,2,3,4
|
||||
*
|
||||
* @param calendarTypeOptions
|
||||
* @return
|
||||
*/
|
||||
public static String getSqlCalendarTypeOptionsInString(final List<Integer> calendarTypeOptions) {
|
||||
String sqlCalendarTypeOptions = "";
|
||||
final int size = calendarTypeOptions.size();
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
sqlCalendarTypeOptions += calendarTypeOptions.get(i).toString() + ",";
|
||||
}
|
||||
sqlCalendarTypeOptions += calendarTypeOptions.get(size - 1).toString();
|
||||
return sqlCalendarTypeOptions;
|
||||
}
|
||||
|
||||
public static LocalDate getRecentEligibleMeetingDate(final String recurringRule, final LocalDate seedDate,
|
||||
final boolean isSkipMeetingOnFirstDay, final Integer numberOfDays) {
|
||||
LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isValidRecurringDate(recur, seedDate, currentDate, isSkipMeetingOnFirstDay, numberOfDays)) {
|
||||
return currentDate;
|
||||
}
|
||||
|
||||
if (recur.getFrequency().equals(Recur.Frequency.DAILY)) {
|
||||
currentDate = currentDate.plusDays(recur.getInterval());
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.WEEKLY)) {
|
||||
currentDate = currentDate.plusWeeks(recur.getInterval());
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.MONTHLY)) {
|
||||
currentDate = currentDate.plusMonths(recur.getInterval());
|
||||
} else if (recur.getFrequency().equals(Recur.Frequency.YEARLY)) {
|
||||
currentDate = currentDate.plusYears(recur.getInterval());
|
||||
}
|
||||
|
||||
return getNextRecurringDate(recur, seedDate, currentDate);
|
||||
}
|
||||
|
||||
public static LocalDate getNextScheduleDate(final Calendar calendar, final LocalDate startDate) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(calendar.getRecurrence());
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
LocalDate date = startDate;
|
||||
final LocalDate seedDate = calendar.getStartDateLocalDate();
|
||||
/**
|
||||
* if (isValidRedurringDate(calendar.getRecurrence(), seedDate, date)) { date = date.plusDays(1); }
|
||||
**/
|
||||
|
||||
final LocalDate scheduleDate = getNextRecurringDate(recur, seedDate, date);
|
||||
|
||||
return scheduleDate;
|
||||
}
|
||||
|
||||
public static void validateNthDayOfMonthFrequency(DataValidatorBuilder baseDataValidator, final String repeatsOnNthDayOfMonthParamName,
|
||||
final String repeatsOnDayParamName, final JsonElement element, final FromJsonHelper fromApiJsonHelper) {
|
||||
final Integer repeatsOnNthDayOfMonth = fromApiJsonHelper.extractIntegerSansLocaleNamed(repeatsOnNthDayOfMonthParamName, element);
|
||||
baseDataValidator.reset().parameter(repeatsOnNthDayOfMonthParamName).value(repeatsOnNthDayOfMonth).ignoreIfNull()
|
||||
.isOneOfTheseValues(NthDayType.ONE.getValue(), NthDayType.TWO.getValue(), NthDayType.THREE.getValue(),
|
||||
NthDayType.FOUR.getValue(), NthDayType.LAST.getValue(), NthDayType.ONDAY.getValue());
|
||||
final Integer repeatsOnDay = fromApiJsonHelper.extractIntegerSansLocaleNamed(repeatsOnDayParamName, element);
|
||||
baseDataValidator.reset().parameter(repeatsOnDayParamName).value(repeatsOnDay).ignoreIfNull()
|
||||
.inMinMaxRange(CalendarWeekDaysType.getMinValue(), CalendarWeekDaysType.getMaxValue());
|
||||
NthDayType nthDayType = null;
|
||||
if (repeatsOnNthDayOfMonth != null) {
|
||||
nthDayType = NthDayType.fromInt(repeatsOnNthDayOfMonth);
|
||||
}
|
||||
if (nthDayType != null && nthDayType != NthDayType.INVALID) {
|
||||
if (nthDayType == NthDayType.ONE || nthDayType == NthDayType.TWO || nthDayType == NthDayType.THREE
|
||||
|| nthDayType == NthDayType.FOUR) {
|
||||
baseDataValidator.reset().parameter(repeatsOnDayParamName).value(repeatsOnDay).cantBeBlankWhenParameterProvidedIs(
|
||||
repeatsOnNthDayOfMonthParamName, NthDayNameEnum.from(nthDayType.toString()).getCode().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Integer getMonthOnDay(String recurringRule) {
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
NumberList monthDayList = null;
|
||||
Integer monthOnDay = null;
|
||||
if (getMeetingPeriodFrequencyType(recur).isMonthly()) {
|
||||
monthDayList = recur.getMonthDayList();
|
||||
if (!monthDayList.isEmpty()) {
|
||||
monthOnDay = monthDayList.get(0);
|
||||
}
|
||||
}
|
||||
return monthOnDay;
|
||||
}
|
||||
|
||||
public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate repaymentDate,
|
||||
final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays,
|
||||
boolean isSkipRepaymentOnFirstDayOfMonth, final Integer numberOfDays, boolean applyWorkingDays) {
|
||||
boolean isCalledFirstTime = true;
|
||||
return getNextRepaymentMeetingDate(recurringRule, seedDate, repaymentDate, loanRepaymentInterval, frequency, workingDays,
|
||||
isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime, applyWorkingDays);
|
||||
}
|
||||
|
||||
public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate repaymentDate,
|
||||
final Integer loanRepaymentInterval, final String frequency, boolean isSkipRepaymentOnFirstDayOfMonth,
|
||||
final Integer numberOfDays) {
|
||||
boolean isCalledFirstTime = true;
|
||||
final WorkingDays workingDays = null;
|
||||
boolean applyWorkingDays = false;
|
||||
return getNextRepaymentMeetingDate(recurringRule, seedDate, repaymentDate, loanRepaymentInterval, frequency, workingDays,
|
||||
isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime, applyWorkingDays);
|
||||
}
|
||||
|
||||
public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate repaymentDate,
|
||||
final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays,
|
||||
boolean isSkipRepaymentOnFirstDayOfMonth, final Integer numberOfDays, boolean isCalledFirstTime, boolean applyWorkingDays) {
|
||||
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) {
|
||||
return null;
|
||||
}
|
||||
LocalDate tmpDate = repaymentDate;
|
||||
|
||||
final Integer repaymentInterval = getMeetingIntervalFromFrequency(loanRepaymentInterval, frequency, recur);
|
||||
/*
|
||||
* Recurring dates should follow loanRepaymentInterval.
|
||||
*
|
||||
* e.g. The weekly meeting will have interval of 1, if the loan product with fortnightly frequency will have
|
||||
* interval of 2, to generate right set of meeting dates reset interval same as loan repayment interval.
|
||||
*/
|
||||
int meetingInterval = recur.getInterval();
|
||||
if (meetingInterval < 1) {
|
||||
meetingInterval = 1;
|
||||
}
|
||||
int rep = repaymentInterval < meetingInterval ? 1 : repaymentInterval / meetingInterval;
|
||||
|
||||
/*
|
||||
* Recurring dates should follow loanRepayment frequency. //e.g. daily meeting frequency should support all loan
|
||||
* products with any type of frequency. to generate right set of meeting dates reset frequency same as loan
|
||||
* repayment frequency.
|
||||
*/
|
||||
|
||||
Recur.Builder recurBuilder = getRecurBuilder(recur);
|
||||
|
||||
if (recur.getFrequency().equals(Recur.Frequency.DAILY)) {
|
||||
recurBuilder = recurBuilder.frequency(Recur.Frequency.valueOf(frequency));
|
||||
}
|
||||
|
||||
Recur modifiedRecur = recurBuilder.build();
|
||||
|
||||
/**
|
||||
* Below code modified as discussed with Pramod N
|
||||
*/
|
||||
LocalDate newRepaymentDate = tmpDate;
|
||||
int newRepayment = rep;
|
||||
while (newRepayment > 0) {
|
||||
newRepaymentDate = getNextRecurringDate(modifiedRecur, seedDate, newRepaymentDate);
|
||||
newRepayment--;
|
||||
}
|
||||
|
||||
LocalDate nextRepaymentDate = null;
|
||||
if (applyWorkingDays) {
|
||||
if (WorkingDaysUtil.isNonWorkingDay(workingDays, newRepaymentDate)
|
||||
&& WorkingDaysUtil.getRepaymentRescheduleType(workingDays, newRepaymentDate).isMoveToNextRepaymentDay()) {
|
||||
newRepaymentDate = getNextRepaymentMeetingDate(recurringRule, seedDate, newRepaymentDate.plusDays(1), loanRepaymentInterval,
|
||||
frequency, workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime, applyWorkingDays);
|
||||
} else {
|
||||
newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDate, nextRepaymentDate, workingDays);
|
||||
}
|
||||
}
|
||||
|
||||
if (isCalledFirstTime && newRepaymentDate.equals(repaymentDate)) {
|
||||
isCalledFirstTime = false;
|
||||
newRepaymentDate = getNextRepaymentMeetingDate(recurringRule, seedDate, repaymentDate.plusDays(1), loanRepaymentInterval,
|
||||
frequency, workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime, applyWorkingDays);
|
||||
}
|
||||
|
||||
if (isSkipRepaymentOnFirstDayOfMonth) {
|
||||
final LocalDate newRepaymentDateTemp = adjustRecurringDate(newRepaymentDate, numberOfDays);
|
||||
if (applyWorkingDays) {
|
||||
if (WorkingDaysUtil.isNonWorkingDay(workingDays, newRepaymentDateTemp)
|
||||
&& WorkingDaysUtil.getRepaymentRescheduleType(workingDays, newRepaymentDateTemp).isMoveToNextRepaymentDay()) {
|
||||
newRepaymentDate = getNextRepaymentMeetingDate(recurringRule, seedDate, newRepaymentDate.plusDays(1),
|
||||
loanRepaymentInterval, frequency, workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays,
|
||||
isCalledFirstTime, applyWorkingDays);
|
||||
} else {
|
||||
newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDateTemp, nextRepaymentDate, workingDays);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newRepaymentDate;
|
||||
}
|
||||
|
||||
public static Integer getMeetingIntervalFromFrequency(final Integer loanRepaymentInterval, final String frequency, final Recur recur) {
|
||||
final Integer interval = 4;
|
||||
Integer repaymentInterval = loanRepaymentInterval;
|
||||
/*
|
||||
* check loanRepaymentInterval equal to 1, if repayments frequency is monthly and meeting frequency is weekly,
|
||||
* then generate repayments schedule as every 4 weeks
|
||||
*/
|
||||
if (frequency.equals(Recur.Frequency.MONTHLY.name()) && recur.getFrequency().equals(Recur.Frequency.WEEKLY)) {
|
||||
repaymentInterval = loanRepaymentInterval * interval;
|
||||
}
|
||||
return repaymentInterval;
|
||||
}
|
||||
|
||||
private static Recur.Builder getRecurBuilder(Recur recur) {
|
||||
Recur.Builder recurBuilder = new Recur.Builder();
|
||||
recurBuilder = recurBuilder.frequency(recur.getFrequency()).until(recur.getUntil()).count(recur.getCount())
|
||||
.interval(recur.getInterval()).secondList(recur.getSecondList()).minuteList(recur.getMinuteList())
|
||||
.hourList(recur.getHourList()).dayList(recur.getDayList()).monthDayList(recur.getMonthDayList())
|
||||
.yearDayList(recur.getYearDayList()).weekNoList(recur.getWeekNoList()).monthList(recur.getMonthList())
|
||||
.setPosList(recur.getSetPosList()).weekStartDay(recur.getWeekStartDay());
|
||||
return recurBuilder;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.charge.api;
|
||||
|
||||
public final class ChargesApiConstants {
|
||||
|
||||
private ChargesApiConstants() {
|
||||
|
||||
}
|
||||
|
||||
public static final String glAccountIdParamName = "incomeAccountId";
|
||||
public static final String taxGroupIdParamName = "taxGroupId";
|
||||
|
||||
}
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* 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.charge.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.MonthDay;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
|
||||
/**
|
||||
* Immutable data object for charge data.
|
||||
*/
|
||||
@Getter
|
||||
public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final String name;
|
||||
private final boolean active;
|
||||
private final boolean penalty;
|
||||
private final boolean freeWithdrawal;
|
||||
private final Integer freeWithdrawalChargeFrequency;
|
||||
private final Integer restartFrequency;
|
||||
private final Integer restartFrequencyEnum;
|
||||
private final boolean isPaymentType;
|
||||
private final PaymentTypeData paymentTypeOptions;
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal amount;
|
||||
private final EnumOptionData chargeTimeType;
|
||||
private final EnumOptionData chargeAppliesTo;
|
||||
private final EnumOptionData chargeCalculationType;
|
||||
private final EnumOptionData chargePaymentMode;
|
||||
private final MonthDay feeOnMonthDay;
|
||||
private final Integer feeInterval;
|
||||
private final BigDecimal minCap;
|
||||
private final BigDecimal maxCap;
|
||||
private final EnumOptionData feeFrequency;
|
||||
private final GLAccountData incomeOrLiabilityAccount;
|
||||
private final TaxGroupData taxGroup;
|
||||
|
||||
// template attributes
|
||||
private final Collection<CurrencyData> currencyOptions;
|
||||
private final List<EnumOptionData> chargeCalculationTypeOptions;//
|
||||
private final List<EnumOptionData> chargeAppliesToOptions;//
|
||||
private final List<EnumOptionData> chargeTimeTypeOptions;//
|
||||
private final List<EnumOptionData> chargePaymetModeOptions;//
|
||||
|
||||
private final List<EnumOptionData> loanChargeCalculationTypeOptions;
|
||||
private final List<EnumOptionData> loanChargeTimeTypeOptions;
|
||||
private final List<EnumOptionData> savingsChargeCalculationTypeOptions;
|
||||
private final List<EnumOptionData> savingsChargeTimeTypeOptions;
|
||||
private final List<EnumOptionData> clientChargeCalculationTypeOptions;
|
||||
private final List<EnumOptionData> clientChargeTimeTypeOptions;
|
||||
private final List<EnumOptionData> shareChargeCalculationTypeOptions;
|
||||
private final List<EnumOptionData> shareChargeTimeTypeOptions;
|
||||
|
||||
private final List<EnumOptionData> feeFrequencyOptions;
|
||||
|
||||
private final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions;
|
||||
private final Collection<TaxGroupData> taxGroupOptions;
|
||||
|
||||
private final String accountMappingForChargeConfig;
|
||||
private final List<GLAccountData> expenseAccountOptions;
|
||||
private final List<GLAccountData> assetAccountOptions;
|
||||
|
||||
public static ChargeData template(final Collection<CurrencyData> currencyOptions,
|
||||
final List<EnumOptionData> chargeCalculationTypeOptions, final List<EnumOptionData> chargeAppliesToOptions,
|
||||
final List<EnumOptionData> chargeTimeTypeOptions, final List<EnumOptionData> chargePaymentModeOptions,
|
||||
final List<EnumOptionData> loansChargeCalculationTypeOptions, final List<EnumOptionData> loansChargeTimeTypeOptions,
|
||||
final List<EnumOptionData> savingsChargeCalculationTypeOptions, final List<EnumOptionData> savingsChargeTimeTypeOptions,
|
||||
final List<EnumOptionData> clientChargeCalculationTypeOptions, final List<EnumOptionData> clientChargeTimeTypeOptions,
|
||||
final List<EnumOptionData> feeFrequencyOptions, final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions,
|
||||
final Collection<TaxGroupData> taxGroupOptions, final List<EnumOptionData> shareChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions, String accountMappingForChargeConfig,
|
||||
List<GLAccountData> expenseAccountOptions, List<GLAccountData> assetAccountOptions) {
|
||||
final GLAccountData account = null;
|
||||
final TaxGroupData taxGroupData = null;
|
||||
|
||||
return new ChargeData(null, null, null, null, null, null, null, null, false, false, false, null, null, null, false, null,
|
||||
taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
|
||||
chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, null, null, null, null, null, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions,
|
||||
taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig,
|
||||
expenseAccountOptions, assetAccountOptions);
|
||||
}
|
||||
|
||||
public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) {
|
||||
return new ChargeData(charge.id, charge.name, charge.amount, charge.currency, charge.chargeTimeType, charge.chargeAppliesTo,
|
||||
charge.chargeCalculationType, charge.chargePaymentMode, charge.penalty, charge.active, charge.freeWithdrawal,
|
||||
charge.freeWithdrawalChargeFrequency, charge.restartFrequency, charge.restartFrequencyEnum, charge.isPaymentType,
|
||||
charge.paymentTypeOptions, charge.taxGroup, template.currencyOptions, template.chargeCalculationTypeOptions,
|
||||
template.chargeAppliesToOptions, template.chargeTimeTypeOptions, template.chargePaymetModeOptions,
|
||||
template.loanChargeCalculationTypeOptions, template.loanChargeTimeTypeOptions, template.savingsChargeCalculationTypeOptions,
|
||||
template.savingsChargeTimeTypeOptions, template.clientChargeCalculationTypeOptions, template.clientChargeTimeTypeOptions,
|
||||
charge.feeOnMonthDay, charge.feeInterval, charge.minCap, charge.maxCap, charge.feeFrequency, template.feeFrequencyOptions,
|
||||
charge.incomeOrLiabilityAccount, template.incomeOrLiabilityAccountOptions, template.taxGroupOptions,
|
||||
template.shareChargeCalculationTypeOptions, template.shareChargeTimeTypeOptions, template.accountMappingForChargeConfig,
|
||||
template.expenseAccountOptions, template.assetAccountOptions);
|
||||
}
|
||||
|
||||
public static ChargeData instance(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
|
||||
final EnumOptionData chargeTimeType, final EnumOptionData chargeAppliesTo, final EnumOptionData chargeCalculationType,
|
||||
final EnumOptionData chargePaymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final boolean penalty,
|
||||
final boolean active, final boolean freeWithdrawal, final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency,
|
||||
final Integer restartFrequencyEnum, final boolean isPaymentType, final PaymentTypeData paymentTypeOptions,
|
||||
final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency, final GLAccountData accountData,
|
||||
TaxGroupData taxGroupData) {
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final List<EnumOptionData> chargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> chargeAppliesToOptions = null;
|
||||
final List<EnumOptionData> chargeTimeTypeOptions = null;
|
||||
final List<EnumOptionData> chargePaymentModeOptions = null;
|
||||
final List<EnumOptionData> loansChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> loansChargeTimeTypeOptions = null;
|
||||
final List<EnumOptionData> savingsChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> savingsChargeTimeTypeOptions = null;
|
||||
final List<EnumOptionData> feeFrequencyOptions = null;
|
||||
final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> clientChargeTimeTypeOptions = null;
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions = null;
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions = null;
|
||||
final Collection<TaxGroupData> taxGroupOptions = null;
|
||||
final String accountMappingForChargeConfig = null;
|
||||
final List<GLAccountData> expenseAccountOptions = null;
|
||||
final List<GLAccountData> assetAccountOptions = null;
|
||||
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
|
||||
penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, isPaymentType,
|
||||
paymentTypeOptions, taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions,
|
||||
chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions,
|
||||
accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions);
|
||||
}
|
||||
|
||||
public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) {
|
||||
final BigDecimal amount = null;
|
||||
final CurrencyData currency = null;
|
||||
final EnumOptionData chargeTimeType = null;
|
||||
final EnumOptionData chargeAppliesTo = null;
|
||||
final EnumOptionData chargeCalculationType = null;
|
||||
final EnumOptionData chargePaymentMode = null;
|
||||
final MonthDay feeOnMonthDay = null;
|
||||
final Integer feeInterval = null;
|
||||
final Boolean penalty = isPenalty;
|
||||
final Boolean active = false;
|
||||
final Boolean freeWithdrawal = false;
|
||||
final Integer freeWithdrawalChargeFrequency = null;
|
||||
final Integer restartFrequency = null;
|
||||
final Integer restartFrequencyEnum = null;
|
||||
final Boolean isPaymentType = false;
|
||||
final PaymentTypeData paymentTypeOptions = null;
|
||||
final BigDecimal minCap = null;
|
||||
final BigDecimal maxCap = null;
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final List<EnumOptionData> chargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> chargeAppliesToOptions = null;
|
||||
final List<EnumOptionData> chargeTimeTypeOptions = null;
|
||||
final List<EnumOptionData> chargePaymentModeOptions = null;
|
||||
final List<EnumOptionData> loansChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> loansChargeTimeTypeOptions = null;
|
||||
final List<EnumOptionData> savingsChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> savingsChargeTimeTypeOptions = null;
|
||||
final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> clientChargeTimeTypeOptions = null;
|
||||
final EnumOptionData feeFrequency = null;
|
||||
final List<EnumOptionData> feeFrequencyOptions = null;
|
||||
final GLAccountData account = null;
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions = null;
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions = null;
|
||||
final TaxGroupData taxGroupData = null;
|
||||
final Collection<TaxGroupData> taxGroupOptions = null;
|
||||
final String accountMappingForChargeConfig = null;
|
||||
final List<GLAccountData> expenseAccountOptions = null;
|
||||
final List<GLAccountData> assetAccountOptions = null;
|
||||
|
||||
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
|
||||
penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, isPaymentType,
|
||||
paymentTypeOptions, taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions,
|
||||
chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, account,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions,
|
||||
accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions);
|
||||
}
|
||||
|
||||
private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
|
||||
final EnumOptionData chargeTimeType, final EnumOptionData chargeAppliesTo, final EnumOptionData chargeCalculationType,
|
||||
final EnumOptionData chargePaymentMode, final boolean penalty, final boolean active, final boolean freeWithdrawal,
|
||||
final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency, final Integer restartFrequencyEnum,
|
||||
final boolean isPaymentType, final PaymentTypeData paymentTypeOptions, final TaxGroupData taxGroupData,
|
||||
final Collection<CurrencyData> currencyOptions, final List<EnumOptionData> chargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> chargeAppliesToOptions, final List<EnumOptionData> chargeTimeTypeOptions,
|
||||
final List<EnumOptionData> chargePaymentModeOptions, final List<EnumOptionData> loansChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> loansChargeTimeTypeOptions, final List<EnumOptionData> savingsChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> savingsChargeTimeTypeOptions, final List<EnumOptionData> clientChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> clientChargeTimeTypeOptions, final MonthDay feeOnMonthDay, final Integer feeInterval,
|
||||
final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
|
||||
final List<EnumOptionData> feeFrequencyOptions, final GLAccountData account,
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions, final Collection<TaxGroupData> taxGroupOptions,
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions, final List<EnumOptionData> shareChargeTimeTypeOptions,
|
||||
final String accountMappingForChargeConfig, final List<GLAccountData> expenseAccountOptions,
|
||||
final List<GLAccountData> assetAccountOptions) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.amount = amount;
|
||||
this.currency = currency;
|
||||
this.chargeTimeType = chargeTimeType;
|
||||
this.chargeAppliesTo = chargeAppliesTo;
|
||||
this.chargeCalculationType = chargeCalculationType;
|
||||
this.chargePaymentMode = chargePaymentMode;
|
||||
this.feeInterval = feeInterval;
|
||||
this.feeOnMonthDay = feeOnMonthDay;
|
||||
this.penalty = penalty;
|
||||
this.active = active;
|
||||
this.freeWithdrawal = freeWithdrawal;
|
||||
this.freeWithdrawalChargeFrequency = freeWithdrawalChargeFrequency;
|
||||
this.restartFrequency = restartFrequency;
|
||||
this.restartFrequencyEnum = restartFrequencyEnum;
|
||||
this.isPaymentType = isPaymentType;
|
||||
this.paymentTypeOptions = paymentTypeOptions;
|
||||
this.minCap = minCap;
|
||||
this.maxCap = maxCap;
|
||||
this.currencyOptions = currencyOptions;
|
||||
this.chargeCalculationTypeOptions = chargeCalculationTypeOptions;
|
||||
this.chargeAppliesToOptions = chargeAppliesToOptions;
|
||||
this.chargeTimeTypeOptions = chargeTimeTypeOptions;
|
||||
this.chargePaymetModeOptions = chargePaymentModeOptions;
|
||||
this.savingsChargeCalculationTypeOptions = savingsChargeCalculationTypeOptions;
|
||||
this.savingsChargeTimeTypeOptions = savingsChargeTimeTypeOptions;
|
||||
this.clientChargeCalculationTypeOptions = clientChargeCalculationTypeOptions;
|
||||
this.clientChargeTimeTypeOptions = clientChargeTimeTypeOptions;
|
||||
this.loanChargeCalculationTypeOptions = loansChargeCalculationTypeOptions;
|
||||
this.loanChargeTimeTypeOptions = loansChargeTimeTypeOptions;
|
||||
this.feeFrequency = feeFrequency;
|
||||
this.feeFrequencyOptions = feeFrequencyOptions;
|
||||
this.incomeOrLiabilityAccount = account;
|
||||
this.incomeOrLiabilityAccountOptions = incomeOrLiabilityAccountOptions;
|
||||
this.taxGroup = taxGroupData;
|
||||
this.taxGroupOptions = taxGroupOptions;
|
||||
this.shareChargeCalculationTypeOptions = shareChargeCalculationTypeOptions;
|
||||
this.shareChargeTimeTypeOptions = shareChargeTimeTypeOptions;
|
||||
this.accountMappingForChargeConfig = accountMappingForChargeConfig;
|
||||
this.assetAccountOptions = assetAccountOptions;
|
||||
this.expenseAccountOptions = expenseAccountOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof ChargeData)) {
|
||||
return false;
|
||||
}
|
||||
final ChargeData chargeData = (ChargeData) obj;
|
||||
return this.id.equals(chargeData.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ChargeData obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return obj.id.compareTo(this.id);
|
||||
}
|
||||
|
||||
public boolean isOverdueInstallmentCharge() {
|
||||
boolean isOverdueInstallmentCharge = false;
|
||||
if (this.chargeTimeType != null) {
|
||||
isOverdueInstallmentCharge = ChargeTimeType.fromInt(this.chargeTimeType.getId().intValue()).isOverdueInstallment();
|
||||
}
|
||||
return isOverdueInstallmentCharge;
|
||||
}
|
||||
|
||||
public boolean isIsPaymentType() {
|
||||
return this.isPaymentType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,783 @@
|
||||
/**
|
||||
* 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.charge.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
|
||||
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.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.charge.api.ChargesApiConstants;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeDueAtDisbursementCannotBePenaltyException;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeMustBePenaltyException;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeParameterUpdateNotSupportedException;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.paymenttype.domain.PaymentType;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroup;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_charge", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "name") })
|
||||
public class Charge extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "name", length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "currency_code", length = 3)
|
||||
private String currencyCode;
|
||||
|
||||
@Column(name = "charge_applies_to_enum", nullable = false)
|
||||
private Integer chargeAppliesTo;
|
||||
|
||||
@Column(name = "charge_time_enum", nullable = false)
|
||||
private Integer chargeTimeType;
|
||||
|
||||
@Column(name = "charge_calculation_enum")
|
||||
private Integer chargeCalculation;
|
||||
|
||||
@Column(name = "charge_payment_mode_enum", nullable = true)
|
||||
private Integer chargePaymentMode;
|
||||
|
||||
@Column(name = "fee_on_day", nullable = true)
|
||||
private Integer feeOnDay;
|
||||
|
||||
@Column(name = "fee_interval", nullable = true)
|
||||
private Integer feeInterval;
|
||||
|
||||
@Column(name = "fee_on_month", nullable = true)
|
||||
private Integer feeOnMonth;
|
||||
|
||||
@Column(name = "is_penalty", nullable = false)
|
||||
private boolean penalty;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private boolean active;
|
||||
|
||||
@Column(name = "is_deleted", nullable = false)
|
||||
private boolean deleted = false;
|
||||
|
||||
@Column(name = "min_cap", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minCap;
|
||||
|
||||
@Column(name = "max_cap", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal maxCap;
|
||||
|
||||
@Column(name = "fee_frequency", nullable = true)
|
||||
private Integer feeFrequency;
|
||||
|
||||
@Column(name = "is_free_withdrawal", nullable = false)
|
||||
private boolean enableFreeWithdrawal;
|
||||
|
||||
@Column(name = "free_withdrawal_charge_frequency", nullable = true)
|
||||
private Integer freeWithdrawalFrequency;
|
||||
|
||||
@Column(name = "restart_frequency", nullable = true)
|
||||
private Integer restartFrequency;
|
||||
|
||||
@Column(name = "restart_frequency_enum", nullable = true)
|
||||
private Integer restartFrequencyEnum;
|
||||
|
||||
@Column(name = "is_payment_type", nullable = false)
|
||||
private boolean enablePaymentType;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "payment_type_id", nullable = false)
|
||||
private PaymentType paymentType;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "income_or_liability_account_id")
|
||||
private GLAccount account;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "tax_group_id")
|
||||
private TaxGroup taxGroup;
|
||||
|
||||
public static Charge fromJson(final JsonCommand command, final GLAccount account, final TaxGroup taxGroup,
|
||||
final PaymentType paymentType) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
|
||||
final ChargeAppliesTo chargeAppliesTo = ChargeAppliesTo.fromInt(command.integerValueOfParameterNamed("chargeAppliesTo"));
|
||||
final ChargeTimeType chargeTimeType = ChargeTimeType.fromInt(command.integerValueOfParameterNamed("chargeTimeType"));
|
||||
final ChargeCalculationType chargeCalculationType = ChargeCalculationType
|
||||
.fromInt(command.integerValueOfParameterNamed("chargeCalculationType"));
|
||||
final Integer chargePaymentMode = command.integerValueOfParameterNamed("chargePaymentMode");
|
||||
|
||||
final ChargePaymentMode paymentMode = chargePaymentMode == null ? null : ChargePaymentMode.fromInt(chargePaymentMode);
|
||||
|
||||
final boolean penalty = command.booleanPrimitiveValueOfParameterNamed("penalty");
|
||||
final boolean active = command.booleanPrimitiveValueOfParameterNamed("active");
|
||||
final MonthDay feeOnMonthDay = command.extractMonthDayNamed("feeOnMonthDay");
|
||||
final Integer feeInterval = command.integerValueOfParameterNamed("feeInterval");
|
||||
final BigDecimal minCap = command.bigDecimalValueOfParameterNamed("minCap");
|
||||
final BigDecimal maxCap = command.bigDecimalValueOfParameterNamed("maxCap");
|
||||
final Integer feeFrequency = command.integerValueOfParameterNamed("feeFrequency");
|
||||
|
||||
boolean enableFreeWithdrawalCharge = false;
|
||||
enableFreeWithdrawalCharge = command.booleanPrimitiveValueOfParameterNamed("enableFreeWithdrawalCharge");
|
||||
|
||||
boolean enablePaymentType = false;
|
||||
enablePaymentType = command.booleanPrimitiveValueOfParameterNamed("enablePaymentType");
|
||||
|
||||
Integer freeWithdrawalFrequency = null;
|
||||
Integer restartCountFrequency = null;
|
||||
PeriodFrequencyType countFrequencyType = null;
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
freeWithdrawalFrequency = command.integerValueOfParameterNamed("freeWithdrawalFrequency");
|
||||
restartCountFrequency = command.integerValueOfParameterNamed("restartCountFrequency");
|
||||
|
||||
countFrequencyType = PeriodFrequencyType.fromInt(command.integerValueOfParameterNamed("countFrequencyType"));
|
||||
}
|
||||
|
||||
return new Charge(name, amount, currencyCode, chargeAppliesTo, chargeTimeType, chargeCalculationType, penalty, active, paymentMode,
|
||||
feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, enableFreeWithdrawalCharge, freeWithdrawalFrequency,
|
||||
restartCountFrequency, countFrequencyType, account, taxGroup, enablePaymentType, paymentType);
|
||||
}
|
||||
|
||||
protected Charge() {}
|
||||
|
||||
private Charge(final String name, final BigDecimal amount, final String currencyCode, final ChargeAppliesTo chargeAppliesTo,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, final boolean active,
|
||||
final ChargePaymentMode paymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap,
|
||||
final BigDecimal maxCap, final Integer feeFrequency, final boolean enableFreeWithdrawalCharge,
|
||||
final Integer freeWithdrawalFrequency, final Integer restartFrequency, final PeriodFrequencyType restartFrequencyEnum,
|
||||
final GLAccount account, final TaxGroup taxGroup, final boolean enablePaymentType, final PaymentType paymentType) {
|
||||
this.name = name;
|
||||
this.amount = amount;
|
||||
this.currencyCode = currencyCode;
|
||||
this.chargeAppliesTo = chargeAppliesTo.getValue();
|
||||
this.chargeTimeType = chargeTime.getValue();
|
||||
this.chargeCalculation = chargeCalculationType.getValue();
|
||||
this.penalty = penalty;
|
||||
this.active = active;
|
||||
this.account = account;
|
||||
this.taxGroup = taxGroup;
|
||||
this.chargePaymentMode = paymentMode == null ? null : paymentMode.getValue();
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charges");
|
||||
|
||||
if (isMonthlyFee() || isAnnualFee()) {
|
||||
this.feeOnMonth = feeOnMonthDay.getMonthValue();
|
||||
this.feeOnDay = feeOnMonthDay.getDayOfMonth();
|
||||
}
|
||||
this.feeInterval = feeInterval;
|
||||
this.feeFrequency = feeFrequency;
|
||||
|
||||
if (isSavingsCharge()) {
|
||||
// TODO vishwas, this validation seems unnecessary as identical
|
||||
// validation is performed in the write service
|
||||
if (!isAllowedSavingsChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.savings");
|
||||
}
|
||||
// TODO vishwas, this validation seems unnecessary as identical
|
||||
// validation is performed in the writeservice
|
||||
if (!isAllowedSavingsChargeCalculationType()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||
}
|
||||
|
||||
if (!(ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee()
|
||||
|| ChargeTimeType.fromInt(getChargeTimeType()).isSavingsNoActivityFee())
|
||||
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode(
|
||||
"savings.charge.calculation.type.percentage.allowed.only.for.withdrawal.or.NoActivity");
|
||||
}
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
this.enableFreeWithdrawal = true;
|
||||
this.freeWithdrawalFrequency = freeWithdrawalFrequency;
|
||||
this.restartFrequency = restartFrequency;
|
||||
this.restartFrequencyEnum = restartFrequencyEnum.getValue();
|
||||
}
|
||||
|
||||
if (enablePaymentType) {
|
||||
if (paymentType != null) {
|
||||
|
||||
this.enablePaymentType = true;
|
||||
this.paymentType = paymentType;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (isLoanCharge()) {
|
||||
|
||||
if (penalty && (chargeTime.isTimeOfDisbursement() || chargeTime.isTrancheDisbursement())) {
|
||||
throw new ChargeDueAtDisbursementCannotBePenaltyException(name);
|
||||
}
|
||||
if (!penalty && chargeTime.isOverdueInstallment()) {
|
||||
throw new ChargeMustBePenaltyException(name);
|
||||
}
|
||||
// TODO vishwas, this validation seems unnecessary as identical
|
||||
// validation is performed in the write service
|
||||
if (!isAllowedLoanChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan");
|
||||
}
|
||||
}
|
||||
|
||||
if (isPercentageOfApprovedAmount()) {
|
||||
this.minCap = minCap;
|
||||
this.maxCap = maxCap;
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return this.currencyCode;
|
||||
}
|
||||
|
||||
public Integer getChargeTimeType() {
|
||||
return this.chargeTimeType;
|
||||
}
|
||||
|
||||
public Integer getChargeCalculation() {
|
||||
return this.chargeCalculation;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
public boolean isPenalty() {
|
||||
return this.penalty;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return this.deleted;
|
||||
}
|
||||
|
||||
public boolean isLoanCharge() {
|
||||
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isLoanCharge();
|
||||
}
|
||||
|
||||
public boolean isAllowedLoanChargeTime() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAllowedLoanChargeTime();
|
||||
}
|
||||
|
||||
public boolean isAllowedClientChargeTime() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAllowedClientChargeTime();
|
||||
}
|
||||
|
||||
public boolean isSavingsCharge() {
|
||||
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isSavingsCharge();
|
||||
}
|
||||
|
||||
public boolean isClientCharge() {
|
||||
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isClientCharge();
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeTime() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAllowedSavingsChargeTime();
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeCalculationType() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedSavingsChargeCalculationType();
|
||||
}
|
||||
|
||||
public boolean isAllowedClientChargeCalculationType() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedClientChargeCalculationType();
|
||||
}
|
||||
|
||||
public boolean isPercentageOfApprovedAmount() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfAmount();
|
||||
}
|
||||
|
||||
public boolean isPercentageOfDisbursementAmount() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfDisbursementAmount();
|
||||
}
|
||||
|
||||
public BigDecimal getMinCap() {
|
||||
return this.minCap;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxCap() {
|
||||
return this.maxCap;
|
||||
}
|
||||
|
||||
public boolean isEnableFreeWithdrawal() {
|
||||
return this.enableFreeWithdrawal;
|
||||
}
|
||||
|
||||
public boolean isEnablePaymentType() {
|
||||
return this.enablePaymentType;
|
||||
}
|
||||
|
||||
public Integer getFrequencyFreeWithdrawalCharge() {
|
||||
return this.freeWithdrawalFrequency;
|
||||
}
|
||||
|
||||
public Integer getRestartFrequency() {
|
||||
return this.restartFrequency;
|
||||
}
|
||||
|
||||
public Integer getRestartFrequencyEnum() {
|
||||
return this.restartFrequencyEnum;
|
||||
}
|
||||
|
||||
public PaymentType getPaymentType() {
|
||||
return this.paymentType;
|
||||
}
|
||||
|
||||
public void setPaymentType(PaymentType paymentType) {
|
||||
this.paymentType = paymentType;
|
||||
}
|
||||
|
||||
private Long getPaymentTypeId() {
|
||||
Long paymentTypeId = null;
|
||||
if (this.paymentType != null) {
|
||||
paymentTypeId = this.paymentType.getId();
|
||||
}
|
||||
return paymentTypeId;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charges");
|
||||
|
||||
final String nameParamName = "name";
|
||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(nameParamName);
|
||||
actualChanges.put(nameParamName, newValue);
|
||||
this.name = newValue;
|
||||
}
|
||||
|
||||
final String currencyCodeParamName = "currencyCode";
|
||||
if (command.isChangeInStringParameterNamed(currencyCodeParamName, this.currencyCode)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(currencyCodeParamName);
|
||||
actualChanges.put(currencyCodeParamName, newValue);
|
||||
this.currencyCode = newValue;
|
||||
}
|
||||
|
||||
final String amountParamName = "amount";
|
||||
if (command.isChangeInBigDecimalParameterNamed(amountParamName, this.amount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(amountParamName, locale);
|
||||
actualChanges.put(amountParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.amount = newValue;
|
||||
}
|
||||
|
||||
final String chargeTimeParamName = "chargeTimeType";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeTimeParamName, this.chargeTimeType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeTimeParamName);
|
||||
actualChanges.put(chargeTimeParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.chargeTimeType = ChargeTimeType.fromInt(newValue).getValue();
|
||||
|
||||
if (isSavingsCharge()) {
|
||||
if (!isAllowedSavingsChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.savings");
|
||||
}
|
||||
// if charge time is changed to monthly then validate for
|
||||
// feeOnMonthDay and feeInterval
|
||||
if (isMonthlyFee()) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed("feeOnMonthDay");
|
||||
baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull();
|
||||
|
||||
final Integer feeInterval = command.integerValueOfParameterNamed("feeInterval");
|
||||
baseDataValidator.reset().parameter("feeInterval").value(feeInterval).notNull().inMinMaxRange(1, 12);
|
||||
}
|
||||
} else if (isLoanCharge()) {
|
||||
if (!isAllowedLoanChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan");
|
||||
}
|
||||
} else if (isClientCharge()) {
|
||||
if (!isAllowedLoanChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.client");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String freeWithdrawalFrequencyParamName = "freeWithdrawalFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(freeWithdrawalFrequencyParamName, this.freeWithdrawalFrequency)) {
|
||||
final Integer enableFreeWithdrawalChargeNewValue = command.integerValueOfParameterNamed(freeWithdrawalFrequencyParamName);
|
||||
actualChanges.put(freeWithdrawalFrequencyParamName, enableFreeWithdrawalChargeNewValue);
|
||||
this.freeWithdrawalFrequency = enableFreeWithdrawalChargeNewValue;
|
||||
}
|
||||
|
||||
final String restartCountFrequencyParamName = "restartCountFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(restartCountFrequencyParamName, this.restartFrequency)) {
|
||||
final Integer restartCountFrequencyNewValue = command.integerValueOfParameterNamed(restartCountFrequencyParamName);
|
||||
actualChanges.put(restartCountFrequencyParamName, restartCountFrequencyNewValue);
|
||||
this.restartFrequency = restartCountFrequencyNewValue;
|
||||
}
|
||||
|
||||
final String countFrequencyTypeParamName = "countFrequencyType";
|
||||
if (command.isChangeInIntegerParameterNamed(countFrequencyTypeParamName, this.restartFrequencyEnum)) {
|
||||
final Integer countFrequencyTypeNewValue = command.integerValueOfParameterNamed(countFrequencyTypeParamName);
|
||||
actualChanges.put(countFrequencyTypeParamName, countFrequencyTypeNewValue);
|
||||
this.restartFrequencyEnum = ChargeTimeType.fromInt(countFrequencyTypeNewValue).getValue();
|
||||
}
|
||||
|
||||
final String enableFreeWithdrawalChargeParamName = "enableFreeWithdrawalCharge";
|
||||
if (command.isChangeInBooleanParameterNamed(enableFreeWithdrawalChargeParamName, this.enableFreeWithdrawal)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enableFreeWithdrawalChargeParamName);
|
||||
actualChanges.put(enableFreeWithdrawalChargeParamName, newValue);
|
||||
this.enableFreeWithdrawal = newValue;
|
||||
|
||||
}
|
||||
|
||||
final String enablePaymentTypeParamName = "enablePaymentType";
|
||||
if (command.isChangeInBooleanParameterNamed(enablePaymentTypeParamName, this.enablePaymentType)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enablePaymentTypeParamName);
|
||||
actualChanges.put(enablePaymentTypeParamName, newValue);
|
||||
this.enablePaymentType = newValue;
|
||||
}
|
||||
|
||||
final String paymentTypeParamName = "paymentTypeId";
|
||||
if (command.isChangeInLongParameterNamed(paymentTypeParamName, getPaymentTypeId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(paymentTypeParamName);
|
||||
actualChanges.put(paymentTypeParamName, newValue);
|
||||
}
|
||||
|
||||
final String chargeAppliesToParamName = "chargeAppliesTo";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeAppliesToParamName, this.chargeAppliesTo)) {
|
||||
/*
|
||||
* final Integer newValue = command.integerValueOfParameterNamed(chargeAppliesToParamName);
|
||||
* actualChanges.put(chargeAppliesToParamName, newValue); actualChanges.put("locale", localeAsInput);
|
||||
* this.chargeAppliesTo = ChargeAppliesTo.fromInt(newValue).getValue();
|
||||
*/
|
||||
|
||||
// AA: Do not allow to change chargeAppliesTo.
|
||||
final String errorMessage = "Update of Charge applies to is not supported";
|
||||
throw new ChargeParameterUpdateNotSupportedException("charge.applies.to", errorMessage);
|
||||
}
|
||||
|
||||
final String chargeCalculationParamName = "chargeCalculationType";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeCalculationParamName, this.chargeCalculation)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeCalculationParamName);
|
||||
actualChanges.put(chargeCalculationParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.chargeCalculation = ChargeCalculationType.fromInt(newValue).getValue();
|
||||
|
||||
if (isSavingsCharge()) {
|
||||
if (!isAllowedSavingsChargeCalculationType()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||
}
|
||||
|
||||
if (!(ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee()
|
||||
|| ChargeTimeType.fromInt(getChargeTimeType()).isSavingsNoActivityFee())
|
||||
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode(
|
||||
"charge.calculation.type.percentage.allowed.only.for.withdrawal.or.noactivity");
|
||||
}
|
||||
} else if (isClientCharge()) {
|
||||
if (!isAllowedClientChargeCalculationType()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.client");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate only for loan charge
|
||||
if (isLoanCharge()) {
|
||||
final String paymentModeParamName = "chargePaymentMode";
|
||||
if (command.isChangeInIntegerParameterNamed(paymentModeParamName, this.chargePaymentMode)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(paymentModeParamName);
|
||||
actualChanges.put(paymentModeParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.chargePaymentMode = ChargePaymentMode.fromInt(newValue).getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (command.hasParameter("feeOnMonthDay")) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed("feeOnMonthDay");
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed("feeOnMonthDay");
|
||||
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
|
||||
if (!this.feeOnDay.equals(dayOfMonthValue)) {
|
||||
actualChanges.put("feeOnMonthDay", actualValueEntered);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeOnDay = dayOfMonthValue;
|
||||
}
|
||||
|
||||
final Integer monthOfYear = monthDay.getMonthValue();
|
||||
if (!this.feeOnMonth.equals(monthOfYear)) {
|
||||
actualChanges.put("feeOnMonthDay", actualValueEntered);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeOnMonth = monthOfYear;
|
||||
}
|
||||
}
|
||||
|
||||
final String feeInterval = "feeInterval";
|
||||
if (command.isChangeInIntegerParameterNamed(feeInterval, this.feeInterval)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(feeInterval);
|
||||
actualChanges.put(feeInterval, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeInterval = newValue;
|
||||
}
|
||||
|
||||
final String feeFrequency = "feeFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(feeFrequency, this.feeFrequency)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(feeFrequency);
|
||||
actualChanges.put(feeFrequency, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeFrequency = newValue;
|
||||
}
|
||||
|
||||
if (this.feeFrequency != null) {
|
||||
baseDataValidator.reset().parameter("feeInterval").value(this.feeInterval).notNull();
|
||||
}
|
||||
|
||||
final String penaltyParamName = "penalty";
|
||||
if (command.isChangeInBooleanParameterNamed(penaltyParamName, this.penalty)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(penaltyParamName);
|
||||
actualChanges.put(penaltyParamName, newValue);
|
||||
this.penalty = newValue;
|
||||
}
|
||||
|
||||
final String activeParamName = "active";
|
||||
if (command.isChangeInBooleanParameterNamed(activeParamName, this.active)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(activeParamName);
|
||||
actualChanges.put(activeParamName, newValue);
|
||||
this.active = newValue;
|
||||
}
|
||||
// allow min and max cap to be only added to PERCENT_OF_AMOUNT for now
|
||||
if (isPercentageOfApprovedAmount()) {
|
||||
final String minCapParamName = "minCap";
|
||||
if (command.isChangeInBigDecimalParameterNamed(minCapParamName, this.minCap)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(minCapParamName);
|
||||
actualChanges.put(minCapParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.minCap = newValue;
|
||||
}
|
||||
final String maxCapParamName = "maxCap";
|
||||
if (command.isChangeInBigDecimalParameterNamed(maxCapParamName, this.maxCap)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(maxCapParamName);
|
||||
actualChanges.put(maxCapParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.maxCap = newValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (this.penalty && ChargeTimeType.fromInt(this.chargeTimeType).isTimeOfDisbursement()) {
|
||||
throw new ChargeDueAtDisbursementCannotBePenaltyException(this.name);
|
||||
}
|
||||
if (!penalty && ChargeTimeType.fromInt(this.chargeTimeType).isOverdueInstallment()) {
|
||||
throw new ChargeMustBePenaltyException(name);
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(ChargesApiConstants.glAccountIdParamName, getIncomeAccountId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(ChargesApiConstants.glAccountIdParamName);
|
||||
actualChanges.put(ChargesApiConstants.glAccountIdParamName, newValue);
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(ChargesApiConstants.taxGroupIdParamName, getTaxGroupId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(ChargesApiConstants.taxGroupIdParamName);
|
||||
actualChanges.put(ChargesApiConstants.taxGroupIdParamName, newValue);
|
||||
if (taxGroup != null) {
|
||||
baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).failWithCode("modification.not.supported");
|
||||
}
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete is a <i>soft delete</i>. Updates flag on charge so it wont appear in query/report results.
|
||||
*
|
||||
* Any fields with unique constraints and prepended with id of record.
|
||||
*/
|
||||
public void delete() {
|
||||
this.deleted = true;
|
||||
this.name = getId() + "_" + this.name;
|
||||
}
|
||||
|
||||
public ChargeData toData() {
|
||||
final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(this.chargeTimeType);
|
||||
final EnumOptionData chargeAppliesTo = ChargeEnumerations.chargeAppliesTo(this.chargeAppliesTo);
|
||||
final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(this.chargeCalculation);
|
||||
final EnumOptionData chargePaymentMode = ChargeEnumerations.chargePaymentMode(this.chargePaymentMode);
|
||||
EnumOptionData feeFrequencyType = null;
|
||||
if (this.feeFrequency != null) {
|
||||
feeFrequencyType = ChargeEnumerations.feeFrequencyType(this.feeFrequency);
|
||||
}
|
||||
GLAccountData accountData = null;
|
||||
if (account != null) {
|
||||
accountData = new GLAccountData().setId(account.getId()).setName(account.getName()).setGlCode(account.getGlCode());
|
||||
}
|
||||
TaxGroupData taxGroupData = null;
|
||||
if (this.taxGroup != null) {
|
||||
taxGroupData = TaxGroupData.lookup(taxGroup.getId(), taxGroup.getName());
|
||||
}
|
||||
|
||||
PaymentTypeData paymentTypeData = null;
|
||||
if (this.paymentType != null) {
|
||||
paymentTypeData = PaymentTypeData.instance(paymentType.getId(), paymentType.getName());
|
||||
}
|
||||
|
||||
final CurrencyData currency = new CurrencyData(this.currencyCode, null, 0, 0, null, null);
|
||||
return ChargeData.instance(getId(), this.name, this.amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType,
|
||||
chargePaymentMode, getFeeOnMonthDay(), this.feeInterval, this.penalty, this.active, this.enableFreeWithdrawal,
|
||||
this.freeWithdrawalFrequency, this.restartFrequency, this.restartFrequencyEnum, this.enablePaymentType, paymentTypeData,
|
||||
this.minCap, this.maxCap, feeFrequencyType, accountData, taxGroupData);
|
||||
}
|
||||
|
||||
public Integer getChargePaymentMode() {
|
||||
return this.chargePaymentMode;
|
||||
}
|
||||
|
||||
public Integer getFeeInterval() {
|
||||
return this.feeInterval;
|
||||
}
|
||||
|
||||
public boolean isMonthlyFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isMonthlyFee();
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAnnualFee();
|
||||
}
|
||||
|
||||
public boolean isOverdueInstallment() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isOverdueInstallment();
|
||||
}
|
||||
|
||||
public MonthDay getFeeOnMonthDay() {
|
||||
MonthDay feeOnMonthDay = null;
|
||||
if (this.feeOnDay != null && this.feeOnMonth != null) {
|
||||
feeOnMonthDay = MonthDay.now(DateUtils.getDateTimeZoneOfTenant()).withMonth(this.feeOnMonth).withDayOfMonth(this.feeOnDay);
|
||||
}
|
||||
return feeOnMonthDay;
|
||||
}
|
||||
|
||||
public Integer feeInterval() {
|
||||
return this.feeInterval;
|
||||
}
|
||||
|
||||
public Integer feeFrequency() {
|
||||
return this.feeFrequency;
|
||||
}
|
||||
|
||||
public GLAccount getAccount() {
|
||||
return this.account;
|
||||
}
|
||||
|
||||
public void setAccount(GLAccount account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Long getIncomeAccountId() {
|
||||
Long incomeAccountId = null;
|
||||
if (this.account != null) {
|
||||
incomeAccountId = this.account.getId();
|
||||
}
|
||||
return incomeAccountId;
|
||||
}
|
||||
|
||||
private Long getTaxGroupId() {
|
||||
Long taxGroupId = null;
|
||||
if (this.taxGroup != null) {
|
||||
taxGroupId = this.taxGroup.getId();
|
||||
}
|
||||
return taxGroupId;
|
||||
}
|
||||
|
||||
public boolean isDisbursementCharge() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).equals(ChargeTimeType.DISBURSEMENT)
|
||||
|| ChargeTimeType.fromInt(this.chargeTimeType).equals(ChargeTimeType.TRANCHE_DISBURSEMENT);
|
||||
}
|
||||
|
||||
public TaxGroup getTaxGroup() {
|
||||
return this.taxGroup;
|
||||
}
|
||||
|
||||
public void setTaxGroup(TaxGroup taxGroup) {
|
||||
this.taxGroup = taxGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Charge)) {
|
||||
return false;
|
||||
}
|
||||
Charge other = (Charge) o;
|
||||
return Objects.equals(name, other.name) && Objects.equals(amount, other.amount) && Objects.equals(currencyCode, other.currencyCode)
|
||||
&& Objects.equals(chargeAppliesTo, other.chargeAppliesTo) && Objects.equals(chargeTimeType, other.chargeTimeType)
|
||||
&& Objects.equals(chargeCalculation, other.chargeCalculation) && Objects.equals(chargePaymentMode, other.chargePaymentMode)
|
||||
&& Objects.equals(feeOnDay, other.feeOnDay) && Objects.equals(feeInterval, other.feeInterval)
|
||||
&& Objects.equals(feeOnMonth, other.feeOnMonth) && penalty == other.penalty && active == other.active
|
||||
&& deleted == other.deleted && Objects.equals(minCap, other.minCap) && Objects.equals(maxCap, other.maxCap)
|
||||
&& Objects.equals(feeFrequency, other.feeFrequency) && Objects.equals(account, other.account)
|
||||
&& Objects.equals(taxGroup, other.taxGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, amount, currencyCode, chargeAppliesTo, chargeTimeType, chargeCalculation, chargePaymentMode, feeOnDay,
|
||||
feeInterval, feeOnMonth, penalty, active, deleted, minCap, maxCap, feeFrequency, account, taxGroup);
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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.charge.domain;
|
||||
|
||||
public enum ChargeAppliesTo {
|
||||
|
||||
INVALID(0, "chargeAppliesTo.invalid"), //
|
||||
LOAN(1, "chargeAppliesTo.loan"), //
|
||||
SAVINGS(2, "chargeAppliesTo.savings"), //
|
||||
CLIENT(3, "chargeAppliesTo.client"), SHARES(4, "chargeAppliesTo.shares");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
ChargeAppliesTo(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static ChargeAppliesTo fromInt(final Integer chargeAppliesTo) {
|
||||
ChargeAppliesTo chargeAppliesToType = ChargeAppliesTo.INVALID;
|
||||
|
||||
if (chargeAppliesTo != null) {
|
||||
switch (chargeAppliesTo) {
|
||||
case 1:
|
||||
chargeAppliesToType = LOAN;
|
||||
break;
|
||||
case 2:
|
||||
chargeAppliesToType = SAVINGS;
|
||||
break;
|
||||
case 3:
|
||||
chargeAppliesToType = CLIENT;
|
||||
break;
|
||||
case 4:
|
||||
chargeAppliesToType = SHARES;
|
||||
break;
|
||||
default:
|
||||
chargeAppliesToType = INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return chargeAppliesToType;
|
||||
}
|
||||
|
||||
public boolean isLoanCharge() {
|
||||
return this.value.equals(ChargeAppliesTo.LOAN.getValue());
|
||||
}
|
||||
|
||||
public boolean isSavingsCharge() {
|
||||
return this.value.equals(ChargeAppliesTo.SAVINGS.getValue());
|
||||
}
|
||||
|
||||
public boolean isClientCharge() {
|
||||
return this.value.equals(ChargeAppliesTo.CLIENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isSharesCharge() {
|
||||
return this.value.equals(SHARES.getValue());
|
||||
}
|
||||
|
||||
public static Object[] validValues() {
|
||||
return new Object[] { ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.getValue(), ChargeAppliesTo.CLIENT.getValue(),
|
||||
ChargeAppliesTo.SHARES.getValue() };
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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.charge.domain;
|
||||
|
||||
public enum ChargeCalculationType {
|
||||
|
||||
INVALID(0, "chargeCalculationType.invalid"), //
|
||||
FLAT(1, "chargeCalculationType.flat"), //
|
||||
PERCENT_OF_AMOUNT(2, "chargeCalculationType.percent.of.amount"), //
|
||||
PERCENT_OF_AMOUNT_AND_INTEREST(3, "chargeCalculationType.percent.of.amount.and.interest"), //
|
||||
PERCENT_OF_INTEREST(4, "chargeCalculationType.percent.of.interest"), PERCENT_OF_DISBURSEMENT_AMOUNT(5,
|
||||
"chargeCalculationType.percent.of.disbursement.amount");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
ChargeCalculationType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] validValuesForLoan() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue(),
|
||||
ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue(), ChargeCalculationType.PERCENT_OF_INTEREST.getValue(),
|
||||
ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForSavings() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForShares() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForClients() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForShareAccountActivation() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForTrancheDisbursement() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static ChargeCalculationType fromInt(final Integer chargeCalculation) {
|
||||
ChargeCalculationType chargeCalculationType = ChargeCalculationType.INVALID;
|
||||
switch (chargeCalculation) {
|
||||
case 1:
|
||||
chargeCalculationType = FLAT;
|
||||
break;
|
||||
case 2:
|
||||
chargeCalculationType = PERCENT_OF_AMOUNT;
|
||||
break;
|
||||
case 3:
|
||||
chargeCalculationType = PERCENT_OF_AMOUNT_AND_INTEREST;
|
||||
break;
|
||||
case 4:
|
||||
chargeCalculationType = PERCENT_OF_INTEREST;
|
||||
break;
|
||||
case 5:
|
||||
chargeCalculationType = PERCENT_OF_DISBURSEMENT_AMOUNT;
|
||||
break;
|
||||
}
|
||||
return chargeCalculationType;
|
||||
}
|
||||
|
||||
public boolean isPercentageOfAmount() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue());
|
||||
}
|
||||
|
||||
public boolean isPercentageOfAmountAndInterest() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue());
|
||||
}
|
||||
|
||||
public boolean isPercentageOfInterest() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_INTEREST.getValue());
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
return this.value.equals(ChargeCalculationType.FLAT.getValue());
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeCalculationType() {
|
||||
return isFlat() || isPercentageOfAmount();
|
||||
}
|
||||
|
||||
public boolean isAllowedClientChargeCalculationType() {
|
||||
return isFlat();
|
||||
}
|
||||
|
||||
public boolean isPercentageBased() {
|
||||
return isPercentageOfAmount() || isPercentageOfAmountAndInterest() || isPercentageOfInterest()
|
||||
|| isPercentageOfDisbursementAmount();
|
||||
}
|
||||
|
||||
public boolean isPercentageOfDisbursementAmount() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue());
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.charge.domain;
|
||||
|
||||
public enum ChargePaymentMode {
|
||||
|
||||
REGULAR(0, "chargepaymentmode.regular"), //
|
||||
ACCOUNT_TRANSFER(1, "chargepaymentmode.accounttransfer");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
ChargePaymentMode(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] validValues() {
|
||||
return new Integer[] { ChargePaymentMode.REGULAR.getValue(), ChargePaymentMode.ACCOUNT_TRANSFER.getValue() };
|
||||
}
|
||||
|
||||
public static ChargePaymentMode fromInt(final Integer paymentMode) {
|
||||
ChargePaymentMode chargeAppliesToType = ChargePaymentMode.REGULAR;
|
||||
switch (paymentMode) {
|
||||
case 1:
|
||||
chargeAppliesToType = ACCOUNT_TRANSFER;
|
||||
break;
|
||||
default:
|
||||
chargeAppliesToType = REGULAR;
|
||||
break;
|
||||
}
|
||||
return chargeAppliesToType;
|
||||
}
|
||||
|
||||
public boolean isPaymentModeAccountTransfer() {
|
||||
return this.value.equals(ChargePaymentMode.ACCOUNT_TRANSFER.getValue());
|
||||
}
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* 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.charge.domain;
|
||||
|
||||
public enum ChargeTimeType {
|
||||
|
||||
INVALID(0, "chargeTimeType.invalid"), //
|
||||
DISBURSEMENT(1, "chargeTimeType.disbursement"), // only for loan charges
|
||||
SPECIFIED_DUE_DATE(2, "chargeTimeType.specifiedDueDate"), // for loan and
|
||||
SAVINGS_ACTIVATION(3, "chargeTimeType.savingsActivation"), // only for
|
||||
SAVINGS_CLOSURE(4, "chargeTimeType.savingsClosure"), // only for savings
|
||||
WITHDRAWAL_FEE(5, "chargeTimeType.withdrawalFee"), // only for savings
|
||||
ANNUAL_FEE(6, "chargeTimeType.annualFee"), // only for savings
|
||||
MONTHLY_FEE(7, "chargeTimeType.monthlyFee"), // only for savings
|
||||
INSTALMENT_FEE(8, "chargeTimeType.instalmentFee"), // only for loan charges
|
||||
OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"), // only for
|
||||
OVERDRAFT_FEE(10, "chargeTimeType.overdraftFee"), // only for savings
|
||||
WEEKLY_FEE(11, "chargeTimeType.weeklyFee"), // only for savings
|
||||
TRANCHE_DISBURSEMENT(12, "chargeTimeType.tranchedisbursement"), // only for
|
||||
// loan
|
||||
SHAREACCOUNT_ACTIVATION(13, "chargeTimeType.activation"), // only for loan
|
||||
SHARE_PURCHASE(14, "chargeTimeType.sharespurchase"), SHARE_REDEEM(15, "chargeTimeType.sharesredeem"),
|
||||
|
||||
SAVINGS_NOACTIVITY_FEE(16, "chargeTimeType.savingsNoActivityFee");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
ChargeTimeType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] validLoanValues() {
|
||||
return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(),
|
||||
ChargeTimeType.INSTALMENT_FEE.getValue(), ChargeTimeType.OVERDUE_INSTALLMENT.getValue(),
|
||||
ChargeTimeType.TRANCHE_DISBURSEMENT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validLoanChargeValues() {
|
||||
return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(),
|
||||
ChargeTimeType.INSTALMENT_FEE.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validSavingsValues() {
|
||||
return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), ChargeTimeType.SAVINGS_ACTIVATION.getValue(),
|
||||
ChargeTimeType.SAVINGS_CLOSURE.getValue(), ChargeTimeType.WITHDRAWAL_FEE.getValue(), ChargeTimeType.ANNUAL_FEE.getValue(),
|
||||
ChargeTimeType.MONTHLY_FEE.getValue(), ChargeTimeType.OVERDRAFT_FEE.getValue(), ChargeTimeType.WEEKLY_FEE.getValue(),
|
||||
ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validClientValues() {
|
||||
return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validShareValues() {
|
||||
return new Integer[] { ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue(), ChargeTimeType.SHARE_PURCHASE.getValue(),
|
||||
ChargeTimeType.SHARE_REDEEM.getValue() };
|
||||
}
|
||||
|
||||
public static ChargeTimeType fromInt(final Integer chargeTime) {
|
||||
ChargeTimeType chargeTimeType = ChargeTimeType.INVALID;
|
||||
if (chargeTime != null) {
|
||||
switch (chargeTime) {
|
||||
case 1:
|
||||
chargeTimeType = DISBURSEMENT;
|
||||
break;
|
||||
case 2:
|
||||
chargeTimeType = SPECIFIED_DUE_DATE;
|
||||
break;
|
||||
case 3:
|
||||
chargeTimeType = SAVINGS_ACTIVATION;
|
||||
break;
|
||||
case 4:
|
||||
chargeTimeType = SAVINGS_CLOSURE;
|
||||
break;
|
||||
case 5:
|
||||
chargeTimeType = WITHDRAWAL_FEE;
|
||||
break;
|
||||
case 6:
|
||||
chargeTimeType = ANNUAL_FEE;
|
||||
break;
|
||||
case 7:
|
||||
chargeTimeType = MONTHLY_FEE;
|
||||
break;
|
||||
case 8:
|
||||
chargeTimeType = INSTALMENT_FEE;
|
||||
break;
|
||||
case 9:
|
||||
chargeTimeType = OVERDUE_INSTALLMENT;
|
||||
break;
|
||||
case 10:
|
||||
chargeTimeType = OVERDRAFT_FEE;
|
||||
break;
|
||||
case 11:
|
||||
chargeTimeType = WEEKLY_FEE;
|
||||
break;
|
||||
case 12:
|
||||
chargeTimeType = TRANCHE_DISBURSEMENT;
|
||||
break;
|
||||
case 13:
|
||||
chargeTimeType = SHAREACCOUNT_ACTIVATION;
|
||||
break;
|
||||
case 14:
|
||||
chargeTimeType = SHARE_PURCHASE;
|
||||
break;
|
||||
case 15:
|
||||
chargeTimeType = SHARE_REDEEM;
|
||||
break;
|
||||
case 16:
|
||||
chargeTimeType = SAVINGS_NOACTIVITY_FEE;
|
||||
break;
|
||||
default:
|
||||
chargeTimeType = INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return chargeTimeType;
|
||||
}
|
||||
|
||||
public boolean isTimeOfDisbursement() {
|
||||
return ChargeTimeType.DISBURSEMENT.getValue().equals(this.value);
|
||||
}
|
||||
|
||||
public boolean isOnSpecifiedDueDate() {
|
||||
return this.value.equals(ChargeTimeType.SPECIFIED_DUE_DATE.getValue());
|
||||
}
|
||||
|
||||
public boolean isSavingsActivation() {
|
||||
return this.value.equals(ChargeTimeType.SAVINGS_ACTIVATION.getValue());
|
||||
}
|
||||
|
||||
public boolean isSavingsClosure() {
|
||||
return this.value.equals(ChargeTimeType.SAVINGS_CLOSURE.getValue());
|
||||
}
|
||||
|
||||
public boolean isWithdrawalFee() {
|
||||
return this.value.equals(ChargeTimeType.WITHDRAWAL_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isSavingsNoActivityFee() {
|
||||
return this.value.equals(ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return this.value.equals(ChargeTimeType.ANNUAL_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isMonthlyFee() {
|
||||
return this.value.equals(ChargeTimeType.MONTHLY_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isWeeklyFee() {
|
||||
return this.value.equals(ChargeTimeType.WEEKLY_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isInstalmentFee() {
|
||||
return this.value.equals(ChargeTimeType.INSTALMENT_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isOverdueInstallment() {
|
||||
return this.value.equals(ChargeTimeType.OVERDUE_INSTALLMENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isAllowedLoanChargeTime() {
|
||||
return isTimeOfDisbursement() || isOnSpecifiedDueDate() || isInstalmentFee() || isOverdueInstallment() || isTrancheDisbursement();
|
||||
}
|
||||
|
||||
public boolean isAllowedClientChargeTime() {
|
||||
return isOnSpecifiedDueDate();
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeTime() {
|
||||
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee() || isMonthlyFee()
|
||||
|| isWeeklyFee() || isOverdraftFee() || isSavingsNoActivityFee();
|
||||
}
|
||||
|
||||
public boolean isOverdraftFee() {
|
||||
return this.value.equals(ChargeTimeType.OVERDRAFT_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isTrancheDisbursement() {
|
||||
return this.value.equals(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isShareAccountActivation() {
|
||||
return this.value.equals(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue());
|
||||
}
|
||||
|
||||
public boolean isSharesPurchase() {
|
||||
return this.value.equals(ChargeTimeType.SHARE_PURCHASE.getValue());
|
||||
}
|
||||
|
||||
public boolean isSharesRedeem() {
|
||||
return this.value.equals(ChargeTimeType.SHARE_REDEEM.getValue());
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when attempting to crate charge of type penalty due at
|
||||
* disbursement .
|
||||
*/
|
||||
public class ChargeDueAtDisbursementCannotBePenaltyException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeDueAtDisbursementCannotBePenaltyException(final String name) {
|
||||
super("error.msg.charge.due.at.disbursement.cannot.be.penalty", "Charge '" + name + "' is invalid.", name, name);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when attempting to crate charge of type penalty due at
|
||||
* disbursement .
|
||||
*/
|
||||
public class ChargeMustBePenaltyException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeMustBePenaltyException(final String name) {
|
||||
super("error.msg.charge.must.be.penalty", "Charge '" + name + "' is invalid.", name, name);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when Calendar resources are not found.
|
||||
*/
|
||||
public class ChargeParameterUpdateNotSupportedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeParameterUpdateNotSupportedException(final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg.charge.update.of." + postFix + ".is.not.supported", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when loan charge is not allowed to be added to the loan.
|
||||
*/
|
||||
public class LoanChargeCannotBeAddedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public LoanChargeCannotBeAddedException(final String entity, final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg." + entity + ".cannot.be.added.as." + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* 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.charge.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeAppliesTo;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
|
||||
public final class ChargeEnumerations {
|
||||
|
||||
private ChargeEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeTimeType(final int id) {
|
||||
return chargeTimeType(ChargeTimeType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeTimeType(final ChargeTimeType type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case DISBURSEMENT:
|
||||
optionData = new EnumOptionData(ChargeTimeType.DISBURSEMENT.getValue().longValue(), ChargeTimeType.DISBURSEMENT.getCode(),
|
||||
"Disbursement");
|
||||
break;
|
||||
case SPECIFIED_DUE_DATE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SPECIFIED_DUE_DATE.getValue().longValue(),
|
||||
ChargeTimeType.SPECIFIED_DUE_DATE.getCode(), "Specified due date");
|
||||
break;
|
||||
case SAVINGS_ACTIVATION:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_ACTIVATION.getValue().longValue(),
|
||||
ChargeTimeType.SAVINGS_ACTIVATION.getCode(), "Savings Activation");
|
||||
break;
|
||||
case SAVINGS_CLOSURE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_CLOSURE.getValue().longValue(),
|
||||
ChargeTimeType.SAVINGS_CLOSURE.getCode(), "Savings Closure");
|
||||
break;
|
||||
case WITHDRAWAL_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.WITHDRAWAL_FEE.getValue().longValue(),
|
||||
ChargeTimeType.WITHDRAWAL_FEE.getCode(), "Withdrawal Fee");
|
||||
break;
|
||||
case ANNUAL_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.ANNUAL_FEE.getValue().longValue(), ChargeTimeType.ANNUAL_FEE.getCode(),
|
||||
"Annual Fee");
|
||||
break;
|
||||
case MONTHLY_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.MONTHLY_FEE.getValue().longValue(), ChargeTimeType.MONTHLY_FEE.getCode(),
|
||||
"Monthly Fee");
|
||||
break;
|
||||
case WEEKLY_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.WEEKLY_FEE.getValue().longValue(), ChargeTimeType.WEEKLY_FEE.getCode(),
|
||||
"Weekly Fee");
|
||||
break;
|
||||
case INSTALMENT_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.INSTALMENT_FEE.getValue().longValue(),
|
||||
ChargeTimeType.INSTALMENT_FEE.getCode(), "Installment Fee");
|
||||
break;
|
||||
case OVERDUE_INSTALLMENT:
|
||||
optionData = new EnumOptionData(ChargeTimeType.OVERDUE_INSTALLMENT.getValue().longValue(),
|
||||
ChargeTimeType.OVERDUE_INSTALLMENT.getCode(), "Overdue Fees");
|
||||
break;
|
||||
case OVERDRAFT_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.OVERDRAFT_FEE.getValue().longValue(), ChargeTimeType.OVERDRAFT_FEE.getCode(),
|
||||
"Overdraft Fee");
|
||||
break;
|
||||
case TRANCHE_DISBURSEMENT:
|
||||
optionData = new EnumOptionData(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue().longValue(),
|
||||
ChargeTimeType.TRANCHE_DISBURSEMENT.getCode(), "Tranche Disbursement");
|
||||
break;
|
||||
case SHAREACCOUNT_ACTIVATION:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue().longValue(),
|
||||
ChargeTimeType.SHAREACCOUNT_ACTIVATION.getCode(), "Share Account Activate");
|
||||
break;
|
||||
|
||||
case SHARE_PURCHASE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHARE_PURCHASE.getValue().longValue(),
|
||||
ChargeTimeType.SHARE_PURCHASE.getCode(), "Share Purchase");
|
||||
break;
|
||||
case SHARE_REDEEM:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHARE_REDEEM.getValue().longValue(), ChargeTimeType.SHARE_REDEEM.getCode(),
|
||||
"Share Redeem");
|
||||
break;
|
||||
case SAVINGS_NOACTIVITY_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getValue().longValue(),
|
||||
ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getCode(), "Saving No Activity Fee");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeAppliesTo(final int id) {
|
||||
return chargeAppliesTo(ChargeAppliesTo.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeAppliesTo(final ChargeAppliesTo type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case LOAN:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.LOAN.getValue().longValue(), ChargeAppliesTo.LOAN.getCode(), "Loan");
|
||||
break;
|
||||
case SAVINGS:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.SAVINGS.getValue().longValue(), ChargeAppliesTo.SAVINGS.getCode(),
|
||||
"Savings");
|
||||
break;
|
||||
case CLIENT:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.CLIENT.getValue().longValue(), ChargeAppliesTo.CLIENT.getCode(), "Client");
|
||||
break;
|
||||
case SHARES:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.SHARES.getValue().longValue(), ChargeAppliesTo.SHARES.getCode(), "Shares");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.INVALID.getValue().longValue(), ChargeAppliesTo.INVALID.getCode(),
|
||||
"Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeCalculationType(final int id) {
|
||||
return chargeCalculationType(ChargeCalculationType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeCalculationType(final ChargeCalculationType type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case FLAT:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.FLAT.getValue().longValue(), ChargeCalculationType.FLAT.getCode(),
|
||||
"Flat");
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_AMOUNT.getCode(), "% Amount");
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getCode(), "% Loan Amount + Interest");
|
||||
break;
|
||||
case PERCENT_OF_INTEREST:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_INTEREST.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_INTEREST.getCode(), "% Interest");
|
||||
break;
|
||||
case PERCENT_OF_DISBURSEMENT_AMOUNT:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getCode(), "% Disbursement Amount");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.INVALID.getValue().longValue(),
|
||||
ChargeCalculationType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData chargePaymentMode(final int id) {
|
||||
return chargePaymentMode(ChargePaymentMode.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargePaymentMode(final ChargePaymentMode type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case ACCOUNT_TRANSFER:
|
||||
optionData = new EnumOptionData(ChargePaymentMode.ACCOUNT_TRANSFER.getValue().longValue(),
|
||||
ChargePaymentMode.ACCOUNT_TRANSFER.getCode(), "Account transfer");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargePaymentMode.REGULAR.getValue().longValue(), ChargePaymentMode.REGULAR.getCode(),
|
||||
"Regular");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData feeFrequencyType(final int id) {
|
||||
return feeFrequencyType(PeriodFrequencyType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData feeFrequencyType(final PeriodFrequencyType frequencyType) {
|
||||
EnumOptionData optionData;
|
||||
switch (frequencyType) {
|
||||
case DAYS -> optionData = new EnumOptionData(PeriodFrequencyType.DAYS.getValue().longValue(),
|
||||
PeriodFrequencyType.DAYS.getCode(), "Daily");
|
||||
case WEEKS -> optionData = new EnumOptionData(PeriodFrequencyType.WEEKS.getValue().longValue(),
|
||||
PeriodFrequencyType.WEEKS.getCode(), "Weekly");
|
||||
case MONTHS -> optionData = new EnumOptionData(PeriodFrequencyType.MONTHS.getValue().longValue(),
|
||||
PeriodFrequencyType.MONTHS.getCode(), "Monthly");
|
||||
case YEARS -> optionData = new EnumOptionData(PeriodFrequencyType.YEARS.getValue().longValue(),
|
||||
PeriodFrequencyType.YEARS.getCode(), "Yearly");
|
||||
case WHOLE_TERM -> optionData = new EnumOptionData(PeriodFrequencyType.WHOLE_TERM.getValue().longValue(),
|
||||
PeriodFrequencyType.WHOLE_TERM.getCode(), "Whole term");
|
||||
default -> throw new UnsupportedOperationException(frequencyType + " is not supported");
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -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.portfolio.client.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public final class ClientCollateralManagementData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final String name;
|
||||
private final BigDecimal quantity;
|
||||
private final BigDecimal pctToBase;
|
||||
private final BigDecimal unitPrice;
|
||||
private final BigDecimal total;
|
||||
private final BigDecimal totalCollateral;
|
||||
|
||||
}
|
||||
+645
@@ -0,0 +1,645 @@
|
||||
/**
|
||||
* 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.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
|
||||
import org.apache.fineract.organisation.office.data.OfficeData;
|
||||
import org.apache.fineract.organisation.staff.data.StaffData;
|
||||
import org.apache.fineract.portfolio.address.data.AddressData;
|
||||
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing client data.
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public final class ClientData implements Comparable<ClientData>, Serializable {
|
||||
|
||||
private Long id;
|
||||
private String accountNo;
|
||||
private ExternalId externalId;
|
||||
|
||||
private EnumOptionData status;
|
||||
private CodeValueData subStatus;
|
||||
|
||||
private Boolean active;
|
||||
private LocalDate activationDate;
|
||||
|
||||
private String firstname;
|
||||
private String middlename;
|
||||
private String lastname;
|
||||
private String fullname;
|
||||
private String displayName;
|
||||
private String mobileNo;
|
||||
private String emailAddress;
|
||||
private LocalDate dateOfBirth;
|
||||
private CodeValueData gender;
|
||||
private CodeValueData clientType;
|
||||
private CodeValueData clientClassification;
|
||||
private Boolean isStaff;
|
||||
|
||||
private Long officeId;
|
||||
private String officeName;
|
||||
private Long transferToOfficeId;
|
||||
private String transferToOfficeName;
|
||||
|
||||
private Long imageId;
|
||||
private Boolean imagePresent;
|
||||
private Long staffId;
|
||||
private String staffName;
|
||||
private ClientTimelineData timeline;
|
||||
|
||||
private Long savingsProductId;
|
||||
private String savingsProductName;
|
||||
|
||||
private Long savingsAccountId;
|
||||
private EnumOptionData legalForm;
|
||||
private Set<ClientCollateralManagementData> clientCollateralManagements;
|
||||
|
||||
// associations
|
||||
private Collection<GroupGeneralData> groups;
|
||||
|
||||
// template
|
||||
private Collection<OfficeData> officeOptions;
|
||||
private Collection<StaffData> staffOptions;
|
||||
private Collection<CodeValueData> narrations;
|
||||
private Collection<SavingsProductData> savingProductOptions;
|
||||
private Collection<SavingsAccountData> savingAccountOptions;
|
||||
private Collection<CodeValueData> genderOptions;
|
||||
private Collection<CodeValueData> clientTypeOptions;
|
||||
private Collection<CodeValueData> clientClassificationOptions;
|
||||
private Collection<CodeValueData> clientNonPersonConstitutionOptions;
|
||||
private Collection<CodeValueData> clientNonPersonMainBusinessLineOptions;
|
||||
private List<EnumOptionData> clientLegalFormOptions;
|
||||
private ClientFamilyMembersData familyMemberOptions;
|
||||
|
||||
private ClientNonPersonData clientNonPersonDetails;
|
||||
|
||||
private Collection<AddressData> address;
|
||||
|
||||
private Boolean isAddressEnabled;
|
||||
|
||||
private List<DatatableData> datatables;
|
||||
|
||||
// import fields
|
||||
private transient Integer rowIndex;
|
||||
private String dateFormat;
|
||||
private String locale;
|
||||
private Long clientTypeId;
|
||||
private Long genderId;
|
||||
private Long clientClassificationId;
|
||||
private Long legalFormId;
|
||||
private LocalDate submittedOnDate;
|
||||
|
||||
public static ClientData importClientEntityInstance(Long legalFormId, Integer rowIndex, String fullname, Long officeId,
|
||||
Long clientTypeId, Long clientClassificationId, Long staffId, Boolean active, LocalDate activationDate,
|
||||
LocalDate submittedOnDate, ExternalId externalId, LocalDate dateOfBirth, String mobileNo,
|
||||
ClientNonPersonData clientNonPersonDetails, Collection<AddressData> address, String locale, String dateFormat) {
|
||||
return new ClientData(legalFormId, rowIndex, fullname, null, null, null, submittedOnDate, activationDate, active, externalId,
|
||||
officeId, staffId, mobileNo, dateOfBirth, clientTypeId, null, clientClassificationId, null, address, clientNonPersonDetails,
|
||||
locale, dateFormat);
|
||||
}
|
||||
|
||||
public static ClientData createClientForInterestPosting(final Long id, final Long officeId) {
|
||||
return new ClientData(id, officeId);
|
||||
}
|
||||
|
||||
private ClientData(final Long clientId, final Long officeId) {
|
||||
this.rowIndex = null;
|
||||
this.dateFormat = null;
|
||||
this.locale = null;
|
||||
this.firstname = null;
|
||||
this.lastname = null;
|
||||
this.middlename = null;
|
||||
this.fullname = null;
|
||||
this.activationDate = null;
|
||||
this.submittedOnDate = null;
|
||||
this.active = null;
|
||||
this.externalId = null;
|
||||
this.officeId = officeId;
|
||||
this.staffId = null;
|
||||
this.legalFormId = null;
|
||||
this.mobileNo = null;
|
||||
this.dateOfBirth = null;
|
||||
this.clientTypeId = null;
|
||||
this.genderId = null;
|
||||
this.clientClassificationId = null;
|
||||
this.isStaff = false;
|
||||
this.address = null;
|
||||
this.accountNo = null;
|
||||
this.status = null;
|
||||
this.subStatus = null;
|
||||
this.displayName = null;
|
||||
this.gender = null;
|
||||
this.clientType = null;
|
||||
this.clientClassification = null;
|
||||
this.officeName = null;
|
||||
this.transferToOfficeId = null;
|
||||
this.transferToOfficeName = null;
|
||||
this.imageId = null;
|
||||
this.imagePresent = null;
|
||||
this.staffName = null;
|
||||
this.timeline = null;
|
||||
this.savingsProductId = null;
|
||||
this.savingsProductName = null;
|
||||
this.savingsAccountId = null;
|
||||
this.legalForm = null;
|
||||
this.groups = null;
|
||||
this.officeOptions = null;
|
||||
this.staffOptions = null;
|
||||
this.narrations = null;
|
||||
this.savingProductOptions = null;
|
||||
this.savingAccountOptions = null;
|
||||
this.genderOptions = null;
|
||||
this.clientTypeOptions = null;
|
||||
this.clientClassificationOptions = null;
|
||||
this.clientNonPersonConstitutionOptions = null;
|
||||
this.clientNonPersonMainBusinessLineOptions = null;
|
||||
this.clientLegalFormOptions = null;
|
||||
this.clientNonPersonDetails = null;
|
||||
this.isAddressEnabled = null;
|
||||
this.datatables = null;
|
||||
this.familyMemberOptions = null;
|
||||
this.emailAddress = null;
|
||||
this.clientCollateralManagements = null;
|
||||
this.id = clientId;
|
||||
}
|
||||
|
||||
public static ClientData importClientPersonInstance(Long legalFormId, Integer rowIndex, String firstname, String lastname,
|
||||
String middlename, LocalDate submittedOn, LocalDate activationDate, Boolean active, ExternalId externalId, Long officeId,
|
||||
Long staffId, String mobileNo, LocalDate dob, Long clientTypeId, Long genderId, Long clientClassificationId, Boolean isStaff,
|
||||
Collection<AddressData> address, String locale, String dateFormat) {
|
||||
|
||||
return new ClientData(legalFormId, rowIndex, null, firstname, lastname, middlename, submittedOn, activationDate, active, externalId,
|
||||
officeId, staffId, mobileNo, dob, clientTypeId, genderId, clientClassificationId, isStaff, address, null, locale,
|
||||
dateFormat);
|
||||
}
|
||||
|
||||
public static ClientData emptyInstance(Long clientId) {
|
||||
return lookup(clientId, null, null, null);
|
||||
}
|
||||
|
||||
private ClientData(Long legalFormId, Integer rowIndex, String fullname, String firstname, String lastname, String middlename,
|
||||
LocalDate submittedOn, LocalDate activationDate, Boolean active, ExternalId externalId, Long officeId, Long staffId,
|
||||
String mobileNo, LocalDate dob, Long clientTypeId, Long genderId, Long clientClassificationId, Boolean isStaff,
|
||||
Collection<AddressData> address, ClientNonPersonData clientNonPersonDetails, String locale, String dateFormat) {
|
||||
this.rowIndex = rowIndex;
|
||||
this.dateFormat = dateFormat;
|
||||
this.locale = locale;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.middlename = middlename;
|
||||
this.fullname = fullname;
|
||||
this.activationDate = activationDate;
|
||||
this.submittedOnDate = submittedOn;
|
||||
this.active = active;
|
||||
this.externalId = externalId;
|
||||
this.officeId = officeId;
|
||||
this.staffId = staffId;
|
||||
this.legalFormId = legalFormId;
|
||||
this.mobileNo = mobileNo;
|
||||
this.dateOfBirth = dob;
|
||||
this.clientTypeId = clientTypeId;
|
||||
this.genderId = genderId;
|
||||
this.clientClassificationId = clientClassificationId;
|
||||
this.isStaff = isStaff;
|
||||
this.address = address;
|
||||
this.id = null;
|
||||
this.accountNo = null;
|
||||
this.status = null;
|
||||
this.subStatus = null;
|
||||
this.displayName = null;
|
||||
this.gender = null;
|
||||
this.clientType = null;
|
||||
this.clientClassification = null;
|
||||
this.officeName = null;
|
||||
this.transferToOfficeId = null;
|
||||
this.transferToOfficeName = null;
|
||||
this.imageId = null;
|
||||
this.imagePresent = null;
|
||||
this.staffName = null;
|
||||
this.timeline = null;
|
||||
this.savingsProductId = null;
|
||||
this.savingsProductName = null;
|
||||
this.savingsAccountId = null;
|
||||
this.legalForm = null;
|
||||
this.groups = null;
|
||||
this.officeOptions = null;
|
||||
this.staffOptions = null;
|
||||
this.narrations = null;
|
||||
this.savingProductOptions = null;
|
||||
this.savingAccountOptions = null;
|
||||
this.genderOptions = null;
|
||||
this.clientTypeOptions = null;
|
||||
this.clientClassificationOptions = null;
|
||||
this.clientNonPersonConstitutionOptions = null;
|
||||
this.clientNonPersonMainBusinessLineOptions = null;
|
||||
this.clientLegalFormOptions = null;
|
||||
this.clientNonPersonDetails = null;
|
||||
this.isAddressEnabled = null;
|
||||
this.datatables = null;
|
||||
this.familyMemberOptions = null;
|
||||
this.emailAddress = null;
|
||||
this.clientCollateralManagements = null;
|
||||
}
|
||||
|
||||
public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection<OfficeData> officeOptions,
|
||||
final Collection<StaffData> staffOptions, final Collection<CodeValueData> narrations,
|
||||
final Collection<CodeValueData> genderOptions, final Collection<SavingsProductData> savingProductOptions,
|
||||
final Collection<CodeValueData> clientTypeOptions, final Collection<CodeValueData> clientClassificationOptions,
|
||||
final Collection<CodeValueData> clientNonPersonConstitutionOptions,
|
||||
final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions, final List<EnumOptionData> clientLegalFormOptions,
|
||||
final ClientFamilyMembersData familyMemberOptions, final Collection<AddressData> address, final Boolean isAddressEnabled,
|
||||
final List<DatatableData> datatables) {
|
||||
final String accountNo = null;
|
||||
final EnumOptionData status = null;
|
||||
final CodeValueData subStatus = null;
|
||||
final String officeName = null;
|
||||
final Long transferToOfficeId = null;
|
||||
final String transferToOfficeName = null;
|
||||
final Long id = null;
|
||||
final String firstname = null;
|
||||
final String middlename = null;
|
||||
final String lastname = null;
|
||||
final String fullname = null;
|
||||
final String displayName = null;
|
||||
final ExternalId externalId = ExternalId.empty();
|
||||
final String mobileNo = null;
|
||||
final String emailAddress = null;
|
||||
final LocalDate dateOfBirth = null;
|
||||
final CodeValueData gender = null;
|
||||
final Long imageId = null;
|
||||
final Long staffId = null;
|
||||
final String staffName = null;
|
||||
final Collection<GroupGeneralData> groups = null;
|
||||
final ClientTimelineData timeline = null;
|
||||
final Long savingsProductId = null;
|
||||
final String savingsProductName = null;
|
||||
final Long savingsAccountId = null;
|
||||
final Collection<SavingsAccountData> savingAccountOptions = null;
|
||||
final CodeValueData clientType = null;
|
||||
final CodeValueData clientClassification = null;
|
||||
final EnumOptionData legalForm = null;
|
||||
final Boolean isStaff = false;
|
||||
final ClientNonPersonData clientNonPersonDetails = null;
|
||||
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
|
||||
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, joinedDate, imageId,
|
||||
staffId, staffName, officeOptions, groups, staffOptions, narrations, genderOptions, timeline, savingProductOptions,
|
||||
savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification,
|
||||
clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions,
|
||||
clientNonPersonDetails, clientLegalFormOptions, familyMemberOptions, legalForm, address, isAddressEnabled, datatables,
|
||||
isStaff, clientCollateralManagements);
|
||||
|
||||
}
|
||||
|
||||
public static ClientData templateOnTop(final ClientData clientData, final ClientData templateData) {
|
||||
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
|
||||
return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName,
|
||||
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
|
||||
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
|
||||
clientData.emailAddress, clientData.dateOfBirth, clientData.gender, clientData.activationDate, clientData.imageId,
|
||||
clientData.staffId, clientData.staffName, templateData.officeOptions, clientData.groups, templateData.staffOptions,
|
||||
templateData.narrations, templateData.genderOptions, clientData.timeline, templateData.savingProductOptions,
|
||||
clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, clientData.savingAccountOptions,
|
||||
clientData.clientType, clientData.clientClassification, templateData.clientTypeOptions,
|
||||
templateData.clientClassificationOptions, templateData.clientNonPersonConstitutionOptions,
|
||||
templateData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, templateData.clientLegalFormOptions,
|
||||
templateData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null,
|
||||
clientData.isStaff, clientCollateralManagements);
|
||||
|
||||
}
|
||||
|
||||
public static ClientData templateWithSavingAccountOptions(final ClientData clientData,
|
||||
final Collection<SavingsAccountData> savingAccountOptions) {
|
||||
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
|
||||
return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName,
|
||||
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
|
||||
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
|
||||
clientData.emailAddress, clientData.dateOfBirth, clientData.gender, clientData.activationDate, clientData.imageId,
|
||||
clientData.staffId, clientData.staffName, clientData.officeOptions, clientData.groups, clientData.staffOptions,
|
||||
clientData.narrations, clientData.genderOptions, clientData.timeline, clientData.savingProductOptions,
|
||||
clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, savingAccountOptions,
|
||||
clientData.clientType, clientData.clientClassification, clientData.clientTypeOptions,
|
||||
clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions,
|
||||
clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, clientData.clientLegalFormOptions,
|
||||
clientData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null,
|
||||
clientData.isStaff, clientCollateralManagements);
|
||||
|
||||
}
|
||||
|
||||
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups,
|
||||
final Set<ClientCollateralManagementData> clientCollateralManagements) {
|
||||
return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName,
|
||||
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
|
||||
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
|
||||
clientData.emailAddress, clientData.dateOfBirth, clientData.gender, clientData.activationDate, clientData.imageId,
|
||||
clientData.staffId, clientData.staffName, clientData.officeOptions, parentGroups, clientData.staffOptions, null, null,
|
||||
clientData.timeline, clientData.savingProductOptions, clientData.savingsProductId, clientData.savingsProductName,
|
||||
clientData.savingsAccountId, clientData.savingAccountOptions, clientData.clientType, clientData.clientClassification,
|
||||
clientData.clientTypeOptions, clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions,
|
||||
clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, clientData.clientLegalFormOptions,
|
||||
clientData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null,
|
||||
clientData.isStaff, clientCollateralManagements);
|
||||
|
||||
}
|
||||
|
||||
public static ClientData clientIdentifier(final Long id, final String accountNo, final String firstname, final String middlename,
|
||||
final String lastname, final String fullname, final String displayName, final Long officeId, final String officeName) {
|
||||
|
||||
final Long transferToOfficeId = null;
|
||||
final String transferToOfficeName = null;
|
||||
final ExternalId externalId = ExternalId.empty();
|
||||
final String mobileNo = null;
|
||||
final String emailAddress = null;
|
||||
final LocalDate dateOfBirth = null;
|
||||
final CodeValueData gender = null;
|
||||
final LocalDate activationDate = null;
|
||||
final Long imageId = null;
|
||||
final Long staffId = null;
|
||||
final String staffName = null;
|
||||
final Collection<OfficeData> allowedOffices = null;
|
||||
final Collection<GroupGeneralData> groups = null;
|
||||
final Collection<StaffData> staffOptions = null;
|
||||
final Collection<CodeValueData> closureReasons = null;
|
||||
final Collection<CodeValueData> genderOptions = null;
|
||||
final ClientTimelineData timeline = null;
|
||||
final Collection<SavingsProductData> savingProductOptions = null;
|
||||
final Long savingsProductId = null;
|
||||
final String savingsProductName = null;
|
||||
final Long savingsAccountId = null;
|
||||
final Collection<SavingsAccountData> savingAccountOptions = null;
|
||||
final CodeValueData clientType = null;
|
||||
final CodeValueData clientClassification = null;
|
||||
final Collection<CodeValueData> clientTypeOptions = null;
|
||||
final Collection<CodeValueData> clientClassificationOptions = null;
|
||||
final Collection<CodeValueData> clientNonPersonConstitutionOptions = null;
|
||||
final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions = null;
|
||||
final List<EnumOptionData> clientLegalFormOptions = null;
|
||||
final ClientFamilyMembersData familyMemberOptions = null;
|
||||
final EnumOptionData status = null;
|
||||
final CodeValueData subStatus = null;
|
||||
final EnumOptionData legalForm = null;
|
||||
final Boolean isStaff = false;
|
||||
final ClientNonPersonData clientNonPerson = null;
|
||||
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
|
||||
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate,
|
||||
imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline,
|
||||
savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType,
|
||||
clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions,
|
||||
clientNonPersonMainBusinessLineOptions, clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null,
|
||||
null, isStaff, clientCollateralManagements);
|
||||
}
|
||||
|
||||
public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) {
|
||||
final String accountNo = null;
|
||||
final EnumOptionData status = null;
|
||||
final CodeValueData subStatus = null;
|
||||
final Long transferToOfficeId = null;
|
||||
final String transferToOfficeName = null;
|
||||
final String firstname = null;
|
||||
final String middlename = null;
|
||||
final String lastname = null;
|
||||
final String fullname = null;
|
||||
final ExternalId externalId = ExternalId.empty();
|
||||
final String mobileNo = null;
|
||||
final String emailAddress = null;
|
||||
final LocalDate dateOfBirth = null;
|
||||
final CodeValueData gender = null;
|
||||
final LocalDate activationDate = null;
|
||||
final Long imageId = null;
|
||||
final Long staffId = null;
|
||||
final String staffName = null;
|
||||
final Collection<OfficeData> allowedOffices = null;
|
||||
final Collection<GroupGeneralData> groups = null;
|
||||
final Collection<StaffData> staffOptions = null;
|
||||
final Collection<CodeValueData> closureReasons = null;
|
||||
final Collection<CodeValueData> genderOptions = null;
|
||||
final ClientTimelineData timeline = null;
|
||||
final Collection<SavingsProductData> savingProductOptions = null;
|
||||
final Long savingsProductId = null;
|
||||
final String savingsProductName = null;
|
||||
final Long savingsAccountId = null;
|
||||
final Collection<SavingsAccountData> savingAccountOptions = null;
|
||||
final CodeValueData clientType = null;
|
||||
final CodeValueData clientClassification = null;
|
||||
final Collection<CodeValueData> clientTypeOptions = null;
|
||||
final Collection<CodeValueData> clientClassificationOptions = null;
|
||||
final Collection<CodeValueData> clientNonPersonConstitutionOptions = null;
|
||||
final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions = null;
|
||||
final List<EnumOptionData> clientLegalFormOptions = null;
|
||||
final ClientFamilyMembersData familyMemberOptions = null;
|
||||
final EnumOptionData legalForm = null;
|
||||
final Boolean isStaff = false;
|
||||
final ClientNonPersonData clientNonPerson = null;
|
||||
final Set<ClientCollateralManagementData> clientCollateralManagements = null;
|
||||
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate,
|
||||
imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline,
|
||||
savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType,
|
||||
clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions,
|
||||
clientNonPersonMainBusinessLineOptions, clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null,
|
||||
null, isStaff, clientCollateralManagements);
|
||||
|
||||
}
|
||||
|
||||
public static ClientData instance(final Long id, final String displayName) {
|
||||
final Long officeId = null;
|
||||
final String officeName = null;
|
||||
return lookup(id, displayName, officeId, officeName);
|
||||
}
|
||||
|
||||
public static ClientData instance(final String accountNo, final EnumOptionData status, final CodeValueData subStatus,
|
||||
final Long officeId, final String officeName, final Long transferToOfficeId, final String transferToOfficeName, final Long id,
|
||||
final String firstname, final String middlename, final String lastname, final String fullname, final String displayName,
|
||||
final ExternalId externalId, final String mobileNo, final String emailAddress, final LocalDate dateOfBirth,
|
||||
final CodeValueData gender, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,
|
||||
final ClientTimelineData timeline, final Long savingsProductId, final String savingsProductName, final Long savingsAccountId,
|
||||
final CodeValueData clientType, final CodeValueData clientClassification, final EnumOptionData legalForm,
|
||||
final ClientNonPersonData clientNonPerson, final Boolean isStaff) {
|
||||
|
||||
final Collection<OfficeData> allowedOffices = null;
|
||||
final Collection<GroupGeneralData> groups = null;
|
||||
final Collection<StaffData> staffOptions = null;
|
||||
final Collection<CodeValueData> closureReasons = null;
|
||||
final Collection<CodeValueData> genderOptions = null;
|
||||
final Collection<SavingsProductData> savingProductOptions = null;
|
||||
final Collection<CodeValueData> clientTypeOptions = null;
|
||||
final Collection<CodeValueData> clientClassificationOptions = null;
|
||||
final Collection<CodeValueData> clientNonPersonConstitutionOptions = null;
|
||||
final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions = null;
|
||||
final List<EnumOptionData> clientLegalFormOptions = null;
|
||||
final ClientFamilyMembersData familyMemberOptions = null;
|
||||
return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate,
|
||||
imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline,
|
||||
savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, null, clientType, clientClassification,
|
||||
clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions,
|
||||
clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null, null, isStaff, null);
|
||||
|
||||
}
|
||||
|
||||
private ClientData(final String accountNo, final EnumOptionData status, final CodeValueData subStatus, final Long officeId,
|
||||
final String officeName, final Long transferToOfficeId, final String transferToOfficeName, final Long id,
|
||||
final String firstname, final String middlename, final String lastname, final String fullname, final String displayName,
|
||||
final ExternalId externalId, final String mobileNo, final String emailAddress, final LocalDate dateOfBirth,
|
||||
final CodeValueData gender, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,
|
||||
final Collection<OfficeData> allowedOffices, final Collection<GroupGeneralData> groups,
|
||||
final Collection<StaffData> staffOptions, final Collection<CodeValueData> narrations,
|
||||
final Collection<CodeValueData> genderOptions, final ClientTimelineData timeline,
|
||||
final Collection<SavingsProductData> savingProductOptions, final Long savingsProductId, final String savingsProductName,
|
||||
final Long savingsAccountId, final Collection<SavingsAccountData> savingAccountOptions, final CodeValueData clientType,
|
||||
final CodeValueData clientClassification, final Collection<CodeValueData> clientTypeOptions,
|
||||
final Collection<CodeValueData> clientClassificationOptions, final Collection<CodeValueData> clientNonPersonConstitutionOptions,
|
||||
final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions, final ClientNonPersonData clientNonPerson,
|
||||
final List<EnumOptionData> clientLegalFormOptions, final ClientFamilyMembersData familyMemberOptions,
|
||||
final EnumOptionData legalForm, final Collection<AddressData> address, final Boolean isAddressEnabled,
|
||||
final List<DatatableData> datatables, final Boolean isStaff,
|
||||
final Set<ClientCollateralManagementData> clientCollateralManagements) {
|
||||
this.accountNo = accountNo;
|
||||
this.status = status;
|
||||
if (status != null) {
|
||||
this.active = status.getId().equals(300L);
|
||||
} else {
|
||||
this.active = null;
|
||||
}
|
||||
this.subStatus = subStatus;
|
||||
this.officeId = officeId;
|
||||
this.officeName = officeName;
|
||||
this.transferToOfficeId = transferToOfficeId;
|
||||
this.transferToOfficeName = transferToOfficeName;
|
||||
this.id = id;
|
||||
this.firstname = StringUtils.defaultIfEmpty(firstname, null);
|
||||
this.middlename = StringUtils.defaultIfEmpty(middlename, null);
|
||||
this.lastname = StringUtils.defaultIfEmpty(lastname, null);
|
||||
this.fullname = StringUtils.defaultIfEmpty(fullname, null);
|
||||
this.displayName = StringUtils.defaultIfEmpty(displayName, null);
|
||||
this.externalId = externalId;
|
||||
this.mobileNo = StringUtils.defaultIfEmpty(mobileNo, null);
|
||||
this.emailAddress = StringUtils.defaultIfEmpty(emailAddress, null);
|
||||
this.activationDate = activationDate;
|
||||
this.dateOfBirth = dateOfBirth;
|
||||
this.gender = gender;
|
||||
this.clientClassification = clientClassification;
|
||||
this.clientType = clientType;
|
||||
this.imageId = imageId;
|
||||
if (imageId != null) {
|
||||
this.imagePresent = Boolean.TRUE;
|
||||
} else {
|
||||
this.imagePresent = null;
|
||||
}
|
||||
this.staffId = staffId;
|
||||
this.staffName = staffName;
|
||||
|
||||
// associations
|
||||
this.groups = groups;
|
||||
|
||||
// template
|
||||
this.officeOptions = allowedOffices;
|
||||
this.staffOptions = staffOptions;
|
||||
this.narrations = narrations;
|
||||
|
||||
this.genderOptions = genderOptions;
|
||||
this.clientClassificationOptions = clientClassificationOptions;
|
||||
this.clientTypeOptions = clientTypeOptions;
|
||||
|
||||
this.clientNonPersonConstitutionOptions = clientNonPersonConstitutionOptions;
|
||||
this.clientNonPersonMainBusinessLineOptions = clientNonPersonMainBusinessLineOptions;
|
||||
this.clientLegalFormOptions = clientLegalFormOptions;
|
||||
this.familyMemberOptions = familyMemberOptions;
|
||||
|
||||
this.timeline = timeline;
|
||||
this.savingProductOptions = savingProductOptions;
|
||||
this.savingsProductId = savingsProductId;
|
||||
this.savingsProductName = savingsProductName;
|
||||
this.savingsAccountId = savingsAccountId;
|
||||
this.savingAccountOptions = savingAccountOptions;
|
||||
this.legalForm = legalForm;
|
||||
this.isStaff = isStaff;
|
||||
this.clientNonPersonDetails = clientNonPerson;
|
||||
|
||||
this.address = address;
|
||||
this.isAddressEnabled = isAddressEnabled;
|
||||
this.datatables = datatables;
|
||||
this.clientCollateralManagements = clientCollateralManagements;
|
||||
}
|
||||
|
||||
public ExternalId getExternalId() {
|
||||
if (this.externalId == null) {
|
||||
return ExternalId.empty();
|
||||
}
|
||||
return this.externalId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ClientData obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
}
|
||||
return new CompareToBuilder() //
|
||||
.append(this.id, obj.id) //
|
||||
.append(this.displayName, obj.displayName) //
|
||||
.toComparison();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
final ClientData rhs = (ClientData) obj;
|
||||
return new EqualsBuilder() //
|
||||
.append(this.id, rhs.id) //
|
||||
.append(this.displayName, rhs.displayName) //
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37) //
|
||||
.append(this.id) //
|
||||
.append(this.displayName) //
|
||||
.toHashCode();
|
||||
}
|
||||
}
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* 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.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
|
||||
public final class ClientFamilyMembersData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final Long clientId;
|
||||
|
||||
private final String firstName;
|
||||
|
||||
private final String middleName;
|
||||
|
||||
private final String lastName;
|
||||
|
||||
private final String qualification;
|
||||
|
||||
private final Long relationshipId;
|
||||
|
||||
private final String relationship;
|
||||
|
||||
private final Long maritalStatusId;
|
||||
|
||||
private final String maritalStatus;
|
||||
|
||||
private final Long genderId;
|
||||
|
||||
private final String gender;
|
||||
|
||||
private final LocalDate dateOfBirth;
|
||||
|
||||
private final Long professionId;
|
||||
|
||||
private final String profession;
|
||||
|
||||
private final String mobileNumber;
|
||||
|
||||
private final Long age;
|
||||
|
||||
private final Boolean isDependent;
|
||||
|
||||
// template holder
|
||||
private final Collection<CodeValueData> relationshipIdOptions;
|
||||
private final Collection<CodeValueData> genderIdOptions;
|
||||
private final Collection<CodeValueData> maritalStatusIdOptions;
|
||||
private final Collection<CodeValueData> professionIdOptions;
|
||||
|
||||
private ClientFamilyMembersData(final Long id, final Long clientId, final String firstName, final String middleName,
|
||||
final String lastName, final String qualification, final String mobileNumber, final Long age, final Boolean isDependent,
|
||||
final String relationship, final Long relationshipId, final String maritalStatus, final Long maritalStatusId,
|
||||
final String gender, final Long genderId, final LocalDate dateOfBirth, final String profession, final Long professionId,
|
||||
final Collection<CodeValueData> relationshipIdOptions, final Collection<CodeValueData> genderIdOptions,
|
||||
final Collection<CodeValueData> maritalStatusIdOptions, final Collection<CodeValueData> professionIdOptions) {
|
||||
this.id = id;
|
||||
this.clientId = clientId;
|
||||
this.firstName = firstName;
|
||||
this.middleName = middleName;
|
||||
this.lastName = lastName;
|
||||
this.qualification = qualification;
|
||||
this.relationship = relationship;
|
||||
this.relationshipId = relationshipId;
|
||||
this.maritalStatus = maritalStatus;
|
||||
this.maritalStatusId = maritalStatusId;
|
||||
this.gender = gender;
|
||||
this.genderId = genderId;
|
||||
this.dateOfBirth = dateOfBirth;
|
||||
this.profession = profession;
|
||||
this.professionId = professionId;
|
||||
this.mobileNumber = mobileNumber;
|
||||
this.age = age;
|
||||
this.isDependent = isDependent;
|
||||
this.relationshipIdOptions = relationshipIdOptions;
|
||||
this.genderIdOptions = genderIdOptions;
|
||||
this.maritalStatusIdOptions = maritalStatusIdOptions;
|
||||
this.professionIdOptions = professionIdOptions;
|
||||
|
||||
}
|
||||
|
||||
public static ClientFamilyMembersData instance(final Long id, final Long clientId, final String firstName, final String middleName,
|
||||
final String lastName, final String qualification, final String mobileNumber, final Long age, final Boolean isDependent,
|
||||
final String relationship, final Long relationshipId, final String maritalStatus, final Long maritalStatusId,
|
||||
final String gender, final Long genderId, final LocalDate dateOfBirth, final String profession, final Long professionId) {
|
||||
return new ClientFamilyMembersData(id, clientId, firstName, middleName, lastName, qualification, mobileNumber, age, isDependent,
|
||||
relationship, relationshipId, maritalStatus, maritalStatusId, gender, genderId, dateOfBirth, profession, professionId, null,
|
||||
null, null, null);
|
||||
}
|
||||
|
||||
public static ClientFamilyMembersData templateInstance(final Collection<CodeValueData> relationshipIdOptions,
|
||||
final Collection<CodeValueData> genderIdOptions, final Collection<CodeValueData> maritalStatusIdOptions,
|
||||
final Collection<CodeValueData> professionIdOptions) {
|
||||
|
||||
return new ClientFamilyMembersData(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, relationshipIdOptions, genderIdOptions, maritalStatusIdOptions, professionIdOptions);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public Long getClientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
public String getMiddleName() {
|
||||
return this.middleName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return this.lastName;
|
||||
}
|
||||
|
||||
public String getQualification() {
|
||||
return this.qualification;
|
||||
}
|
||||
|
||||
public Long getRelationshipId() {
|
||||
return this.relationshipId;
|
||||
}
|
||||
|
||||
public String getRelationship() {
|
||||
return this.relationship;
|
||||
}
|
||||
|
||||
public Long getMaritalStatusId() {
|
||||
return this.maritalStatusId;
|
||||
}
|
||||
|
||||
public String getMaritalStatus() {
|
||||
return this.maritalStatus;
|
||||
}
|
||||
|
||||
public Long getGenderId() {
|
||||
return this.genderId;
|
||||
}
|
||||
|
||||
public String getGender() {
|
||||
return this.gender;
|
||||
}
|
||||
|
||||
public LocalDate getDateOfBirth() {
|
||||
return this.dateOfBirth;
|
||||
}
|
||||
|
||||
public Long getProfessionId() {
|
||||
return this.professionId;
|
||||
}
|
||||
|
||||
public String getProfession() {
|
||||
return this.profession;
|
||||
}
|
||||
|
||||
public String getMobileNumber() {
|
||||
return this.mobileNumber;
|
||||
}
|
||||
|
||||
public Long getAge() {
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public Boolean getIsDependent() {
|
||||
return this.isDependent;
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing the ClientNonPerson
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientNonPersonData implements Serializable {
|
||||
|
||||
private final CodeValueData constitution;
|
||||
private final String incorpNumber;
|
||||
private final LocalDate incorpValidityTillDate;
|
||||
private final CodeValueData mainBusinessLine;
|
||||
private final String remarks;
|
||||
|
||||
// import fields
|
||||
private Long mainBusinessLineId;
|
||||
private Long constitutionId;
|
||||
private String locale;
|
||||
private String dateFormat;
|
||||
|
||||
public static ClientNonPersonData importInstance(String incorporationNo, LocalDate incorpValidityTillDate, String remarks,
|
||||
Long mainBusinessLineId, Long constitutionId, String locale, String dateFormat) {
|
||||
return new ClientNonPersonData(incorporationNo, incorpValidityTillDate, remarks, mainBusinessLineId, constitutionId, locale,
|
||||
dateFormat);
|
||||
}
|
||||
|
||||
private ClientNonPersonData(String incorpNumber, LocalDate incorpValidityTillDate, String remarks, Long mainBusinessLineId,
|
||||
Long constitutionId, String locale, String dateFormat) {
|
||||
|
||||
this.incorpNumber = incorpNumber;
|
||||
this.incorpValidityTillDate = incorpValidityTillDate;
|
||||
this.remarks = remarks;
|
||||
this.mainBusinessLineId = mainBusinessLineId;
|
||||
this.constitutionId = constitutionId;
|
||||
this.dateFormat = dateFormat;
|
||||
this.locale = locale;
|
||||
this.constitution = null;
|
||||
this.mainBusinessLine = null;
|
||||
}
|
||||
|
||||
public ClientNonPersonData(CodeValueData constitution, String incorpNo, LocalDate incorpValidityTillDate,
|
||||
CodeValueData mainBusinessLine, String remarks) {
|
||||
|
||||
this.constitution = constitution;
|
||||
this.incorpNumber = incorpNo;
|
||||
this.incorpValidityTillDate = incorpValidityTillDate;
|
||||
this.mainBusinessLine = mainBusinessLine;
|
||||
this.remarks = remarks;
|
||||
}
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Immutable data object represent the important time-line events of a loan application and loan.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Getter
|
||||
public class ClientTimelineData implements Serializable {
|
||||
|
||||
private final LocalDate submittedOnDate;
|
||||
private final String submittedByUsername;
|
||||
private final String submittedByFirstname;
|
||||
private final String submittedByLastname;
|
||||
|
||||
private final LocalDate activatedOnDate;
|
||||
private final String activatedByUsername;
|
||||
private final String activatedByFirstname;
|
||||
private final String activatedByLastname;
|
||||
|
||||
private final LocalDate closedOnDate;
|
||||
private final String closedByUsername;
|
||||
private final String closedByFirstname;
|
||||
private final String closedByLastname;
|
||||
|
||||
public ClientTimelineData(final LocalDate submittedOnDate, final String submittedByUsername, final String submittedByFirstname,
|
||||
final String submittedByLastname, final LocalDate activatedOnDate, final String activatedByUsername,
|
||||
final String activatedByFirstname, final String activatedByLastname, final LocalDate closedOnDate,
|
||||
final String closedByUsername, final String closedByFirstname, final String closedByLastname) {
|
||||
this.submittedOnDate = submittedOnDate;
|
||||
this.submittedByUsername = submittedByUsername;
|
||||
this.submittedByFirstname = submittedByFirstname;
|
||||
this.submittedByLastname = submittedByLastname;
|
||||
|
||||
this.activatedOnDate = activatedOnDate;
|
||||
this.activatedByUsername = activatedByUsername;
|
||||
this.activatedByFirstname = activatedByFirstname;
|
||||
this.activatedByLastname = activatedByLastname;
|
||||
|
||||
this.closedOnDate = closedOnDate;
|
||||
this.closedByUsername = closedByUsername;
|
||||
this.closedByFirstname = closedByFirstname;
|
||||
this.closedByLastname = closedByLastname;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,774 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.documentmanagement.domain.Image;
|
||||
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.organisation.staff.domain.Staff;
|
||||
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "m_client", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "account_no_UNIQUE"), //
|
||||
@UniqueConstraint(columnNames = { "mobile_no" }, name = "mobile_no_UNIQUE") })
|
||||
public class Client extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
@Column(name = "account_no", length = 20, unique = true, nullable = false)
|
||||
private String accountNumber;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "office_id", nullable = false)
|
||||
private Office office;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "transfer_to_office_id")
|
||||
private Office transferToOffice;
|
||||
|
||||
@OneToOne(optional = true)
|
||||
@JoinColumn(name = "image_id")
|
||||
private Image image;
|
||||
|
||||
/**
|
||||
* A value from {@link ClientStatus}.
|
||||
*/
|
||||
@Column(name = "status_enum", nullable = false)
|
||||
private Integer status;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "sub_status")
|
||||
private CodeValue subStatus;
|
||||
|
||||
@Column(name = "activation_date")
|
||||
private LocalDate activationDate;
|
||||
|
||||
@Column(name = "office_joining_date")
|
||||
private LocalDate officeJoiningDate;
|
||||
|
||||
@Column(name = "firstname", length = 50)
|
||||
private String firstname;
|
||||
|
||||
@Column(name = "middlename", length = 50)
|
||||
private String middlename;
|
||||
|
||||
@Column(name = "lastname", length = 50)
|
||||
private String lastname;
|
||||
|
||||
@Column(name = "fullname", length = 100)
|
||||
private String fullname;
|
||||
|
||||
@Column(name = "display_name", length = 100, nullable = false)
|
||||
private String displayName;
|
||||
|
||||
@Column(name = "mobile_no", length = 50, unique = true)
|
||||
private String mobileNo;
|
||||
|
||||
@Column(name = "email_address", length = 50, unique = true)
|
||||
private String emailAddress;
|
||||
|
||||
@Column(name = "is_staff", nullable = false)
|
||||
private boolean isStaff;
|
||||
|
||||
@Column(name = "external_id", length = 100, unique = true)
|
||||
private ExternalId externalId;
|
||||
|
||||
@Column(name = "date_of_birth")
|
||||
private LocalDate dateOfBirth;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "gender_cv_id")
|
||||
private CodeValue gender;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "staff_id")
|
||||
private Staff staff;
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
|
||||
private Set<Group> groups;
|
||||
|
||||
@Transient
|
||||
private boolean accountNumberRequiresAutoGeneration = false;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "closure_reason_cv_id")
|
||||
private CodeValue closureReason;
|
||||
|
||||
@Column(name = "closedon_date")
|
||||
private LocalDate closureDate;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "reject_reason_cv_id")
|
||||
private CodeValue rejectionReason;
|
||||
|
||||
@Column(name = "rejectedon_date")
|
||||
private LocalDate rejectionDate;
|
||||
|
||||
@ManyToOne(optional = true, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "rejectedon_userid")
|
||||
private AppUser rejectedBy;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "withdraw_reason_cv_id")
|
||||
private CodeValue withdrawalReason;
|
||||
|
||||
@Column(name = "withdrawn_on_date")
|
||||
private LocalDate withdrawalDate;
|
||||
|
||||
@ManyToOne(optional = true, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "withdraw_on_userid")
|
||||
private AppUser withdrawnBy;
|
||||
|
||||
@Column(name = "reactivated_on_date")
|
||||
private LocalDate reactivateDate;
|
||||
|
||||
@ManyToOne(optional = true, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "reactivated_on_userid")
|
||||
private AppUser reactivatedBy;
|
||||
|
||||
@ManyToOne(optional = true, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "closedon_userid")
|
||||
private AppUser closedBy;
|
||||
|
||||
@Column(name = "submittedon_date")
|
||||
private LocalDate submittedOnDate;
|
||||
|
||||
/*
|
||||
* Deprecated since common Auditable fields were introduced. Columns and data left untouched to help migration.
|
||||
*
|
||||
* @Column(name = "updated_on") private LocalDate updatedOnDate;
|
||||
*
|
||||
* @ManyToOne(optional = true, fetch = FetchType.LAZY)
|
||||
*
|
||||
* @JoinColumn(name = "updated_by") private AppUser updatedBy;
|
||||
*/
|
||||
|
||||
@ManyToOne(optional = true, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "activatedon_userid")
|
||||
private AppUser activatedBy;
|
||||
|
||||
@Column(name = "default_savings_product")
|
||||
private Long savingsProductId;
|
||||
|
||||
@Column(name = "default_savings_account")
|
||||
private Long savingsAccountId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "client_type_cv_id")
|
||||
private CodeValue clientType;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "client_classification_cv_id")
|
||||
private CodeValue clientClassification;
|
||||
|
||||
@Column(name = "legal_form_enum")
|
||||
private Integer legalForm;
|
||||
|
||||
@Column(name = "reopened_on_date")
|
||||
private LocalDate reopenedDate;
|
||||
|
||||
@ManyToOne(optional = true, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "reopened_by_userid")
|
||||
private AppUser reopenedBy;
|
||||
|
||||
@Column(name = "proposed_transfer_date")
|
||||
private LocalDate proposedTransferDate;
|
||||
|
||||
public static Client instance(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,
|
||||
final LocalDate activationDate, final LocalDate officeJoiningDate, final ExternalId externalId, final String mobileNo,
|
||||
final String emailAddress, final Staff staff, final LocalDate submittedOnDate, final Long savingsProductId,
|
||||
final Long savingsAccountId, final LocalDate dateOfBirth, final CodeValue gender, final CodeValue clientType,
|
||||
final CodeValue clientClassification, final Integer legalForm, final Boolean isStaff) {
|
||||
return new Client(currentUser, status, office, clientParentGroup, accountNo, firstname, middlename, lastname, fullname,
|
||||
activationDate, officeJoiningDate, externalId, mobileNo, emailAddress, staff, submittedOnDate, savingsProductId,
|
||||
savingsAccountId, dateOfBirth, gender, clientType, clientClassification, legalForm, isStaff);
|
||||
}
|
||||
|
||||
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,
|
||||
final LocalDate activationDate, final LocalDate officeJoiningDate, final ExternalId externalId, final String mobileNo,
|
||||
final String emailAddress, final Staff staff, final LocalDate submittedOnDate, final Long savingsProductId,
|
||||
final Long savingsAccountId, final LocalDate dateOfBirth, final CodeValue gender, final CodeValue clientType,
|
||||
final CodeValue clientClassification, final Integer legalForm, final Boolean isStaff) {
|
||||
|
||||
if (StringUtils.isBlank(accountNo)) {
|
||||
this.accountNumber = new RandomPasswordGenerator(19).generate();
|
||||
this.accountNumberRequiresAutoGeneration = true;
|
||||
} else {
|
||||
this.accountNumber = accountNo;
|
||||
}
|
||||
|
||||
this.submittedOnDate = submittedOnDate;
|
||||
|
||||
this.status = status.getValue();
|
||||
this.office = office;
|
||||
this.externalId = externalId;
|
||||
|
||||
if (StringUtils.isNotBlank(mobileNo)) {
|
||||
this.mobileNo = mobileNo.trim();
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(emailAddress)) {
|
||||
this.emailAddress = emailAddress.trim();
|
||||
}
|
||||
|
||||
if (activationDate != null) {
|
||||
this.activationDate = activationDate;
|
||||
this.activatedBy = currentUser;
|
||||
}
|
||||
|
||||
this.officeJoiningDate = officeJoiningDate;
|
||||
|
||||
if (StringUtils.isNotBlank(firstname)) {
|
||||
this.firstname = firstname.trim();
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(middlename)) {
|
||||
this.middlename = middlename.trim();
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(lastname)) {
|
||||
this.lastname = lastname.trim();
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(fullname)) {
|
||||
this.fullname = fullname.trim();
|
||||
}
|
||||
|
||||
if (clientParentGroup != null) {
|
||||
this.groups = new HashSet<>();
|
||||
this.groups.add(clientParentGroup);
|
||||
}
|
||||
|
||||
this.staff = staff;
|
||||
this.savingsProductId = savingsProductId;
|
||||
this.savingsAccountId = savingsAccountId;
|
||||
|
||||
if (gender != null) {
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
this.dateOfBirth = dateOfBirth;
|
||||
|
||||
this.clientType = clientType;
|
||||
this.clientClassification = clientClassification;
|
||||
this.setLegalForm(legalForm);
|
||||
|
||||
deriveDisplayName();
|
||||
validate();
|
||||
}
|
||||
|
||||
private void validate() {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
validateNameParts(dataValidationErrors);
|
||||
validateActivationDate(dataValidationErrors);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void validateUpdate() {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
// Not validating name parts while update request as firstname/lastname
|
||||
// can be along with fullname
|
||||
// when we change clientType from Individual to Organisation or
|
||||
// vice-cersa
|
||||
validateActivationDate(dataValidationErrors);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isAccountNumberRequiresAutoGeneration() {
|
||||
return this.accountNumberRequiresAutoGeneration;
|
||||
}
|
||||
|
||||
public void setAccountNumberRequiresAutoGeneration(final boolean accountNumberRequiresAutoGeneration) {
|
||||
this.accountNumberRequiresAutoGeneration = accountNumberRequiresAutoGeneration;
|
||||
}
|
||||
|
||||
public boolean identifiedBy(final Long clientId) {
|
||||
return getId().equals(clientId);
|
||||
}
|
||||
|
||||
public void updateAccountNo(final String accountIdentifier) {
|
||||
this.accountNumber = accountIdentifier;
|
||||
this.accountNumberRequiresAutoGeneration = false;
|
||||
}
|
||||
|
||||
public void activate(final AppUser currentUser, final DateTimeFormatter formatter, final LocalDate activationLocalDate) {
|
||||
|
||||
if (isActive()) {
|
||||
final String defaultUserMessage = "Cannot activate client. Client is already active.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.already.active", defaultUserMessage,
|
||||
ClientApiConstants.activationDateParamName, activationLocalDate.format(formatter));
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
this.activationDate = activationLocalDate;
|
||||
this.activatedBy = currentUser;
|
||||
this.officeJoiningDate = this.activationDate;
|
||||
this.status = ClientStatus.ACTIVE.getValue();
|
||||
|
||||
// in case a closed client is being re open
|
||||
this.closureDate = null;
|
||||
this.closureReason = null;
|
||||
this.closedBy = null;
|
||||
|
||||
validate();
|
||||
}
|
||||
|
||||
public boolean isNotActive() {
|
||||
return !isActive();
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return ClientStatus.fromInt(this.status).isActive();
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return ClientStatus.fromInt(this.status).isClosed();
|
||||
}
|
||||
|
||||
public boolean isTransferInProgress() {
|
||||
return ClientStatus.fromInt(this.status).isTransferInProgress();
|
||||
}
|
||||
|
||||
public boolean isTransferOnHold() {
|
||||
return ClientStatus.fromInt(this.status).isTransferOnHold();
|
||||
}
|
||||
|
||||
public boolean isTransferInProgressOrOnHold() {
|
||||
return isTransferInProgress() || isTransferOnHold();
|
||||
}
|
||||
|
||||
public boolean isNotPending() {
|
||||
return !isPending();
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return ClientStatus.fromInt(this.status).isPending();
|
||||
}
|
||||
|
||||
private boolean isDateInTheFuture(final LocalDate localDate) {
|
||||
return localDate.isAfter(DateUtils.getBusinessLocalDate());
|
||||
}
|
||||
|
||||
public boolean isRejected() {
|
||||
return ClientStatus.fromInt(this.status).isRejected();
|
||||
}
|
||||
|
||||
public boolean isWithdrawn() {
|
||||
return ClientStatus.fromInt(this.status).isWithdrawn();
|
||||
}
|
||||
|
||||
private void validateNameParts(final List<ApiParameterError> dataValidationErrors) {
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("client");
|
||||
|
||||
if (StringUtils.isNotBlank(this.fullname)) {
|
||||
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.firstnameParamName).value(this.firstname)
|
||||
.mustBeBlankWhenParameterProvided(ClientApiConstants.fullnameParamName, this.fullname);
|
||||
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.middlenameParamName).value(this.middlename)
|
||||
.mustBeBlankWhenParameterProvided(ClientApiConstants.fullnameParamName, this.fullname);
|
||||
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.lastnameParamName).value(this.lastname)
|
||||
.mustBeBlankWhenParameterProvided(ClientApiConstants.fullnameParamName, this.fullname);
|
||||
} else {
|
||||
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.firstnameParamName).value(this.firstname).notBlank()
|
||||
.notExceedingLengthOf(50);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.middlenameParamName).value(this.middlename).ignoreIfNull()
|
||||
.notExceedingLengthOf(50);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.lastnameParamName).value(this.lastname).notBlank()
|
||||
.notExceedingLengthOf(50);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) {
|
||||
|
||||
final String defaultUserMessage = "submitted date cannot be in the future.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.in.the.future",
|
||||
defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
|
||||
if (getActivationLocalDate() != null && getSubmittedOnDate() != null && getSubmittedOnDate().isAfter(getActivationLocalDate())) {
|
||||
|
||||
final String defaultUserMessage = "submitted date cannot be after the activation date";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.activation.date",
|
||||
defaultUserMessage, ClientApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
|
||||
if (getReopenedDate() != null && getActivationLocalDate() != null && getReopenedDate().isAfter(getActivationLocalDate())) {
|
||||
|
||||
final String defaultUserMessage = "reopened date cannot be after the submittedon date";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.submittedOnDate.after.reopened.date",
|
||||
defaultUserMessage, ClientApiConstants.reopenedDateParamName, this.reopenedDate);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
|
||||
if (getActivationLocalDate() != null && isDateInTheFuture(getActivationLocalDate())) {
|
||||
|
||||
final String defaultUserMessage = "Activation date cannot be in the future.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.clients.activationDate.in.the.future",
|
||||
defaultUserMessage, ClientApiConstants.activationDateParamName, getActivationLocalDate());
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
|
||||
if (getActivationLocalDate() != null) {
|
||||
if (this.office.isOpeningDateAfter(getActivationLocalDate())) {
|
||||
final String defaultUserMessage = "Client activation date cannot be a date before the office opening date.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError(
|
||||
"error.msg.clients.activationDate.cannot.be.before.office.activation.date", defaultUserMessage,
|
||||
ClientApiConstants.activationDateParamName, getActivationLocalDate());
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deriveDisplayName() {
|
||||
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
Integer legalForm = this.getLegalForm();
|
||||
if (legalForm == null || LegalForm.fromInt(legalForm).isPerson()) {
|
||||
if (StringUtils.isNotBlank(this.firstname)) {
|
||||
nameBuilder.append(this.firstname).append(' ');
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(this.middlename)) {
|
||||
nameBuilder.append(this.middlename).append(' ');
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(this.lastname)) {
|
||||
nameBuilder.append(this.lastname);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(this.fullname)) {
|
||||
nameBuilder = new StringBuilder(this.fullname);
|
||||
}
|
||||
} else if (LegalForm.fromInt(legalForm).isEntity()) {
|
||||
if (StringUtils.isNotBlank(this.fullname)) {
|
||||
nameBuilder = new StringBuilder(this.fullname);
|
||||
}
|
||||
}
|
||||
|
||||
this.displayName = nameBuilder.toString();
|
||||
}
|
||||
|
||||
public LocalDate getActivationLocalDate() {
|
||||
return this.activationDate;
|
||||
}
|
||||
|
||||
public LocalDate getOfficeJoiningLocalDate() {
|
||||
return this.officeJoiningDate;
|
||||
}
|
||||
|
||||
public boolean isOfficeIdentifiedBy(final Long officeId) {
|
||||
return this.office.identifiedBy(officeId);
|
||||
}
|
||||
|
||||
public Long officeId() {
|
||||
return this.office.getId();
|
||||
}
|
||||
|
||||
public void setImage(final Image image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public String mobileNo() {
|
||||
return this.mobileNo;
|
||||
}
|
||||
|
||||
public String emailAddress() {
|
||||
return this.emailAddress;
|
||||
}
|
||||
|
||||
public void setMobileNo(final String mobileNo) {
|
||||
this.mobileNo = mobileNo;
|
||||
}
|
||||
|
||||
public boolean isNotStaff() {
|
||||
return !isStaff();
|
||||
}
|
||||
|
||||
public boolean isStaff() {
|
||||
return this.isStaff;
|
||||
}
|
||||
|
||||
public void setEmailAddress(final String emailAddress) {
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
public void setDisplayName(final String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public void updateOffice(final Office office) {
|
||||
this.office = office;
|
||||
}
|
||||
|
||||
public void updateTransferToOffice(final Office office) {
|
||||
this.transferToOffice = office;
|
||||
}
|
||||
|
||||
public void updateOfficeJoiningDate(final LocalDate date) {
|
||||
this.officeJoiningDate = date;
|
||||
}
|
||||
|
||||
public Long staffId() {
|
||||
Long staffId = null;
|
||||
if (this.staff != null) {
|
||||
staffId = this.staff.getId();
|
||||
}
|
||||
return staffId;
|
||||
}
|
||||
|
||||
public void updateStaff(final Staff staff) {
|
||||
this.staff = staff;
|
||||
}
|
||||
|
||||
public void unassignStaff() {
|
||||
this.staff = null;
|
||||
}
|
||||
|
||||
public void assignStaff(final Staff staff) {
|
||||
this.staff = staff;
|
||||
}
|
||||
|
||||
public void close(final AppUser currentUser, final CodeValue closureReason, final LocalDate closureDate) {
|
||||
this.closureReason = closureReason;
|
||||
this.closureDate = closureDate;
|
||||
this.closedBy = currentUser;
|
||||
this.status = ClientStatus.CLOSED.getValue();
|
||||
}
|
||||
|
||||
public CodeValue subStatus() {
|
||||
return this.subStatus;
|
||||
}
|
||||
|
||||
public Long subStatusId() {
|
||||
Long subStatusId = null;
|
||||
if (this.subStatus != null) {
|
||||
subStatusId = this.subStatus.getId();
|
||||
}
|
||||
return subStatusId;
|
||||
}
|
||||
|
||||
public boolean isActivatedAfter(final LocalDate submittedOn) {
|
||||
return getActivationLocalDate().isAfter(submittedOn);
|
||||
}
|
||||
|
||||
public boolean isChildOfGroup(final Long groupId) {
|
||||
if (groupId != null && this.groups != null && !this.groups.isEmpty()) {
|
||||
for (final Group group : this.groups) {
|
||||
if (group.getId().equals(groupId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Long savingsProductId() {
|
||||
return this.savingsProductId;
|
||||
}
|
||||
|
||||
public void updateSavingsProduct(final Long savingsProductId) {
|
||||
this.savingsProductId = savingsProductId;
|
||||
}
|
||||
|
||||
public AppUser activatedBy() {
|
||||
return this.activatedBy;
|
||||
}
|
||||
|
||||
public Long savingsAccountId() {
|
||||
return this.savingsAccountId;
|
||||
}
|
||||
|
||||
public void updateSavingsAccount(Long savingsAccountId) {
|
||||
this.savingsAccountId = savingsAccountId;
|
||||
}
|
||||
|
||||
public Long genderId() {
|
||||
Long genderId = null;
|
||||
if (this.gender != null) {
|
||||
genderId = this.gender.getId();
|
||||
}
|
||||
return genderId;
|
||||
}
|
||||
|
||||
public Long clientTypeId() {
|
||||
Long clientTypeId = null;
|
||||
if (this.clientType != null) {
|
||||
clientTypeId = this.clientType.getId();
|
||||
}
|
||||
return clientTypeId;
|
||||
}
|
||||
|
||||
public Long clientClassificationId() {
|
||||
Long clientClassificationId = null;
|
||||
if (this.clientClassification != null) {
|
||||
clientClassificationId = this.clientClassification.getId();
|
||||
}
|
||||
return clientClassificationId;
|
||||
}
|
||||
|
||||
public LocalDate getRejectedDate() {
|
||||
return this.rejectionDate;
|
||||
}
|
||||
|
||||
public CodeValue gender() {
|
||||
return this.gender;
|
||||
}
|
||||
|
||||
public CodeValue clientType() {
|
||||
return this.clientType;
|
||||
}
|
||||
|
||||
public void updateClientType(CodeValue clientType) {
|
||||
this.clientType = clientType;
|
||||
}
|
||||
|
||||
public CodeValue clientClassification() {
|
||||
return this.clientClassification;
|
||||
}
|
||||
|
||||
public void updateClientClassification(CodeValue clientClassification) {
|
||||
this.clientClassification = clientClassification;
|
||||
}
|
||||
|
||||
public void updateGender(CodeValue gender) {
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
public LocalDate dateOfBirth() {
|
||||
return this.dateOfBirth;
|
||||
}
|
||||
|
||||
public LocalDate dateOfBirthLocalDate() {
|
||||
return this.dateOfBirth;
|
||||
}
|
||||
|
||||
public void reject(AppUser currentUser, CodeValue rejectionReason, LocalDate rejectionDate) {
|
||||
this.rejectionReason = rejectionReason;
|
||||
this.rejectionDate = rejectionDate;
|
||||
this.rejectedBy = currentUser;
|
||||
this.status = ClientStatus.REJECTED.getValue();
|
||||
|
||||
}
|
||||
|
||||
public void withdraw(AppUser currentUser, CodeValue withdrawalReason, LocalDate withdrawalDate) {
|
||||
this.withdrawalReason = withdrawalReason;
|
||||
this.withdrawalDate = withdrawalDate;
|
||||
this.withdrawnBy = currentUser;
|
||||
this.status = ClientStatus.WITHDRAWN.getValue();
|
||||
|
||||
}
|
||||
|
||||
public void reActivate(AppUser currentUser, LocalDate reactivateDate) {
|
||||
this.closureDate = null;
|
||||
this.closureReason = null;
|
||||
this.reactivateDate = reactivateDate;
|
||||
this.reactivatedBy = currentUser;
|
||||
this.status = ClientStatus.PENDING.getValue();
|
||||
}
|
||||
|
||||
public void reOpened(AppUser currentUser, LocalDate reopenedDate) {
|
||||
this.reopenedDate = reopenedDate;
|
||||
this.reopenedBy = currentUser;
|
||||
this.status = ClientStatus.PENDING.getValue();
|
||||
}
|
||||
|
||||
public void setLegalForm(Integer legalForm) {
|
||||
this.legalForm = legalForm;
|
||||
}
|
||||
|
||||
public void loadLazyCollections() {
|
||||
this.groups.size();
|
||||
}
|
||||
|
||||
public LocalDate getProposedTransferDate() {
|
||||
return proposedTransferDate;
|
||||
}
|
||||
|
||||
public void updateProposedTransferDate(LocalDate proposedTransferDate) {
|
||||
this.proposedTransferDate = proposedTransferDate;
|
||||
}
|
||||
|
||||
public void resetDerivedNames(final LegalForm legalForm) {
|
||||
if (legalForm.isPerson()) {
|
||||
setFullname(null);
|
||||
} else if (legalForm.isEntity()) {
|
||||
setFirstname(null);
|
||||
setLastname(null);
|
||||
setDisplayName(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Enum representation of client status states.
|
||||
*/
|
||||
public enum ClientStatus {
|
||||
|
||||
INVALID(0, "clientStatusType.invalid"), //
|
||||
PENDING(100, "clientStatusType.pending"), //
|
||||
ACTIVE(300, "clientStatusType.active"), //
|
||||
TRANSFER_IN_PROGRESS(303, "clientStatusType.transfer.in.progress"), //
|
||||
TRANSFER_ON_HOLD(304, "clientStatusType.transfer.on.hold"), //
|
||||
CLOSED(600, "clientStatusType.closed"), REJECTED(700, "clientStatusType.rejected"), WITHDRAWN(800, "clientStatusType.withdraw");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
public static ClientStatus fromInt(final Integer statusValue) {
|
||||
|
||||
ClientStatus enumeration = ClientStatus.INVALID;
|
||||
switch (statusValue) {
|
||||
case 100:
|
||||
enumeration = ClientStatus.PENDING;
|
||||
break;
|
||||
case 300:
|
||||
enumeration = ClientStatus.ACTIVE;
|
||||
break;
|
||||
case 303:
|
||||
enumeration = ClientStatus.TRANSFER_IN_PROGRESS;
|
||||
break;
|
||||
case 304:
|
||||
enumeration = ClientStatus.TRANSFER_ON_HOLD;
|
||||
break;
|
||||
case 600:
|
||||
enumeration = ClientStatus.CLOSED;
|
||||
break;
|
||||
case 700:
|
||||
enumeration = ClientStatus.REJECTED;
|
||||
break;
|
||||
case 800:
|
||||
enumeration = ClientStatus.WITHDRAWN;
|
||||
break;
|
||||
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
public static ClientStatus fromString(final String clientString) {
|
||||
|
||||
ClientStatus clientStatus = ClientStatus.INVALID;
|
||||
|
||||
if (!StringUtils.hasLength(clientString)) {
|
||||
return clientStatus;
|
||||
}
|
||||
|
||||
if (clientString.equalsIgnoreCase(ClientStatus.PENDING.toString())) {
|
||||
clientStatus = ClientStatus.PENDING;
|
||||
} else if (clientString.equalsIgnoreCase(ClientStatus.ACTIVE.toString())) {
|
||||
clientStatus = ClientStatus.ACTIVE;
|
||||
} else if (clientString.equalsIgnoreCase(ClientStatus.TRANSFER_IN_PROGRESS.toString())) {
|
||||
clientStatus = ClientStatus.TRANSFER_IN_PROGRESS;
|
||||
} else if (clientString.equalsIgnoreCase(ClientStatus.WITHDRAWN.toString())) {
|
||||
clientStatus = ClientStatus.WITHDRAWN;
|
||||
} else if (clientString.equalsIgnoreCase(ClientStatus.CLOSED.toString())) {
|
||||
clientStatus = ClientStatus.CLOSED;
|
||||
} else if (clientString.equalsIgnoreCase(ClientStatus.TRANSFER_ON_HOLD.toString())) {
|
||||
clientStatus = ClientStatus.TRANSFER_ON_HOLD;
|
||||
} else if (clientString.equalsIgnoreCase(ClientStatus.REJECTED.toString())) {
|
||||
clientStatus = ClientStatus.REJECTED;
|
||||
}
|
||||
|
||||
return clientStatus;
|
||||
}
|
||||
|
||||
ClientStatus(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public boolean hasStateOf(final ClientStatus state) {
|
||||
return this.value.equals(state.getValue());
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return this.value.equals(ClientStatus.PENDING.getValue());
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.value.equals(ClientStatus.ACTIVE.getValue());
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return this.value.equals(ClientStatus.CLOSED.getValue());
|
||||
}
|
||||
|
||||
public boolean isRejected() {
|
||||
return this.value.equals(ClientStatus.REJECTED.getValue());
|
||||
}
|
||||
|
||||
public boolean isWithdrawn() {
|
||||
return this.value.equals(ClientStatus.WITHDRAWN.getValue());
|
||||
}
|
||||
|
||||
public boolean isTransferInProgress() {
|
||||
return this.value.equals(ClientStatus.TRANSFER_IN_PROGRESS.getValue());
|
||||
}
|
||||
|
||||
public boolean isTransferOnHold() {
|
||||
return this.value.equals(ClientStatus.TRANSFER_ON_HOLD.getValue());
|
||||
}
|
||||
|
||||
public boolean isUnderTransfer() {
|
||||
return isTransferInProgress() || isTransferOnHold();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user