Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ buildscript {
'fineract-e2e-tests-core',
'fineract-e2e-tests-runner',
'fineract-progressive-loan',
'fineract-progressive-loan-embeddable-schedule-generator'
'fineract-progressive-loan-embeddable-schedule-generator',
'fineract-working-capital-loan'
].contains(it.name)
}
fineractPublishProjects = subprojects.findAll{
Expand All @@ -77,7 +78,8 @@ buildscript {
'fineract-branch',
'fineract-document',
'fineract-progressive-loan',
'fineract-progressive-loan-embeddable-schedule-generator'
'fineract-progressive-loan-embeddable-schedule-generator',
'fineract-working-capital-loan'
].contains(it.name)
}
npmRepository = 'https://npm.pkg.github.com'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
import org.apache.fineract.client.feign.services.TwoFactorApi;
import org.apache.fineract.client.feign.services.UserGeneratedDocumentsApi;
import org.apache.fineract.client.feign.services.UsersApi;
import org.apache.fineract.client.feign.services.WorkingCapitalLoanProductsApi;
import org.apache.fineract.client.feign.services.WorkingDaysApi;

/**
Expand Down Expand Up @@ -837,6 +838,10 @@ public UsersApi users() {
return create(UsersApi.class);
}

public WorkingCapitalLoanProductsApi workingCapitalLoanProducts() {
return create(WorkingCapitalLoanProductsApi.class);
}

public WorkingDaysApi workingDays() {
return create(WorkingDaysApi.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,30 @@ public CommandWrapperBuilder updateLoanProduct(final Long productId) {
return this;
}

public CommandWrapperBuilder createWorkingCapitalLoanProduct() {
this.actionName = "CREATE";
this.entityName = "WORKINGCAPITALLOANPRODUCT";
this.entityId = null;
this.href = "/workingcapitalloanproducts/template";
return this;
}

public CommandWrapperBuilder updateWorkingCapitalLoanProduct(final Long productId) {
this.actionName = "UPDATE";
this.entityName = "WORKINGCAPITALLOANPRODUCT";
this.entityId = productId;
this.href = "/workingcapitalloanproducts/" + productId;
return this;
}

public CommandWrapperBuilder deleteWorkingCapitalLoanProduct(final Long productId) {
this.actionName = "DELETE";
this.entityName = "WORKINGCAPITALLOANPRODUCT";
this.entityId = productId;
this.href = "/workingcapitalloanproducts/" + productId;
return this;
}

public CommandWrapperBuilder createClientIdentifier(final Long clientId) {
this.actionName = "CREATE";
this.entityName = "CLIENTIDENTIFIER";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected GenericEnumListConverter(Class<E> clazz) {

@Override
public String convertToDatabaseColumn(List<E> values) {
if (values.isEmpty()) {
if (values == null || values.isEmpty()) {
return null;
}
Stream<E> valueStream;
Expand All @@ -54,10 +54,10 @@ public String convertToDatabaseColumn(List<E> values) {

@Override
public List<E> convertToEntityAttribute(String string) {
if (StringUtils.isBlank(string)) {
if (string == null || StringUtils.isBlank(string)) {
return List.of();
}
Stream<E> stream = Stream.of(string.split(SPLIT_CHAR)).map(e -> Enum.valueOf(clazz, e));
Stream<E> stream = Stream.of(string.split(SPLIT_CHAR)).filter(s -> !s.isBlank()).map(e -> Enum.valueOf(clazz, e.trim()));
if (isUnique()) {
return stream.distinct().toList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import jakarta.persistence.UniqueConstraint;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
Expand All @@ -33,6 +34,7 @@
@UniqueConstraint(columnNames = { "external_id" }, name = "fund_externalid_org") })
public class Fund extends AbstractPersistableCustom<Long> {

@Getter
@Column(name = "name")
private String name;

Expand Down
1 change: 1 addition & 0 deletions fineract-provider/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ dependencies {
implementation(project(path: ':fineract-tax'))
implementation(project(path: ':fineract-loan-origination'))
implementation(project(path: ':fineract-security'))
implementation(project(path: ':fineract-working-capital-loan'))

providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<include file="/db/changelog/tenant/module/progressiveloan/module-changelog-master.xml" context="tenant_db AND !initial_switch"/>
<include file="db/changelog/tenant/module/loanorigination/module-changelog-master.xml" context="tenant_db AND !initial_switch"/>
<include file="db/changelog/tenant/module/command/module-changelog-master.xml" context="tenant_db AND !initial_switch"/>
<include file="db/changelog/tenant/module/workingcapitalloan/module-changelog-master.xml" context="tenant_db AND !initial_switch"/>
<!-- Scripts to run after the modules were initialized -->
<include file="tenant/final-changelog-tenant.xml" relativeToChangelogFile="true" context="tenant_db AND !initial_switch"/>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@
<class>org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain</class>
<class>org.apache.fineract.portfolio.collateral.domain.LoanCollateral</class>

<!-- Working Capital Loan Module Entities -->
<class>org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WorkingCapitalLoanProduct</class>
<class>org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WCPPaymentAllocationRule</class>
<class>org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WCPConfigurableAttributes</class>

<!-- Loan Module Converters -->
<class>org.apache.fineract.portfolio.loanproduct.domain.AllocationTypeListConverter</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.AccountingRuleTypeConverter</class>
Expand All @@ -228,6 +233,9 @@
<class>org.apache.fineract.portfolio.loanproduct.domain.SupportedInterestRefundTypesListConverter</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanStatusConverter</class>

<!-- Working Capital Loan Module Converters -->
<class>org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WCPPaymentAllocationTypeListConverter</class>

<!-- Document Module Entities -->
<class>org.apache.fineract.infrastructure.documentmanagement.domain.Document</class>

Expand Down
1 change: 1 addition & 0 deletions fineract-war/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ dependencies {
implementation project(':fineract-progressive-loan')
implementation project(':fineract-savings')
implementation project(':fineract-provider')
implementation project(':fineract-working-capital-loan')
}

tasks.withType(Tar) {
Expand Down
83 changes: 83 additions & 0 deletions fineract-working-capital-loan/build.gradle
Original file line number Diff line number Diff line change
@@ -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.
*/
description = 'Fineract Working Capital Loan'

