Skip to content

Commit

Permalink
Merge pull request #1 from xurror/credit-scorecard
Browse files Browse the repository at this point in the history
Credit scorecard
  • Loading branch information
eshbeata authored Aug 11, 2022
2 parents f51d8e8 + af902f9 commit 6bd7d41
Show file tree
Hide file tree
Showing 52 changed files with 2,114 additions and 23 deletions.
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM node:12-alpine as builder

WORKDIR /usr/src/app

ENV PATH /usr/src/app/node_modules/.bin:$PATH

COPY package.json /usr/src/app/package.json

RUN npm install -g @angular/cli@9.1.12

RUN npm install

COPY . .

FROM nginx:1.19.3

COPY --from=builder /usr/src/app/dist/web-app /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Run `ng generate component component-name` to generate a new component. You can

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.

Run `npm run build:prod` to build a production artifacts Instead.

### Further help

To get more help on the Angular CLI use `ng help` or go check out the
Expand All @@ -78,6 +80,20 @@ For connecting to server running elsewhere update the base API URL and/or tenant

By default OAuth2 is disabled. To enable it, change the value of oauth.enabled property to true in the `environments/environment.ts` file and `environments/environment.prod.ts` file for development and production use respectively.

### Docker


To locally build this Docker image from source (after `git clone` this repo), run:
```
docker build -t openmf/web-app:latest .
```
You can then run a Docker Container from the image above like this:
```
docker run -d -p 4200:80 openmf/web-app:latest
```

Access the webapp on http://localhost:4200 in your browser.


## Want to help? [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/openMF/web-app/issues)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,26 @@

<ng-template matStepLabel>CHARGES</ng-template>

<mifosx-loans-account-charges-step [loansAccountProductTemplate]="loansAccountProductTemplate"
<mifosx-loans-account-charges-step
[loansAccountProductTemplate]="loansAccountProductTemplate"
[loansAccountTemplate]="loansAccountTemplate" [collateralOptions]="collateralOptions"
[loansAccountFormValid]="loansAccountFormValid">
</mifosx-loans-account-charges-step>

</mat-step>

<mat-step>

<ng-template matStepLabel>SCORECARD</ng-template>

<mifosx-loans-account-scorecard-step
[loansAccountProductTemplate]="loansAccountProductTemplate"
[loansAccountTemplate]="loansAccountTemplate"
[loansAccountFormValid]="loansAccountFormValid">
</mifosx-loans-account-scorecard-step>

</mat-step>

<mat-step state="preview" *ngIf="loansAccountFormValid" completed>

<ng-template matStepLabel>PREVIEW</ng-template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SettingsService } from 'app/settings/settings.service';
import { LoansAccountDetailsStepComponent } from '../loans-account-stepper/loans-account-details-step/loans-account-details-step.component';
import { LoansAccountTermsStepComponent } from '../loans-account-stepper/loans-account-terms-step/loans-account-terms-step.component';
import { LoansAccountChargesStepComponent } from '../loans-account-stepper/loans-account-charges-step/loans-account-charges-step.component';
import { LoansAccountScorecardStepComponent } from '../loans-account-stepper/loans-account-scorecard-step/loans-account-scorecard-step.component';

/**
* Create loans account
Expand All @@ -26,6 +27,7 @@ export class CreateLoansAccountComponent implements OnInit {
@ViewChild(LoansAccountDetailsStepComponent, { static: true }) loansAccountDetailsStep: LoansAccountDetailsStepComponent;
@ViewChild(LoansAccountTermsStepComponent, { static: true }) loansAccountTermsStep: LoansAccountTermsStepComponent;
@ViewChild(LoansAccountChargesStepComponent, { static: true }) loansAccountChargesStep: LoansAccountChargesStepComponent;
@ViewChild(LoansAccountScorecardStepComponent, { static: true }) loanAccountScorecardStep: LoansAccountScorecardStepComponent;

/** Loans Account Template */
loansAccountTemplate: any;
Expand Down Expand Up @@ -81,7 +83,8 @@ export class CreateLoansAccountComponent implements OnInit {
get loansAccountFormValid() {
return (
this.loansAccountDetailsForm.valid &&
this.loansAccountTermsForm.valid
this.loansAccountTermsForm.valid &&
this.loanAccountScorecardStep.formIsNotPristineAndValid()
);
}

Expand All @@ -91,6 +94,7 @@ export class CreateLoansAccountComponent implements OnInit {
...this.loansAccountDetailsStep.loansAccountDetails,
...this.loansAccountTermsStep.loansAccountTerms,
...this.loansAccountChargesStep.loansAccountCharges,
...this.loanAccountScorecardStep.loansAccountScorecard,
};
}

