FINCN-351 Make the scorecard integration into a plugin
diff --git a/.classpath b/.classpath
index c0c2f18..4f3f504 100644
--- a/.classpath
+++ b/.classpath
@@ -1,11 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" output="bin/generated" path="build/generated/java/src/main/java">
- <attributes>
- <attribute name="gradle_scope" value="generated"/>
- <attribute name="gradle_used_by_scope" value="generated"/>
- </attributes>
- </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e4a2c68..809f075 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -16,14 +16,14 @@
python-version: [3.7, 3.8]
services:
- mysql:
- image: mysql:5.7
- env:
- MYSQL_ROOT_PASSWORD: mysql
- MYSQL_DATABASE: fineract_credit_scorecard
- ports:
- - '3306:3306'
- options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
+ mysql:
+ image: mysql:5.7
+ env:
+ MYSQL_ROOT_PASSWORD: mysql
+ MYSQL_DATABASE: fineract_credit_scorecard
+ ports:
+ - '3306:3306'
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v2
diff --git a/.gitignore b/.gitignore
index 040215e..623696e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -121,5 +121,8 @@
.settings
.project
+.classpath
-data/
\ No newline at end of file
+data/
+
+.idea
diff --git a/README.md b/README.md
index e34a5b0..5a2b294 100644
--- a/README.md
+++ b/README.md
Binary files differ
diff --git a/api/views.py b/api/views.py
index 4198d29..33ee8c8 100644
--- a/api/views.py
+++ b/api/views.py
@@ -19,7 +19,7 @@
import json
import logging
-from statistical_scripts.statistical_scoring import stat_score
+from stats.statistical_scoring import stat_score
from typing import Any, Dict
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiExample, inline_serializer
diff --git a/build.gradle b/build.gradle
index ca95c94..cbd7246 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,7 +25,7 @@
plugins {
id "java"
- id "org.openapi.generator" version "5.1.0"
+ id "org.openapi.generator" version "5.2.1"
id "com.github.hierynomus.license" version"0.15.0"
}
@@ -33,6 +33,11 @@
ext['openapiSpecFile'] = "$rootDir/openapi.yml".toString()
+java {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
+
license {
header rootProject.file("$rootDir/APACHE_LICENSETEXT.md")
excludes([
@@ -93,36 +98,6 @@
]
generateModelTests = false
generateApiTests = false
- finalizedBy = ["copyClients"]
-}
-
-task buildTypescriptAngularSdk(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
- generatorName = 'typescript-angular'
- verbose = false
- validateSpec = false
- skipValidateSpec = true
- inputSpec = "$openapiSpecFile"
- outputDir = "$buildDir/generated/typescript".toString()
- apiPackage = 'org.apache.fineract.credit.scorecard.services'
- invokerPackage = 'org.apache.fineract.credit.scorecard'
- modelPackage = 'org.apache.fineract.credit.scorecard.models'
- configOptions = [
- apiModulePrefix: 'scorecard',
- configurationPrefix: 'scorecard',
- ngVersion: '10.0.0',
- npmName: 'apache-fineract-credit-scorecard-client'
- ]
- finalizedBy = [licenseFormat]
-}
-
-task copyClients {
- copy {
- from 'build/generated'
- into 'clients'
- exclude '**/*.sbt', '**/*.yml', '**/*.sh', '**/api', '**/.openapi-generator', '**/.openapi-generator-ignore'
- // filter(ReplaceTokens, tokens: [version: '2.3.1'])
- }
-
finalizedBy = [licenseFormat]
}
@@ -134,11 +109,6 @@
}
}
-java {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
-}
-
compileJava {
source += sourceSets.generated.java
}
@@ -147,7 +117,3 @@
generatedCompile.extendsFrom implementation
generatedRuntime.extendsFrom runtime
}
-
-test {
- useJUnitPlatform()
-}
diff --git a/clients/java/.idea/.gitignore b/clients/java/.idea/.gitignore
deleted file mode 100644
index 4aa91ea..0000000
--- a/clients/java/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
-# Editor-based HTTP Client requests
-/httpRequests/
diff --git a/clients/java/.idea/.name b/clients/java/.idea/.name
deleted file mode 100644
index da9779d..0000000
--- a/clients/java/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-credit-scorecard-java-client
\ No newline at end of file
diff --git a/clients/java/.idea/compiler.xml b/clients/java/.idea/compiler.xml
deleted file mode 100644
index 245a82c..0000000
--- a/clients/java/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="CompilerConfiguration">
- <bytecodeTargetLevel target="1.8" />
- </component>
-</project>
\ No newline at end of file
diff --git a/clients/java/.idea/gradle.xml b/clients/java/.idea/gradle.xml
deleted file mode 100644
index 222345a..0000000
--- a/clients/java/.idea/gradle.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="GradleSettings">
- <option name="linkedExternalProjectsSettings">
- <GradleProjectSettings>
- <option name="distributionType" value="DEFAULT_WRAPPED" />
- <option name="externalProjectPath" value="$PROJECT_DIR$" />
- <option name="gradleHome" value="$PROJECT_DIR$/../../../../../../../../tools/Gradle/gradle-7.1" />
- <option name="gradleJvm" value="#JAVA_HOME" />
- <option name="modules">
- <set>
- <option value="$PROJECT_DIR$" />
- </set>
- </option>
- </GradleProjectSettings>
- </option>
- </component>
-</project>
\ No newline at end of file
diff --git a/clients/java/.idea/jarRepositories.xml b/clients/java/.idea/jarRepositories.xml
deleted file mode 100644
index 83f06a7..0000000
--- a/clients/java/.idea/jarRepositories.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="RemoteRepositoriesConfiguration">
- <remote-repository>
- <option name="id" value="central" />
- <option name="name" value="Maven Central repository" />
- <option name="url" value="https://repo1.maven.org/maven2" />
- </remote-repository>
- <remote-repository>
- <option name="id" value="jboss.community" />
- <option name="name" value="JBoss Community repository" />
- <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
- </remote-repository>
- <remote-repository>
- <option name="id" value="BintrayJCenter" />
- <option name="name" value="BintrayJCenter" />
- <option name="url" value="https://jcenter.bintray.com/" />
- </remote-repository>
- </component>
-</project>
\ No newline at end of file
diff --git a/clients/java/.idea/misc.xml b/clients/java/.idea/misc.xml
deleted file mode 100644
index a2556d3..0000000
--- a/clients/java/.idea/misc.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ExternalStorageConfigurationManager" enabled="true" />
- <component name="FrameworkDetectionExcludesConfiguration">
- <file type="web" url="file://$PROJECT_DIR$" />
- </component>
- <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="11" project-jdk-type="JavaSDK" />
-</project>
\ No newline at end of file
diff --git a/clients/java/.idea/vcs.xml b/clients/java/.idea/vcs.xml
deleted file mode 100644
index c8ade07..0000000
--- a/clients/java/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="VcsDirectoryMappings">
- <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
- </component>
-</project>
\ No newline at end of file
diff --git a/clients/java/build.gradle b/clients/java/build.gradle
deleted file mode 100644
index 58ff79f..0000000
--- a/clients/java/build.gradle
+++ /dev/null
@@ -1,114 +0,0 @@
-apply plugin: 'idea'
-apply plugin: 'eclipse'
-apply plugin: 'java'
-
-group = 'org.apache.fineract'
-version = '0.1.0-SNAPSHOT'
-
-buildscript {
- repositories {
- maven { url "https://repo1.maven.org/maven2" }
- jcenter()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:2.3.+'
- classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
- }
-}
-
-repositories {
- jcenter()
-}
-sourceSets {
- main.java.srcDirs = ['src/main/java']
-}
-
-if(hasProperty('target') && target == 'android') {
-
- apply plugin: 'com.android.library'
- apply plugin: 'com.github.dcendents.android-maven'
-
- android {
- compileSdkVersion 25
- buildToolsVersion '25.0.2'
- defaultConfig {
- minSdkVersion 14
- targetSdkVersion 25
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- // Rename the aar correctly
- libraryVariants.all { variant ->
- variant.outputs.each { output ->
- def outputFile = output.outputFile
- if (outputFile != null && outputFile.name.endsWith('.aar')) {
- def fileName = "${project.name}-${variant.baseName}-${version}.aar"
- output.outputFile = new File(outputFile.parent, fileName)
- }
- }
- }
-
- dependencies {
- provided 'javax.annotation:javax.annotation-api:1.3.2'
- }
- }
-
- afterEvaluate {
- android.libraryVariants.all { variant ->
- def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
- task.description = "Create jar artifact for ${variant.name}"
- task.dependsOn variant.javaCompile
- task.from variant.javaCompile.destinationDir
- task.destinationDir = project.file("${project.buildDir}/outputs/jar")
- task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
- artifacts.add('archives', task);
- }
- }
-
- task sourcesJar(type: Jar) {
- from android.sourceSets.main.java.srcDirs
- classifier = 'sources'
- }
-
- artifacts {
- archives sourcesJar
- }
-
-} else {
-
- apply plugin: 'java'
- apply plugin: 'maven'
-
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
-
- install {
- repositories.mavenInstaller {
- pom.artifactId = 'credit-scorecard-java-client'
- }
- }
-
- task execute(type:JavaExec) {
- main = System.getProperty('mainClass')
- classpath = sourceSets.main.runtimeClasspath
- }
-}
-
-dependencies {
- implementation 'io.swagger:swagger-annotations:1.5.24'
- implementation "com.google.code.findbugs:jsr305:3.0.2"
- implementation 'com.squareup.okhttp3:okhttp:3.14.7'
- implementation 'com.squareup.okhttp3:logging-interceptor:3.14.7'
- implementation 'com.google.code.gson:gson:2.8.6'
- implementation 'io.gsonfire:gson-fire:1.8.4'
- implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
- implementation 'javax.annotation:javax.annotation-api:1.3.2'
- testImplementation 'junit:junit:4.13.1'
-}
-
-javadoc {
- options.tags = [ "http.response.details:a:Http Response Details" ]
-}
diff --git a/clients/java/gradle.properties b/clients/java/gradle.properties
deleted file mode 100644
index 05644f0..0000000
--- a/clients/java/gradle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-# Uncomment to build for Android
-#target = android
\ No newline at end of file
diff --git a/clients/java/gradle/wrapper/gradle-wrapper.jar b/clients/java/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index e708b1c..0000000
--- a/clients/java/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/clients/java/gradle/wrapper/gradle-wrapper.properties b/clients/java/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/clients/java/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/clients/java/gradlew b/clients/java/gradlew
deleted file mode 100644
index 4f906e0..0000000
--- a/clients/java/gradlew
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or authors.
-#
-# Licensed 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
-#
-# https://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.
-#
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-exec "$JAVACMD" "$@"
diff --git a/clients/java/gradlew.bat b/clients/java/gradlew.bat
deleted file mode 100644
index 107acd3..0000000
--- a/clients/java/gradlew.bat
+++ /dev/null
@@ -1,89 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/clients/java/pom.xml b/clients/java/pom.xml
deleted file mode 100644
index 83e6745..0000000
--- a/clients/java/pom.xml
+++ /dev/null
@@ -1,276 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.apache.fineract</groupId>
- <artifactId>credit-scorecard-java-client</artifactId>
- <packaging>jar</packaging>
- <name>credit-scorecard-java-client</name>
- <version>0.1.0-SNAPSHOT</version>
- <url>https://github.com/openapitools/openapi-generator</url>
- <description>OpenAPI Java</description>
- <scm>
- <connection>scm:git:git@github.com:openapitools/openapi-generator.git</connection>
- <developerConnection>scm:git:git@github.com:openapitools/openapi-generator.git</developerConnection>
- <url>https://github.com/openapitools/openapi-generator</url>
- </scm>
-
- <licenses>
- <license>
- <name>Unlicense</name>
- <url>https://www.apache.org/licenses/LICENSE-2.0.html</url>
- <distribution>repo</distribution>
- </license>
- </licenses>
-
- <developers>
- <developer>
- <name>Apache Fineract</name>
- <email>dev@fineract.apache.org</email>
- <organization>Apache Software Foundation</organization>
- <organizationUrl>https://apache.org</organizationUrl>
- </developer>
- </developers>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.8.1</version>
- <configuration>
- <fork>true</fork>
- <meminitial>128m</meminitial>
- <maxmem>512m</maxmem>
- <compilerArgs>
- <arg>-Xlint:all</arg>
- <arg>-J-Xss4m</arg><!-- Compiling the generated JSON.java file may require larger stack size. -->
- </compilerArgs>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-enforcer-plugin</artifactId>
- <version>3.0.0-M1</version>
- <executions>
- <execution>
- <id>enforce-maven</id>
- <goals>
- <goal>enforce</goal>
- </goals>
- <configuration>
- <rules>
- <requireMavenVersion>
- <version>2.2.0</version>
- </requireMavenVersion>
- </rules>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>3.0.0-M4</version>
- <configuration>
- <systemProperties>
- <property>
- <name>loggerPath</name>
- <value>conf/log4j.properties</value>
- </property>
- </systemProperties>
- <argLine>-Xms512m -Xmx1500m</argLine>
- <parallel>methods</parallel>
- <threadCount>10</threadCount>
- </configuration>
- </plugin>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/lib</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- <!-- attach test jar -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>2.2</version>
- <executions>
- <execution>
- <goals>
- <goal>jar</goal>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <version>1.10</version>
- <executions>
- <execution>
- <id>add_sources</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>src/main/java</source>
- </sources>
- </configuration>
- </execution>
- <execution>
- <id>add_test_sources</id>
- <phase>generate-test-sources</phase>
- <goals>
- <goal>add-test-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>src/test/java</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <version>3.1.1</version>
- <executions>
- <execution>
- <id>attach-javadocs</id>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <doclint>none</doclint>
- <tags>
- <tag>
- <name>http.response.details</name>
- <placement>a</placement>
- <head>Http Response Details:</head>
- </tag>
- </tags>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- <version>2.2.1</version>
- <executions>
- <execution>
- <id>attach-sources</id>
- <goals>
- <goal>jar-no-fork</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
- <profiles>
- <profile>
- <id>sign-artifacts</id>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-gpg-plugin</artifactId>
- <version>1.5</version>
- <executions>
- <execution>
- <id>sign-artifacts</id>
- <phase>verify</phase>
- <goals>
- <goal>sign</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
-
- <dependencies>
- <dependency>
- <groupId>io.swagger</groupId>
- <artifactId>swagger-annotations</artifactId>
- <version>${swagger-core-version}</version>
- </dependency>
- <!-- @Nullable annotation -->
- <dependency>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- <version>3.0.2</version>
- </dependency>
- <dependency>
- <groupId>com.squareup.okhttp3</groupId>
- <artifactId>okhttp</artifactId>
- <version>${okhttp-version}</version>
- </dependency>
- <dependency>
- <groupId>com.squareup.okhttp3</groupId>
- <artifactId>logging-interceptor</artifactId>
- <version>${okhttp-version}</version>
- </dependency>
- <dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>${gson-version}</version>
- </dependency>
- <dependency>
- <groupId>io.gsonfire</groupId>
- <artifactId>gson-fire</artifactId>
- <version>${gson-fire-version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>${commons-lang3-version}</version>
- </dependency>
- <dependency>
- <groupId>javax.annotation</groupId>
- <artifactId>javax.annotation-api</artifactId>
- <version>${javax-annotation-version}</version>
- <scope>provided</scope>
- </dependency>
- <!-- test dependencies -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>${junit-version}</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- <properties>
- <java.version>1.8</java.version>
- <maven.compiler.source>${java.version}</maven.compiler.source>
- <maven.compiler.target>${java.version}</maven.compiler.target>
- <gson-fire-version>1.8.5</gson-fire-version>
- <swagger-core-version>1.6.2</swagger-core-version>
- <okhttp-version>4.9.1</okhttp-version>
- <gson-version>2.8.6</gson-version>
- <commons-lang3-version>3.11</commons-lang3-version>
- <javax-annotation-version>1.3.2</javax-annotation-version>
- <junit-version>4.13.1</junit-version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
-</project>
diff --git a/clients/java/settings.gradle b/clients/java/settings.gradle
deleted file mode 100644
index 805e86f..0000000
--- a/clients/java/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-rootProject.name = "credit-scorecard-java-client"
\ No newline at end of file
diff --git a/openapi.yml b/openapi.yml
index f26c051..e28c543 100644
--- a/openapi.yml
+++ b/openapi.yml
@@ -1,547 +1,547 @@
-openapi: 3.0.3
-info:
- title: Fineract Credit Scorecard
- version: 0.1.0-SNAPSHOT
- description: An API module for credit risk assessment
- license:
- name: Apache-2.0
- url: https://www.apache.org/licenses/LICENSE-2.0.html
-paths:
- /api/v1/algorithms:
- get:
- operationId: algorithms_list
- description: ''
- tags:
- - algorithms
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/Algorithm'
- description: ''
- post:
- operationId: algorithms_create
- description: ''
- tags:
- - algorithms
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Algorithm'
- application/x-www-form-urlencoded:
- schema:
- $ref: '#/components/schemas/Algorithm'
- multipart/form-data:
- schema:
- $ref: '#/components/schemas/Algorithm'
- required: true
- security:
- - {}
- responses:
- '201':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Algorithm'
- description: ''
- /api/v1/algorithms/{id}:
- get:
- operationId: algorithms_retrieve
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this algorithm.
- required: true
- tags:
- - algorithms
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Algorithm'
- description: ''
- put:
- operationId: algorithms_update
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this algorithm.
- required: true
- tags:
- - algorithms
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Algorithm'
- application/x-www-form-urlencoded:
- schema:
- $ref: '#/components/schemas/Algorithm'
- multipart/form-data:
- schema:
- $ref: '#/components/schemas/Algorithm'
- required: true
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Algorithm'
- description: ''
- patch:
- operationId: algorithms_partial_update
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this algorithm.
- required: true
- tags:
- - algorithms
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Algorithm'
- application/x-www-form-urlencoded:
- schema:
- $ref: '#/components/schemas/Algorithm'
- multipart/form-data:
- schema:
- $ref: '#/components/schemas/Algorithm'
- required: true
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Algorithm'
- description: ''
- delete:
- operationId: algorithms_destroy
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this algorithm.
- required: true
- tags:
- - algorithms
- security:
- - {}
- responses:
- '204':
- description: No response body
- /api/v1/algorithms/predict:
- post:
- operationId: algorithms_predict
- description: Predict credit risk for a loan
- parameters:
- - in: query
- name: classifier
- schema:
- type: string
- description: The algorithm/classifier to use
- required: true
- examples:
- Example1:
- value: RandomForestClassifier
- summary: Example 1
- - in: query
- name: dataset
- schema:
- type: string
- description: The name of the dataset
- examples:
- Example1:
- value: german
- summary: Example 1
- - in: query
- name: status
- schema:
- type: string
- description: The status of the algorithm
- deprecated: true
- examples:
- Example1:
- value: production
- summary: Example 1
- - in: query
- name: version
- schema:
- type: string
- default: 0.0.1
- description: Algorithm version
- required: true
- examples:
- Example1:
- value: 0.0.1
- summary: Example 1
- tags:
- - algorithms
- requestBody:
- content:
- application/json:
- schema:
- type: object
- additionalProperties: {}
- description: Unspecified request body
- application/x-www-form-urlencoded:
- schema:
- type: object
- additionalProperties: {}
- description: Unspecified request body
- multipart/form-data:
- schema:
- type: object
- additionalProperties: {}
- description: Unspecified request body
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionResponse'
- description: ''
- /api/v1/datasets:
- get:
- operationId: datasets_list
- description: ''
- tags:
- - datasets
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/Dataset'
- description: ''
- /api/v1/datasets/{id}:
- get:
- operationId: datasets_retrieve
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this dataset.
- required: true
- tags:
- - datasets
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Dataset'
- description: ''
- /api/v1/requests:
- get:
- operationId: requests_list
- description: ''
- tags:
- - requests
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- type: array
- items:
- $ref: '#/components/schemas/PredictionRequest'
- description: ''
- post:
- operationId: requests_create
- description: ''
- tags:
- - requests
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- application/x-www-form-urlencoded:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- multipart/form-data:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- required: true
- security:
- - {}
- responses:
- '201':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- description: ''
- /api/v1/requests/{id}:
- get:
- operationId: requests_retrieve
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this prediction request.
- required: true
- tags:
- - requests
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- description: ''
- put:
- operationId: requests_update
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this prediction request.
- required: true
- tags:
- - requests
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- application/x-www-form-urlencoded:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- multipart/form-data:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- required: true
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- description: ''
- patch:
- operationId: requests_partial_update
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this prediction request.
- required: true
- tags:
- - requests
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- application/x-www-form-urlencoded:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- multipart/form-data:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- required: true
- security:
- - {}
- responses:
- '200':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/PredictionRequest'
- description: ''
- delete:
- operationId: requests_destroy
- description: ''
- parameters:
- - in: path
- name: id
- schema:
- type: integer
- description: A unique integer value identifying this prediction request.
- required: true
- tags:
- - requests
- security:
- - {}
- responses:
- '204':
- description: No response body
-components:
- schemas:
- Algorithm:
- type: object
- properties:
- id:
- type: integer
- readOnly: true
- classifier:
- type: string
- maxLength: 128
- description:
- type: string
- nullable: true
- version:
- type: string
- maxLength: 128
- status:
- type: string
- maxLength: 128
- created_at:
- type: string
- format: date-time
- readOnly: true
- created_by:
- type: string
- maxLength: 128
- dataset:
- type: string
- nullable: true
- required:
- - classifier
- - created_at
- - created_by
- - id
- - status
- - version
- Dataset:
- type: object
- properties:
- id:
- type: integer
- readOnly: true
- name:
- type: string
- maxLength: 128
- region:
- type: string
- maxLength: 128
- required:
- - id
- - name
- - region
- PredictionRequest:
- type: object
- properties:
- id:
- type: integer
- readOnly: true
- input:
- type: object
- additionalProperties: {}
- response:
- type: object
- additionalProperties: {}
- prediction:
- type: string
- maxLength: 128
- feedback:
- type: string
- nullable: true
- maxLength: 128
- notes:
- type: string
- nullable: true
- created_at:
- type: string
- format: date-time
- readOnly: true
- created_by:
- type: string
- maxLength: 128
- algorithm:
- type: integer
- required:
- - created_at
- - created_by
- - id
- - input
- - prediction
- - response
- PredictionResponse:
- type: object
- properties:
- probability:
- type: number
- format: float
- label:
- type: string
- method:
- type: string
- color:
- type: string
- wilkis_lambda:
- type: number
- format: float
- pillais_trace:
- type: number
- format: float
- hotelling_tawley:
- type: number
- format: float
- roys_reatest_roots:
- type: number
- format: float
- request_id:
- type: integer
- required:
- - color
- - hotelling_tawley
- - label
- - method
- - pillais_trace
- - probability
- - request_id
- - roys_reatest_roots
- - wilkis_lambda
-servers:
-- url: http://127.0.0.1:8000
- description: server on localhost
+openapi: 3.0.3
+info:
+ title: Fineract Credit Scorecard
+ version: 0.1.0-SNAPSHOT
+ description: An API module for credit risk assessment
+ license:
+ name: Apache-2.0
+ url: https://www.apache.org/licenses/LICENSE-2.0.html
+paths:
+ /api/v1/algorithms:
+ get:
+ operationId: algorithms_list
+ description: ''
+ tags:
+ - algorithms
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ post:
+ operationId: algorithms_create
+ description: ''
+ tags:
+ - algorithms
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ required: true
+ security:
+ - {}
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ /api/v1/algorithms/{id}:
+ get:
+ operationId: algorithms_retrieve
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithms
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ put:
+ operationId: algorithms_update
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithms
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ required: true
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ patch:
+ operationId: algorithms_partial_update
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithms
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ required: true
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ delete:
+ operationId: algorithms_destroy
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithms
+ security:
+ - {}
+ responses:
+ '204':
+ description: No response body
+ /api/v1/algorithms/predict:
+ post:
+ operationId: algorithms_predict
+ description: Predict credit risk for a loan
+ parameters:
+ - in: query
+ name: classifier
+ schema:
+ type: string
+ description: The algorithm/classifier to use
+ required: true
+ examples:
+ Example1:
+ value: RandomForestClassifier
+ summary: Example 1
+ - in: query
+ name: dataset
+ schema:
+ type: string
+ description: The name of the dataset
+ examples:
+ Example1:
+ value: german
+ summary: Example 1
+ - in: query
+ name: status
+ schema:
+ type: string
+ description: The status of the algorithm
+ deprecated: true
+ examples:
+ Example1:
+ value: production
+ summary: Example 1
+ - in: query
+ name: version
+ schema:
+ type: string
+ default: 0.0.1
+ description: Algorithm version
+ required: true
+ examples:
+ Example1:
+ value: 0.0.1
+ summary: Example 1
+ tags:
+ - algorithms
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ additionalProperties: {}
+ description: Unspecified request body
+ application/x-www-form-urlencoded:
+ schema:
+ type: object
+ additionalProperties: {}
+ description: Unspecified request body
+ multipart/form-data:
+ schema:
+ type: object
+ additionalProperties: {}
+ description: Unspecified request body
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionResponse'
+ description: ''
+ /api/v1/datasets:
+ get:
+ operationId: datasets_list
+ description: ''
+ tags:
+ - datasets
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ /api/v1/datasets/{id}:
+ get:
+ operationId: datasets_retrieve
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - datasets
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ /api/v1/requests:
+ get:
+ operationId: requests_list
+ description: ''
+ tags:
+ - requests
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/PredictionRequest'
+ description: ''
+ post:
+ operationId: requests_create
+ description: ''
+ tags:
+ - requests
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ required: true
+ security:
+ - {}
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ description: ''
+ /api/v1/requests/{id}:
+ get:
+ operationId: requests_retrieve
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this prediction request.
+ required: true
+ tags:
+ - requests
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ description: ''
+ put:
+ operationId: requests_update
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this prediction request.
+ required: true
+ tags:
+ - requests
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ required: true
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ description: ''
+ patch:
+ operationId: requests_partial_update
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this prediction request.
+ required: true
+ tags:
+ - requests
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ required: true
+ security:
+ - {}
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PredictionRequest'
+ description: ''
+ delete:
+ operationId: requests_destroy
+ description: ''
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this prediction request.
+ required: true
+ tags:
+ - requests
+ security:
+ - {}
+ responses:
+ '204':
+ description: No response body
+components:
+ schemas:
+ Algorithm:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ classifier:
+ type: string
+ maxLength: 128
+ description:
+ type: string
+ nullable: true
+ version:
+ type: string
+ maxLength: 128
+ status:
+ type: string
+ maxLength: 128
+ created_at:
+ type: string
+ format: date-time
+ readOnly: true
+ created_by:
+ type: string
+ maxLength: 128
+ dataset:
+ type: string
+ nullable: true
+ required:
+ - classifier
+ - created_at
+ - created_by
+ - id
+ - status
+ - version
+ Dataset:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ maxLength: 128
+ region:
+ type: string
+ maxLength: 128
+ required:
+ - id
+ - name
+ - region
+ PredictionRequest:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ input:
+ type: object
+ additionalProperties: {}
+ response:
+ type: object
+ additionalProperties: {}
+ prediction:
+ type: string
+ maxLength: 128
+ feedback:
+ type: string
+ nullable: true
+ maxLength: 128
+ notes:
+ type: string
+ nullable: true
+ created_at:
+ type: string
+ format: date-time
+ readOnly: true
+ created_by:
+ type: string
+ maxLength: 128
+ algorithm:
+ type: integer
+ required:
+ - created_at
+ - created_by
+ - id
+ - input
+ - prediction
+ - response
+ PredictionResponse:
+ type: object
+ properties:
+ probability:
+ type: number
+ format: float
+ label:
+ type: string
+ method:
+ type: string
+ color:
+ type: string
+ wilkis_lambda:
+ type: number
+ format: float
+ pillais_trace:
+ type: number
+ format: float
+ hotelling_tawley:
+ type: number
+ format: float
+ roys_reatest_roots:
+ type: number
+ format: float
+ request_id:
+ type: integer
+ required:
+ - color
+ - hotelling_tawley
+ - label
+ - method
+ - pillais_trace
+ - probability
+ - request_id
+ - roys_reatest_roots
+ - wilkis_lambda
+servers:
+ - url: http://127.0.0.1:8000
+ description: server on localhost
diff --git a/clients/java/README.md b/scorecard-client/README.md
similarity index 100%
rename from clients/java/README.md
rename to scorecard-client/README.md
diff --git a/scorecard-client/build.gradle b/scorecard-client/build.gradle
new file mode 100644
index 0000000..b49b6fa
--- /dev/null
+++ b/scorecard-client/build.gradle
@@ -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.
+ */
+
+plugins {
+ id 'java-library'
+}
+
+group = 'org.apache.fineract'
+version = '0.1.0-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+sourceSets {
+ main.java.srcDirs = ['src/main/java']
+}
+
+task execute(type:JavaExec) {
+ classpath = sourceSets.main.runtimeClasspath
+}
+
+dependencies {
+ implementation 'io.swagger:swagger-annotations:1.5.24'
+ implementation "com.google.code.findbugs:jsr305:3.0.2"
+
+ api 'com.squareup.okhttp3:okhttp:3.14.7'
+ api 'com.squareup.okhttp3:logging-interceptor:3.14.7'
+ api 'com.google.code.gson:gson:2.8.6'
+ api 'io.gsonfire:gson-fire:1.8.4'
+
+ implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
+ implementation 'javax.annotation:javax.annotation-api:1.3.2'
+ testImplementation 'junit:junit:4.13.1'
+}
+
+javadoc {
+ options.tags = [ "http.response.details:a:Http Response Details" ]
+}
diff --git a/clients/java/docs/Algorithm.md b/scorecard-client/docs/Algorithm.md
similarity index 100%
rename from clients/java/docs/Algorithm.md
rename to scorecard-client/docs/Algorithm.md
diff --git a/clients/java/docs/AlgorithmsApi.md b/scorecard-client/docs/AlgorithmsApi.md
similarity index 100%
rename from clients/java/docs/AlgorithmsApi.md
rename to scorecard-client/docs/AlgorithmsApi.md
diff --git a/clients/java/docs/Dataset.md b/scorecard-client/docs/Dataset.md
similarity index 100%
rename from clients/java/docs/Dataset.md
rename to scorecard-client/docs/Dataset.md
diff --git a/clients/java/docs/DatasetsApi.md b/scorecard-client/docs/DatasetsApi.md
similarity index 100%
rename from clients/java/docs/DatasetsApi.md
rename to scorecard-client/docs/DatasetsApi.md
diff --git a/clients/java/docs/PredictionRequest.md b/scorecard-client/docs/PredictionRequest.md
similarity index 100%
rename from clients/java/docs/PredictionRequest.md
rename to scorecard-client/docs/PredictionRequest.md
diff --git a/clients/java/docs/PredictionResponse.md b/scorecard-client/docs/PredictionResponse.md
similarity index 100%
rename from clients/java/docs/PredictionResponse.md
rename to scorecard-client/docs/PredictionResponse.md
diff --git a/clients/java/docs/RequestsApi.md b/scorecard-client/docs/RequestsApi.md
similarity index 100%
rename from clients/java/docs/RequestsApi.md
rename to scorecard-client/docs/RequestsApi.md
diff --git a/clients/java/src/main/AndroidManifest.xml b/scorecard-client/src/main/AndroidManifest.xml
similarity index 100%
rename from clients/java/src/main/AndroidManifest.xml
rename to scorecard-client/src/main/AndroidManifest.xml
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiCallback.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiCallback.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiCallback.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiCallback.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiClient.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiClient.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiClient.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiClient.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiException.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiException.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiException.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiException.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiResponse.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiResponse.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ApiResponse.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ApiResponse.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/Configuration.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/Configuration.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/Configuration.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/Configuration.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/GzipRequestInterceptor.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/GzipRequestInterceptor.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/GzipRequestInterceptor.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/GzipRequestInterceptor.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/JSON.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/JSON.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/JSON.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/JSON.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/Pair.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/Pair.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/Pair.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/Pair.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ProgressRequestBody.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ProgressRequestBody.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ProgressRequestBody.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ProgressRequestBody.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ProgressResponseBody.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ProgressResponseBody.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ProgressResponseBody.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ProgressResponseBody.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ServerConfiguration.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ServerConfiguration.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ServerConfiguration.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ServerConfiguration.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/ServerVariable.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ServerVariable.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/ServerVariable.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/ServerVariable.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/StringUtil.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/StringUtil.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/StringUtil.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/StringUtil.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/ApiKeyAuth.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/ApiKeyAuth.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/ApiKeyAuth.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/ApiKeyAuth.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/Authentication.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/Authentication.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/Authentication.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/Authentication.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBasicAuth.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBasicAuth.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBasicAuth.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBasicAuth.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBearerAuth.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBearerAuth.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBearerAuth.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/auth/HttpBearerAuth.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/Algorithm.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/Algorithm.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/Algorithm.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/Algorithm.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/Dataset.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/Dataset.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/Dataset.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/Dataset.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionRequest.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionRequest.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionRequest.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionRequest.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionResponse.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionResponse.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionResponse.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/models/PredictionResponse.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/services/AlgorithmsApi.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/services/AlgorithmsApi.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/services/AlgorithmsApi.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/services/AlgorithmsApi.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/services/DatasetsApi.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/services/DatasetsApi.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/services/DatasetsApi.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/services/DatasetsApi.java
diff --git a/clients/java/src/main/java/org/apache/fineract/credit/scorecard/services/RequestsApi.java b/scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/services/RequestsApi.java
similarity index 100%
rename from clients/java/src/main/java/org/apache/fineract/credit/scorecard/services/RequestsApi.java
rename to scorecard-client/src/main/java/org/apache/fineract/credit/scorecard/services/RequestsApi.java
diff --git a/scorecard-plugin/README.md b/scorecard-plugin/README.md
new file mode 100644
index 0000000..7c79239
--- /dev/null
+++ b/scorecard-plugin/README.md
@@ -0,0 +1,39 @@
+# Credit Scorecard Plugin for Apache Fineract
+
+This is a [_Plugin_ for Apache Fineract](https://github.com/apache/fineract/blob/develop/fineract-doc/src/docs/en/deployment.adoc).
+(This work is inspired by the design approach of the [fineract-pentaho plugin](https://github.com/openMF/fineract-pentaho).)
+
+see [TODO](TODO.md) for possible future follow-up enhancement work. The TODO list was inherited from [fineract-pentaho plugin]((https://github.com/openMF/fineract-pentaho))
+
+
+## Build & Use
+
+This project is currently only tested against the very latest and greatest
+bleeding edge Fineract `develop` branch. Building and using it against
+older versions may be possible, but is not tested or documented here.
+
+ git clone https://github.com/apache/fineract.git
+ cd fineract && ./gradlew bootJar && cd ..
+
+ git clone https://github.com/apache/fineract-credit-scorecard.git
+ cd fineract-credit-scorecard && ./gradlew -x test distZip && cd ..
+
+ ./fineract-credit-scorecard/scorecard-plugin/run
+
+The [`run`](run) script basically just creates the following directory structure:
+
+ fineract-provider.jar
+ lib/scorecard-plugin.jar
+ lib/lib*.jar
+
+and then launches Apache Fineract with the Pentaho Plugin and all its JARs like this:
+
+ java -Dloader.path=lib/ -jar fineract-provider.jar
+
+## Contribute
+
+If this Fineract plugin project is useful to you, please contribute back to it (and
+Fineract) by raising Pull Requests yourself with any enhancements you make, and by helping
+to maintain this project by helping other users on Issues and reviewing PR from others
+(you will be promoted to committer on this project when you contribute). We recommend
+that you _Watch_ and _Star_ this project on GitHub to make it easy to get notified.
diff --git a/scorecard-plugin/TODO.md b/scorecard-plugin/TODO.md
new file mode 100644
index 0000000..deb28c0
--- /dev/null
+++ b/scorecard-plugin/TODO.md
@@ -0,0 +1,17 @@
+# TODO
+
+1. move Java package name (back, again); see [FINERACT-1174](https://issues.apache.org/jira/browse/FINERACT-1174)
+
+1. how to avoid `files("../")` ? We would have to have an `api` artifact, and publish it..
+ watch [FINERACT-1171](https://issues.apache.org/jira/browse/FINERACT-1171)
+
+1. inherit dependency management from Fineract, so that e.g.
+ JAX RS & commons lang versions don't have to be repeated.
+ Actually, perhaps JAX RS & commons lang should be considered
+ part of a (future..) Fineract Plugin API, and not need to be declared at all!
+
+1. run `ClasspathDuplicateTest`, on all such plugins
+
+1. run usual Fineract code style checks against plugin code like this
+
+1. build standalone "service", not just "plugin"
diff --git a/scorecard-plugin/build.gradle b/scorecard-plugin/build.gradle
new file mode 100644
index 0000000..8e3d14f
--- /dev/null
+++ b/scorecard-plugin/build.gradle
@@ -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.
+ */
+
+plugins {
+ id 'java-library'
+ id 'java-library-distribution'
+ id 'io.spring.dependency-management' version '1.0.10.RELEASE'
+}
+
+repositories {
+ flatDir {
+ dirs "$rootDir/scorecard-client/build/libs"
+ }
+ mavenCentral()
+}
+
+dependencies {
+ compileOnly(
+ // Fineract!
+ files("../../fineract/fineract-provider/build/classes/java/main/"),
+
+ // Fineract dependencies (TODO version should *NOT* be specified here...)
+ 'org.slf4j:slf4j-api:1.7.30',
+ 'javax.ws.rs:jsr311-api:1.1.1',
+ 'org.apache.openjpa:openjpa:3.1.2',
+ 'org.apache.commons:commons-lang3:3.10',
+ 'org.springframework:spring-context:5.2.6.RELEASE',
+ 'org.springframework.data:spring-data-commons:2.3.4.RELEASE',
+ 'org.springframework.security:spring-security-core:5.3.4.RELEASE',
+ 'org.springframework.boot:spring-boot-starter-data-jpa:2.3.5.RELEASE'
+ )
+
+ implementation(
+ // Fineract Credit Scorecard Dependencies
+ project(":scorecard-client"),
+ 'com.google.code.gson:gson:2.8.7'
+ )
+
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
+}
+
+tasks.named('test') {
+ // Use JUnit Platform for unit tests.
+ useJUnitPlatform()
+}
+
+distributions {
+ main {
+ contents {
+ into('/') {
+ from "README.md", "../LICENSE", "run", "run.bat"
+ }
+
+ into('/lib') {
+ from(jar)
+ }
+
+ eachFile { FileCopyDetails fcp ->
+ fcp.relativePath = new RelativePath(true, fcp.relativePath.pathString.replace('scorecard-plugin/', ''))
+ }
+ }
+ }
+}
diff --git a/scorecard-plugin/run b/scorecard-plugin/run
new file mode 100644
index 0000000..5e36220
--- /dev/null
+++ b/scorecard-plugin/run
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+set -euxo pipefail
+
+# Copy Apache Fineract JAR
+mkdir -p build/run
+cp ./fineract/fineract-provider/build/libs/fineract-provider*.jar build/run
+
+# Add our scorecard-plugin reporting plugin, like so:
+unzip ./FINCS/scorecard-plugin/build/distributions/scorecard-plugin.zip -d build/run/
+rm build/run/scorecard-plugin.jar
+
+# Start!
+java -Dloader.path=build/run/lib/ -jar build/run/fineract-provider.jar
diff --git a/scorecard-plugin/run.bat b/scorecard-plugin/run.bat
new file mode 100644
index 0000000..32b7c40
--- /dev/null
+++ b/scorecard-plugin/run.bat
@@ -0,0 +1,33 @@
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+
+@echo on
+
+rem Copy Apache Fineract JAR
+md build\run
+copy .\fineract\fineract-provider\build\libs\fineract-provider.jar build\run
+
+rem Add our scorecard-plugin reporting plugin, like so:
+
+powershell -command "Expand-Archive -Force '.\fineract-credit-scorecard\scorecard-plugin\build\distributions\scorecard-plugin.zip' 'build\run'"
+del .\build\run\scorecard-plugin.jar
+
+rem Start!
+
+java -Dloader.path=build\run\lib\ -jar build\run\fineract-provider.jar
\ No newline at end of file
diff --git a/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardAssemblerImpl.java b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardAssemblerImpl.java
new file mode 100644
index 0000000..a1f8f04
--- /dev/null
+++ b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardAssemblerImpl.java
@@ -0,0 +1,255 @@
+/**
+ * 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.creditscorecard.service;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.portfolio.creditscorecard.annotation.ScorecardService;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecard;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecardFeature;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureCriteria;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureCriteriaScore;
+import org.apache.fineract.portfolio.creditscorecard.domain.MLScorecard;
+import org.apache.fineract.portfolio.creditscorecard.domain.MLScorecardFields;
+import org.apache.fineract.portfolio.creditscorecard.domain.RuleBasedScorecard;
+import org.apache.fineract.portfolio.creditscorecard.domain.StatScorecard;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProductScorecardFeature;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProductScorecardFeatureRepositoryWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@ScorecardService(name = "CreditScorecardAssembler")
+public class CreditScorecardAssemblerImpl implements CreditScorecardAssembler {
+
+ private final FromJsonHelper fromApiJsonHelper;
+ private final CreditScorecardReadPlatformService readPlatformService;
+ private final LoanProductScorecardFeatureRepositoryWrapper productFeatureRepository;
+
+ @Autowired
+ public CreditScorecardAssemblerImpl(final FromJsonHelper fromApiJsonHelper,
+ final CreditScorecardReadPlatformService readPlatformService,
+ final LoanProductScorecardFeatureRepositoryWrapper productFeatureRepository) {
+ this.fromApiJsonHelper = fromApiJsonHelper;
+ this.readPlatformService = readPlatformService;
+ this.productFeatureRepository = productFeatureRepository;
+ }
+
+ @Override
+ public CreditScorecard assembleFrom(final JsonElement element) {
+ CreditScorecard creditScorecard = null;
+
+ if (element.isJsonObject()) {
+
+ final String scoringMethod = this.fromApiJsonHelper.extractStringNamed("scoringMethod", element);
+ final String scoringModel = this.fromApiJsonHelper.extractStringNamed("scoringModel", element);
+
+ RuleBasedScorecard ruleBasedScorecard = null;
+ StatScorecard statScorecard = null;
+ MLScorecard mlScorecard = null;
+
+ if (scoringMethod.equalsIgnoreCase("ruleBased")) {
+ ruleBasedScorecard = this.assembleRuleBasedScorecard(element);
+ }
+
+ if (scoringMethod.equalsIgnoreCase("ml")) {
+ mlScorecard = this.assembleMLScorecard(element);
+ }
+
+ if (scoringMethod.equalsIgnoreCase("stat")) {
+ statScorecard = this.assembleStatScorecard(element);
+ }
+
+ creditScorecard = new CreditScorecard(scoringMethod, scoringModel, ruleBasedScorecard, statScorecard, mlScorecard);
+ }
+
+ return creditScorecard;
+ }
+
+ public RuleBasedScorecard assembleRuleBasedScorecard(final JsonElement element) {
+
+ final RuleBasedScorecard ruleBasedScorecard = new RuleBasedScorecard();
+
+ final List<FeatureCriteriaScore> criteriaScores = new ArrayList<>();
+
+ if (element.isJsonObject()) {
+ final JsonObject topLevelJsonElement = element.getAsJsonObject();
+
+ final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement);
+ final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
+
+ final String rbScorecardParameterName = "ruleBasedScorecard";
+ if (topLevelJsonElement.has(rbScorecardParameterName) && topLevelJsonElement.get(rbScorecardParameterName).isJsonObject()) {
+ final JsonObject rbScorecardElement = topLevelJsonElement.getAsJsonObject(rbScorecardParameterName);
+
+ final String criteriaScoresParameterName = "criteriaScores";
+ if (rbScorecardElement.has(criteriaScoresParameterName)
+ && rbScorecardElement.get(criteriaScoresParameterName).isJsonArray()) {
+ final JsonArray array = rbScorecardElement.get(criteriaScoresParameterName).getAsJsonArray();
+ for (int i = 0; i < array.size(); i++) {
+
+ final JsonObject criteriaScoreElement = array.get(i).getAsJsonObject();
+
+ final Long featureId = this.fromApiJsonHelper.extractLongNamed("featureId", criteriaScoreElement);
+ final String value = this.fromApiJsonHelper.extractStringNamed("value", criteriaScoreElement);
+
+ final LoanProductScorecardFeature lpScorecardFeature = this.productFeatureRepository
+ .findOneWithNotFoundDetection(featureId);
+
+ criteriaScores.add(new FeatureCriteriaScore(lpScorecardFeature, value));
+
+ }
+
+ } else {
+ return null;
+
+ }
+ }
+ }
+
+ ruleBasedScorecard.setCriteriaScores(criteriaScores);
+
+ return ruleBasedScorecard;
+ }
+
+ public StatScorecard assembleStatScorecard(final JsonElement element) {
+
+ StatScorecard statScorecard = null;
+
+ if (element.isJsonObject()) {
+
+ final JsonObject topLevelJsonElement = element.getAsJsonObject();
+
+ final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement);
+ final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
+
+ final String statScorecardParameterName = "statScorecard";
+ if (topLevelJsonElement.has(statScorecardParameterName) && topLevelJsonElement.get(statScorecardParameterName).isJsonObject()) {
+ final JsonObject scorecardDataElement = topLevelJsonElement.getAsJsonObject(statScorecardParameterName);
+
+ statScorecard = new StatScorecard(
+ new MLScorecardFields(this.fromApiJsonHelper.extractIntegerWithLocaleNamed("age", scorecardDataElement),
+ this.fromApiJsonHelper.extractStringNamed("sex", scorecardDataElement),
+ this.fromApiJsonHelper.extractStringNamed("job", scorecardDataElement),
+ this.fromApiJsonHelper.extractStringNamed("housing", scorecardDataElement),
+ this.fromApiJsonHelper.extractBigDecimalNamed("creditAmount", scorecardDataElement, locale),
+ this.fromApiJsonHelper.extractIntegerNamed("duration", scorecardDataElement, locale),
+ this.fromApiJsonHelper.extractStringNamed("purpose", scorecardDataElement)));
+ }
+ }
+ return statScorecard;
+ }
+
+ public MLScorecard assembleMLScorecard(final JsonElement element) {
+
+ MLScorecard mlScorecard = null;
+
+ if (element.isJsonObject()) {
+
+ final JsonObject topLevelJsonElement = element.getAsJsonObject();
+
+ final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement);
+ final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
+
+ final String mlScorecardParameterName = "mlScorecard";
+ if (topLevelJsonElement.has(mlScorecardParameterName) && topLevelJsonElement.get(mlScorecardParameterName).isJsonObject()) {
+ final JsonObject scorecardDataElement = topLevelJsonElement.getAsJsonObject(mlScorecardParameterName);
+
+ mlScorecard = new MLScorecard(
+ new MLScorecardFields(this.fromApiJsonHelper.extractIntegerWithLocaleNamed("age", scorecardDataElement),
+ this.fromApiJsonHelper.extractStringNamed("sex", scorecardDataElement),
+ this.fromApiJsonHelper.extractStringNamed("job", scorecardDataElement),
+ this.fromApiJsonHelper.extractStringNamed("housing", scorecardDataElement),
+ this.fromApiJsonHelper.extractBigDecimalNamed("creditAmount", scorecardDataElement, locale),
+ this.fromApiJsonHelper.extractIntegerNamed("duration", scorecardDataElement, locale),
+ this.fromApiJsonHelper.extractStringNamed("purpose", scorecardDataElement)));
+ }
+ }
+ return mlScorecard;
+ }
+
+
+ @Override
+ public List<LoanProductScorecardFeature> assembleListOfProductScoringFeatures(final JsonCommand command, LoanProduct loanProduct) {
+
+ final List<LoanProductScorecardFeature> loanProductFeatures = new ArrayList<>();
+
+ // JsonCommand incentivesCommand = JsonCommand.fromExistingCommand(command, incentiveElement);
+ // chartSlab.slabFields().validateChartSlabPlatformRules(chartSlabsCommand, baseDataValidator, locale);
+
+ if (command.parameterExists("scorecardFeatures")) {
+ final JsonArray featuresArray = command.arrayOfParameterNamed("scorecardFeatures");
+ if (featuresArray != null) {
+ for (int i = 0; i < featuresArray.size(); i++) {
+
+ final JsonObject jsonObject = featuresArray.get(i).getAsJsonObject();
+ if (jsonObject.has("featureId")) {
+ final Long id = jsonObject.get("featureId").getAsLong();
+
+ final BigDecimal weightage = jsonObject.get("weightage").getAsBigDecimal();
+ final Integer greenMin = jsonObject.get("greenMin").getAsInt();
+ final Integer greenMax = jsonObject.get("greenMax").getAsInt();
+ final Integer amberMin = jsonObject.get("amberMin").getAsInt();
+ final Integer amberMax = jsonObject.get("amberMax").getAsInt();
+ final Integer redMin = jsonObject.get("redMin").getAsInt();
+ final Integer redMax = jsonObject.get("redMax").getAsInt();
+
+ final List<FeatureCriteria> criteria = this
+ .assembleListOfProductScoringFeatureCriteriaScores(jsonObject.get("criteriaScores").getAsJsonArray());
+
+ final CreditScorecardFeature feature = this.readPlatformService.findOneFeatureWithNotFoundDetection(id);
+
+ final LoanProductScorecardFeature loanProductFeature = new LoanProductScorecardFeature(feature, weightage, greenMin,
+ greenMax, amberMin, amberMax, redMin, redMax);
+
+ loanProductFeature.setFeatureCriteria(criteria);
+ loanProductFeatures.add(loanProductFeature);
+ }
+ }
+ }
+ }
+
+ return loanProductFeatures;
+ }
+
+ private List<FeatureCriteria> assembleListOfProductScoringFeatureCriteriaScores(final JsonArray jsonArray) {
+
+ final List<FeatureCriteria> featureCriteria = new ArrayList<>();
+
+ if (jsonArray != null) {
+ for (int i = 0; i < jsonArray.size(); i++) {
+
+ final JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
+ final BigDecimal score = jsonObject.get("score").getAsBigDecimal();
+ final String scoreCriteria = jsonObject.get("criteria").getAsString();
+
+ featureCriteria.add(new FeatureCriteria(scoreCriteria, score));
+ }
+ }
+
+ return featureCriteria;
+ }
+
+}
diff --git a/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardFeatureDropdownReadPlatformService.java b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardFeatureDropdownReadPlatformService.java
new file mode 100644
index 0000000..e3f0eb7
--- /dev/null
+++ b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardFeatureDropdownReadPlatformService.java
@@ -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.creditscorecard.service;
+
+import java.util.List;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
+public interface CreditScorecardFeatureDropdownReadPlatformService {
+
+ List<EnumOptionData> retrieveValueTypes();
+
+ List<EnumOptionData> retrieveDataTypes();
+
+ List<EnumOptionData> retrieveCategoryTypes();
+
+}
diff --git a/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardFeatureDropdownReadPlatformServiceImpl.java b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardFeatureDropdownReadPlatformServiceImpl.java
new file mode 100644
index 0000000..e92fa76
--- /dev/null
+++ b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardFeatureDropdownReadPlatformServiceImpl.java
@@ -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.portfolio.creditscorecard.service;
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureCategory;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureDataType;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureValueType;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CreditScorecardFeatureDropdownReadPlatformServiceImpl implements CreditScorecardFeatureDropdownReadPlatformService {
+
+ @Override
+ public List<EnumOptionData> retrieveValueTypes() {
+ return Arrays.asList(CreditScorecardEnumerations.featureValueType(FeatureValueType.BINARY),
+ CreditScorecardEnumerations.featureValueType(FeatureValueType.NOMINAL),
+ CreditScorecardEnumerations.featureValueType(FeatureValueType.RATIO),
+ CreditScorecardEnumerations.featureValueType(FeatureValueType.INTERVAL));
+ }
+
+ @Override
+ public List<EnumOptionData> retrieveDataTypes() {
+ return Arrays.asList(CreditScorecardEnumerations.featureDataType(FeatureDataType.STRING),
+ CreditScorecardEnumerations.featureDataType(FeatureDataType.NUMERIC),
+ CreditScorecardEnumerations.featureDataType(FeatureDataType.DATE));
+ }
+
+ @Override
+ public List<EnumOptionData> retrieveCategoryTypes() {
+ return Arrays.asList(CreditScorecardEnumerations.featureCategory(FeatureCategory.INDIVIDUAL),
+ CreditScorecardEnumerations.featureCategory(FeatureCategory.ORGANISATION),
+ CreditScorecardEnumerations.featureCategory(FeatureCategory.COUNTRY),
+ CreditScorecardEnumerations.featureCategory(FeatureCategory.CREDIT_HISTORY),
+ CreditScorecardEnumerations.featureCategory(FeatureCategory.LOAN));
+ }
+}
diff --git a/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardReadPlatformServiceImpl.java b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardReadPlatformServiceImpl.java
new file mode 100644
index 0000000..d99255e
--- /dev/null
+++ b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardReadPlatformServiceImpl.java
@@ -0,0 +1,228 @@
+/**
+ * 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.creditscorecard.service;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.portfolio.charge.exception.ChargeIsNotActiveException;
+import org.apache.fineract.portfolio.creditscorecard.annotation.ScorecardService;
+import org.apache.fineract.portfolio.creditscorecard.data.CreditScorecardData;
+import org.apache.fineract.portfolio.creditscorecard.data.CreditScorecardFeatureData;
+import org.apache.fineract.portfolio.creditscorecard.data.MLScorecardData;
+import org.apache.fineract.portfolio.creditscorecard.data.RuleBasedScorecardData;
+import org.apache.fineract.portfolio.creditscorecard.data.ScorecardFeatureCriteriaData;
+import org.apache.fineract.portfolio.creditscorecard.data.StatScorecardData;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecard;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecardFeature;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecardFeatureRepository;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecardRepository;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+
+@ScorecardService(name = "CreditScorecardReadPlatformService")
+public class CreditScorecardReadPlatformServiceImpl implements CreditScorecardReadPlatformService {
+
+ private final JdbcTemplate jdbcTemplate;
+ private final CreditScorecardRepository scorecardRepository;
+ private final CreditScorecardFeatureRepository featureRepository;
+ private final CreditScorecardFeatureDropdownReadPlatformService creditScorecardFeatureDropdownReadPlatformService;
+
+ @Autowired
+ public CreditScorecardReadPlatformServiceImpl(final RoutingDataSource dataSource, final CreditScorecardRepository scorecardRepository,
+ final CreditScorecardFeatureRepository featureRepository,
+ final CreditScorecardFeatureDropdownReadPlatformService creditScorecardFeatureDropdownReadPlatformService) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ this.scorecardRepository = scorecardRepository;
+ this.featureRepository = featureRepository;
+ this.creditScorecardFeatureDropdownReadPlatformService = creditScorecardFeatureDropdownReadPlatformService;
+ }
+
+ @Override
+ public CreditScorecardFeatureData retrieveNewScorecardFeatureDetails() {
+
+ final Collection<EnumOptionData> valueTypeOptions = this.creditScorecardFeatureDropdownReadPlatformService.retrieveValueTypes();
+ final Collection<EnumOptionData> dataTypeOptions = this.creditScorecardFeatureDropdownReadPlatformService.retrieveDataTypes();
+ final Collection<EnumOptionData> categoryOptions = this.creditScorecardFeatureDropdownReadPlatformService.retrieveCategoryTypes();
+
+ return CreditScorecardFeatureData.template(valueTypeOptions, dataTypeOptions, categoryOptions);
+ }
+
+ @Override
+ public Collection<CreditScorecardFeatureData> retrieveLoanProductFeatures(Long productId) {
+ final ScorecardFeatureMapper rm = new ScorecardFeatureMapper();
+
+ final String sql = "SELECT " + rm.featureSchema()
+ + " WHERE scf.is_deleted=false AND scf.is_active=true AND lpscf.product_loan_id=? ";
+
+ final Collection<CreditScorecardFeatureData> scorecardFeatures = this.jdbcTemplate.query(sql, rm, new Object[] { productId });
+
+ for (CreditScorecardFeatureData scorecardFeature : scorecardFeatures) {
+ Collection<ScorecardFeatureCriteriaData> criteriaData = this.retrieveFeatureCriteria(scorecardFeature.getId());
+ scorecardFeature.getCriteria().addAll(criteriaData);
+ }
+ return scorecardFeatures;
+ }
+
+ @Override
+ public CreditScorecardData retrieveCreditScorecard(Long scorecardId) {
+ final CreditScorecard scorecard = this.scorecardRepository.findById(scorecardId).orElse(null);
+
+ if (scorecard == null) {
+ return null;
+ }
+
+ CreditScorecardData scorecardData = null;
+
+ final String method = scorecard.getScoringMethod();
+ switch (method) {
+ case "ml":
+ final MLScorecardData mlScorecardData = MLScorecardData.instance(scorecard.getMlScorecard());
+ scorecardData = CreditScorecardData.mlInstance(scorecard.getId(), scorecard.getScoringMethod(), scorecard.getScoringModel(),
+ mlScorecardData);
+ break;
+
+ case "stat":
+ final StatScorecardData statScorecardData = StatScorecardData.instance(scorecard.getStatScorecard());
+ scorecardData = CreditScorecardData.statInstance(scorecard.getId(), scorecard.getScoringMethod(),
+ scorecard.getScoringModel(), statScorecardData);
+ break;
+
+ case "ruleBased":
+ final RuleBasedScorecardData ruleBasedScorecardData = RuleBasedScorecardData.instance(scorecard.getRuleBasedScorecard());
+ scorecardData = CreditScorecardData.ruleBasedInstance(scorecard.getId(), scorecard.getScoringMethod(),
+ scorecard.getScoringModel(), ruleBasedScorecardData);
+ break;
+
+ default:
+ break;
+ }
+
+ return scorecardData;
+ }
+
+ @Override
+ public CreditScorecardData loanScorecardTemplate() {
+ return CreditScorecardData.loanTemplate();
+ }
+
+ @Override
+ public CreditScorecardData loanScorecardTemplate(CreditScorecardData scorecard) {
+ return CreditScorecardData.loanScorecardWithTemplate(scorecard);
+ }
+
+ private Collection<ScorecardFeatureCriteriaData> retrieveFeatureCriteria(Long featureId) {
+ final FeatureCriteriaMapper rm = new FeatureCriteriaMapper();
+
+ final String sql = "SELECT " + rm.featureCriteriaSchema() + " WHERE crit.product_loan_scorecard_feature_id=?";
+
+ return this.jdbcTemplate.query(sql, rm, new Object[] { featureId });
+ }
+
+ private static final class FeatureCriteriaMapper implements RowMapper<ScorecardFeatureCriteriaData> {
+
+ public String featureCriteriaSchema() {
+ return "crit.id as id, crit.criteria as criteria, crit.score as score " + "FROM m_scorecard_feature_criteria crit";
+ }
+
+ @Override
+ public ScorecardFeatureCriteriaData mapRow(ResultSet rs, int rowNum) throws SQLException {
+ final Long id = rs.getLong("id");
+ final String criteria = rs.getString("criteria");
+ final int score = rs.getInt("score");
+ return ScorecardFeatureCriteriaData.instance(id, criteria, BigDecimal.valueOf(score));
+ }
+ }
+
+ private static final class ScorecardFeatureMapper implements RowMapper<CreditScorecardFeatureData> {
+
+ public String featureSchema() {
+ return "scf.id as featureId, scf.name as name, scf.value_type_enum as valueType, "
+ + "scf.data_type_enum as dataType, scf.category_enum as category, scf.is_active as active, "
+ + "lpscf.id as id, lpscf.weightage as weightage, lpscf.green_min as greenMin, "
+ + "lpscf.green_max as greenMax, lpscf.amber_min as amberMin, lpscf.amber_max as amberMax, "
+ + "lpscf.red_min as redMin, lpscf.red_max as redMax "
+
+ + "FROM m_product_loan_scorecard_feature lpscf "
+ + "JOIN m_credit_scorecard_feature scf ON scf.id = lpscf.scorecard_feature_id ";
+ }
+
+ @Override
+ public CreditScorecardFeatureData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
+ final Long id = rs.getLong("id");
+
+ final Long featureId = rs.getLong("featureId");
+ final String name = rs.getString("name");
+
+ final int valueType = rs.getInt("valueType");
+ final EnumOptionData valueTypeEnum = CreditScorecardEnumerations.featureValueType(valueType);
+
+ final int dataType = rs.getInt("dataType");
+ final EnumOptionData dataTypeEnum = CreditScorecardEnumerations.featureDataType(dataType);
+
+ final int category = rs.getInt("category");
+ final EnumOptionData categoryEnum = CreditScorecardEnumerations.featureCategory(category);
+
+ final boolean active = rs.getBoolean("active");
+
+ final BigDecimal weightage = rs.getBigDecimal("weightage");
+
+ final int greenMin = rs.getInt("greenMin");
+ final int greenMax = rs.getInt("greenMax");
+
+ final int amberMin = rs.getInt("amberMin");
+ final int amberMax = rs.getInt("amberMax");
+
+ final int redMin = rs.getInt("redMin");
+ final int redMax = rs.getInt("redMax");
+
+ return CreditScorecardFeatureData.instance(id, featureId, name, valueTypeEnum, dataTypeEnum, categoryEnum, active, weightage,
+ greenMin, greenMax, amberMin, amberMax, redMin, redMax);
+ }
+ }
+
+ @Override
+ public CreditScorecardFeature findOneFeatureWithNotFoundDetection(final Long id) {
+
+ final CreditScorecardFeature scorecardFeature = this.featureRepository.findById(id)
+ .orElseThrow(() -> new FeatureNotFoundException(id));
+ if (scorecardFeature.isDeleted()) {
+ throw new FeatureNotFoundException(id);
+ }
+ if (!scorecardFeature.isActive()) {
+ throw new ChargeIsNotActiveException(id, scorecardFeature.getName());
+ }
+
+ return scorecardFeature;
+ }
+
+ @Override
+ public List<CreditScorecardFeature> findAllFeaturesWithNotFoundDetection() {
+ return this.featureRepository.findAll().stream().filter(CreditScorecardFeature::isActive).filter(feature -> !feature.isDeleted())
+ .collect(Collectors.toList());
+ }
+
+}
diff --git a/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardWritePlatformServiceImpl.java b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardWritePlatformServiceImpl.java
new file mode 100644
index 0000000..178a3b0
--- /dev/null
+++ b/scorecard-plugin/src/main/java/org/apache/fineract/portfolio/creditscorecard/service/CreditScorecardWritePlatformServiceImpl.java
@@ -0,0 +1,376 @@
+/**
+ * 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.creditscorecard.service;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.persistence.PersistenceException;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.fineract.credit.scorecard.ApiException;
+import org.apache.fineract.credit.scorecard.Configuration;
+import org.apache.fineract.credit.scorecard.models.PredictionResponse;
+import org.apache.fineract.credit.scorecard.services.AlgorithmsApi;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.creditscorecard.annotation.ScorecardService;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecard;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecardFeature;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecardFeatureRepository;
+import org.apache.fineract.portfolio.creditscorecard.domain.CreditScorecardRepository;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureConfiguration;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureCriteria;
+import org.apache.fineract.portfolio.creditscorecard.domain.FeatureCriteriaScore;
+import org.apache.fineract.portfolio.creditscorecard.domain.MLScorecard;
+import org.apache.fineract.portfolio.creditscorecard.domain.MLScorecardFields;
+import org.apache.fineract.portfolio.creditscorecard.domain.RuleBasedScorecard;
+import org.apache.fineract.portfolio.creditscorecard.domain.StatScorecard;
+import org.apache.fineract.portfolio.creditscorecard.exception.FeatureCannotBeDeletedException;
+import org.apache.fineract.portfolio.creditscorecard.exception.FeatureNotFoundException;
+import org.apache.fineract.portfolio.creditscorecard.serialization.CreditScorecardApiJsonHelper;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProductScorecardFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.orm.jpa.JpaSystemException;
+import org.springframework.transaction.annotation.Transactional;
+
+@PropertySource(value = "classpath:scorecard-client.properties")
+@ScorecardService(name = "CreditScorecardWritePlatformService")
+public class CreditScorecardWritePlatformServiceImpl implements CreditScorecardWritePlatformService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CreditScorecardWritePlatformServiceImpl.class);
+
+ @Value("${fineract.credit.scorecard.uid}")
+ String username;
+
+ @Value("${fineract.credit.scorecard.password}")
+ String password;
+
+ @Value("${fineract.credit.scorecard.baseUrl}")
+ String baseUrl;
+
+ private final PlatformSecurityContext context;
+
+ private final LoanProductRepository loanProductRepository;
+ private final CreditScorecardApiJsonHelper fromApiJsonDeserializer;
+ private final CreditScorecardFeatureRepository featureRepository;
+ private final CreditScorecardRepository scorecardRepository;
+
+ AlgorithmsApi scorecardApiClient;
+
+ @Autowired
+ public CreditScorecardWritePlatformServiceImpl(final PlatformSecurityContext context,
+ final CreditScorecardApiJsonHelper fromApiJsonDeserializer,
+ final LoanProductRepository loanProductRepository,
+ final CreditScorecardFeatureRepository featureRepository,
+ final CreditScorecardRepository scorecardRepository) {
+ this.context = context;
+ this.fromApiJsonDeserializer = fromApiJsonDeserializer;
+ this.loanProductRepository = loanProductRepository;
+ this.featureRepository = featureRepository;
+ this.scorecardRepository = scorecardRepository;
+
+ }
+
+ private void initScorecardClient() {
+ LOG.warn("Base URL at init : {}", baseUrl);
+ this.scorecardApiClient = new AlgorithmsApi(Configuration.getDefaultApiClient().setBasePath(baseUrl));
+ }
+
+ @Override
+ public CommandProcessingResult createScoringFeature(JsonCommand command) {
+
+ try {
+ this.context.authenticatedUser();
+ this.fromApiJsonDeserializer.validateFeatureForCreate(command.json());
+
+ final CreditScorecardFeature scorecardFeature = CreditScorecardFeature.fromJson(command);
+ this.featureRepository.save(scorecardFeature);
+
+ return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(scorecardFeature.getId()).build();
+ } catch (final JpaSystemException | DataIntegrityViolationException dve) {
+ handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve);
+ return CommandProcessingResult.empty();
+ } catch (final PersistenceException dve) {
+ Throwable throwable = ExceptionUtils.getRootCause(dve.getCause());
+ handleDataIntegrityIssues(command, throwable, dve);
+ return CommandProcessingResult.empty();
+ }
+ }
+
+ @Override
+ public CommandProcessingResult updateScoringFeature(Long featureId, JsonCommand command) {
+
+ try {
+ this.context.authenticatedUser();
+ this.fromApiJsonDeserializer.validateFeatureForUpdate(command.json());
+
+ final CreditScorecardFeature featureForUpdate = this.featureRepository.findById(featureId)
+ .orElseThrow(() -> new FeatureNotFoundException(featureId));
+
+ final Map<String, Object> changes = featureForUpdate.update(command);
+
+ if (!changes.isEmpty()) {
+ this.featureRepository.save(featureForUpdate);
+ }
+
+ return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(featureId).with(changes).build();
+ } catch (final JpaSystemException | DataIntegrityViolationException dve) {
+ handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve);
+ return CommandProcessingResult.empty();
+ } catch (final PersistenceException dve) {
+ Throwable throwable = ExceptionUtils.getRootCause(dve.getCause());
+ handleDataIntegrityIssues(command, throwable, dve);
+ return CommandProcessingResult.empty();
+ }
+ }
+
+ @Transactional
+ @Override
+ public CreditScorecard assessCreditRisk(final Loan loan) {
+ final CreditScorecard scorecard = loan.getScorecard();
+
+ if (scorecard != null) {
+ final String scoringMethod = scorecard.getScoringMethod();
+ final String scoringModel = scorecard.getScoringModel();
+
+ if (scoringMethod.equalsIgnoreCase("ruleBased")) {
+
+ final RuleBasedScorecard ruleBasedScorecard = scorecard.getRuleBasedScorecard();
+
+ final List<FeatureCriteriaScore> criteriaScores = ruleBasedScorecard.getCriteriaScores();
+
+ for (final FeatureCriteriaScore criteriaScore : criteriaScores) {
+
+ final LoanProductScorecardFeature lpFeature = criteriaScore.getFeature();
+
+ final FeatureConfiguration featureConfig = lpFeature.getFeatureConfiguration();
+
+ final EnumOptionData dataType = lpFeature.getScorecardFeature().getDataType();
+
+ final List<FeatureCriteria> featureCriteriaList = lpFeature.getFeatureCriteria();
+
+ for (final FeatureCriteria featureCriteria : featureCriteriaList) {
+
+ final String value = criteriaScore.getValue();
+
+ if (value != null) {
+
+ if (dataType.getValue().equalsIgnoreCase("string")) {
+
+ if (value.equalsIgnoreCase(featureCriteria.getCriteria())) {
+ final BigDecimal score = featureCriteria.getScore().multiply(featureConfig.getWeightage());
+ final String color = featureConfig.getColorFromScore(score);
+ criteriaScore.setScore(score, color);
+ break;
+
+ }
+
+ } else if (dataType.getValue().equalsIgnoreCase("numeric")) {
+
+ final String criteria = featureCriteria.getCriteria().strip();
+
+ final float min = Float.parseFloat(criteria.substring(0, criteria.indexOf("-")).strip());
+ final float max = Float.parseFloat(criteria.substring(criteria.indexOf("-") + 1).strip());
+
+ final float floatValue = Float.parseFloat(value);
+
+ if (floatValue >= min && floatValue <= max) {
+ final BigDecimal score = featureCriteria.getScore().multiply(featureConfig.getWeightage());
+ final String color = featureConfig.getColorFromScore(score);
+ criteriaScore.setScore(score, color);
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ BigDecimal scorecardScore = BigDecimal.ZERO;
+ int greenCount = 0;
+ int amberCount = 0;
+ int redCount = 0;
+ for (final FeatureCriteriaScore ctScore : criteriaScores) {
+ scorecardScore = scorecardScore.add(ctScore.getScore());
+
+ if (ctScore.getColor().equalsIgnoreCase("green")) {
+ greenCount += 1;
+
+ } else if (ctScore.getColor().equalsIgnoreCase("amber")) {
+ amberCount += 1;
+
+ } else if (ctScore.getColor().equalsIgnoreCase("red")) {
+ redCount += 1;
+
+ }
+
+ }
+
+ String scorecardColor = "amber";
+ if (greenCount > amberCount && greenCount > redCount) {
+ scorecardColor = "green";
+
+ } else if (redCount >= greenCount && redCount >= amberCount) {
+ scorecardColor = "red";
+
+ }
+
+ ruleBasedScorecard.setScore(scorecardScore, scorecardColor);
+
+ return scorecard;
+
+ } else {
+
+ this.initScorecardClient();
+
+ if (scoringMethod.equalsIgnoreCase("ml")) {
+
+ final MLScorecard mlScorecard = scorecard.getMlScorecard();
+
+ final MLScorecardFields loanScorecardFields = mlScorecard.getScorecardFields();
+
+ final PredictionResponse response = this.fetchScorecard(loanScorecardFields, scoringModel);
+
+ if (response != null) {
+ mlScorecard.setPredictionResponse(BigDecimal.valueOf(response.getProbability()),
+ response.getLabel(), response.getRequestId());
+ }
+
+ } else if (scoringMethod.equalsIgnoreCase("stat")) {
+
+ final StatScorecard statScorecard = scorecard.getStatScorecard();
+
+ final MLScorecardFields loanScorecardFields = statScorecard.getScorecardFields();
+
+ final PredictionResponse response = this.fetchScorecard(loanScorecardFields, scoringModel);
+
+ if (response != null) {
+ final String method = response.getMethod();
+ final String color = response.getColor();
+ final BigDecimal probability = BigDecimal.valueOf(response.getProbability());
+
+ BigDecimal wilikis = null;
+ BigDecimal pillaisTrace = null;
+ BigDecimal hotelling = null;
+ BigDecimal roys = null;
+
+ if (method.equalsIgnoreCase("manova")) {
+ wilikis = BigDecimal.valueOf(response.getWilkisLambda());
+ pillaisTrace = BigDecimal.valueOf(response.getPillaisTrace());
+ hotelling = BigDecimal.valueOf(response.getHotellingTawley());
+ roys = BigDecimal.valueOf(response.getRoysReatestRoots());
+ }
+ statScorecard.setPredictionResponse(method, color, probability, wilikis, pillaisTrace, hotelling, roys);
+ }
+
+ }
+ }
+
+ } else {
+ return null;
+
+ }
+
+ this.scorecardRepository.save(scorecard);
+
+ return scorecard;
+ }
+
+ private PredictionResponse fetchScorecard(final MLScorecardFields fields, final String scoringModel) {
+ try {
+
+ final Map<String, Object> predictionData = new HashMap<>();
+
+ predictionData.put("age", fields.getAge());
+ predictionData.put("sex", fields.getSex());
+ predictionData.put("job", fields.getJob());
+ predictionData.put("housing", fields.getHousing());
+ predictionData.put("credit_amount", fields.getCreditAmount());
+ predictionData.put("duration", fields.getDuration());
+ predictionData.put("purpose", fields.getPurpose());
+
+ return this.scorecardApiClient.algorithmsPredict(scoringModel, "0.0.1", null, null,
+ predictionData);
+
+ } catch (ApiException e) {
+ LOG.debug("An Error Occurred: {}", e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+ @Override
+ public CommandProcessingResult deleteScoringFeature(Long entityId) {
+
+ this.context.authenticatedUser();
+
+ final CreditScorecardFeature featureForDelete = this.featureRepository.findById(entityId)
+ .orElseThrow(() -> new FeatureNotFoundException(entityId));
+ if (featureForDelete.isDeleted()) {
+ throw new FeatureNotFoundException(entityId);
+ }
+
+ final Collection<LoanProduct> loanProducts = this.loanProductRepository.retrieveLoanProductsByScorecardFeatureId(entityId);
+
+ if (!loanProducts.isEmpty()) {
+ throw new FeatureCannotBeDeletedException("error.msg.scorecard.feature.cannot.be.deleted.it.is.already.used.in.loan",
+ "This Scoring Feature cannot be deleted, it is already used in loan");
+ }
+
+ featureForDelete.delete();
+
+ this.featureRepository.save(featureForDelete);
+
+ return new CommandProcessingResultBuilder().withEntityId(featureForDelete.getId()).build();
+ }
+
+ /*
+ * Guaranteed to throw an exception no matter what the data integrity issue is.
+ */
+ private void handleDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dve) {
+
+ if (realCause.getMessage().contains("name")) {
+ final String name = command.stringValueOfParameterNamed("name");
+ throw new PlatformDataIntegrityException("error.msg.scorecard.feature.duplicate.name",
+ "Scorecard Feature with name `" + name + "` already exists", "name", name);
+ }
+
+ LOG.error("Error occured.", dve);
+ throw new PlatformDataIntegrityException("error.msg.scorecard.feature.unknown.data.integrity.issue",
+ "Unknown data integrity issue with resource: " + realCause.getMessage());
+ }
+
+}
diff --git a/MySQL.cnf b/scorecard-plugin/src/main/resources/scorecard-client.properties
similarity index 85%
rename from MySQL.cnf
rename to scorecard-plugin/src/main/resources/scorecard-client.properties
index eba0a5f..55f3e96 100644
--- a/MySQL.cnf
+++ b/scorecard-plugin/src/main/resources/scorecard-client.properties
@@ -1,3 +1,4 @@
+#
# 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
@@ -14,10 +15,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+#
-# MySQL.cnf
-[client]
-database = fineract_credit_scorecard
-user = root
-password = mysql
-default-character-set = utf8
\ No newline at end of file
+fineract.credit.scorecard.uid=
+fineract.credit.scorecard.password=
+fineract.credit.scorecard.baseUrl=http://127.0.0.1:8000
diff --git a/server/settings.py b/server/settings.py
index 6f78666..b67a098 100644
--- a/server/settings.py
+++ b/server/settings.py
@@ -116,10 +116,7 @@
'USER': os.environ.get('DB_USER', 'root'),
'PASSWORD': os.environ.get('DB_PASSWORD', 'mysql'),
'HOST': os.environ.get('DB_HOST', '127.0.0.1'),
- 'PORT': os.environ.get('DB_PORT', '3306'),
- 'OPTIONS': {
- 'read_default_file': 'MySQL.cnf',
- },
+ 'PORT': os.environ.get('DB_PORT', '3306')
},
'sqlite3': {
'ENGINE': 'django.db.backends.sqlite3',
diff --git a/settings.gradle b/settings.gradle
index e278339..3f5001d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -18,3 +18,7 @@
*/
rootProject.name = 'fineract-credit-scorecard'
+include(
+ 'scorecard-plugin',
+ 'scorecard-client'
+)
diff --git a/statistical_scripts/statistical_scoring.py b/stats/statistical_scoring.py
similarity index 100%
rename from statistical_scripts/statistical_scoring.py
rename to stats/statistical_scoring.py