apply plugin: 'java'
apply plugin: 'eclipse'

compileJava {
dependsOn ':fineract-avro-schemas:buildJavaSdk'
}

configurations {
providedRuntime // needed for Spring Boot executable WAR
providedCompile
compile() {
exclude module: 'hibernate-entitymanager'
exclude module: 'hibernate-validator'
exclude module: 'activation'
exclude module: 'bcmail-jdk14'
exclude module: 'bcprov-jdk14'
exclude module: 'bctsp-jdk14'
exclude module: 'c3p0'
exclude module: 'stax-api'
exclude module: 'jaxb-api'
exclude module: 'jaxb-impl'
exclude module: 'jboss-logging'
exclude module: 'itext-rtf'
exclude module: 'classworlds'
}
runtime
}

apply from: 'dependencies.gradle'

// Configuration for the modernizer plugin
// https://github.com/andygoossens/gradle-modernizer-plugin
modernizer {
ignoreClassNamePatterns = [
'.*AbstractPersistableCustom',
'.*EntityTables',
'.*domain.*'
]
}

// If we are running Gradle within Eclipse to enhance classes with OpenJPA,
// set the classes directory to point to Eclipse's default build directory
if (project.hasProperty('env') && project.getProperty('env') == 'eclipse') {
sourceSets.main.java.outputDir = new File(rootProject.projectDir, "fineract-working-capital-loan/bin/main")
}

eclipse {
project {
buildCommand([ LaunchConfigHandle: "<project>/.externalToolBuilders/OpenJPA Enhance Builder.launch" ], 'org.eclipse.ui.externaltools.ExternalToolBuilder')
}
}

if (!(project.hasProperty('env') && project.getProperty('env') == 'dev')) {
sourceSets {
test {
java {
exclude '**/core/boot/tests/**'
}
}
}
}


78 changes: 78 additions & 0 deletions fineract-working-capital-loan/dependencies.gradle
Original file line number Diff line number Diff line change
@@ -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.
*/

