From 42342085392e50cc96d5b5aceb30ef8da9d1b4c4 Mon Sep 17 00:00:00 2001 From: "Oussema.exe" Date: Mon, 30 Dec 2019 19:32:55 +0100 Subject: [PATCH] feat: add working days component (#530) Fixes: #162 --- .../organization-routing.module.ts | 13 +- .../organization/organization.component.html | 2 +- src/app/organization/organization.module.ts | 4 +- src/app/organization/organization.service.ts | 15 +++ .../working-days/working-days.component.html | 48 +++++++ .../working-days/working-days.component.scss | 3 + .../working-days.component.spec.ts | 25 ++++ .../working-days/working-days.component.ts | 119 ++++++++++++++++++ .../working-days/working-days.resolver.ts | 30 +++++ 9 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 src/app/organization/working-days/working-days.component.html create mode 100644 src/app/organization/working-days/working-days.component.scss create mode 100644 src/app/organization/working-days/working-days.component.spec.ts create mode 100644 src/app/organization/working-days/working-days.component.ts create mode 100644 src/app/organization/working-days/working-days.resolver.ts diff --git a/src/app/organization/organization-routing.module.ts b/src/app/organization/organization-routing.module.ts index cb03e5e53..68c38eba1 100644 --- a/src/app/organization/organization-routing.module.ts +++ b/src/app/organization/organization-routing.module.ts @@ -20,6 +20,7 @@ import { TellersComponent } from './tellers/tellers.component'; import { PaymentTypesComponent } from './payment-types/payment-types.component'; import { PasswordPreferencesComponent } from './password-preferences/password-preferences.component'; import { EntityDataTableChecksComponent } from './entity-data-table-checks/entity-data-table-checks.component'; +import { WorkingDaysComponent } from './working-days/working-days.component'; /** Custom Resolvers */ import { LoanProvisioningCriteriaResolver } from './loan-provisioning-criteria/loan-provisioning-criteria.resolver'; @@ -32,6 +33,7 @@ import { TellersResolver } from './tellers/tellers.resolver'; import { PaymentTypesResolver } from './payment-types/payment-types.resolver'; import { PasswordPreferencesTemplateResolver } from './password-preferences/password-preferences-template.resolver'; import { EntityDataTableChecksResolver } from './entity-data-table-checks/entity-data-table-checks.resolver'; +import { WorkingDaysResolver } from './working-days/working-days.resolver'; /** Organization Routes */ const routes: Routes = [ @@ -128,6 +130,14 @@ const routes: Routes = [ resolve: { entityDataTableChecks: EntityDataTableChecksResolver } + }, + { + path: 'working-days', + component: WorkingDaysComponent, + data: { title: extract('Working Days'), breadcrumb: 'Working Days' }, + resolve: { + workingDays: WorkingDaysResolver + } } ] } @@ -152,7 +162,8 @@ const routes: Routes = [ TellersResolver, PaymentTypesResolver, PasswordPreferencesTemplateResolver, - EntityDataTableChecksResolver + EntityDataTableChecksResolver, + WorkingDaysResolver ] }) export class OrganizationRoutingModule { } diff --git a/src/app/organization/organization.component.html b/src/app/organization/organization.component.html index 135b8f0af..095eea70c 100644 --- a/src/app/organization/organization.component.html +++ b/src/app/organization/organization.component.html @@ -113,7 +113,7 @@

Manage Tellers / Cashiers and Cash Allocation and Settlement

- + diff --git a/src/app/organization/organization.module.ts b/src/app/organization/organization.module.ts index 6dc901b52..d7f0006a8 100644 --- a/src/app/organization/organization.module.ts +++ b/src/app/organization/organization.module.ts @@ -18,6 +18,7 @@ import { TellersComponent } from './tellers/tellers.component'; import { PaymentTypesComponent } from './payment-types/payment-types.component'; import { PasswordPreferencesComponent } from './password-preferences/password-preferences.component'; import { EntityDataTableChecksComponent } from './entity-data-table-checks/entity-data-table-checks.component'; +import { WorkingDaysComponent } from './working-days/working-days.component'; /** * Organization Module @@ -41,7 +42,8 @@ import { EntityDataTableChecksComponent } from './entity-data-table-checks/entit TellersComponent, PaymentTypesComponent, PasswordPreferencesComponent, - EntityDataTableChecksComponent + EntityDataTableChecksComponent, + WorkingDaysComponent ] }) export class OrganizationModule { } diff --git a/src/app/organization/organization.service.ts b/src/app/organization/organization.service.ts index 9f3cfa3e7..f1d74acbf 100644 --- a/src/app/organization/organization.service.ts +++ b/src/app/organization/organization.service.ts @@ -117,4 +117,19 @@ export class OrganizationService { return this.http.delete(`/entityDatatableChecks/${entityDataTableCheckId}`); } + /** + * @returns {Observable} Working days data. + */ + getWorkingDays(): Observable { + return this.http.get('/workingdays'); + } + + /** + * @param {any} workingDays Working days data. + * @returns {Observable} + */ + updateWorkingDays(workingDays: any): Observable { + return this.http.put('/workingdays', workingDays); + } + } diff --git a/src/app/organization/working-days/working-days.component.html b/src/app/organization/working-days/working-days.component.html new file mode 100644 index 000000000..89f48d6db --- /dev/null +++ b/src/app/organization/working-days/working-days.component.html @@ -0,0 +1,48 @@ +
+ + + +
+ + + +
+ +
+ Working Days +
+
+ + {{ weekDays[i].name }} + +
+
+
+ + + Payments due on non working days + + + {{ repaymentRescheduleType.value }} + + + + + + Extend the term for loans following a daily repayment schedule + + +
+ +
+ + + + + + +
+ +
+ +
diff --git a/src/app/organization/working-days/working-days.component.scss b/src/app/organization/working-days/working-days.component.scss new file mode 100644 index 000000000..d774f68da --- /dev/null +++ b/src/app/organization/working-days/working-days.component.scss @@ -0,0 +1,3 @@ +.container { + max-width: 37rem; +} diff --git a/src/app/organization/working-days/working-days.component.spec.ts b/src/app/organization/working-days/working-days.component.spec.ts new file mode 100644 index 000000000..e256e38ba --- /dev/null +++ b/src/app/organization/working-days/working-days.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { WorkingDaysComponent } from './working-days.component'; + +describe('WorkingDaysComponent', () => { + let component: WorkingDaysComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ WorkingDaysComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(WorkingDaysComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/working-days/working-days.component.ts b/src/app/organization/working-days/working-days.component.ts new file mode 100644 index 000000000..5488e63de --- /dev/null +++ b/src/app/organization/working-days/working-days.component.ts @@ -0,0 +1,119 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, FormArray, FormControl } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; + +/** Custom Services */ +import { OrganizationService } from '../organization.service'; + +/** Recurrence default value. */ +const recurrenceDefaultValue = 'FREQ=WEEKLY;INTERVAL=1;BYDAY='; + +/** + * Working days component. + */ +@Component({ + selector: 'mifosx-working-days', + templateUrl: './working-days.component.html', + styleUrls: ['./working-days.component.scss'] +}) +export class WorkingDaysComponent implements OnInit { + + /** Working days form. */ + workingDaysForm: FormGroup; + /** Working days data. */ + workingDaysData: any; + /** Week days */ + weekDays = [ + { name: 'Monday', value: 'MO', checked: false }, + { name: 'Tuesday', value: 'TU', checked: false }, + { name: 'Wednesday', value: 'WE', checked: false }, + { name: 'Thursday', value: 'TH', checked: false }, + { name: 'Friday', value: 'FR', checked: false }, + { name: 'Saturday', value: 'SA', checked: false }, + { name: 'Sunday', value: 'SU', checked: false } + ]; + /** Repayment schedule type data. */ + repaymentRescheduleTypeData: any; + + /** + * Retrieves the working days data from `resolve`. + * @param {FormBuilder} formBuilder Form Builder. + * @param {ActivatedRoute} route Activated Route. + * @param {OrganizationService} organizationService Organization Service. + * @param {Router} router Router for navigation. + */ + constructor(private formBuilder: FormBuilder, + private route: ActivatedRoute, + private organizationService: OrganizationService, + private router: Router) { + this.route.data.subscribe((data: { workingDays: any }) => { + this.workingDaysData = data.workingDays; + }); + } + + /** + * Creates the working days form. + */ + ngOnInit() { + this.createWorkingDaysForm(); + } + + /** + * Creates the working days form. + */ + createWorkingDaysForm() { + this.setWeeklyWorkingDays(); + this.repaymentRescheduleTypeData = this.workingDaysData.repaymentRescheduleOptions; + this.workingDaysForm = this.formBuilder.group({ + 'recurrence': this.formBuilder.array(this.createRecurrenceFormArray()), + 'repaymentRescheduleType': [this.workingDaysData.repaymentRescheduleType.id], + 'extendTermForDailyRepayments': [this.workingDaysData.extendTermForDailyRepayments] + }); + } + + /** + * @returns {FormArray} recurrence form array. + */ + get recurrence(): FormArray { + return this.workingDaysForm.get('recurrence') as FormArray; + } + + /** + * Sets weekly working days. + */ + setWeeklyWorkingDays() { + const days = this.workingDaysData.recurrence.replace(recurrenceDefaultValue, ''); + for (let i = 0; i < this.weekDays.length; i++) { + this.weekDays[i].checked = days.includes(this.weekDays[i].value); + } + } + + /** + * Creates the recurrence form array. + */ + createRecurrenceFormArray() { + return this.weekDays.map(weekDay => new FormControl(weekDay.checked)); + } + + /** + * Submits the working days form and updates working days configuration, + * if successful redirects to organization view. + */ + submit() { + const workingDays = this.workingDaysForm.value; + // TODO: Update once language and date settings are setup + workingDays.locale = 'en'; + let recurrence = recurrenceDefaultValue; + for (let i = 0; i < this.weekDays.length; i++) { + if (workingDays.recurrence[i]) { + recurrence = recurrence + this.weekDays[i].value + ','; + } + } + workingDays.recurrence = recurrence; + this.organizationService.updateWorkingDays(workingDays).subscribe(response => { + this.router.navigate(['../'], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/organization/working-days/working-days.resolver.ts b/src/app/organization/working-days/working-days.resolver.ts new file mode 100644 index 000000000..ff516222e --- /dev/null +++ b/src/app/organization/working-days/working-days.resolver.ts @@ -0,0 +1,30 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { OrganizationService } from '../organization.service'; + +/** + * Working Days data resolver. + */ +@Injectable() +export class WorkingDaysResolver implements Resolve { + + /** + * @param {OrganizationService} organizationService Organization service. + */ + constructor(private organizationService: OrganizationService) {} + + /** + * Returns the working days data. + * @returns {Observable} + */ + resolve(): Observable { + return this.organizationService.getWorkingDays(); + } + +}