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