Expand Down
12 changes: 12 additions & 0 deletions src/app/loans/edit-loans-account/edit-loans-account.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@

</mat-step>

<mat-step>

<ng-template matStepLabel>SCORECARD</ng-template>

<mifosx-loans-account-scorecard-step
[loansAccountProductTemplate]="loansAccountProductTemplate"
[loansAccountTemplate]="loansAccountAndTemplate"
[loansAccountFormValid]="loansAccountFormValidAndNotPristine">
</mifosx-loans-account-scorecard-step>

</mat-step>

<mat-step state="preview" *ngIf="loansAccountFormValidAndNotPristine" completed>

<ng-template matStepLabel>PREVIEW</ng-template>
Expand Down
14 changes: 8 additions & 6 deletions src/app/loans/edit-loans-account/edit-loans-account.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { LoansAccountChargesStepComponent } from '../loans-account-stepper/loans

/** Custom Services */
import { SettingsService } from 'app/settings/settings.service';
import { LoansAccountScorecardStepComponent } from '../loans-account-stepper/loans-account-scorecard-step/loans-account-scorecard-step.component';

/**
* Edit Loans
Expand All @@ -22,7 +23,7 @@ export class EditLoansAccountComponent implements OnInit {
@ViewChild(LoansAccountDetailsStepComponent, { static: true }) loansAccountDetailsStep: LoansAccountDetailsStepComponent;
@ViewChild(LoansAccountTermsStepComponent, { static: true }) loansAccountTermsStep: LoansAccountTermsStepComponent;
@ViewChild(LoansAccountChargesStepComponent, { static: true }) loansAccountChargesStep: LoansAccountChargesStepComponent;

@ViewChild(LoansAccountScorecardStepComponent, { static: true }) loansAccountScorecardStep: LoansAccountScorecardStepComponent;
loansAccountAndTemplate: any;
/** Loans Account Product Template */
loansAccountProductTemplate: any;
Expand Down Expand Up @@ -80,11 +81,8 @@ export class EditLoansAccountComponent implements OnInit {
return (
this.loansAccountDetailsForm.valid &&
this.loansAccountTermsForm.valid &&
(
!this.loansAccountDetailsForm.pristine ||
!this.loansAccountTermsForm.pristine ||
!this.loansAccountChargesStep.pristine
)
this.loansAccountScorecardStep.formIsNotPristineAndValid() &&
(!this.loansAccountDetailsForm.pristine || !this.loansAccountTermsForm.pristine)
);
}

Expand All @@ -94,6 +92,7 @@ export class EditLoansAccountComponent implements OnInit {
...this.loansAccountDetailsStep.loansAccountDetails,
...this.loansAccountTermsStep.loansAccountTerms,
...this.loansAccountChargesStep.loansAccountCharges,
...this.loansAccountScorecardStep.loansAccountScorecard
};
}