dependencies {
// Never use "compile" scope, but make all dependencies either 'implementation', 'runtimeOnly' or 'testCompile'.
// Note that we never use 'api', because Fineract at least currently is a simple monolithic application ("WAR"), not a library.
// We also (normally should have) no need to ever use 'compileOnly'.

// implementation dependencies are directly used (compiled against) in src/main (and src/test)
//
implementation(project(path: ':fineract-core'))
implementation(project(path: ':fineract-loan'))
implementation('org.apache.avro:avro')
implementation(
project(path: ':fineract-avro-schemas')
)

implementation(
'org.springframework.boot:spring-boot-starter-web',
'org.springframework.boot:spring-boot-starter-security',
'jakarta.ws.rs:jakarta.ws.rs-api',
'org.glassfish.jersey.media:jersey-media-multipart',

'com.google.guava:guava',
'com.google.code.gson:gson',

'org.apache.commons:commons-lang3',

'com.jayway.jsonpath:json-path',

'com.github.spotbugs:spotbugs-annotations',
'io.swagger.core.v3:swagger-annotations-jakarta',

'com.squareup.retrofit2:converter-gson',

'org.springdoc:springdoc-openapi-starter-webmvc-ui',
'org.mapstruct:mapstruct',

'io.github.resilience4j:resilience4j-spring-boot3',
)
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.mapstruct:mapstruct-processor'
implementation ('org.springframework.boot:spring-boot-starter-data-jpa') {
exclude group: 'org.hibernate'
}
implementation('org.eclipse.persistence:org.eclipse.persistence.jpa') {
exclude group: 'org.eclipse.persistence', module: 'jakarta.persistence'
}
// testCompile dependencies are ONLY used in src/test, not src/main.
// Do NOT repeat dependencies which are ALREADY in implementation or runtimeOnly!
//
testImplementation( 'io.github.classgraph:classgraph' )
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'com.jayway.jsonpath', module: 'json-path'
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
exclude group: 'jakarta.activation'
exclude group: 'javax.activation'
exclude group: 'org.skyscreamer'
}
testImplementation ('org.mockito:mockito-inline')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* 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.workingcapitalloanproduct;

public final class WCPConstants {

private WCPConstants() {
// Prevent instantiation
}

// JSON property names
public static final String nameParamName = "name";
public static final String shortNameParamName = "shortName";
public static final String descriptionParamName = "description";
public static final String fundIdParamName = "fundId";
public static final String startDateParamName = "startDate";
public static final String closeDateParamName = "closeDate";
public static final String externalIdParamName = "externalId";

// Currency
public static final String currencyCodeParamName = "currencyCode";
public static final String decimalPlaceParamName = "decimalPlace";
public static final String currencyInMultiplesOfParamName = "currencyInMultiplesOf";

// Settings
public static final String amortizationParamName = "amortization";
public static final String flatPercentageAmountParamName = "flatPercentageAmount";
public static final String delinquencyBucketClassificationParamName = "delinquencyBucketClassification";
public static final String npvDayCountParamName = "npvDayCount";
public static final String paymentAllocationParamName = "paymentAllocation";

// Term
public static final String principalAmountMinParamName = "principalAmountMin";
public static final String principalAmountDefaultParamName = "principalAmountDefault";
public static final String principalAmountMaxParamName = "principalAmountMax";
public static final String periodPaymentRateMinParamName = "periodPaymentRateMin";
public static final String periodPaymentRateDefaultParamName = "periodPaymentRateDefault";
public static final String periodPaymentRateMaxParamName = "periodPaymentRateMax";
public static final String discountDefaultParamName = "discountDefault";
public static final String periodPaymentFrequencyParamName = "periodPaymentFrequency";
public static final String periodPaymentFrequencyTypeParamName = "periodPaymentFrequencyType";

// Configurable attributes (same as LoanProduct + WCP-specific)
public static final String allowAttributeOverridesParamName = "allowAttributeOverrides";
public static final String amortizationTypeParamName = "amortizationType";
public static final String interestTypeParamName = "interestType";
public static final String transactionProcessingStrategyCodeParamName = "transactionProcessingStrategyCode";
public static final String interestCalculationPeriodTypeParamName = "interestCalculationPeriodType";
public static final String inArrearsToleranceParamName = "inArrearsTolerance";
public static final String repaymentEveryParamName = "repaymentEvery";
public static final String graceOnPrincipalAndInterestPaymentParamName = "graceOnPrincipalAndInterestPayment";
public static final String graceOnArrearsAgeingParamName = "graceOnArrearsAgeing";
// WCP-specific overridable fields
public static final String flatPercentageAmountOverridableParamName = "flatPercentageAmount";
public static final String delinquencyBucketClassificationOverridableParamName = "delinquencyBucketClassification";
public static final String discountDefaultOverridableParamName = "discountDefault";
public static final String periodPaymentFrequencyOverridableParamName = "periodPaymentFrequency";
public static final String periodPaymentFrequencyTypeOverridableParamName = "periodPaymentFrequencyType";

// Payment allocation
public static final String allocationTypesParamName = "allocationTypes";

// Resource name for permissions
public static final String RESOURCE_NAME = "WORKINGCAPITALLOANPRODUCT";
}
Loading
Loading