diff --git a/src/app/products/loan-products/loan-product.resolver.ts b/src/app/products/loan-products/loan-product.resolver.ts index 7c4a5746c..de963c772 100644 --- a/src/app/products/loan-products/loan-product.resolver.ts +++ b/src/app/products/loan-products/loan-product.resolver.ts @@ -17,7 +17,7 @@ export class LoanProductResolver implements Resolve { /** * @param {ProductsService} productsService Products service. */ - constructor(private productsService: ProductsService) {} + constructor(private productsService: ProductsService) { } /** * Returns the loan product data. diff --git a/src/app/products/products-routing.module.ts b/src/app/products/products-routing.module.ts index 7ae2b9ab7..2d9c78aab 100644 --- a/src/app/products/products-routing.module.ts +++ b/src/app/products/products-routing.module.ts @@ -24,6 +24,7 @@ import { ViewShareProductComponent } from './share-products/view-share-product/v import { EditShareProductComponent } from './share-products/edit-share-product/edit-share-product.component'; import { ManageTaxConfigurationsComponent } from './manage-tax-configurations/manage-tax-configurations.component'; import { RecurringDepositProductsComponent } from './recurring-deposit-products/recurring-deposit-products.component'; +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 { FixedDepositProductsComponent } from './fixed-deposit-products/fixed-deposit-products.component'; @@ -56,6 +57,7 @@ import { ShareProductsTemplateResolver } from './share-products/share-products-t import { ShareProductResolver } from './share-products/share-product-resolver'; import { ShareProductAndTemplateResolver } from './share-products/edit-share-product/share-product-and-template.resolver'; import { RecurringDepositProductsResolver } from './recurring-deposit-products/recurring-deposit-products.resolver'; +import { RecurringDepositProductResolver } from './recurring-deposit-products/recurring-deposit-product.resolver'; import { ChargesResolver } from './charges/charges.resolver'; import { ChargeResolver } from './charges/charge.resolver'; import { FixedDepositProductsResolver } from './fixed-deposit-products/fixed-deposit-products.resolver'; @@ -72,6 +74,7 @@ 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'; /** Products Routes */ const routes: Routes = [ @@ -298,11 +301,30 @@ const routes: Routes = [ }, { path: 'recurring-deposit-products', - component: RecurringDepositProductsComponent, - resolve: { + data: { title: extract('Recurring Deposit Products'), breadcrumb: 'Recurring Deposit Products' }, + children: [ + { + path: '', + component: RecurringDepositProductsComponent, + resolve: { recurringDepositProducts: RecurringDepositProductsResolver - }, - data: { title: extract('Recurring Deposit Products'), breadcrumb: 'Recurring Deposit Products' }, + } + }, + { + path: ':id', + data: { title: extract('View Recurring Deposit Product'), routeParamBreadcrumb: 'id' }, + children: [ + { + path: '', + component: ViewRecurringDepositProductComponent, + resolve: { + recurringDepositProduct: RecurringDepositProductResolver, + recurringDepositProductsTemplate: RecurringDepositProductsTemplateResolver + } + } + ] + }, + ] }, { path: 'fixed-deposit-products', @@ -448,6 +470,7 @@ const routes: Routes = [ ShareProductResolver, ShareProductAndTemplateResolver, RecurringDepositProductsResolver, + RecurringDepositProductResolver, ChargesResolver, ChargeResolver, ChargesTemplateResolver, @@ -463,7 +486,8 @@ const routes: Routes = [ TaxComponentTemplateResolver, EditTaxComponentComponent, TaxGroupResolver, - DividendsResolver + DividendsResolver, + RecurringDepositProductsTemplateResolver ] }) export class ProductsRoutingModule { } diff --git a/src/app/products/products.module.ts b/src/app/products/products.module.ts index 0ea17a150..f13f31715 100644 --- a/src/app/products/products.module.ts +++ b/src/app/products/products.module.ts @@ -75,6 +75,7 @@ import { MatFormFieldModule, MatSelectModule, MatOptionModule } from '@angular/m import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ViewTaxGroupComponent } from './manage-tax-groups/view-tax-group/view-tax-group.component'; import { ShareProductsDividendsComponent } from './share-products/dividends-share-product/dividends.components'; +import { ViewRecurringDepositProductComponent } from './recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component'; /** * Products Module @@ -153,7 +154,8 @@ import { ShareProductsDividendsComponent } from './share-products/dividends-shar EditChargeComponent, ViewTaxGroupComponent, ShareProductsDividendsComponent, - DepositProductIncentiveFormDialogComponent + DepositProductIncentiveFormDialogComponent, + ViewRecurringDepositProductComponent ], entryComponents: [ DepositProductIncentiveFormDialogComponent, diff --git a/src/app/products/products.service.ts b/src/app/products/products.service.ts index e483978df..102655c9a 100644 --- a/src/app/products/products.service.ts +++ b/src/app/products/products.service.ts @@ -101,6 +101,20 @@ export class ProductsService { return this.http.get('/recurringdepositproducts'); } + /** + * @param {string} recurringDepositProductId Product Id of recurring Deposit + * @param {boolean} template Template + * @return {Observable} Recurring Deposit Product Details + */ + getRecurringDepositProduct(recurringDepositProductId: string, template: boolean = false): Observable { + const httpParams = new HttpParams().set('template', template.toString()); + return this.http.get(`/recurringdepositproducts/${recurringDepositProductId}`, { params: httpParams }); + } + + getRecurringDepositProductsTemplate(): Observable { + return this.http.get('/recurringdepositproducts/template'); + } + /** * @returns {Observable} Charges data. */ @@ -253,4 +267,13 @@ export class ProductsService { getProductMix(productId: string): Observable { return this.http.get(`/loanproducts/${productId}/productmix`); } + + /* + * @param {string} productId Product ID + * @returns {Observable} + */ + getAllInterestRateCharts(productId: string): Observable { + const httpParams = new HttpParams().set('productId', productId); + return this.http.get(`/interestratecharts`, {params: httpParams}); + } } diff --git a/src/app/products/recurring-deposit-products/recurring-deposit-product.resolver.ts b/src/app/products/recurring-deposit-products/recurring-deposit-product.resolver.ts new file mode 100644 index 000000000..48d48806d --- /dev/null +++ b/src/app/products/recurring-deposit-products/recurring-deposit-product.resolver.ts @@ -0,0 +1,31 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { ProductsService } from '../products.service'; + +/** + * Recurring Deposit Product data resolver. + */ +@Injectable() +export class RecurringDepositProductResolver implements Resolve { + + /** + * @param {ProductsService} productsService Products service. + */ + constructor(private productsService: ProductsService) { } + + /** + * Returns the recurring deposit product data. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const id = route.paramMap.get('id'); + return this.productsService.getRecurringDepositProduct(id); + } + +} diff --git a/src/app/products/recurring-deposit-products/recurring-deposit-products-template.resolver.ts b/src/app/products/recurring-deposit-products/recurring-deposit-products-template.resolver.ts new file mode 100644 index 000000000..a0287db68 --- /dev/null +++ b/src/app/products/recurring-deposit-products/recurring-deposit-products-template.resolver.ts @@ -0,0 +1,24 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { ProductsService } from '../products.service'; + +@Injectable() +export class RecurringDepositProductsTemplateResolver implements Resolve { + + constructor(private productsService: ProductsService) {} + + /** + * Returns the recurring deposit products template data. + * @returns {Observable} + */ + resolve(): Observable { + return this.productsService.getRecurringDepositProductsTemplate(); + } + +} diff --git a/src/app/products/recurring-deposit-products/recurring-deposit-products.component.html b/src/app/products/recurring-deposit-products/recurring-deposit-products.component.html index 73ccea622..ae1207dad 100644 --- a/src/app/products/recurring-deposit-products/recurring-deposit-products.component.html +++ b/src/app/products/recurring-deposit-products/recurring-deposit-products.component.html @@ -29,7 +29,7 @@ - + diff --git a/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.html b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.html new file mode 100644 index 000000000..d68de02db --- /dev/null +++ b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.html @@ -0,0 +1,499 @@ +
+ +
+ +
+ + + + + +
+ +

{{ recurringDepositProduct.name }}

+ + + +

Details

+ + + +
+ Short Name: + {{ recurringDepositProduct.shortName }} +
+ +
+ Description: + {{ recurringDepositProduct.description }} +
+ +

Currency Details

+ + + +
+ Currency: + {{ recurringDepositProduct.currency.name }} +
+ +
+ Decimal Places: + {{ recurringDepositProduct.currency.decimalPlaces }} +
+ +
+ Currency in Multiples Of: + {{ recurringDepositProduct.currency.inMultiplesOf | number}} +
+ +

Terms

+ + + +
+ Deposit Amount: + {{ recurringDepositProduct.depositAmount + ' (Min: ' + (recurringDepositProduct.minDepositAmount ? recurringDepositProduct.minDepositAmount : recurringDepositProduct.depositAmount) + ', Max: ' + (recurringDepositProduct.maxDepositAmount ? recurringDepositProduct.maxDepositAmount : recurringDepositProduct.depositAmount) + ')' }} +
+ +
+ Interest Compounding Period: + {{ recurringDepositProduct.interestCompoundingPeriodType.value }} +
+ +
+ Interest Posting Period: + {{ recurringDepositProduct.interestPostingPeriodType.value }} +
+ +
+ Interested Calculated Using: + {{ recurringDepositProduct.interestCalculationType.value }} +
+ +
+ Days in Years: + {{ recurringDepositProduct.interestCalculationDaysInYearType.value }} +
+ +

Settings

+ + + +
+ Lock-in Period: + + {{ recurringDepositProduct.lockinPeriodFrequency }} + {{ recurringDepositProduct.lockinPeriodFrequencyType.value }} +
+ +
+ Minimum Deposit Term: + {{ recurringDepositProduct.minDepositTerm }} +   + {{ recurringDepositProduct.minDepositTermType.value }} +
+ +
+ Maximum Deposit Term: + {{ recurringDepositProduct.maxDepositTerm }} +   + {{ recurringDepositProduct.maxDepositTermType.value }} +
+ +
+ Deposit Term In multiple of: + {{ recurringDepositProduct.inMultipleOfDepositTerm }} + - + {{ recurringDepositProduct.inMultipleOfDepositTermType.value }} +
+ +
+ Recurring Deposit Type: + Mandatory + Voluntary +
+ +
+ Apply penal interest (less): + {{recurringDepositProduct.preClosurePenalInterest}}     %     On +    + {{recurringDepositProduct.preClosurePenalInterestOnType.value}} +
+ +
+ Is withhold tax Applicable: + {{ recurringDepositProduct.withHoldTax }} +
+ +
+ Withhold Tax group: + {{ recurringDepositProduct.taxGroup.name }} +
+ +
+ +

Interest Rate Charts

+ + + +
+ +
+ Name: + {{ recurringDepositProduct.activeChart.name }} +
+ +
+ Valid from Date: + {{ recurringDepositProduct.activeChart.fromDate | date }} +
+ +
+ End Date: + {{ recurringDepositProduct.activeChart.endDate | date }} +
+ +
+ Description: + {{ recurringDepositProduct.activeChart.description }} +
+ +
+ Primary Grouping by Amount: + {{ recurringDepositProduct.activeChart.isPrimaryGroupingByAmount ? 'Yes' : 'No' }} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Period +
+ {{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{ chartSlab.periodType.value }} +
+
+   +
+
Amount Range +
+ {{ chartSlab.amountRangeFrom }} - {{ chartSlab.amountRangeTo }} +
+ +
+   +
+
Interest + {{ chartSlab.annualInterestRate }} + Description + {{ chartSlab.description }} + Actions + + +
+ + +

+ Incentives +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Entity Type + {{ incentive.entityType | find:recurringDepositProductTemplate.chartTemplate.entityTypeOptions:'id':'value' }} + Attribute Name + {{ incentive.attributeName | find:recurringDepositProductTemplate.chartTemplate.attributeNameOptions:'id':'value' }} + Condition Type + {{ incentive.conditionType | find:recurringDepositProductTemplate.chartTemplate.conditionTypeOptions:'id':'value' }} + Attribute Value + {{ incentive.attributeValue | find:recurringDepositProductTemplate.chartTemplate.genderOptions:'id':'name' }} + {{ incentive.attributeValue }} + {{ incentive.attributeValue | find:recurringDepositProductTemplate.chartTemplate.clientTypeOptions:'id':'name' }} + {{ incentive.attributeValue | find:recurringDepositProductTemplate.chartTemplate.clientClassificationOptions:'id':'name' }} + Incentive Type + {{ incentive.incentiveType | find:recurringDepositProductTemplate.chartTemplate.incentiveTypeOptions:'id':'value'}} + Amount + {{ incentive.amount }} +
+ +
+
+
+ + + +
+ +
+ +
+ +

Charges

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name + {{ charge.name }} + Type + {{ charge.chargeCalculationType.value }} + Amount + {{ charge.amount | number }} + Collected On + {{ charge.chargeTimeType.value }} +
+ +
+ +

Accounting

+ + + +
+ Type: + {{ recurringDepositProduct.accountingRule.value }} +
+ +
+ +

Assets

+ +
+ Saving reference: + {{ recurringDepositProduct.accountingMappings.savingsReferenceAccount.name }} +
+ +

Liabilities

+ +
+ Saving control: + {{ recurringDepositProduct.accountingMappings.savingsControlAccount.name }} + Savings transfers in suspense: + {{ recurringDepositProduct.accountingMappings.transfersInSuspenseAccount.name }} +
+ +

Expenses

+ +
+ Interest on savings: + {{ recurringDepositProduct.accountingMappings.interestOnSavingsAccount.name }} + Write-off: + {{ recurringDepositProduct.accountingMappings.writeOffAccount.name }} +
+ +

Income

+ +
+ Income from fees: + {{ recurringDepositProduct.accountingMappings.incomeFromFeeAccount.name }} + Income from penalties: + {{ recurringDepositProduct.accountingMappings.incomeFromPenaltyAccount.name }} +
+ +
+ +

Advanced Accounting Rules

+ + + +
+

Configure Fund Sources for Payment Channels

+ + + + + + + + + + + + + + + + +
Payment Type + {{ paymentFundSource.paymentType.name }} + Fund Source + {{ paymentFundSource.fundSourceAccount.name }} +
+
+ + +
+ + +

Fees to Specific Income Accounts

+ + + + + + + + + + + + + + + + +
Fees + {{ feesIncome.charge.name }} + Income Account + {{ feesIncome.incomeAccount.name }} +
+ +
+ +
+ +

Penalties to Specific Income Accounts

+ + + + + + + + + + + + + + + + +
Penalty + {{ penaltyIncome.charge.name }} + Income Account + {{ penaltyIncome.incomeAccount.name }} +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
diff --git a/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.scss b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.scss new file mode 100644 index 000000000..edcf8f5c1 --- /dev/null +++ b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.scss @@ -0,0 +1,70 @@ +table { + width: 100%; +} + +.mat-elevation-z1 { + margin: 1em 0 1.5em 0; +} + +h2, h3, h4 { + margin: 0; + font-weight: 500; +} + +span { + margin: 0.5em 0; +} + +.margin-t { + margin-top: 1em; +} + +.interestCarts { + float:right; +} + +table { + width: 100%; + + tr.incentives-row { + height: 0; + + > td { + padding: 0; + } + + .incentives { + overflow: hidden; + } + + .mat-card { + border-radius: 0; + + > h4 { + font-weight: 500; + margin: 0.5em 0 0; + } + } + } + } + + .mat-elevation-z1 { + margin: 1em 0 1.5em 0; + } + + h2, h3, h4 { + margin: 0; + font-weight: 500; + } + + span { + margin: 0.5em 0; + } + + mat-divider { + margin: 0 0 0.5em 0; + } + + .margin-t { + margin-top: 1em; + } diff --git a/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.spec.ts b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.spec.ts new file mode 100644 index 000000000..48439e3ba --- /dev/null +++ b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewRecurringDepositProductComponent } from './view-recurring-deposit-product.component'; + +describe('ViewRecurringDepositProductComponent', () => { + let component: ViewRecurringDepositProductComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ViewRecurringDepositProductComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewRecurringDepositProductComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.ts b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.ts new file mode 100644 index 000000000..e8ff8a505 --- /dev/null +++ b/src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { trigger, state, transition, animate, style } from '@angular/animations'; + +@Component({ + selector: 'mifosx-view-recurring-deposit-product', + templateUrl: './view-recurring-deposit-product.component.html', + styleUrls: ['./view-recurring-deposit-product.component.scss'], + animations: [ + trigger('expandChartSlab', [ + state('collapsed', style({height: '0px', minHeight: '0'})), + state('expanded', style({height: '*'})), + transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')) + ]) + ] +}) +export class ViewRecurringDepositProductComponent implements OnInit { + + recurringDepositProduct: any; + recurringDepositProductTemplate: any; + + chartSlabsIncentivesDisplayedColumns: string[] = ['incentives']; + chartSlabsDisplayedColumns: string[] = ['period', 'amountRange', 'annualInterestRate', 'description', 'actions']; + incentivesDisplayedColumns: string[] = ['entityType', 'attributeName', 'conditionType', 'attributeValue', 'incentiveType', 'amount']; + chargesDisplayedColumns: string[] = ['name', 'type', 'amount', 'collectedon']; + paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId']; + feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId']; + + constructor(private route: ActivatedRoute) { + this.route.data.subscribe((data: { recurringDepositProduct: any, recurringDepositProductsTemplate: any}) => { + this.recurringDepositProduct = data.recurringDepositProduct; + this.recurringDepositProductTemplate = data.recurringDepositProductsTemplate; + }); + } + + ngOnInit() { + } + +}