feat: add create charge component (#1175)
Fixes: #191 Refer: #187 Co-authored-by: punwai <punwaiw@gmail.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/** Angular Imports */
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve, ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
|
||||
|
||||
/** rxjs Imports */
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/** Custom Services */
|
||||
import { ProductsService } from '../products.service';
|
||||
|
||||
@Injectable()
|
||||
export class ChargesTemplateAndResolver implements Resolve<Object> {
|
||||
|
||||
constructor(private productsService: ProductsService) { }
|
||||
|
||||
/**
|
||||
* Returns the changes template and data.
|
||||
* @returns {Observable<any>}
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<any> {
|
||||
const savingProductId = route.paramMap.get('id');
|
||||
return this.productsService.getCharge(savingProductId, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/** Angular Imports */
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve, ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { Resolve } from '@angular/router';
|
||||
|
||||
/** rxjs Imports */
|
||||
import { Observable } from 'rxjs';
|
||||
@@ -8,18 +8,23 @@ import { Observable } from 'rxjs';
|
||||
/** Custom Services */
|
||||
import { ProductsService } from '../products.service';
|
||||
|
||||
/**
|
||||
* Charges template data resolver.
|
||||
*/
|
||||
@Injectable()
|
||||
export class ChargesTemplateResolver implements Resolve<Object> {
|
||||
|
||||
/**
|
||||
* @param {ProductsService} productsService Products service.
|
||||
*/
|
||||
constructor(private productsService: ProductsService) {}
|
||||
|
||||
/**
|
||||
* Returns the share products template data.
|
||||
* Returns the charges template data.
|
||||
* @returns {Observable<any>}
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<any> {
|
||||
const savingProductId = route.paramMap.get('id');
|
||||
return this.productsService.getCharge(savingProductId, true);
|
||||
resolve(): Observable<any> {
|
||||
return this.productsService.getChargesTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="container m-b-20" fxLayout="row" fxLayoutAlign="end" fxLayoutGap="20px">
|
||||
<button mat-raised-button color="primary">
|
||||
<button mat-raised-button color="primary" [routerLink]="['create']" *mifosxHasPermission="'CREATE_CHARGE'">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
Create Charge
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
<div class="container">
|
||||
|
||||
<mat-card>
|
||||
|
||||
<form [formGroup]="chargeForm" (ngSubmit)="submit()">
|
||||
|
||||
<mat-card-content>
|
||||
|
||||
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Charge Applies To</mat-label>
|
||||
<mat-select required formControlName="chargeAppliesTo">
|
||||
<mat-option *ngFor="let chargeAppliesTo of chargesTemplateData.chargeAppliesToOptions" [value]="chargeAppliesTo.id">
|
||||
{{ chargeAppliesTo.value }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="chargeForm.controls.chargeAppliesTo.hasError('required')">
|
||||
Charge Applies To is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
|
||||
<div *ngIf="chargeForm.controls.chargeAppliesTo.value" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Charge Name</mat-label>
|
||||
<input matInput required formControlName="name">
|
||||
<mat-error *ngIf="chargeForm.controls.name.hasError('required')">
|
||||
Charge Name is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Currency</mat-label>
|
||||
<mat-select required formControlName="currencyCode">
|
||||
<mat-option *ngFor="let currency of chargesTemplateData.currencyOptions" [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="chargeForm.controls.currencyCode.hasError('required')">
|
||||
Currency is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Charge Time Type</mat-label>
|
||||
<mat-select required formControlName="chargeTimeType">
|
||||
<mat-option *ngFor="let chargeTimeType of chargeTimeTypeData" [value]="chargeTimeType.id">
|
||||
{{ chargeTimeType.value }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="chargeForm.controls.chargeTimeType.hasError('required')">
|
||||
Charge Time Type is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Charge Calculation Type</mat-label>
|
||||
<mat-select required formControlName="chargeCalculationType">
|
||||
<mat-option *ngFor="let chargeCalculationType of filteredChargeCalculationType()" [value]="chargeCalculationType.id">
|
||||
{{ chargeCalculationType.value }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="chargeForm.controls.chargeCalculationType.hasError('required')">
|
||||
Charge Calculation Type is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field *ngIf="chargeForm.controls.chargeAppliesTo.value === 1" fxFlex="48%">
|
||||
<mat-label>Charge Payment Mode</mat-label>
|
||||
<mat-select required formControlName="chargePaymentMode">
|
||||
<mat-option *ngFor="let chargePaymentMode of chargesTemplateData.chargePaymetModeOptions" [value]="chargePaymentMode.id">
|
||||
{{ chargePaymentMode.value }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="chargeForm.controls.chargePaymentMode.hasError('required')">
|
||||
Charge Payment Mode is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<div fxFlex="48%" *ngIf="chargeForm.controls.chargeTimeType.value === 9" class="add-fee-frequency-wrapper">
|
||||
<mat-checkbox labelPosition="before" formControlName="addFeeFrequency">
|
||||
Add Fee Frequency
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<mat-form-field *ngIf="chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value" fxFlex="48%">
|
||||
<mat-label>Charge Frequency</mat-label>
|
||||
<mat-select required formControlName="feeFrequency">
|
||||
<mat-option *ngFor="let feeFrequency of chargesTemplateData.feeFrequencyOptions" [value]="feeFrequency.id">
|
||||
{{ feeFrequency.value }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="chargeForm.controls.feeFrequency.hasError('required')">
|
||||
Charge Frequency is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field *ngIf="chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value" fxFlex="48%">
|
||||
<mat-label>Frequency Interval</mat-label>
|
||||
<input matInput required formControlName="feeInterval">
|
||||
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('required')">
|
||||
Frequency Interval is <strong>required</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('pattern')">
|
||||
Frequency Interval <strong>must be a positive integer</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field *ngIf="chargeForm.controls.chargeTimeType.value === 6 || chargeForm.controls.chargeTimeType.value === 7" fxFlex="48%">
|
||||
<mat-label>Due Date</mat-label>
|
||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="dueDatePicker" required formControlName="feeOnMonthDay">
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
<mat-error *ngIf="chargeForm.controls.feeOnMonthDay.hasError('required')">
|
||||
Due Date is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%" *ngIf="chargeForm.controls.chargeTimeType.value === 7 || chargeForm.controls.chargeTimeType.value === 11">
|
||||
<mat-label>Repeat Every ({{ repeatEveryLabel }})</mat-label>
|
||||
<input matInput required formControlName="feeInterval">
|
||||
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('required')">
|
||||
Repeat Every ({{ repeatEveryLabel }}) is <strong>required</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="(chargeForm.controls.feeInterval.hasError('min') || chargeForm.controls.feeInterval.hasError('max')) && !chargeForm.controls.feeInterval.hasError('pattern')">
|
||||
Repeat Every ({{ repeatEveryLabel }}) <strong>must be between 1 and 12</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('pattern')">
|
||||
Repeat Every ({{ repeatEveryLabel }}) <strong>must be a positive integer</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Amount</mat-label>
|
||||
<input matInput required formControlName="amount">
|
||||
<mat-error *ngIf="chargeForm.controls.amount.hasError('required')">
|
||||
Amount is <strong>required</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="chargeForm.controls.amount.hasError('pattern') && currencyDecimalPlaces !== undefined">
|
||||
Amount must be <strong>a positive number with {{ currencyDecimalPlaces ? 'up to ' + currencyDecimalPlaces : 'no' }} decimal places</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="chargeForm.controls.amount.hasError('pattern') && currencyDecimalPlaces === undefined">
|
||||
Amount must be <strong>a positive number</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<div fxFlex="48%" fxLayout="row" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
<div fxFlex="50%" class="active-wrapper">
|
||||
<mat-checkbox labelPosition="before" formControlName="active">
|
||||
Active
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div fxFlex="50%" class="penalty-wrapper">
|
||||
<mat-checkbox labelPosition="before" formControlName="penalty">
|
||||
Is Penalty
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-form-field *ngIf="chargeForm.controls.chargeAppliesTo.value === 3" fxFlex="48%">
|
||||
<mat-label>Income from Charge </mat-label>
|
||||
<mat-select formControlName="incomeAccountId">
|
||||
<mat-option *ngFor="let incomeOrLiabilityAccount of incomeAndLiabilityAccountData" [value]="incomeOrLiabilityAccount.id">
|
||||
{{ incomeOrLiabilityAccount.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Tax Group</mat-label>
|
||||
<mat-select formControlName="taxGroupId">
|
||||
<mat-option *ngFor="let taxGroup of chargesTemplateData.taxGroupOptions" [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!chargeForm.valid" *mifosxHasPermission="'CREATE_CHARGE'">Submit</button>
|
||||
</mat-card-actions>
|
||||
|
||||
</form>
|
||||
|
||||
</mat-card>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,11 @@
|
||||
.penalty-wrapper {
|
||||
padding: 17.5px 0 17.5px 0;
|
||||
}
|
||||
|
||||
.active-wrapper {
|
||||
padding: 17.5px 0 17.5px 0;
|
||||
}
|
||||
|
||||
.add-fee-frequency-wrapper {
|
||||
padding: 17.5px 0 17.5px 0;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CreateChargeComponent } from './create-charge.component';
|
||||
|
||||
describe('CreateChargeComponent', () => {
|
||||
let component: CreateChargeComponent;
|
||||
let fixture: ComponentFixture<CreateChargeComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CreateChargeComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CreateChargeComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,230 @@
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { DatePipe } from '@angular/common';
|
||||
|
||||
/** Custom Services */
|
||||
import { ProductsService } from '../../products.service';
|
||||
|
||||
/**
|
||||
* Create charge component.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-create-charge',
|
||||
templateUrl: './create-charge.component.html',
|
||||
styleUrls: ['./create-charge.component.scss']
|
||||
})
|
||||
export class CreateChargeComponent implements OnInit {
|
||||
|
||||
/** Charge form. */
|
||||
chargeForm: FormGroup;
|
||||
/** Charges template data. */
|
||||
chargesTemplateData: any;
|
||||
/** Charge time type data. */
|
||||
chargeTimeTypeData: any;
|
||||
/** Charge calculation type data. */
|
||||
chargeCalculationTypeData: any = '';
|
||||
/** Income and liability account data */
|
||||
incomeAndLiabilityAccountData: any;
|
||||
/** Minimum due date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum due date allowed. */
|
||||
maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 1));
|
||||
/** Repeat every label */
|
||||
repeatEveryLabel: string;
|
||||
/** Currency decimal places */
|
||||
currencyDecimalPlaces: number;
|
||||
|
||||
/**
|
||||
* Retrieves the charges template data and income and liability account data from `resolve`.
|
||||
* @param {FormBuilder} formBuilder Form Builder.
|
||||
* @param {ProductsService} productsService Products Service.
|
||||
* @param {ActivatedRoute} route Activated Route.
|
||||
* @param {Router} router Router for navigation.
|
||||
* @param {DatePipe} datePipe Date Pipe to format date.
|
||||
*/
|
||||
constructor(private formBuilder: FormBuilder,
|
||||
private productsService: ProductsService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private datePipe: DatePipe) {
|
||||
this.route.data.subscribe((data: { chargesTemplate: any }) => {
|
||||
this.chargesTemplateData = data.chargesTemplate;
|
||||
this.incomeAndLiabilityAccountData = data.chargesTemplate.incomeOrLiabilityAccountOptions.incomeAccountOptions
|
||||
.concat(data.chargesTemplate.incomeOrLiabilityAccountOptions.liabilityAccountOptions);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and sets the charge form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.createChargeForm();
|
||||
this.setChargeForm();
|
||||
this.setConditionalControls();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the charge form.
|
||||
*/
|
||||
createChargeForm() {
|
||||
this.chargeForm = this.formBuilder.group({
|
||||
'chargeAppliesTo': ['', Validators.required],
|
||||
'name': ['', Validators.required],
|
||||
'currencyCode': ['', Validators.required],
|
||||
'chargeTimeType': ['', Validators.required],
|
||||
'chargeCalculationType': ['', Validators.required],
|
||||
'amount': ['', [Validators.required, Validators.pattern('^\\s*(?=.*[1-9])\\d*(?:\\.\\d+)?\\s*$')]],
|
||||
'active': [false],
|
||||
'penalty': [false],
|
||||
'taxGroupId': ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the charge calculation type and charge time type data
|
||||
*/
|
||||
setChargeForm() {
|
||||
this.chargeForm.get('chargeAppliesTo').valueChanges.subscribe((chargeAppliesTo) => {
|
||||
switch (chargeAppliesTo) {
|
||||
case 1:
|
||||
this.chargeCalculationTypeData = this.chargesTemplateData.loanChargeCalculationTypeOptions;
|
||||
this.chargeTimeTypeData = this.chargesTemplateData.loanChargeTimeTypeOptions;
|
||||
break;
|
||||
case 2:
|
||||
this.chargeCalculationTypeData = this.chargesTemplateData.savingsChargeCalculationTypeOptions;
|
||||
this.chargeTimeTypeData = this.chargesTemplateData.savingsChargeTimeTypeOptions;
|
||||
break;
|
||||
case 3:
|
||||
this.chargeCalculationTypeData = this.chargesTemplateData.clientChargeCalculationTypeOptions;
|
||||
this.chargeTimeTypeData = this.chargesTemplateData.clientChargeTimeTypeOptions;
|
||||
break;
|
||||
case 4:
|
||||
this.chargeCalculationTypeData = this.chargesTemplateData.shareChargeCalculationTypeOptions;
|
||||
this.chargeTimeTypeData = this.chargesTemplateData.shareChargeTimeTypeOptions;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {any} Filtered charge calculation type data.
|
||||
*/
|
||||
filteredChargeCalculationType(): any {
|
||||
return this.chargeCalculationTypeData.filter((chargeCalculationType: any) => {
|
||||
if (this.chargeForm.get('chargeTimeType').value === 12 && (chargeCalculationType.id === 3 || chargeCalculationType.id === 4)) {
|
||||
return false;
|
||||
}
|
||||
if (this.chargeForm.get('chargeTimeType').value !== 12 && chargeCalculationType.id === 5) {
|
||||
return false;
|
||||
}
|
||||
if (this.chargeForm.get('chargeAppliesTo').value === 2) {
|
||||
if (!(this.chargeForm.get('chargeTimeType').value === 5 || this.chargeForm.get('chargeTimeType').value === 16) && chargeCalculationType.id === 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the conditional controls of the user form
|
||||
*/
|
||||
setConditionalControls() {
|
||||
this.chargeForm.get('chargeAppliesTo').valueChanges.subscribe((chargeAppliesTo) => {
|
||||
this.chargeForm.get('penalty').enable();
|
||||
switch (chargeAppliesTo) {
|
||||
case 1: // Loan
|
||||
this.chargeForm.addControl('chargePaymentMode', new FormControl('', Validators.required));
|
||||
this.chargeForm.removeControl('incomeAccountId');
|
||||
break;
|
||||
case 2: // Savings
|
||||
this.chargeForm.removeControl('chargePaymentMode');
|
||||
this.chargeForm.removeControl('incomeAccountId');
|
||||
break;
|
||||
case 3: // Client
|
||||
this.chargeForm.removeControl('chargePaymentMode');
|
||||
this.chargeForm.addControl('incomeAccountId', new FormControl(''));
|
||||
break;
|
||||
case 4: // Shares
|
||||
this.chargeForm.removeControl('chargePaymentMode');
|
||||
this.chargeForm.removeControl('incomeAccountId');
|
||||
this.chargeForm.get('penalty').setValue(false);
|
||||
this.chargeForm.get('penalty').disable();
|
||||
break;
|
||||
}
|
||||
this.chargeForm.get('chargeCalculationType').reset();
|
||||
this.chargeForm.get('chargeTimeType').reset();
|
||||
});
|
||||
this.chargeForm.get('chargeTimeType').valueChanges.subscribe((chargeTimeType) => {
|
||||
this.chargeForm.removeControl('feeFrequency');
|
||||
this.chargeForm.removeControl('feeInterval');
|
||||
this.chargeForm.removeControl('feeOnMonthDay');
|
||||
this.chargeForm.removeControl('addFeeFrequency');
|
||||
if (this.chargeForm.get('chargeAppliesTo').value !== 4) {
|
||||
this.chargeForm.get('penalty').enable();
|
||||
}
|
||||
switch (chargeTimeType) {
|
||||
case 6: // Annual Fee
|
||||
this.chargeForm.addControl('feeOnMonthDay', new FormControl('', Validators.required));
|
||||
break;
|
||||
case 7: // Monthly Fee
|
||||
this.chargeForm.addControl('feeOnMonthDay', new FormControl(''));
|
||||
this.chargeForm.addControl('feeInterval', new FormControl('', [Validators.required, Validators.min(1), Validators.max(12), Validators.pattern('^[1-9]\\d*$')]));
|
||||
this.repeatEveryLabel = 'Months';
|
||||
break;
|
||||
case 9: // Overdue Fee
|
||||
this.chargeForm.get('penalty').setValue(true);
|
||||
this.chargeForm.get('penalty').disable();
|
||||
this.chargeForm.addControl('addFeeFrequency', new FormControl(false));
|
||||
this.chargeForm.get('addFeeFrequency').valueChanges.subscribe((addFeeFrequency) => {
|
||||
if (addFeeFrequency) {
|
||||
this.chargeForm.addControl('feeFrequency', new FormControl('', Validators.required));
|
||||
this.chargeForm.addControl('feeInterval', new FormControl('', [Validators.required, Validators.pattern('^[1-9]\\d*$')]));
|
||||
} else {
|
||||
this.chargeForm.removeControl('feeFrequency');
|
||||
this.chargeForm.removeControl('feeInterval');
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 11: // Weekly Fee
|
||||
this.chargeForm.addControl('feeInterval', new FormControl('', [Validators.required, Validators.pattern('^[1-9]\\d*$')]));
|
||||
this.repeatEveryLabel = 'Weeks';
|
||||
break;
|
||||
}
|
||||
});
|
||||
this.chargeForm.get('currencyCode').valueChanges.subscribe((currencyCode) => {
|
||||
this.currencyDecimalPlaces = this.chargesTemplateData.currencyOptions.find((currency: any) => currency.code === currencyCode).decimalPlaces;
|
||||
if (this.currencyDecimalPlaces === 0) {
|
||||
this.chargeForm.get('amount').setValidators([Validators.required, Validators.pattern('^[1-9]\\d*$')]);
|
||||
} else {
|
||||
this.chargeForm.get('amount').setValidators([Validators.required, Validators.pattern(`^\\s*(?=.*[1-9])\\d*(\\.\\d{1,${this.currencyDecimalPlaces}})?\\s*$`)]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the charge form and creates charge,
|
||||
* if successful redirects to charges.
|
||||
*/
|
||||
submit() {
|
||||
const prevFeeOnMonthDay: Date = this.chargeForm.value.feeOnMonthDay;
|
||||
const monthDayFormat = 'dd MMM';
|
||||
this.chargeForm.patchValue({
|
||||
feeOnMonthDay: this.datePipe.transform(prevFeeOnMonthDay, monthDayFormat)
|
||||
});
|
||||
const charge = this.chargeForm.getRawValue();
|
||||
// TODO: Update once language and date settings are setup
|
||||
charge.locale = 'en';
|
||||
charge.monthDayFormat = monthDayFormat;
|
||||
delete charge.addFeeFrequency;
|
||||
if (!charge.taxGroupId) {
|
||||
delete charge.taxGroupId;
|
||||
}
|
||||
this.productsService.createCharge(charge).subscribe((response: any) => {
|
||||
this.router.navigate(['../'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -162,7 +162,7 @@
|
||||
|
||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!chargeForm.valid">Submit</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!chargeForm.valid" *mifosxHasPermission="'UPDATE_CHARGE'">Submit</button>
|
||||
</mat-card-actions>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_CHARGE'">
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
Edit
|
||||
</button>
|
||||
<button mat-raised-button color="warn" (click)="deleteCharge()">
|
||||
<button mat-raised-button color="warn" (click)="deleteCharge()" *mifosxHasPermission="'DELETE_CHARGE'">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
Delete
|
||||
</button>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!productMixForm.valid">Submit</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!productMixForm.valid" *mifosxHasPermission="'CREATE_PRODUCTMIX'">Submit</button>
|
||||
</mat-card-actions>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!productMixForm.valid">Submit</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!productMixForm.valid" *mifosxHasPermission="'UPDATE_PRODUCTMIX'">Submit</button>
|
||||
</mat-card-actions>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div fxLayout="row" fxLayoutAlign="end" class="container m-b-20">
|
||||
<button mat-raised-button color="primary" [routerLink]="['create']">
|
||||
<button mat-raised-button color="primary" [routerLink]="['create']" *mifosxHasPermission="'CREATE_PRODUCTMIX'">
|
||||
<fa-icon icon="plus"></fa-icon> Add
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<div class="container m-b-20" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="end" fxLayoutGap="20px">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_PRODUCTMIX'">
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
Edit
|
||||
</button>
|
||||
<button mat-raised-button color="warn" (click)="delete()">
|
||||
<button mat-raised-button color="warn" (click)="delete()" *mifosxHasPermission="'DELETE_PRODUCTMIX'">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
Delete
|
||||
</button>
|
||||
|
||||
@@ -27,6 +27,7 @@ import { RecurringDepositProductsComponent } from './recurring-deposit-products/
|
||||
import { ViewRecurringDepositProductComponent } from './recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component';
|
||||
import { ChargesComponent } from './charges/charges.component';
|
||||
import { ViewChargeComponent } from './charges/view-charge/view-charge.component';
|
||||
import { CreateChargeComponent } from './charges/create-charge/create-charge.component';
|
||||
import { FixedDepositProductsComponent } from './fixed-deposit-products/fixed-deposit-products.component';
|
||||
import { CreateFixedDepositProductComponent } from './fixed-deposit-products/create-fixed-deposit-product/create-fixed-deposit-product.component';
|
||||
import { ProductsMixComponent } from './products-mix/products-mix.component';
|
||||
@@ -67,6 +68,7 @@ import { RecurringDepositProductsResolver } from './recurring-deposit-products/r
|
||||
import { RecurringDepositProductResolver } from './recurring-deposit-products/recurring-deposit-product.resolver';
|
||||
import { ChargesResolver } from './charges/charges.resolver';
|
||||
import { ChargeResolver } from './charges/charge.resolver';
|
||||
import { ChargesTemplateResolver } from './charges/charges-template.resolver';
|
||||
import { FixedDepositProductsResolver } from './fixed-deposit-products/fixed-deposit-products.resolver';
|
||||
import { FixedDepositProductsTemplateResolver } from './fixed-deposit-products/fixed-deposit-products-template.resolver';
|
||||
import { ProductsMixResolver } from './products-mix/products-mix.resolver';
|
||||
@@ -78,7 +80,6 @@ import { ManageTaxGroupsResolver } from './manage-tax-groups/manage-tax-groups.r
|
||||
import { TaxComponentResolver } from './manage-tax-components/tax-component.resolver';
|
||||
import { TaxComponentTemplateResolver } from './manage-tax-components/tax-component-template.resolver';
|
||||
import { EditChargeComponent } from './charges/edit-charge/edit-charge.component';
|
||||
import { ChargesTemplateResolver } from './charges/charges-template.resolver';
|
||||
import { TaxGroupResolver } from './manage-tax-groups/tax-group.resolver';
|
||||
import { DividendsResolver } from './share-products/dividends-share-product/dividends.resolver';
|
||||
import { RecurringDepositProductsTemplateResolver } from './recurring-deposit-products/recurring-deposit-products-template.resolver';
|
||||
@@ -90,6 +91,7 @@ import { ManageTaxGroupTemplateResolver } from './manage-tax-groups/create-tax-g
|
||||
import { EditTaxGroupResolver } from './manage-tax-groups/edit-tax-group/edit-tax-group.resolver';
|
||||
import { ProductsMixTemplateResolver } from './products-mix/products-mix-template.resolver';
|
||||
import { EditProductMixComponent } from './products-mix/edit-product-mix/edit-product-mix.component';
|
||||
import { ChargesTemplateAndResolver } from './charges/charges-template-and-resolver';
|
||||
|
||||
/** Products Routes */
|
||||
const routes: Routes = [
|
||||
@@ -514,6 +516,14 @@ const routes: Routes = [
|
||||
path: 'charges',
|
||||
data: { title: extract('Charges'), breadcrumb: 'Charges' },
|
||||
children: [
|
||||
{
|
||||
path: 'create',
|
||||
component: CreateChargeComponent,
|
||||
data: { title: extract('Create Charge'), breadcrumb: 'Create Charge' },
|
||||
resolve: {
|
||||
chargesTemplate: ChargesTemplateResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: ChargesComponent,
|
||||
@@ -537,7 +547,7 @@ const routes: Routes = [
|
||||
component: EditChargeComponent,
|
||||
data: { title: extract('Edit Charge'), breadcrumb: 'Edit', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
chargesTemplate: ChargesTemplateResolver
|
||||
chargesTemplate: ChargesTemplateAndResolver
|
||||
}
|
||||
},
|
||||
]
|
||||
@@ -574,6 +584,7 @@ const routes: Routes = [
|
||||
RecurringDepositProductResolver,
|
||||
ChargesResolver,
|
||||
ChargeResolver,
|
||||
ChargesTemplateAndResolver,
|
||||
ChargesTemplateResolver,
|
||||
FixedDepositProductsResolver,
|
||||
FixedDepositProductsTemplateResolver,
|
||||
|
||||
@@ -94,6 +94,7 @@ import { CreateTaxGroupComponent } from './manage-tax-groups/create-tax-group/cr
|
||||
import { EditTaxGroupComponent } from './manage-tax-groups/edit-tax-group/edit-tax-group.component';
|
||||
import { CreateProductMixComponent } from './products-mix/create-product-mix/create-product-mix.component';
|
||||
import { EditProductMixComponent } from './products-mix/edit-product-mix/edit-product-mix.component';
|
||||
import { CreateChargeComponent } from './charges/create-charge/create-charge.component';
|
||||
|
||||
/**
|
||||
* Products Module
|
||||
@@ -191,7 +192,9 @@ import { EditProductMixComponent } from './products-mix/edit-product-mix/edit-pr
|
||||
CreateTaxGroupComponent,
|
||||
EditTaxGroupComponent,
|
||||
CreateProductMixComponent,
|
||||
EditProductMixComponent
|
||||
EditProductMixComponent,
|
||||
ManageTaxGroupsComponent,
|
||||
CreateChargeComponent
|
||||
],
|
||||
entryComponents: [
|
||||
DepositProductIncentiveFormDialogComponent,
|
||||
|
||||
@@ -175,6 +175,14 @@ export class ProductsService {
|
||||
return this.http.delete(`/charges/${chargeId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} charge Charge to be created.
|
||||
* @returns {Observable<any>}
|
||||
*/
|
||||
createCharge(charge: any): Observable<any> {
|
||||
return this.http.post('/charges', charge);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<any>} Fixed deposit products data
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user