Expand Down Expand Up @@ -137,6 +136,9 @@ export class EditLoansAccountComponent implements OnInit {

if (loansAccountData.recalculationCompoundingFrequencyDate) {
loansAccountData.recalculationCompoundingFrequencyDate = this.datePipe.transform(this.loansAccount.recalculationCompoundingFrequencyDate, dateFormat);
if (loansAccountData.recalculationCompoundingFrequencyDate === null) {
delete loansAccountData.recalculationCompoundingFrequencyDate;
}
}

if (loansAccountData.interestCalculationPeriodType === 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
<form [formGroup]="loanAccountScorecardForm">
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">

<label id="scoring-method">Scoring Method:</label>
<mat-radio-group aria-labelledby="scoring-method" formControlName="scoringMethod">
<mat-radio-button *ngFor="let method of scoringMethods" [value]="method.code">
{{ method.value }}
</mat-radio-button>
</mat-radio-group>

</div>


<mat-divider></mat-divider>

<div *ngIf="scoringMethod === 'ruleBased'" fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<label id="scoring-model">Rule Based Model : </label>
<mat-radio-group aria-labelledby="scoring-model" formControlName="scoringModel">
<mat-radio-button *ngFor="let model of ruleBasedScoringModels" [value]="model.code">
{{ model.value }}
</mat-radio-button><br>
</mat-radio-group>
</div>

<div *ngIf="scoringMethod === 'ruleBased'" formGroupName="ruleBasedScorecard">

<div *ngIf="featureOptions" formArrayName="criteriaScores" fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">

<div *ngFor="let ft of criteriaScores().controls; let i = index;" [formGroupName]="i" fxFlex="48%" fxLayout.lt-md="column">

<!-- {{ printJSON(ft.value) }} -->

<input type="hidden" formControlName="featureId" [value]="ft.value.featureId">

<mat-form-field fxFlex="98%">

<mat-label>{{ featureFromId(ft.value.featureId).name }}</mat-label>

<input *ngIf="featureFromId(ft.value.featureId).dataType.value.toLowerCase() === 'date'" matInput
[matDatepicker]="submitPicker" formControlName="value" required>


<input *ngIf="featureFromId(ft.value.featureId).dataType.value.toLowerCase() === 'numeric'" matInput
formControlName="value" required>

<mat-select *ngIf="featureFromId(ft.value.featureId).dataType.value.toLowerCase() === 'string'"
formControlName="value" required>
<mat-option *ngFor="let option of featureFromId(ft.value.featureId)?.criteria" [value]="option.criteria">
{{ option.criteria }}
</mat-option>
</mat-select>

</mat-form-field>

</div>

</div>

</div>



<div *ngIf="scoringMethod === 'stat'" fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<label id="scoring-model">Statistical Model : </label>
<mat-radio-group aria-labelledby="scoring-model" formControlName="scoringModel">
<mat-radio-button *ngFor="let model of statScoringModels" [value]="model.code">
{{ model.value }}
</mat-radio-button><br>
</mat-radio-group>
</div>

<div *ngIf="scoringMethod === 'stat'" formGroupName="statScorecard">

<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Age</mat-label>
<input required matInput type="number" formControlName="age">
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Gender</mat-label>
<mat-select required formControlName="sex">
<mat-option *ngFor="let gender of scorecard?.mlScorecard?.genderOptions" [value]="gender?.code">
{{ gender?.value }}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Job</mat-label>
<mat-select required formControlName="job">
<mat-option *ngFor="let job of scorecard?.mlScorecard?.jobOptions" [value]="job?.code">
{{ job?.value }}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Housing</mat-label>
<mat-select required formControlName="housing">
<mat-option *ngFor="let housing of scorecard?.mlScorecard?.housingOptions" [value]="housing?.code">
{{ housing?.value }}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Credit Amount</mat-label>
<input required matInput type="number" formControlName="creditAmount">
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Duration</mat-label>
<input required matInput type="number" formControlName="duration">
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Purpose</mat-label>
<mat-select required formControlName="purpose">
<mat-option *ngFor="let purpose of scorecard?.mlScorecard?.purposeOptions" [value]="purpose?.code">
{{ purpose?.value }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>

<div *ngIf="scoringMethod === 'ml'" fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<label id="scoring-model">Machine Learning Model : </label>
<mat-radio-group aria-labelledby="scoring-model" formControlName="scoringModel">
<mat-radio-button *ngFor="let model of mlScoringModels" [value]="model.code">
{{ model.value }}
</mat-radio-button><br>
</mat-radio-group>
</div>

<div *ngIf="scoringMethod === 'ml'" formGroupName="mlScorecard">

<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Age</mat-label>
<input required matInput type="number" formControlName="age">
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Gender</mat-label>
<mat-select required formControlName="sex">
<mat-option *ngFor="let gender of scorecard?.mlScorecard?.genderOptions" [value]="gender?.code">
{{ gender?.value }}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Job</mat-label>
<mat-select required formControlName="job">
<mat-option *ngFor="let job of scorecard?.mlScorecard?.jobOptions" [value]="job?.code">
{{ job?.value }}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Housing</mat-label>
<mat-select required formControlName="housing">
<mat-option *ngFor="let housing of scorecard?.mlScorecard?.housingOptions" [value]="housing?.code">
{{ housing?.value }}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Credit Amount</mat-label>
<input required matInput type="number" formControlName="creditAmount">
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Duration</mat-label>
<input required matInput type="number" formControlName="duration">
</mat-form-field>

<mat-form-field fxFlex="48%">
<mat-label>Purpose</mat-label>
<mat-select required formControlName="purpose">
<mat-option *ngFor="let purpose of scorecard?.mlScorecard?.purposeOptions" [value]="purpose?.code">
{{ purpose?.value }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</form>


<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
<button mat-raised-button matStepperPrevious>
<fa-icon icon="arrow-left"></fa-icon>&nbsp;&nbsp;
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!loansAccountFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
</button>
</div>
Loading

0 comments on commit 6bd7d41

Please sign in to comment.