From 59620b18468c7904ebe48223ccc8aa738f331bd9 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Thu, 27 Jul 2023 20:10:33 +0530 Subject: [PATCH 01/47] Employee Mapping and Import settings reimbursable --- src/app/app.module.ts | 4 +- src/app/auth/auth.module.ts | 8 +- .../configuration/clone-setting.model.ts | 44 +++++ .../configuration/export-setting.model.ts | 20 +- src/app/core/models/enum/enum.model.ts | 7 +- .../models/misc/confirmation-dialog.model.ts | 3 +- .../clone-setting.service.spec.ts | 0 .../configuration/clone-setting.service.ts | 31 +++ .../configuration/export-setting.service.ts | 140 ++++++++++++- src/app/core/services/core/helper.service.ts | 23 ++- .../services/integration/tracking.service.ts | 4 + .../clone-settings.component.html | 187 ++++++++++++++++++ .../clone-settings.component.scss | 180 +++++++++++++++++ .../clone-settings.component.spec.ts | 23 +++ .../clone-settings.component.ts | 121 ++++++++++++ .../onboarding/onboarding-routing.module.ts | 6 + .../onboarding/onboarding.module.ts | 14 +- .../clone-advanced-settings.component.html | 1 + .../clone-advanced-settings.component.scss | 0 .../clone-advanced-settings.component.spec.ts | 23 +++ .../clone-advanced-settings.component.ts | 10 + .../clone-export-settings.component.html | 1 + .../clone-export-settings.component.scss | 0 .../clone-export-settings.component.spec.ts | 23 +++ .../clone-export-settings.component.ts | 10 + .../clone-import-settings.component.html | 1 + .../clone-import-settings.component.scss | 0 .../clone-import-settings.component.spec.ts | 23 +++ .../clone-import-settings.component.ts | 10 + .../qbo-connector/qbo-connector.component.ts | 40 +++- .../confirmation-dialog.component.html | 6 +- .../confirmation-dialog.component.ts | 4 +- .../core/select/select.component.html | 56 ++++++ .../core/select/select.component.scss | 21 ++ .../core/select/select.component.spec.ts | 23 +++ .../core/select/select.component.ts | 69 +++++++ .../core/toggle/toggle.component.html | 3 + .../core/toggle/toggle.component.scss | 24 +++ .../core/toggle/toggle.component.spec.ts | 23 +++ .../core/toggle/toggle.component.ts | 22 +++ .../onboarding-stepper.component.html | 8 +- .../onboarding-stepper.component.scss | 4 + .../onboarding-stepper.component.ts | 55 ++++-- src/app/shared/shared.module.ts | 16 +- .../svgs/actions/arrow-mark-down-pink.svg | 3 + .../images/svgs/general/calendar-disabled.svg | 12 ++ .../images/svgs/general/connect-arrow.svg | 3 + .../images/svgs/general/document-disabled.svg | 6 + .../images/svgs/general/employee-disabled.svg | 6 + .../images/svgs/general/info-disabled.svg | 3 + .../images/svgs/general/question-disabled.svg | 5 + src/assets/images/svgs/general/setting.svg | 14 ++ .../images/svgs/general/sync-disabled.svg | 4 + .../images/svgs/general/tabs-disabled.svg | 4 + src/assets/images/svgs/general/tick-green.svg | 4 + src/styles.scss | 6 + 56 files changed, 1313 insertions(+), 48 deletions(-) create mode 100644 src/app/core/models/configuration/clone-setting.model.ts create mode 100644 src/app/core/services/configuration/clone-setting.service.spec.ts create mode 100644 src/app/core/services/configuration/clone-setting.service.ts create mode 100644 src/app/integration/onboarding/clone-settings/clone-settings.component.html create mode 100644 src/app/integration/onboarding/clone-settings/clone-settings.component.scss create mode 100644 src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts create mode 100644 src/app/integration/onboarding/clone-settings/clone-settings.component.ts create mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html create mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss create mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts create mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts create mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html create mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss create mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts create mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts create mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html create mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss create mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts create mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts create mode 100644 src/app/shared/components/core/select/select.component.html create mode 100644 src/app/shared/components/core/select/select.component.scss create mode 100644 src/app/shared/components/core/select/select.component.spec.ts create mode 100644 src/app/shared/components/core/select/select.component.ts create mode 100644 src/app/shared/components/core/toggle/toggle.component.html create mode 100644 src/app/shared/components/core/toggle/toggle.component.scss create mode 100644 src/app/shared/components/core/toggle/toggle.component.spec.ts create mode 100644 src/app/shared/components/core/toggle/toggle.component.ts create mode 100644 src/assets/images/svgs/actions/arrow-mark-down-pink.svg create mode 100644 src/assets/images/svgs/general/calendar-disabled.svg create mode 100644 src/assets/images/svgs/general/connect-arrow.svg create mode 100644 src/assets/images/svgs/general/document-disabled.svg create mode 100644 src/assets/images/svgs/general/employee-disabled.svg create mode 100644 src/assets/images/svgs/general/info-disabled.svg create mode 100644 src/assets/images/svgs/general/question-disabled.svg create mode 100644 src/assets/images/svgs/general/setting.svg create mode 100644 src/assets/images/svgs/general/sync-disabled.svg create mode 100644 src/assets/images/svgs/general/tabs-disabled.svg create mode 100644 src/assets/images/svgs/general/tick-green.svg diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 607694fc..a9d28a6f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,6 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt'; import { MatLegacySnackBarModule as MatSnackBarModule, MAT_LEGACY_SNACK_BAR_DEFAULT_OPTIONS as MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/legacy-snack-bar'; +import { MatDialogModule } from '@angular/material/dialog'; import * as Sentry from '@sentry/angular'; @@ -24,7 +25,8 @@ import { GlobalErrorHandler } from './app.errorhandling'; HttpClientModule, FormsModule, ReactiveFormsModule, - MatSnackBarModule + MatSnackBarModule, + MatDialogModule ], providers: [ { diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts index debe9dbb..e9a7b3a4 100644 --- a/src/app/auth/auth.module.ts +++ b/src/app/auth/auth.module.ts @@ -1,15 +1,14 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FlexLayoutModule } from '@angular/flex-layout'; -import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; - +import { MatButtonModule } from '@angular/material/button'; import { LoginComponent } from './login/login.component'; import { LogoutComponent } from './logout/logout.component'; import { FyleCallbackComponent } from './fyle-callback/fyle-callback.component'; import { AuthComponent } from './auth.component'; import { AuthRoutingModule } from './auth-routing.module'; -import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; import { SharedLoginComponent } from './shared-login/shared-login.component'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; @NgModule({ @@ -25,7 +24,8 @@ import { SharedLoginComponent } from './shared-login/shared-login.component'; AuthRoutingModule, FlexLayoutModule, MatButtonModule, - MatProgressSpinnerModule + MatProgressSpinnerModule, + MatButtonModule, ] }) export class AuthModule { } diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts new file mode 100644 index 00000000..ab56a028 --- /dev/null +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -0,0 +1,44 @@ +import { FormGroup } from "@angular/forms"; +import { AdvancedSettingGet, AdvancedSettingModel, AdvancedSettingPost } from "./advanced-setting.model"; +import { ExportSettingGet, ExportSettingModel, ExportSettingPost } from "./export-setting.model"; +import { ImportSettingGet, ImportSettingModel, ImportSettingPost } from "./import-setting.model"; +import { MappingSetting } from "../db/mapping-setting.model"; +import { EmployeeSettingGet, EmployeeSettingModel, EmployeeSettingPost } from "./employee-setting.model"; + +export type CloneSetting = { + workspace_id: number, + export_settings: ExportSettingGet, + import_settings: ImportSettingGet, + advanced_settings: AdvancedSettingGet, + employee_mappings: EmployeeSettingGet +} + +export type CloneSettingPost = { + export_settings: ExportSettingPost, + import_settings: ImportSettingPost, + advanced_settings: AdvancedSettingPost, + employee_mappings: EmployeeSettingPost +} + +export type CloneSettingExist = { + is_available: boolean, + workspace_name: string +} + +export class CloneSettingModel { + static constructPayload(cloneSettingsForm: FormGroup, customMappingSettings: MappingSetting[]): CloneSettingPost { + const exportSettingPayload = ExportSettingModel.constructPayload(cloneSettingsForm); + const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); + const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); + const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm) + + const cloneSettingPayload: CloneSettingPost = { + export_settings: exportSettingPayload, + import_settings: importSettingPayload, + advanced_settings: advancedSettingPayload, + employee_mappings: employeeMappingPayload + }; + + return cloneSettingPayload; + } +} diff --git a/src/app/core/models/configuration/export-setting.model.ts b/src/app/core/models/configuration/export-setting.model.ts index 66fc0acc..90f5f01c 100644 --- a/src/app/core/models/configuration/export-setting.model.ts +++ b/src/app/core/models/configuration/export-setting.model.ts @@ -1,12 +1,18 @@ import { UntypedFormGroup } from "@angular/forms"; -import { CorporateCreditCardExpensesObject, ExpenseGroupingFieldOption, ExpenseState, CCCExpenseState, ExportDateType, ReimbursableExpensesObject } from "../enum/enum.model"; +import { CorporateCreditCardExpensesObject, ExpenseGroupingFieldOption, ExpenseState, CCCExpenseState, ExportDateType, ReimbursableExpensesObject, AutoMapEmployee, EmployeeFieldMapping } from "../enum/enum.model"; import { ExpenseGroupSettingGet, ExpenseGroupSettingPost } from "../db/expense-group-setting.model"; import { DefaultDestinationAttribute, GeneralMapping } from "../db/general-mapping.model"; import { SelectFormOption } from "../misc/select-form-option.model"; -export type ExportSettingWorkspaceGeneralSetting = { +export type ExportSettingWorkspaceGeneralSettingPost = { reimbursable_expenses_object: ReimbursableExpensesObject | null, - corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject | null + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject | null, + employee_field_mapping: EmployeeFieldMapping | null, + auto_map_employees: AutoMapEmployee | null, +} + +export interface ExportSettingWorkspaceGeneralSetting extends ExportSettingWorkspaceGeneralSettingPost { + is_simplify_report_closure_enabled: boolean } export type ExportSettingGeneralMapping = { @@ -20,7 +26,7 @@ export type ExportSettingGeneralMapping = { export type ExportSettingPost = { expense_group_settings: ExpenseGroupSettingPost, - workspace_general_settings: ExportSettingWorkspaceGeneralSetting, + workspace_general_settings: ExportSettingWorkspaceGeneralSettingPost, general_mappings: ExportSettingGeneralMapping } @@ -32,7 +38,7 @@ export type ExportSettingGet = { } export interface ExportSettingFormOption extends SelectFormOption { - value: ExpenseState | CCCExpenseState | ReimbursableExpensesObject | CorporateCreditCardExpensesObject | ExpenseGroupingFieldOption | ExportDateType; + value: ExpenseState | CCCExpenseState | ReimbursableExpensesObject | CorporateCreditCardExpensesObject | ExpenseGroupingFieldOption | ExportDateType | AutoMapEmployee | EmployeeFieldMapping | null; } export class ExportSettingModel { @@ -49,7 +55,9 @@ export class ExportSettingModel { }, workspace_general_settings: { reimbursable_expenses_object: exportSettingsForm.get('reimbursableExportType')?.value, - corporate_credit_card_expenses_object: exportSettingsForm.get('creditCardExportType')?.value + corporate_credit_card_expenses_object: exportSettingsForm.get('creditCardExportType')?.value, + auto_map_employees: exportSettingsForm.get('autoMapEmployees')?.value, + employee_field_mapping: exportSettingsForm.get('employee_field_mapping')?.value }, general_mappings: { bank_account: exportSettingsForm.get('bankAccount')?.value ? exportSettingsForm.get('bankAccount')?.value : emptyDestinationAttribute, diff --git a/src/app/core/models/enum/enum.model.ts b/src/app/core/models/enum/enum.model.ts index 44eaecc0..78c36326 100644 --- a/src/app/core/models/enum/enum.model.ts +++ b/src/app/core/models/enum/enum.model.ts @@ -182,7 +182,9 @@ export enum ClickEvent { UNMAPPED_MAPPINGS_FILTER = 'Unmapped Mappings Filter', MAPPED_MAPPINGS_FILTER = 'Mapped Mappings Filter', DISCONNECT_QBO = 'Disconnect QBO', - SYNC_DIMENSION = 'Sync Dimension' + SYNC_DIMENSION = 'Sync Dimension', + CLONE_SETTINGS_BACK = 'Clone Settings Back', + CLONE_SETTINGS_RESET = 'Clone Settings Reset' } export enum ProgressPhase { @@ -197,7 +199,8 @@ export enum OnboardingStep { EXPORT_SETTINGS = 'Export Settings', IMPORT_SETTINGS = 'Import Settings', ADVANCED_SETTINGS = 'Advanced Settings', - ONBOARDING_DONE = 'Onboarding Done' + ONBOARDING_DONE = 'Onboarding Done', + CLONE_SETTINGS = 'Clone Settings' } export enum UpdateEvent { diff --git a/src/app/core/models/misc/confirmation-dialog.model.ts b/src/app/core/models/misc/confirmation-dialog.model.ts index e8911337..7b0f0ebb 100644 --- a/src/app/core/models/misc/confirmation-dialog.model.ts +++ b/src/app/core/models/misc/confirmation-dialog.model.ts @@ -2,5 +2,6 @@ export type ConfirmationDialog = { title: string, primaryCtaText: string, contents: string, - hideSecondaryCTA?: boolean + hideSecondaryCTA?: boolean, + hideWarningIcon?: boolean }; diff --git a/src/app/core/services/configuration/clone-setting.service.spec.ts b/src/app/core/services/configuration/clone-setting.service.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/core/services/configuration/clone-setting.service.ts b/src/app/core/services/configuration/clone-setting.service.ts new file mode 100644 index 00000000..6804b2d5 --- /dev/null +++ b/src/app/core/services/configuration/clone-setting.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { CloneSetting, CloneSettingExist, CloneSettingPost } from '../../models/configuration/clone-setting.model'; +import { ApiService } from '../core/api.service'; +import { WorkspaceService } from '../workspace/workspace.service'; + +@Injectable({ + providedIn: 'root' +}) + +export class CloneSettingService { + + workspaceId = this.workspaceService.getWorkspaceId(); + + constructor( + private apiService: ApiService, + private workspaceService: WorkspaceService + ) { } + + checkCloneSettingsExists(): Observable { + return this.apiService.get(`/user/clone_settings/exists/`, {}); + } + + getCloneSettings(): Observable { + return this.apiService.get(`/v2/workspaces/${this.workspaceId}/clone_settings/`, {}); + } + + saveCloneSettings(cloneSettingsPayload: CloneSettingPost): Observable { + return this.apiService.put(`/v2/workspaces/${this.workspaceId}/clone_settings/`, cloneSettingsPayload); + } +} diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 4508aed8..16b09194 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -1,9 +1,12 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { ExportSettingGet, ExportSettingPost } from '../../models/configuration/export-setting.model'; +import { ExportSettingGet, ExportSettingPost, ExportSettingFormOption } from '../../models/configuration/export-setting.model'; import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; +import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, ReimbursableExpensesObject } from '../../models/enum/enum.model'; + + @Injectable({ providedIn: 'root' }) @@ -21,4 +24,139 @@ export class ExportSettingService { postExportSettings(exportSettingsPayload: ExportSettingPost): Observable { return this.apiService.put(`/v2/workspaces/${this.workspaceService.getWorkspaceId()}/export_settings/`, exportSettingsPayload); } + + getReimbursableExportTypeOptions(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { + return { + EMPLOYEE: [ + { + label: 'Check', + value: ReimbursableExpensesObject.CHECK + }, + { + label: 'Expense', + value: ReimbursableExpensesObject.EXPENSE + }, + { + label: 'Journal Entry', + value: ReimbursableExpensesObject.JOURNAL_ENTRY + } + ], + VENDOR: [ + { + label: 'Bill', + value: ReimbursableExpensesObject.BILL + }, + { + label: 'Expense', + value: ReimbursableExpensesObject.EXPENSE + }, + { + label: 'Journal Entry', + value: ReimbursableExpensesObject.JOURNAL_ENTRY + } + ] + }[employeeFieldMapping]; + } + + getcreditCardExportTypes(): ExportSettingFormOption[] { + return [ + { + label: 'Bill', + value: CorporateCreditCardExpensesObject.BILL + }, + { + label: 'Credit Card Purchase', + value: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE + }, + { + label: 'Journal Entry', + value: CorporateCreditCardExpensesObject.JOURNAL_ENTRY + }, + { + label: 'Debit Card Expense', + value: CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE + } + ] + } + + getEmployeeFieldMappingOptions(): ExportSettingFormOption[] { + return [ + { + label: 'Employees', + value: EmployeeFieldMapping.EMPLOYEE + }, + { + label: 'Vendor', + value: EmployeeFieldMapping.VENDOR + } + ]; + } + + getAutoMapEmployeeOptions(): ExportSettingFormOption[] { + return [ + { + label: 'None', + value: null + }, + { + label: 'Employee name on Fyle to contact name on Quickbooks', + value: AutoMapEmployee.NAME + }, + { + label: 'Employee email on Fyle to contact email on Quickbooks', + value: AutoMapEmployee.EMAIL + } + ]; + } + + getReimbursableExpenseGroupingDateOptions(): ExportSettingFormOption[] { + return [ + { + label: 'Current Date', + value: ExportDateType.CURRENT_DATE + }, + { + label: 'Verification Date', + value: ExportDateType.VERIFIED_AT + }, + { + label: 'Spend Date', + value: ExportDateType.SPENT_AT + }, + { + label: 'Approval Date', + value: ExportDateType.APPROVED_AT + }, + { + label: 'Last Spend Date', + value: ExportDateType.LAST_SPENT_AT + } + ]; + } + + getReimbursableExpenseStateOptions(isSimplifyReportClosureEnabled: boolean): ExportSettingFormOption[] { + return [ + { + label: isSimplifyReportClosureEnabled ? 'Processing' : 'Payment Processing', + value: ExpenseState.PAYMENT_PROCESSING + }, + { + label: isSimplifyReportClosureEnabled ? 'Closed' : 'Paid', + value: ExpenseState.PAID + } + ]; + } + + getCCCExpenseStateOptions(isSimplifyReportClosureEnabled: boolean): ExportSettingFormOption[] { + return [ + { + label: isSimplifyReportClosureEnabled ? 'Approved' : 'Payment Processing', + value: isSimplifyReportClosureEnabled ? CCCExpenseState.APPROVED: CCCExpenseState.PAYMENT_PROCESSING + }, + { + label: isSimplifyReportClosureEnabled ? 'Closed' : 'Paid', + value: CCCExpenseState.PAID + } + ]; + } } diff --git a/src/app/core/services/core/helper.service.ts b/src/app/core/services/core/helper.service.ts index b976cf03..d6bcdaf2 100644 --- a/src/app/core/services/core/helper.service.ts +++ b/src/app/core/services/core/helper.service.ts @@ -4,6 +4,10 @@ import { UntypedFormGroup } from '@angular/forms'; import { SnakeCaseToSpaceCase } from 'src/app/shared/pipes/snake-case-to-space-case.pipe'; import { DefaultDestinationAttribute } from '../../models/db/general-mapping.model'; import { WindowService } from './window.service'; +import { ConfirmationDialog } from '../../models/misc/confirmation-dialog.model'; +import { ConfirmationDialogComponent } from 'src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; +import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' @@ -12,7 +16,11 @@ export class HelperService { private windowReference: Window; - constructor(private windowService: WindowService) { + constructor( + private windowService: WindowService, + private dialog: MatDialog, + private router: Router, + ) { this.windowReference = this.windowService.nativeWindow; } @@ -37,4 +45,17 @@ export class HelperService { getSpaceCasedTitleCase(word: string): string { return new SnakeCaseToSpaceCase().transform((new TitleCasePipe().transform(word))); } + + openDialogAndSetupRedirection(data: ConfirmationDialog, url: string): void { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + width: '551px', + data: data + }); + + dialogRef.afterClosed().subscribe((ctaClicked: boolean) => { + if (ctaClicked) { + this.router.navigate([url]); + } + }); + } } diff --git a/src/app/core/services/integration/tracking.service.ts b/src/app/core/services/integration/tracking.service.ts index a118a138..04c683de 100644 --- a/src/app/core/services/integration/tracking.service.ts +++ b/src/app/core/services/integration/tracking.service.ts @@ -136,4 +136,8 @@ export class TrackingService { onMappingsAlphabeticalFilter(properties: MappingAlphabeticalFilterAdditionalProperty): void { this.eventTrack('Mappings Alphabetical Filter', properties); } + + onCloneSettingsSave(properties: Partial): void { + this.eventTrack('Clone Settings Saved', properties); + } } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html new file mode 100644 index 00000000..1f6cd3b0 --- /dev/null +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -0,0 +1,187 @@ + + +
+
+
+
+
+
+ +
+
+

Employee Mappings

+
+ In this section, you can configure how map fyle employees to Quickbooks Vendor / Employee +
+
+
+ +
+
+
+ +

Employee Field Mapping

+ +
+ +
+ +
+
+
+ +
+
+
+ +

Auto Map Employee

+ +
+ +
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+

Export Settings

+
In this section, you can configure how + and when expenses from Fyle need to be exported to Xero
+
+
+
+
+
+

Reimbursable Expense

+ +
+ +
+ +
+
+
+ +
+
+
+
+ +

To which Expense Account should the Expense + be posted to?

+ +
+ +
+
+ +
+
+
+
+ +
+
+
+ +

Mode of Export

+ +
+ + +
+
+ +
+
+
+ +

Date of export

+ +
+ +
+ +
+
+
+ +
+
+
+ +

State of export

+ +
+ +
+ +
+
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.scss b/src/app/integration/onboarding/clone-settings/clone-settings.component.scss new file mode 100644 index 00000000..f5d320c9 --- /dev/null +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.scss @@ -0,0 +1,180 @@ +.clone-settings { + &--section { + display: flex; + justify-content: center; + } + + &--block { + margin-top: -140px; + margin-bottom: 58px; + width: 1098px; + background: #FFFFFF; + border: 1px solid #F5F5F5; + box-sizing: border-box; + box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06); + border-radius: 8px; + } + + &--header-section { + padding-top: 24px; + background: #FAFCFF; + border: 1px solid #F5F5F5; + } + + &--header-icon { + padding: 0px 10px 0px 32px; + } + + &--header-caption { + padding-top: 10px; + padding-bottom: 24px; + } + + &--configuration-section { + padding: 24px 32px; + } + + &--info-icon { + padding: 4px 0px 0px 10px; + } + + &--sub-options-icon { + padding-right: 12px; + } + + &--field-section { + width: 500px; + } + + &--sub-options-text { + color: #2C304E; + font-size: 14px; + } + + &--export-type { + padding-left: 10px; + } + + &--export-type-text { + font-weight: 600; + } + + &--field-header-section { + padding: 8px 0px 0px 32px; + } + + &--field-header { + width: 608px; + height: 48px; + font-size: 14px; + } + + &--xero-header { + padding-left: 14px; + padding-right: 280px; + } + + &--coa-import-section { + padding: 20px 0px 12px 32px; + } + + &--xero-field { + height: 34px; + width: 304px; + background: #F5F5F5; + border: 1px solid #DFDFE2; + border-radius: 4px; + font-size: 14px; + color: #2C304E; + } + + &--xero-field-text { + padding-left: 14px; + } + + &--back-btn { + margin-right: 12px; + } + + &--error-message { + padding-top: 10px; + margin-left: -22px; + } + + &--reset-btn { + width: 186px; + } + + &--footer-inner-section { + height: 84px; + padding: 12px 32px; + } + + &--coa-list { + padding-left: 12px; + font-size: 14px; + } + + &--cta-text { + color: #FF3366; + } + + &--coa-list-icon { + padding-left: 15px; + } + + &--delete-icon { + padding-right: 34px; + } + + &--tax-group-field { + margin-right: 12px; + } + + &--header-advanced-setting { + padding-top: 24px; + } + + &--configuration-payment-section { + padding: 0px 32px 24px; + } + + &--configuration-payment-field { + padding-left: 28px; + } + + &--add-email-text { + padding-right: 210px; + padding-top: 18px; + } + + &--add-btn { + margin-bottom: 8px; + height: 16px; + width: 16px; + } + + &--span-or { + margin: 1px 15px 8px 5px ; + font-weight: 500; + font-size: 14px; + color: #2c304e; + } + + &--additional-email-text { + margin-top: -40px; + } + + &--add-field-section { + width: 124px; + } + + &--add-field { + padding-right: 12px; + font-size: 14px; + } +} + +p { + margin: 0; +} diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts new file mode 100644 index 00000000..75f34cde --- /dev/null +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CloneSettingsComponent } from './clone-settings.component'; + +describe('CloneSettingsComponent', () => { + let component: CloneSettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CloneSettingsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CloneSettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts new file mode 100644 index 00000000..1d79c9d1 --- /dev/null +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -0,0 +1,121 @@ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; +import { forkJoin } from 'rxjs'; +import { CloneSetting } from 'src/app/core/models/configuration/clone-setting.model'; +import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; +import { DestinationAttribute } from 'src/app/core/models/db/destination-attribute.model'; +import { AdvancedSettingService } from 'src/app/core/services/configuration/advanced-setting.service'; +import { CloneSettingService } from 'src/app/core/services/configuration/clone-setting.service'; +import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; +import { ImportSettingService } from 'src/app/core/services/configuration/import-setting.service'; +import { HelperService } from 'src/app/core/services/core/helper.service'; +import { ClickEvent, EmployeeFieldMapping, OnboardingStep, PaymentSyncDirection, ReimbursableExpensesObject, ProgressPhase, SimpleSearchPage, SimpleSearchType, } from 'src/app/core/models/enum/enum.model'; + + +@Component({ + selector: 'app-clone-settings', + templateUrl: './clone-settings.component.html', + styleUrls: ['./clone-settings.component.scss'] +}) +export class CloneSettingsComponent { + + isLoading: boolean = true; + + cloneSettingsForm: FormGroup; + + autoMapEmployeeTypes: ExportSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); + + reimbursableExportOptions: ExportSettingFormOption[]; + + reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingDateOptions(); + + employeeFieldMappingOptions: ExportSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); + + bankAccounts: DestinationAttribute[]; + + cloneSettings: CloneSetting; + + reimbursableExpenseStateOptions: ExportSettingFormOption[]; + + cccExpenseStateOptions: ExportSettingFormOption[]; + + cccExpenseExportOptions: ExportSettingFormOption[]; + + ProgressPhase = ProgressPhase; + + constructor( + private exportSettingService: ExportSettingService, + public helperService: HelperService, + private formBuilder: FormBuilder, + private cloneSettingService: CloneSettingService, + ) { } + + + getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { + return { + EMPLOYEE: [ + { + label: 'Check', + value: ReimbursableExpensesObject.CHECK + }, + { + label: 'Expense', + value: ReimbursableExpensesObject.EXPENSE + }, + { + label: 'Journal Entry', + value: ReimbursableExpensesObject.JOURNAL_ENTRY + } + ], + VENDOR: [ + { + label: 'Bill', + value: ReimbursableExpensesObject.BILL + }, + { + label: 'Expense', + value: ReimbursableExpensesObject.EXPENSE + }, + { + label: 'Journal Entry', + value: ReimbursableExpensesObject.JOURNAL_ENTRY + } + ] + }[employeeFieldMapping]; + } + + + private setupForm(): void { + this.cloneSettingsForm = this.formBuilder.group({ + reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], + autoMapEmployees: [this.cloneSettings.employee_mappings.workspace_general_settings.auto_map_employees], + reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings.reimbursable_export_date_type], + reimbursableExpenseState: [this.cloneSettings.export_settings.expense_group_settings.expense_state], + reimbursableExportTypes: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], + employeeFieldMapping: [this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping], + creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object], + cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings.ccc_expense_state] + }); + this.cloneSettingsForm.markAllAsTouched(); + this.isLoading = false; + } + + private setupPage(): void { + forkJoin([ + this.cloneSettingService.getCloneSettings(), + ]).subscribe(responses => { + this.cloneSettings = responses[0]; + this.reimbursableExpenseStateOptions = this.exportSettingService.getReimbursableExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); + this.cccExpenseStateOptions = this.exportSettingService.getCCCExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); + this.reimbursableExportOptions = this.getReimbursableExportTypes(EmployeeFieldMapping.EMPLOYEE); + this.cccExpenseExportOptions = this.exportSettingService.getcreditCardExportTypes(); + this.setupForm(); + }); + } + + ngOnInit(): void { + this.setupPage(); + } + + +} diff --git a/src/app/integration/onboarding/onboarding-routing.module.ts b/src/app/integration/onboarding/onboarding-routing.module.ts index 3b250081..fc7e7688 100644 --- a/src/app/integration/onboarding/onboarding-routing.module.ts +++ b/src/app/integration/onboarding/onboarding-routing.module.ts @@ -9,6 +9,7 @@ import { OnboardingImportSettingsComponent } from './onboarding-import-settings/ import { OnboardingLandingComponent } from './onboarding-landing/onboarding-landing.component'; import { OnboardingQboConnectorComponent } from './onboarding-qbo-connector/onboarding-qbo-connector.component'; import { OnboardingComponent } from './onboarding.component'; +import { CloneSettingsComponent } from './clone-settings/clone-settings.component'; const routes: Routes = [ @@ -20,6 +21,11 @@ const routes: Routes = [ path: '', component: OnboardingComponent, children: [ + { + path: 'clone_settings', + component: CloneSettingsComponent, + canActivate: [WorkspacesGuard] + }, { path: 'export_settings', component: OnboardingExportSettingsComponent, diff --git a/src/app/integration/onboarding/onboarding.module.ts b/src/app/integration/onboarding/onboarding.module.ts index 3d3e83e0..f66b7090 100644 --- a/src/app/integration/onboarding/onboarding.module.ts +++ b/src/app/integration/onboarding/onboarding.module.ts @@ -10,7 +10,9 @@ import { MatLegacySelectModule as MatSelectModule } from '@angular/material/lega import { MatLegacySlideToggleModule as MatSlideToggleModule } from '@angular/material/legacy-slide-toggle'; import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; - +import { MatMenuModule } from '@angular/material/menu'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { SharedModule } from 'src/app/shared/shared.module'; // Components @@ -23,6 +25,7 @@ import { OnboardingLandingComponent } from './onboarding-landing/onboarding-land import { OnboardingQboConnectorComponent } from './onboarding-qbo-connector/onboarding-qbo-connector.component'; import { OnboardingEmployeeSettingsComponent } from './onboarding-employee-settings/onboarding-employee-settings.component'; import { OnboardingRoutingModule } from './onboarding-routing.module'; +import { CloneSettingsComponent } from './clone-settings/clone-settings.component'; @NgModule({ declarations: [ @@ -33,7 +36,8 @@ import { OnboardingRoutingModule } from './onboarding-routing.module'; OnboardingComponent, OnboardingLandingComponent, OnboardingQboConnectorComponent, - OnboardingEmployeeSettingsComponent + OnboardingEmployeeSettingsComponent, + CloneSettingsComponent ], imports: [ CommonModule, @@ -46,7 +50,11 @@ import { OnboardingRoutingModule } from './onboarding-routing.module'; MatSlideToggleModule, MatCheckboxModule, MatDialogModule, - SharedModule + SharedModule, + MatMenuModule, + MatTooltipModule, + SharedModule, + MatProgressSpinnerModule ] }) export class OnboardingModule { } diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html new file mode 100644 index 00000000..86d05cca --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html @@ -0,0 +1 @@ +

clone-advanced-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts new file mode 100644 index 00000000..5a90fabf --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CloneAdvancedSettingsComponent } from './clone-advanced-settings.component'; + +describe('CloneAdvancedSettingsComponent', () => { + let component: CloneAdvancedSettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CloneAdvancedSettingsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CloneAdvancedSettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts new file mode 100644 index 00000000..8dfbfaca --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-clone-advanced-settings', + templateUrl: './clone-advanced-settings.component.html', + styleUrls: ['./clone-advanced-settings.component.scss'] +}) +export class CloneAdvancedSettingsComponent { + +} diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html new file mode 100644 index 00000000..f3325808 --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html @@ -0,0 +1 @@ +

clone-export-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts new file mode 100644 index 00000000..6229e2e6 --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CloneExportSettingsComponent } from './clone-export-settings.component'; + +describe('CloneExportSettingsComponent', () => { + let component: CloneExportSettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CloneExportSettingsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CloneExportSettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts new file mode 100644 index 00000000..52f20f47 --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-clone-export-settings', + templateUrl: './clone-export-settings.component.html', + styleUrls: ['./clone-export-settings.component.scss'] +}) +export class CloneExportSettingsComponent { + +} diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html new file mode 100644 index 00000000..c9238948 --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html @@ -0,0 +1 @@ +

clone-import-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts new file mode 100644 index 00000000..5f078b48 --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CloneImportSettingsComponent } from './clone-import-settings.component'; + +describe('CloneImportSettingsComponent', () => { + let component: CloneImportSettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CloneImportSettingsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CloneImportSettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts new file mode 100644 index 00000000..233f684f --- /dev/null +++ b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-clone-import-settings', + templateUrl: './clone-import-settings.component.html', + styleUrls: ['./clone-import-settings.component.scss'] +}) +export class CloneImportSettingsComponent { + +} diff --git a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts index a7aa8e18..26e6ec8e 100644 --- a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts +++ b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts @@ -15,6 +15,9 @@ import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog'; import { ConfirmationDialogComponent } from '../../core/confirmation-dialog/confirmation-dialog.component'; import { TrackingService } from 'src/app/core/services/integration/tracking.service'; +import { HelperService } from 'src/app/core/services/core/helper.service'; +import { CloneSettingService } from 'src/app/core/services/configuration/clone-setting.service'; +import { CloneSettingExist } from 'src/app/core/models/configuration/clone-setting.model'; @Component({ selector: 'app-qbo-connector', @@ -49,6 +52,9 @@ export class QboConnectorComponent implements OnInit, OnDestroy { private timeSpentEventRecorded: boolean = false; + private disableCloneSettings: boolean + + constructor( private authService: AuthService, private dialog: MatDialog, @@ -60,7 +66,9 @@ export class QboConnectorComponent implements OnInit, OnDestroy { private trackingService: TrackingService, private userService: UserService, private windowService: WindowService, - private workspaceService: WorkspaceService + private workspaceService: WorkspaceService, + private cloneSettingService: CloneSettingService, + private helperService: HelperService ) { this.windowReference = this.windowService.nativeWindow; } @@ -72,13 +80,26 @@ export class QboConnectorComponent implements OnInit, OnDestroy { this.trackingService.trackTimeSpent(OnboardingStep.CONNECT_QBO, {phase: ProgressPhase.ONBOARDING, durationInSeconds: Math.floor(differenceInMs / 1000), eventState: eventState}); } + checkCloneSettingsAvailablity(): void { + this.cloneSettingService.checkCloneSettingsExists().subscribe((response: CloneSettingExist) => { + if (response.is_available) { + this.showCloneSettingsDialog(response.workspace_name); + } else { + this.router.navigate(['/workspaces/onboarding/employee_settings']); + } + }); + } + continueToNextStep(): void { if (this.isContinueDisabled) { return; + } else if (this.disableCloneSettings) { + this.router.navigate(['/workspaces/onboarding/employee_settings']); + return; } this.trackSessionTime('success'); - this.router.navigate([`/workspaces/onboarding/employee_settings`]); + this.checkCloneSettingsAvailablity(); } switchFyleOrg(): void { @@ -116,6 +137,21 @@ export class QboConnectorComponent implements OnInit, OnDestroy { }); } + private showCloneSettingsDialog(workspaceName: string): void { + this.isContinueDisabled = false; + this.disableCloneSettings = true; + const data: ConfirmationDialog = { + title: 'Your settings are pre-filled', + contents: `Your previous organization's settings (${workspaceName}) have been copied over to the current organization +

You can change the settings or reset the configuration to restart the process from the beginning
`, + primaryCtaText: 'Continue', + hideSecondaryCTA: true, + hideWarningIcon: true + }; + + this.helperService.openDialogAndSetupRedirection(data, '/workspaces/onboarding/clone_settings'); + } + private showWarningDialog(): void { const data: ConfirmationDialog = { title: 'Incorrect account selected', diff --git a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.html b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.html index 67fbd414..8f5e9fea 100644 --- a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.html +++ b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.html @@ -2,11 +2,11 @@
-
+
-

- {{ data.title }} +

+ {{ data.title }}

diff --git a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts index de7c06a0..d4eb531c 100644 --- a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts +++ b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts @@ -1,6 +1,6 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { MatLegacyDialogRef as MatDialogRef, MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA } from '@angular/material/legacy-dialog'; import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; @Component({ selector: 'app-confirmation-dialog', @@ -10,6 +10,7 @@ import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog export class ConfirmationDialogComponent implements OnInit { hideSecondaryCTA: boolean; + hideWarningIcon: boolean; constructor( @Inject(MAT_DIALOG_DATA) public data: ConfirmationDialog, @@ -18,6 +19,7 @@ export class ConfirmationDialogComponent implements OnInit { ngOnInit(): void { this.hideSecondaryCTA = this.data.hideSecondaryCTA ? this.data.hideSecondaryCTA : false; + this.hideWarningIcon = this.data.hideWarningIcon ? this.data.hideWarningIcon : false; } } diff --git a/src/app/shared/components/core/select/select.component.html b/src/app/shared/components/core/select/select.component.html new file mode 100644 index 00000000..1a052075 --- /dev/null +++ b/src/app/shared/components/core/select/select.component.html @@ -0,0 +1,56 @@ +
+ + + + {{ option.label }} + + + + +
+ +

{{ option.value }}

+

{{ option.value }}

+ +
+
+
+
+
+ +
+

Click here to Preivew on how + it + looks on QuickBooks

+

Click here to Preivew on how it + looks on QuickBooks

+
+ +
+
+ Example: Ryan Clark will map to Ryan Clark in QuickBooks. +
+
+ Example: ryan.clark@acme.com will map to ryan.clark@acme.com in QuickBooks. +
+
+ Example: E0146 will map to E0146 in QuickBooks. +
+
+
diff --git a/src/app/shared/components/core/select/select.component.scss b/src/app/shared/components/core/select/select.component.scss new file mode 100644 index 00000000..dcbe016d --- /dev/null +++ b/src/app/shared/components/core/select/select.component.scss @@ -0,0 +1,21 @@ +.select-field { + &--preview-text { + font-size: 12px; + padding-top: 4px; + @media only screen and (max-width: 1440px) { + padding-left: 10px; + } + } + + &--preview-btn { + color: #0660F6; + } + + &--select-example-section { + padding: 2px 8px 0px 10px; + } + + &--clone-settings-tax { + width: 280px; + } +} diff --git a/src/app/shared/components/core/select/select.component.spec.ts b/src/app/shared/components/core/select/select.component.spec.ts new file mode 100644 index 00000000..a4d24fa2 --- /dev/null +++ b/src/app/shared/components/core/select/select.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SelectComponent } from './select.component'; + +describe('SelectComponent', () => { + let component: SelectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SelectComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SelectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/components/core/select/select.component.ts b/src/app/shared/components/core/select/select.component.ts new file mode 100644 index 00000000..45dc25ca --- /dev/null +++ b/src/app/shared/components/core/select/select.component.ts @@ -0,0 +1,69 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { AdvancedSettingFormOption } from 'src/app/core/models/configuration/advanced-setting.model'; +import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; +import { DestinationAttribute } from 'src/app/core/models/db/destination-attribute.model'; +import { ClickEvent, CorporateCreditCardExpensesObject, ProgressPhase, ReimbursableExpensesObject, SimpleSearchPage, SimpleSearchType } from 'src/app/core/models/enum/enum.model'; +import { HelperService } from 'src/app/core/services/core/helper.service'; +import { PreviewDialogComponent } from '../../configuration/preview-dialog/preview-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; +import { TrackingService } from 'src/app/core/services/integration/tracking.service'; + +@Component({ + selector: 'app-select', + templateUrl: './select.component.html', + styleUrls: ['./select.component.scss'] +}) +export class SelectComponent implements OnInit { + + @Input() exportType: ReimbursableExpensesObject | CorporateCreditCardExpensesObject; + + @Input() placeholder: string; + + @Input() formControllerName: string; + + @Input() form: FormGroup; + + @Input() options: ExportSettingFormOption[] | AdvancedSettingFormOption[] | any[]; + + @Input() qboAttributes: DestinationAttribute[]; + + @Input() isFieldMandatory: boolean; + + @Input() mandatoryErrorListName: string; + + @Input() customErrorMessage: string; + + @Input() phase: ProgressPhase; + + @Input() isCloneSettingField: boolean; + + SimpleSearchPage = SimpleSearchPage; + + SimpleSearchType = SimpleSearchType; + + constructor( + public dialog: MatDialog, + public helperService: HelperService, + private trackingService: TrackingService + ) { } + + showQboExportPreview(reimbursableExportType: ReimbursableExpensesObject | null, creditCardExportType: CorporateCreditCardExpensesObject | null): void { + const data = { + QboReimburse: reimbursableExportType, + QboCCC: creditCardExportType + }; + + this.trackingService.onClickEvent(ClickEvent.PREVIEW_QBO_EXPORT, {phase: this.phase, exportType: reimbursableExportType || creditCardExportType}); + + this.dialog.open(PreviewDialogComponent, { + width: '960px', + height: '530px', + data: data + }); + } + + ngOnInit(): void { + } + +} diff --git a/src/app/shared/components/core/toggle/toggle.component.html b/src/app/shared/components/core/toggle/toggle.component.html new file mode 100644 index 00000000..8860628f --- /dev/null +++ b/src/app/shared/components/core/toggle/toggle.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/app/shared/components/core/toggle/toggle.component.scss b/src/app/shared/components/core/toggle/toggle.component.scss new file mode 100644 index 00000000..9129ccf0 --- /dev/null +++ b/src/app/shared/components/core/toggle/toggle.component.scss @@ -0,0 +1,24 @@ +:host { + .mat-slide-toggle { + &.mat-checked { + ::ng-deep.mat-slide-toggle-bar::after { + content: 'Yes'; + font-size: 75%; + color: #FFFFFF; + position: absolute; + left: 8px; + top: -1px; + } + } + &:not(.mat-checked) { + ::ng-deep.mat-slide-toggle-bar::after { + content: 'No'; + font-size: 75%; + color: #FFFFFF; + position: absolute; + left: 25px; + top: -1px; + } + } + } +} diff --git a/src/app/shared/components/core/toggle/toggle.component.spec.ts b/src/app/shared/components/core/toggle/toggle.component.spec.ts new file mode 100644 index 00000000..d5343fe5 --- /dev/null +++ b/src/app/shared/components/core/toggle/toggle.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToggleComponent } from './toggle.component'; + +describe('ToggleComponent', () => { + let component: ToggleComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ToggleComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ToggleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/components/core/toggle/toggle.component.ts b/src/app/shared/components/core/toggle/toggle.component.ts new file mode 100644 index 00000000..ee3810d3 --- /dev/null +++ b/src/app/shared/components/core/toggle/toggle.component.ts @@ -0,0 +1,22 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; + +@Component({ + selector: 'app-toggle', + templateUrl: './toggle.component.html', + styleUrls: ['./toggle.component.scss'] +}) +export class ToggleComponent implements OnInit { + + @Input() form: FormGroup; + + @Input() formControllerName: string; + + @Input() isCloneSettings: boolean; + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.html b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.html index 7a63e1d5..fe3a9e98 100644 --- a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.html +++ b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.html @@ -1,8 +1,7 @@

- Complete the following steps to configure your Integration. -

+ {{ isCloneSettingsActive ? 'Fill in the below fields to complete your integration set up' : 'Complete the following steps to configure your Integration'}}

@@ -14,11 +13,10 @@
-
+
-
{{onboardingStep.step}}
-
+
{{onboardingStep.step}}
diff --git a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.scss b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.scss index b593a83d..99c0be4b 100644 --- a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.scss +++ b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.scss @@ -58,6 +58,10 @@ margin-left: -24px; } + &--step-6-text { + margin-left: -10px; + } + &--icon { width: 24px; height: 24px; diff --git a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts index 46ec33e2..ffd7c2dd 100644 --- a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts +++ b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts @@ -14,6 +14,8 @@ export class OnboardingStepperComponent implements OnInit { @Input() currentStep: string; + isCloneSettingsActive: boolean; + onboardingSteps: OnboardingStepper[] = [ { active: false, @@ -83,25 +85,46 @@ export class OnboardingStepperComponent implements OnInit { ) { } private updateActiveAndCompletedSteps(): void { - this.onboardingSteps.forEach(step => { - if (step.step === this.currentStep) { - step.active = true; - } - }); - const onboardingState: OnboardingState = this.workspaceService.getOnboardingState(); + if (this.currentStep == 'Clone Settings') { + this.isCloneSettingsActive = true; + this.onboardingSteps[0].completed = true; + this.onboardingSteps = [this.onboardingSteps[0]]; + this.onboardingSteps.push( + { + active: true, + completed: false, + number: 6, + step: 'Complete the Configurations', + icon: 'advanced-setting', + route: 'clone_settings', + size: { + height: '20px', + width: '20px' + } + } + ); + } else { + this.onboardingSteps.forEach(step => { + if (step.step === this.currentStep) { + step.active = true; + } + }); - const onboardingStateStepMap = { - [OnboardingState.CONNECTION]: 1, - [OnboardingState.MAP_EMPLOYEES]: 2, - [OnboardingState.EXPORT_SETTINGS]: 3, - [OnboardingState.IMPORT_SETTINGS]: 4, - [OnboardingState.ADVANCED_CONFIGURATION]: 5, - [OnboardingState.COMPLETE]: 6 - }; + const onboardingState: OnboardingState = this.workspaceService.getOnboardingState(); - for (let index = onboardingStateStepMap[onboardingState] - 1; index > 0; index--) { - this.onboardingSteps[index - 1].completed = true; + const onboardingStateStepMap = { + [OnboardingState.CONNECTION]: 1, + [OnboardingState.MAP_EMPLOYEES]: 2, + [OnboardingState.EXPORT_SETTINGS]: 3, + [OnboardingState.IMPORT_SETTINGS]: 4, + [OnboardingState.ADVANCED_CONFIGURATION]: 5, + [OnboardingState.COMPLETE]: 6 + }; + + for (let index = onboardingStateStepMap[onboardingState] - 1; index > 0; index--) { + this.onboardingSteps[index - 1].completed = true; + } } } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index a33eb1e1..17fd026f 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -64,6 +64,11 @@ import { MandatoryErrorMessageComponent } from './components/helpers/mandatory-e import { AddEmailDialogComponent } from './components/configuration/advanced-settings/add-email-dialog/add-email-dialog.component'; import { EmailMultiSelectFieldComponent } from './components/configuration/email-multi-select-field/email-multi-select-field.component'; import { SkipExportLogTableComponent } from './components/export-log/skip-export-log-table/skip-export-log-table.component'; +import { CloneAdvancedSettingsComponent } from './components/clone-settings/clone-advanced-settings/clone-advanced-settings.component'; +import { CloneExportSettingsComponent } from './components/clone-settings/clone-export-settings/clone-export-settings.component'; +import { CloneImportSettingsComponent } from './components/clone-settings/clone-import-settings/clone-import-settings.component'; +import { ToggleComponent } from './components/core/toggle/toggle.component'; +import { SelectComponent } from './components/core/select/select.component'; @NgModule({ declarations: [ @@ -104,7 +109,12 @@ import { SkipExportLogTableComponent } from './components/export-log/skip-export MandatoryErrorMessageComponent, AddEmailDialogComponent, EmailMultiSelectFieldComponent, - SkipExportLogTableComponent + SkipExportLogTableComponent, + CloneAdvancedSettingsComponent, + CloneExportSettingsComponent, + CloneImportSettingsComponent, + ToggleComponent, + SelectComponent ], imports: [ CommonModule, @@ -158,7 +168,9 @@ import { SkipExportLogTableComponent } from './components/export-log/skip-export DashboardResolveMappingErrorDialogComponent, ExportLogChildTableComponent, MandatoryErrorMessageComponent, - MatChipsModule + MatChipsModule, + ToggleComponent, + SelectComponent ], schemas: [CUSTOM_ELEMENTS_SCHEMA], providers: [ diff --git a/src/assets/images/svgs/actions/arrow-mark-down-pink.svg b/src/assets/images/svgs/actions/arrow-mark-down-pink.svg new file mode 100644 index 00000000..55911b42 --- /dev/null +++ b/src/assets/images/svgs/actions/arrow-mark-down-pink.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/svgs/general/calendar-disabled.svg b/src/assets/images/svgs/general/calendar-disabled.svg new file mode 100644 index 00000000..6cbbf2af --- /dev/null +++ b/src/assets/images/svgs/general/calendar-disabled.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/images/svgs/general/connect-arrow.svg b/src/assets/images/svgs/general/connect-arrow.svg new file mode 100644 index 00000000..667a5bd2 --- /dev/null +++ b/src/assets/images/svgs/general/connect-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/svgs/general/document-disabled.svg b/src/assets/images/svgs/general/document-disabled.svg new file mode 100644 index 00000000..4b4802d2 --- /dev/null +++ b/src/assets/images/svgs/general/document-disabled.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/images/svgs/general/employee-disabled.svg b/src/assets/images/svgs/general/employee-disabled.svg new file mode 100644 index 00000000..b6d5c85d --- /dev/null +++ b/src/assets/images/svgs/general/employee-disabled.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/images/svgs/general/info-disabled.svg b/src/assets/images/svgs/general/info-disabled.svg new file mode 100644 index 00000000..aa39e986 --- /dev/null +++ b/src/assets/images/svgs/general/info-disabled.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/svgs/general/question-disabled.svg b/src/assets/images/svgs/general/question-disabled.svg new file mode 100644 index 00000000..e746dc09 --- /dev/null +++ b/src/assets/images/svgs/general/question-disabled.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/images/svgs/general/setting.svg b/src/assets/images/svgs/general/setting.svg new file mode 100644 index 00000000..18fb8b0a --- /dev/null +++ b/src/assets/images/svgs/general/setting.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/images/svgs/general/sync-disabled.svg b/src/assets/images/svgs/general/sync-disabled.svg new file mode 100644 index 00000000..04be8acf --- /dev/null +++ b/src/assets/images/svgs/general/sync-disabled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/images/svgs/general/tabs-disabled.svg b/src/assets/images/svgs/general/tabs-disabled.svg new file mode 100644 index 00000000..a8b3382d --- /dev/null +++ b/src/assets/images/svgs/general/tabs-disabled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/images/svgs/general/tick-green.svg b/src/assets/images/svgs/general/tick-green.svg new file mode 100644 index 00000000..c622e5da --- /dev/null +++ b/src/assets/images/svgs/general/tick-green.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/styles.scss b/src/styles.scss index a0f6ac22..cf86df58 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -259,6 +259,12 @@ th.mat-header-cell:last-of-type { .mat-option.mat-active { background: none !important; + + &.clone-settings { + @extend .mat-tooltip, .above, .align-center; + white-space: normal !important; + margin-right: 6px !important; + } } .mat-form-field-appearance-outline.mat-focused .mat-form-field-outline-thick { From e0d34dfdeef3240468884f9258ce76b4dc33d16c Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Thu, 27 Jul 2023 23:20:48 +0530 Subject: [PATCH 02/47] add support --- src/app/auth/auth.module.ts | 2 +- .../configuration/clone-setting.model.ts | 2 +- .../configuration/export-setting.service.ts | 2 +- src/app/core/services/core/helper.service.ts | 2 +- .../clone-settings.component.html | 2 +- .../clone-settings.component.ts | 26 +++++++------------ .../qbo-connector/qbo-connector.component.ts | 2 +- .../confirmation-dialog.component.ts | 1 + .../onboarding-stepper.component.ts | 2 +- 9 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts index e9a7b3a4..0957de74 100644 --- a/src/app/auth/auth.module.ts +++ b/src/app/auth/auth.module.ts @@ -25,7 +25,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; FlexLayoutModule, MatButtonModule, MatProgressSpinnerModule, - MatButtonModule, + MatButtonModule ] }) export class AuthModule { } diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index ab56a028..5c2e8194 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -30,7 +30,7 @@ export class CloneSettingModel { const exportSettingPayload = ExportSettingModel.constructPayload(cloneSettingsForm); const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); - const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm) + const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm); const cloneSettingPayload: CloneSettingPost = { export_settings: exportSettingPayload, diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 16b09194..98ac6201 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -76,7 +76,7 @@ export class ExportSettingService { label: 'Debit Card Expense', value: CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE } - ] + ]; } getEmployeeFieldMappingOptions(): ExportSettingFormOption[] { diff --git a/src/app/core/services/core/helper.service.ts b/src/app/core/services/core/helper.service.ts index d6bcdaf2..73a6bb65 100644 --- a/src/app/core/services/core/helper.service.ts +++ b/src/app/core/services/core/helper.service.ts @@ -19,7 +19,7 @@ export class HelperService { constructor( private windowService: WindowService, private dialog: MatDialog, - private router: Router, + private router: Router ) { this.windowReference = this.windowService.nativeWindow; } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 1f6cd3b0..9c2c556f 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -184,4 +184,4 @@
In this section, you c - \ No newline at end of file + diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 1d79c9d1..390a711a 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -1,15 +1,13 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { FormGroup, FormBuilder } from '@angular/forms'; import { forkJoin } from 'rxjs'; import { CloneSetting } from 'src/app/core/models/configuration/clone-setting.model'; import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; import { DestinationAttribute } from 'src/app/core/models/db/destination-attribute.model'; -import { AdvancedSettingService } from 'src/app/core/services/configuration/advanced-setting.service'; import { CloneSettingService } from 'src/app/core/services/configuration/clone-setting.service'; import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; -import { ImportSettingService } from 'src/app/core/services/configuration/import-setting.service'; import { HelperService } from 'src/app/core/services/core/helper.service'; -import { ClickEvent, EmployeeFieldMapping, OnboardingStep, PaymentSyncDirection, ReimbursableExpensesObject, ProgressPhase, SimpleSearchPage, SimpleSearchType, } from 'src/app/core/models/enum/enum.model'; +import { EmployeeFieldMapping, ReimbursableExpensesObject, ProgressPhase } from 'src/app/core/models/enum/enum.model'; @Component({ @@ -22,23 +20,23 @@ export class CloneSettingsComponent { isLoading: boolean = true; cloneSettingsForm: FormGroup; - + autoMapEmployeeTypes: ExportSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); - + reimbursableExportOptions: ExportSettingFormOption[]; - + reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingDateOptions(); employeeFieldMappingOptions: ExportSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); bankAccounts: DestinationAttribute[]; - + cloneSettings: CloneSetting; - + reimbursableExpenseStateOptions: ExportSettingFormOption[]; cccExpenseStateOptions: ExportSettingFormOption[]; - + cccExpenseExportOptions: ExportSettingFormOption[]; ProgressPhase = ProgressPhase; @@ -49,8 +47,7 @@ export class CloneSettingsComponent { private formBuilder: FormBuilder, private cloneSettingService: CloneSettingService, ) { } - - + getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { return { EMPLOYEE: [ @@ -84,7 +81,6 @@ export class CloneSettingsComponent { }[employeeFieldMapping]; } - private setupForm(): void { this.cloneSettingsForm = this.formBuilder.group({ reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], @@ -102,7 +98,7 @@ export class CloneSettingsComponent { private setupPage(): void { forkJoin([ - this.cloneSettingService.getCloneSettings(), + this.cloneSettingService.getCloneSettings() ]).subscribe(responses => { this.cloneSettings = responses[0]; this.reimbursableExpenseStateOptions = this.exportSettingService.getReimbursableExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); @@ -116,6 +112,4 @@ export class CloneSettingsComponent { ngOnInit(): void { this.setupPage(); } - - } diff --git a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts index 26e6ec8e..712a4896 100644 --- a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts +++ b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts @@ -52,7 +52,7 @@ export class QboConnectorComponent implements OnInit, OnDestroy { private timeSpentEventRecorded: boolean = false; - private disableCloneSettings: boolean + private disableCloneSettings: boolean; constructor( diff --git a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts index d4eb531c..1b1b3e2c 100644 --- a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts +++ b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts @@ -10,6 +10,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; export class ConfirmationDialogComponent implements OnInit { hideSecondaryCTA: boolean; + hideWarningIcon: boolean; constructor( diff --git a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts index ffd7c2dd..8380e845 100644 --- a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts +++ b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts @@ -86,7 +86,7 @@ export class OnboardingStepperComponent implements OnInit { private updateActiveAndCompletedSteps(): void { - if (this.currentStep == 'Clone Settings') { + if (this.currentStep === 'Clone Settings') { this.isCloneSettingsActive = true; this.onboardingSteps[0].completed = true; this.onboardingSteps = [this.onboardingSteps[0]]; From 84a44a260c7a57d730a820d7c3c16d89d56779cd Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Thu, 27 Jul 2023 23:20:48 +0530 Subject: [PATCH 03/47] add support --- src/app/auth/auth.module.ts | 2 +- .../configuration/clone-setting.model.ts | 2 +- .../configuration/export-setting.service.ts | 2 +- src/app/core/services/core/helper.service.ts | 2 +- .../clone-settings.component.html | 2 +- .../clone-settings.component.ts | 26 +++++++------------ .../qbo-connector/qbo-connector.component.ts | 2 +- .../confirmation-dialog.component.ts | 1 + .../onboarding-stepper.component.ts | 2 +- 9 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts index e9a7b3a4..0957de74 100644 --- a/src/app/auth/auth.module.ts +++ b/src/app/auth/auth.module.ts @@ -25,7 +25,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; FlexLayoutModule, MatButtonModule, MatProgressSpinnerModule, - MatButtonModule, + MatButtonModule ] }) export class AuthModule { } diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index ab56a028..5c2e8194 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -30,7 +30,7 @@ export class CloneSettingModel { const exportSettingPayload = ExportSettingModel.constructPayload(cloneSettingsForm); const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); - const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm) + const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm); const cloneSettingPayload: CloneSettingPost = { export_settings: exportSettingPayload, diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 16b09194..98ac6201 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -76,7 +76,7 @@ export class ExportSettingService { label: 'Debit Card Expense', value: CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE } - ] + ]; } getEmployeeFieldMappingOptions(): ExportSettingFormOption[] { diff --git a/src/app/core/services/core/helper.service.ts b/src/app/core/services/core/helper.service.ts index d6bcdaf2..73a6bb65 100644 --- a/src/app/core/services/core/helper.service.ts +++ b/src/app/core/services/core/helper.service.ts @@ -19,7 +19,7 @@ export class HelperService { constructor( private windowService: WindowService, private dialog: MatDialog, - private router: Router, + private router: Router ) { this.windowReference = this.windowService.nativeWindow; } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 1f6cd3b0..9c2c556f 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -184,4 +184,4 @@
In this section, you c - \ No newline at end of file + diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 1d79c9d1..390a711a 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -1,15 +1,13 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { FormGroup, FormBuilder } from '@angular/forms'; import { forkJoin } from 'rxjs'; import { CloneSetting } from 'src/app/core/models/configuration/clone-setting.model'; import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; import { DestinationAttribute } from 'src/app/core/models/db/destination-attribute.model'; -import { AdvancedSettingService } from 'src/app/core/services/configuration/advanced-setting.service'; import { CloneSettingService } from 'src/app/core/services/configuration/clone-setting.service'; import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; -import { ImportSettingService } from 'src/app/core/services/configuration/import-setting.service'; import { HelperService } from 'src/app/core/services/core/helper.service'; -import { ClickEvent, EmployeeFieldMapping, OnboardingStep, PaymentSyncDirection, ReimbursableExpensesObject, ProgressPhase, SimpleSearchPage, SimpleSearchType, } from 'src/app/core/models/enum/enum.model'; +import { EmployeeFieldMapping, ReimbursableExpensesObject, ProgressPhase } from 'src/app/core/models/enum/enum.model'; @Component({ @@ -22,23 +20,23 @@ export class CloneSettingsComponent { isLoading: boolean = true; cloneSettingsForm: FormGroup; - + autoMapEmployeeTypes: ExportSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); - + reimbursableExportOptions: ExportSettingFormOption[]; - + reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingDateOptions(); employeeFieldMappingOptions: ExportSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); bankAccounts: DestinationAttribute[]; - + cloneSettings: CloneSetting; - + reimbursableExpenseStateOptions: ExportSettingFormOption[]; cccExpenseStateOptions: ExportSettingFormOption[]; - + cccExpenseExportOptions: ExportSettingFormOption[]; ProgressPhase = ProgressPhase; @@ -49,8 +47,7 @@ export class CloneSettingsComponent { private formBuilder: FormBuilder, private cloneSettingService: CloneSettingService, ) { } - - + getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { return { EMPLOYEE: [ @@ -84,7 +81,6 @@ export class CloneSettingsComponent { }[employeeFieldMapping]; } - private setupForm(): void { this.cloneSettingsForm = this.formBuilder.group({ reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], @@ -102,7 +98,7 @@ export class CloneSettingsComponent { private setupPage(): void { forkJoin([ - this.cloneSettingService.getCloneSettings(), + this.cloneSettingService.getCloneSettings() ]).subscribe(responses => { this.cloneSettings = responses[0]; this.reimbursableExpenseStateOptions = this.exportSettingService.getReimbursableExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); @@ -116,6 +112,4 @@ export class CloneSettingsComponent { ngOnInit(): void { this.setupPage(); } - - } diff --git a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts index 26e6ec8e..712a4896 100644 --- a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts +++ b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.ts @@ -52,7 +52,7 @@ export class QboConnectorComponent implements OnInit, OnDestroy { private timeSpentEventRecorded: boolean = false; - private disableCloneSettings: boolean + private disableCloneSettings: boolean; constructor( diff --git a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts index d4eb531c..1b1b3e2c 100644 --- a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts +++ b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts @@ -10,6 +10,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; export class ConfirmationDialogComponent implements OnInit { hideSecondaryCTA: boolean; + hideWarningIcon: boolean; constructor( diff --git a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts index ffd7c2dd..8380e845 100644 --- a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts +++ b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts @@ -86,7 +86,7 @@ export class OnboardingStepperComponent implements OnInit { private updateActiveAndCompletedSteps(): void { - if (this.currentStep == 'Clone Settings') { + if (this.currentStep === 'Clone Settings') { this.isCloneSettingsActive = true; this.onboardingSteps[0].completed = true; this.onboardingSteps = [this.onboardingSteps[0]]; From 18ccfe3e8cd493326caed9aeaab10d838658729f Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Thu, 27 Jul 2023 23:33:25 +0530 Subject: [PATCH 04/47] add support --- .../onboarding/clone-settings/clone-settings.component.ts | 6 +++--- .../onboarding-stepper/onboarding-stepper.component.ts | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 390a711a..4a5a594b 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder } from '@angular/forms'; import { forkJoin } from 'rxjs'; import { CloneSetting } from 'src/app/core/models/configuration/clone-setting.model'; @@ -15,7 +15,7 @@ import { EmployeeFieldMapping, ReimbursableExpensesObject, ProgressPhase } from templateUrl: './clone-settings.component.html', styleUrls: ['./clone-settings.component.scss'] }) -export class CloneSettingsComponent { +export class CloneSettingsComponent implements OnInit { isLoading: boolean = true; @@ -45,7 +45,7 @@ export class CloneSettingsComponent { private exportSettingService: ExportSettingService, public helperService: HelperService, private formBuilder: FormBuilder, - private cloneSettingService: CloneSettingService, + private cloneSettingService: CloneSettingService ) { } getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { diff --git a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts index 8380e845..9dc282a0 100644 --- a/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts +++ b/src/app/shared/components/helpers/onboarding-stepper/onboarding-stepper.component.ts @@ -137,5 +137,4 @@ export class OnboardingStepperComponent implements OnInit { ngOnInit(): void { this.updateActiveAndCompletedSteps(); } - } From 5f91d3566a25250518f042504302ffc1e41cb078 Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Thu, 27 Jul 2023 18:10:14 +0000 Subject: [PATCH 05/47] [CodeFactor] Apply fixes --- .../onboarding/clone-settings/clone-settings.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 4a5a594b..e1d53b3a 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -18,7 +18,7 @@ import { EmployeeFieldMapping, ReimbursableExpensesObject, ProgressPhase } from export class CloneSettingsComponent implements OnInit { isLoading: boolean = true; - + cloneSettingsForm: FormGroup; autoMapEmployeeTypes: ExportSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); From 0a6f17a33de356bd7d12791670ddbb809b612f07 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Fri, 28 Jul 2023 00:45:06 +0530 Subject: [PATCH 06/47] test fix --- src/app/core/models/configuration/export-setting.model.ts | 8 ++------ .../services/configuration/export-setting.service.spec.ts | 6 ++++-- .../onboarding/clone-settings/clone-settings.component.ts | 4 ++-- .../employee-settings/employee-settings.fixture.ts | 3 ++- .../export-settings/export-settings.fixture.ts | 6 ++++-- .../configuration/qbo-connector/qbo-connector.fixture.ts | 3 ++- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/app/core/models/configuration/export-setting.model.ts b/src/app/core/models/configuration/export-setting.model.ts index 90f5f01c..b3c10062 100644 --- a/src/app/core/models/configuration/export-setting.model.ts +++ b/src/app/core/models/configuration/export-setting.model.ts @@ -6,9 +6,7 @@ import { SelectFormOption } from "../misc/select-form-option.model"; export type ExportSettingWorkspaceGeneralSettingPost = { reimbursable_expenses_object: ReimbursableExpensesObject | null, - corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject | null, - employee_field_mapping: EmployeeFieldMapping | null, - auto_map_employees: AutoMapEmployee | null, + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject | null } export interface ExportSettingWorkspaceGeneralSetting extends ExportSettingWorkspaceGeneralSettingPost { @@ -55,9 +53,7 @@ export class ExportSettingModel { }, workspace_general_settings: { reimbursable_expenses_object: exportSettingsForm.get('reimbursableExportType')?.value, - corporate_credit_card_expenses_object: exportSettingsForm.get('creditCardExportType')?.value, - auto_map_employees: exportSettingsForm.get('autoMapEmployees')?.value, - employee_field_mapping: exportSettingsForm.get('employee_field_mapping')?.value + corporate_credit_card_expenses_object: exportSettingsForm.get('creditCardExportType')?.value }, general_mappings: { bank_account: exportSettingsForm.get('bankAccount')?.value ? exportSettingsForm.get('bankAccount')?.value : emptyDestinationAttribute, diff --git a/src/app/core/services/configuration/export-setting.service.spec.ts b/src/app/core/services/configuration/export-setting.service.spec.ts index a0957492..a080e0e9 100644 --- a/src/app/core/services/configuration/export-setting.service.spec.ts +++ b/src/app/core/services/configuration/export-setting.service.spec.ts @@ -39,7 +39,8 @@ describe('ExportSettingService', () => { }, workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, - corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL, + is_simplify_report_closure_enabled: true }, general_mappings: { bank_account: { id: '1', name: 'Fyle' }, @@ -96,7 +97,8 @@ describe('ExportSettingService', () => { }, workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, - corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL, + is_simplify_report_closure_enabled: true }, general_mappings: { bank_account: { id: '1', name: 'Fyle' }, diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 4a5a594b..01ef2acf 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -18,7 +18,7 @@ import { EmployeeFieldMapping, ReimbursableExpensesObject, ProgressPhase } from export class CloneSettingsComponent implements OnInit { isLoading: boolean = true; - + cloneSettingsForm: FormGroup; autoMapEmployeeTypes: ExportSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); @@ -85,10 +85,10 @@ export class CloneSettingsComponent implements OnInit { this.cloneSettingsForm = this.formBuilder.group({ reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], autoMapEmployees: [this.cloneSettings.employee_mappings.workspace_general_settings.auto_map_employees], + employeeFieldMapping: [this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping], reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings.reimbursable_export_date_type], reimbursableExpenseState: [this.cloneSettings.export_settings.expense_group_settings.expense_state], reimbursableExportTypes: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], - employeeFieldMapping: [this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping], creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object], cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings.ccc_expense_state] }); diff --git a/src/app/shared/components/configuration/employee-settings/employee-settings.fixture.ts b/src/app/shared/components/configuration/employee-settings/employee-settings.fixture.ts index 3d3c69e8..66b10ec8 100644 --- a/src/app/shared/components/configuration/employee-settings/employee-settings.fixture.ts +++ b/src/app/shared/components/configuration/employee-settings/employee-settings.fixture.ts @@ -18,7 +18,8 @@ export const response1: ExportSettingGet = { }, workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, - corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL, + is_simplify_report_closure_enabled: true }, general_mappings: { bank_account: { id: '1', name: 'Fyle' }, diff --git a/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts b/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts index 797dcd4e..4f9a8fe9 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts @@ -149,7 +149,8 @@ export const exportResponse1: ExportSettingGet = { }, workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, - corporate_credit_card_expenses_object: null + corporate_credit_card_expenses_object: null, + is_simplify_report_closure_enabled: true }, workspace_id: 1, general_mappings: { @@ -190,7 +191,8 @@ export const exportResponse: ExportSettingGet = { }, workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, - corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL, + is_simplify_report_closure_enabled: true }, general_mappings: { bank_account: { id: '1', name: 'Fyle' }, diff --git a/src/app/shared/components/configuration/qbo-connector/qbo-connector.fixture.ts b/src/app/shared/components/configuration/qbo-connector/qbo-connector.fixture.ts index 59b0abaa..6cfc697d 100644 --- a/src/app/shared/components/configuration/qbo-connector/qbo-connector.fixture.ts +++ b/src/app/shared/components/configuration/qbo-connector/qbo-connector.fixture.ts @@ -45,7 +45,8 @@ export const exportResponse: ExportSettingGet = { }, workspace_general_settings: { reimbursable_expenses_object: null, - corporate_credit_card_expenses_object: null + corporate_credit_card_expenses_object: null, + is_simplify_report_closure_enabled: true }, general_mappings: { bank_account: { id: '1', name: 'Fyle' }, From 1ab311f5be88ca3b8c04f74c0951271a8ccfcab2 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Fri, 28 Jul 2023 16:48:50 +0530 Subject: [PATCH 07/47] use legecy mat dialog --- src/app/app.module.ts | 2 +- src/app/auth/auth.module.ts | 4 ++-- .../core/services/core/helper.service.spec.ts | 17 +++++++++++++---- src/app/core/services/core/helper.service.ts | 2 +- .../integration/onboarding/onboarding.module.ts | 4 ++-- .../confirmation-dialog.component.ts | 2 +- .../components/core/select/select.component.ts | 2 +- 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a9d28a6f..02f2334d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,7 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt'; import { MatLegacySnackBarModule as MatSnackBarModule, MAT_LEGACY_SNACK_BAR_DEFAULT_OPTIONS as MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/legacy-snack-bar'; -import { MatDialogModule } from '@angular/material/dialog'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; import * as Sentry from '@sentry/angular'; diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts index 0957de74..cd950b33 100644 --- a/src/app/auth/auth.module.ts +++ b/src/app/auth/auth.module.ts @@ -1,14 +1,14 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FlexLayoutModule } from '@angular/flex-layout'; -import { MatButtonModule } from '@angular/material/button'; +import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; import { LoginComponent } from './login/login.component'; import { LogoutComponent } from './logout/logout.component'; import { FyleCallbackComponent } from './fyle-callback/fyle-callback.component'; import { AuthComponent } from './auth.component'; import { AuthRoutingModule } from './auth-routing.module'; import { SharedLoginComponent } from './shared-login/shared-login.component'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; @NgModule({ diff --git a/src/app/core/services/core/helper.service.spec.ts b/src/app/core/services/core/helper.service.spec.ts index 29e84253..4b3d32fa 100644 --- a/src/app/core/services/core/helper.service.spec.ts +++ b/src/app/core/services/core/helper.service.spec.ts @@ -1,14 +1,23 @@ import { TestBed } from '@angular/core/testing'; -import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { FormControl, FormGroup } from '@angular/forms'; import { DefaultDestinationAttribute } from '../../models/db/general-mapping.model'; import { HelperService } from './helper.service'; +import { Router } from '@angular/router'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; describe('HelperService', () => { let service: HelperService; + const routerSpy = { navigate: jasmine.createSpy('navigate'), url: '/path' }; + let router: Router; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useValue: routerSpy } + ], + imports: [MatDialogModule] + }); service = TestBed.inject(HelperService); }); @@ -17,8 +26,8 @@ describe('HelperService', () => { }); it('clearSearchText service check', () => { - const form=new UntypedFormGroup({ - searchOption: new UntypedFormControl('fyle') + const form=new FormGroup({ + searchOption: new FormControl('fyle') }); service.clearSearchText(form); expect(form.controls.searchOption.value).toBeNull(); diff --git a/src/app/core/services/core/helper.service.ts b/src/app/core/services/core/helper.service.ts index 73a6bb65..f8165f36 100644 --- a/src/app/core/services/core/helper.service.ts +++ b/src/app/core/services/core/helper.service.ts @@ -6,8 +6,8 @@ import { DefaultDestinationAttribute } from '../../models/db/general-mapping.mod import { WindowService } from './window.service'; import { ConfirmationDialog } from '../../models/misc/confirmation-dialog.model'; import { ConfirmationDialogComponent } from 'src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component'; -import { MatDialog } from '@angular/material/dialog'; import { Router } from '@angular/router'; +import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog'; @Injectable({ providedIn: 'root' diff --git a/src/app/integration/onboarding/onboarding.module.ts b/src/app/integration/onboarding/onboarding.module.ts index f66b7090..e80598b7 100644 --- a/src/app/integration/onboarding/onboarding.module.ts +++ b/src/app/integration/onboarding/onboarding.module.ts @@ -11,8 +11,8 @@ import { MatLegacySlideToggleModule as MatSlideToggleModule } from '@angular/mat import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; import { MatMenuModule } from '@angular/material/menu'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; +import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; import { SharedModule } from 'src/app/shared/shared.module'; // Components diff --git a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts index 1b1b3e2c..ec3789bc 100644 --- a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts +++ b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts @@ -1,6 +1,6 @@ import { Component, Inject, OnInit } from '@angular/core'; import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatLegacyDialogRef as MatDialogRef, MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA } from '@angular/material/legacy-dialog'; @Component({ selector: 'app-confirmation-dialog', diff --git a/src/app/shared/components/core/select/select.component.ts b/src/app/shared/components/core/select/select.component.ts index 45dc25ca..89d6e48d 100644 --- a/src/app/shared/components/core/select/select.component.ts +++ b/src/app/shared/components/core/select/select.component.ts @@ -6,8 +6,8 @@ import { DestinationAttribute } from 'src/app/core/models/db/destination-attribu import { ClickEvent, CorporateCreditCardExpensesObject, ProgressPhase, ReimbursableExpensesObject, SimpleSearchPage, SimpleSearchType } from 'src/app/core/models/enum/enum.model'; import { HelperService } from 'src/app/core/services/core/helper.service'; import { PreviewDialogComponent } from '../../configuration/preview-dialog/preview-dialog.component'; -import { MatDialog } from '@angular/material/dialog'; import { TrackingService } from 'src/app/core/services/integration/tracking.service'; +import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog'; @Component({ selector: 'app-select', From 21a69146df10a4b2f9895e3b2a54baf898b6af70 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Fri, 28 Jul 2023 18:59:47 +0530 Subject: [PATCH 08/47] foix --- src/app/app.module.ts | 2 +- .../clone-setting.service.spec.ts | 28 ++++ .../employee-mapping.component.spec.ts | 3 +- .../clone-settings.component.spec.ts | 42 ++++- .../clone-settings/clone-settings.fixture.ts | 151 ++++++++++++++++++ ...tion-step-header-section.component.spec.ts | 3 +- .../core/select/select.component.spec.ts | 4 +- .../skip-export-log-table.component.spec.ts | 5 +- 8 files changed, 232 insertions(+), 6 deletions(-) create mode 100644 src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 02f2334d..7949b807 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -26,7 +26,7 @@ import { GlobalErrorHandler } from './app.errorhandling'; FormsModule, ReactiveFormsModule, MatSnackBarModule, - MatDialogModule + MatDialogModule, ], providers: [ { diff --git a/src/app/core/services/configuration/clone-setting.service.spec.ts b/src/app/core/services/configuration/clone-setting.service.spec.ts index e69de29b..64841903 100644 --- a/src/app/core/services/configuration/clone-setting.service.spec.ts +++ b/src/app/core/services/configuration/clone-setting.service.spec.ts @@ -0,0 +1,28 @@ +import { TestBed, getTestBed } from '@angular/core/testing'; + +import { CloneSettingService } from './clone-setting.service'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { environment } from 'src/environments/environment'; + +describe('CloneSettingService', () => { + let service: CloneSettingService; + let injector: TestBed; + let httpMock: HttpTestingController; + const API_BASE_URL = environment.api_url; + const workspace_id = 1; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + HttpClientTestingModule + ] + }); + injector = getTestBed(); + service = TestBed.inject(CloneSettingService); + httpMock = injector.inject(HttpTestingController); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/integration/main/mapping/employee-mapping/employee-mapping.component.spec.ts b/src/app/integration/main/mapping/employee-mapping/employee-mapping.component.spec.ts index 8c40d6d4..8d6105ba 100644 --- a/src/app/integration/main/mapping/employee-mapping/employee-mapping.component.spec.ts +++ b/src/app/integration/main/mapping/employee-mapping/employee-mapping.component.spec.ts @@ -15,6 +15,7 @@ import { mappingList } from 'src/app/shared/components/mapping/mapping-table/map import { environment } from 'src/environments/environment'; import { EmployeeMappingComponent } from './employee-mapping.component'; import { employeeMappingResponse, getEmployeeMappingResponse, getEmployeeMappingResponse1, mappinglist, MappingStatsResponse, qboData, qboData2, workspaceGeneralSettingResponse } from './employee-mapping.fixture'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; describe('EmployeeMappingComponent', () => { let component: EmployeeMappingComponent; @@ -44,7 +45,7 @@ describe('EmployeeMappingComponent', () => { getPageSize: () => 10 }; await TestBed.configureTestingModule({ - imports: [ FormsModule, ReactiveFormsModule, HttpClientModule, MatSnackBarModule, HttpClientTestingModule, NoopAnimationsModule ], + imports: [ FormsModule, ReactiveFormsModule, HttpClientModule, MatSnackBarModule, MatDialogModule, HttpClientTestingModule, NoopAnimationsModule ], declarations: [ EmployeeMappingComponent ], providers: [ { provide: WorkspaceService, useValue: service1 }, diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts index 75f34cde..0567bd7b 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -1,17 +1,57 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CloneSettingsComponent } from './clone-settings.component'; +import { HttpClientModule } from '@angular/common/http'; +import { MatDialogModule } from '@angular/material/dialog'; +import { FormBuilder } from '@angular/forms'; +import { Router } from '@angular/router'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { of } from 'rxjs'; +import { mockCloneSettingExist, mockCloneSettingsGet, mockGroupedDestinationAttribtues } from './clone-settings.fixture'; +import { CloneSettingService } from 'src/app/core/services/configuration/clone-setting.service'; +import { MappingService } from 'src/app/core/services/misc/mapping.service'; +import { expenseFieldresponse } from 'src/app/shared/components/configuration/import-settings/import-settings.fixture'; +import { getMappingSettingResponse } from 'src/app/shared/components/mapping/generic-mapping/generic-mapping.fixture'; +import { AdvancedSettingService } from 'src/app/core/services/configuration/advanced-setting.service'; +import { MatMenuModule } from '@angular/material/menu'; describe('CloneSettingsComponent', () => { let component: CloneSettingsComponent; let fixture: ComponentFixture; + const routerSpy = { navigate: jasmine.createSpy('navigate'), url: '/path' }; + let service1: any; + let service2: any; + let service3: any; beforeEach(async () => { + service1 = { + checkCloneSettingsExists: () => of(mockCloneSettingExist), + saveCloneSettings: () => of(mockCloneSettingsGet), + getCloneSettings: () => of(mockCloneSettingsGet) + }; + service2 = { + getGroupedXeroDestinationAttributes: () => of(mockGroupedDestinationAttribtues), + getFyleExpenseFields: () => of(expenseFieldresponse), + getXeroField: () => of(expenseFieldresponse), + getMappingSettings: () => of(getMappingSettingResponse) + }; await TestBed.configureTestingModule({ - declarations: [ CloneSettingsComponent ] + declarations: [ CloneSettingsComponent ], + imports: [ + HttpClientModule, MatDialogModule, MatSnackBarModule, MatMenuModule + ], + providers: [ + FormBuilder, + { provide: Router, useValue: routerSpy }, + { provide: CloneSettingService, useValue: service1 }, + { provide: MappingService, useValue: service2 }, + { provide: AdvancedSettingService, useValue: service3 } + ] }) .compileComponents(); + }); + beforeEach(() => { fixture = TestBed.createComponent(CloneSettingsComponent); component = fixture.componentInstance; fixture.detectChanges(); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts b/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts new file mode 100644 index 00000000..f1ae96d2 --- /dev/null +++ b/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts @@ -0,0 +1,151 @@ +import { CloneSetting, CloneSettingExist } from "src/app/core/models/configuration/clone-setting.model"; +import { GroupedDestinationAttribute } from "src/app/core/models/db/destination-attribute.model"; +import {AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, MappingDestinationField, MappingSourceField, ReimbursableExpensesObject } from "src/app/core/models/enum/enum.model"; + +export const mockCloneSettingExist: CloneSettingExist = { + is_available: true, + workspace_name: 'Fyle for Ashwin' +}; + +export const mockCloneSettingsGet: CloneSetting = { + workspace_id: 1, + export_settings: { + expense_group_settings: { + reimbursable_expense_group_fields: null, + corporate_credit_card_expense_group_fields: null, + expense_state: ExpenseState.PAID, + reimbursable_export_date_type: null, + ccc_expense_state: CCCExpenseState.PAID, + ccc_export_date_type: null + }, + workspace_general_settings: { + reimbursable_expenses_object: ReimbursableExpensesObject.BILL, + corporate_credit_card_expenses_object: null, + is_simplify_report_closure_enabled: false + }, + general_mappings: { + accounts_payable: { name: 'fyle', id: "1" }, + bank_account: { name: 'fyle', id: "1" }, + qbo_expense_account: { name: 'fyle', id: "1" }, + default_ccc_account: { name: 'fyle', id: "1" }, + default_ccc_vendor: { name: 'fyle', id: "1" }, + default_debit_card_account: { name: 'fyle', id: "1" } + }, + workspace_id: 1 + }, + import_settings: { + general_mappings: { + id: 1, + created_at: new Date(), + updated_at: new Date(), + workspace: 1, + accounts_payable: { name: 'fyle', id: "1" }, + bank_account: { name: 'fyle', id: "1" }, + qbo_expense_account: { name: 'fyle', id: "1" }, + default_ccc_account: { name: 'fyle', id: "1" }, + default_ccc_vendor: { name: 'fyle', id: "1" }, + default_debit_card_account: { name: 'fyle', id: "1" }, + default_tax_code: { name: 'fyle', id: "1" }, + bill_payment_account: { name: 'fyle', id: "1" } + }, + mapping_settings: [{ + id: 1, + created_at: new Date(), + updated_at: new Date(), + workspace: 1, + source_field: MappingSourceField.TAX_GROUP, + destination_field: MappingSourceField.PROJECT, + import_to_fyle: true, + is_custom: true, + source_placeholder: null + }, + { + id: 2, + created_at: new Date(), + updated_at: new Date(), + workspace: 1, + source_field: 'CUSTOM_FIELD', + destination_field: MappingDestinationField.CLASS, + import_to_fyle: false, + is_custom: true, + source_placeholder: null + }], + workspace_general_settings: { + auto_create_destination_entity: true, + auto_create_merchants_as_vendors: true, + memo_structure: [], + change_accounting_period: true, + charts_of_accounts: ['Expense'], + created_at: new Date("2022-04-27T11:07:17.694377Z"), + id: 1, + employee_field_mapping: EmployeeFieldMapping.EMPLOYEE, + import_vendors_as_merchants: true, + import_items: true, + je_single_credit_line: false, + import_categories: false, + import_projects: false, + import_tax_codes: false, + skip_cards_mapping: false, + sync_fyle_to_qbo_payments: false, + sync_qbo_to_fyle_payments: false, + updated_at: new Date("2022-04-28T12:48:39.150177Z"), + workspace: 1, + reimbursable_expenses_object: null, + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE, + auto_map_employees: AutoMapEmployee.EMAIL, + is_simplify_report_closure_enabled: true + }, + workspace_id: 1 + }, + advanced_settings: { + workspace_general_settings: { + sync_fyle_to_qbo_payments: true, + sync_qbo_to_fyle_payments: false, + auto_create_destination_entity: true, + change_accounting_period: true, + je_single_credit_line: true, + auto_create_merchants_as_vendors: true, + memo_structure: [] + }, + general_mappings: { + bill_payment_account: {id: '1', name: 'Fyle'} + }, + workspace_schedules: { + enabled: true, + interval_hours: 10, + emails_selected: [], + additional_email_options: [] + }, + workspace_id: 1 + }, + employee_mappings: { + workspace_id: 1, + workspace_general_settings: { + auto_map_employees: AutoMapEmployee.NAME, + employee_field_mapping: EmployeeFieldMapping.EMPLOYEE + } + } + }; + +export const mockGroupedDestinationAttribtues: GroupedDestinationAttribute = { + BANK_ACCOUNT: [{ + id: 3, + attribute_type: 'BANK_ACCOUNT', + display_name: "string", + value: "Fyle", + destination_id: "1", + active: true, + created_at: new Date(), + updated_at: new Date(), + workspace: 2, + detail: { + email: 'String', + fully_qualified_name: 'string' + } + }], + TAX_CODE: [], + CREDIT_CARD_ACCOUNT: [], + ACCOUNTS_PAYABLE: [], + VENDOR: [], + ACCOUNT: [] +}; diff --git a/src/app/shared/components/configuration/configuration-step-header-section/configuration-step-header-section.component.spec.ts b/src/app/shared/components/configuration/configuration-step-header-section/configuration-step-header-section.component.spec.ts index ad494f39..8ead9b1b 100644 --- a/src/app/shared/components/configuration/configuration-step-header-section/configuration-step-header-section.component.spec.ts +++ b/src/app/shared/components/configuration/configuration-step-header-section/configuration-step-header-section.component.spec.ts @@ -10,6 +10,7 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/ import { environment } from 'src/environments/environment'; import { WorkspaceService } from 'src/app/core/services/workspace/workspace.service'; import { OnboardingState } from 'src/app/core/models/enum/enum.model'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; describe('ConfigurationStepHeaderSectionComponent', () => { let component: ConfigurationStepHeaderSectionComponent; @@ -25,7 +26,7 @@ describe('ConfigurationStepHeaderSectionComponent', () => { dialogRefSpyObj.componentInstance = { body: '' }; // Attach componentInstance to the spy object... beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [RouterTestingModule, HttpClientModule, MatSnackBarModule, BrowserAnimationsModule, HttpClientTestingModule], + imports: [RouterTestingModule, HttpClientModule, MatSnackBarModule, MatDialogModule, BrowserAnimationsModule, HttpClientTestingModule], declarations: [ ConfigurationStepHeaderSectionComponent], providers: [ WorkspaceService, { provide: Router, diff --git a/src/app/shared/components/core/select/select.component.spec.ts b/src/app/shared/components/core/select/select.component.spec.ts index a4d24fa2..0f788ac0 100644 --- a/src/app/shared/components/core/select/select.component.spec.ts +++ b/src/app/shared/components/core/select/select.component.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { SelectComponent } from './select.component'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; describe('SelectComponent', () => { let component: SelectComponent; @@ -8,7 +9,8 @@ describe('SelectComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ SelectComponent ] + declarations: [ SelectComponent ], + imports: [MatDialogModule] }) .compileComponents(); diff --git a/src/app/shared/components/export-log/skip-export-log-table/skip-export-log-table.component.spec.ts b/src/app/shared/components/export-log/skip-export-log-table/skip-export-log-table.component.spec.ts index a48caaf5..577336c7 100644 --- a/src/app/shared/components/export-log/skip-export-log-table/skip-export-log-table.component.spec.ts +++ b/src/app/shared/components/export-log/skip-export-log-table/skip-export-log-table.component.spec.ts @@ -1,13 +1,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { SkipExportLogTableComponent } from './skip-export-log-table.component'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; describe('SkipExportLogTableComponent', () => { let component: SkipExportLogTableComponent; let fixture: ComponentFixture; beforeEach(async () => { + await TestBed.configureTestingModule({ - declarations: [ SkipExportLogTableComponent ] + declarations: [ SkipExportLogTableComponent ], + imports: [MatDialogModule] }) .compileComponents(); }); From 57f954bb064cd2ccc1b728233a0248d018c56ea7 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Sun, 30 Jul 2023 00:11:42 +0530 Subject: [PATCH 09/47] export settings --- src/app/app.module.ts | 2 +- src/app/core/core.module.ts | 5 +- .../configuration/clone-setting.model.ts | 11 +- .../configuration/import-setting.model.ts | 5 +- .../configuration/export-setting.service.ts | 23 +++ src/app/core/services/core/helper.service.ts | 2 +- .../clone-settings.component.html | 125 ++++++++++++---- .../clone-settings.component.ts | 138 ++++++++++++++++-- .../confirmation-dialog.component.ts | 2 +- .../core/select/select.component.ts | 6 +- src/app/shared/shared.module.ts | 1 + 11 files changed, 262 insertions(+), 58 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a9d28a6f..02f2334d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,7 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt'; import { MatLegacySnackBarModule as MatSnackBarModule, MAT_LEGACY_SNACK_BAR_DEFAULT_OPTIONS as MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/legacy-snack-bar'; -import { MatDialogModule } from '@angular/material/dialog'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; import * as Sentry from '@sentry/angular'; diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 339a9110..17d1d58d 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -1,12 +1,13 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; - +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; @NgModule({ declarations: [], imports: [ - CommonModule + CommonModule, + MatDialogModule ] }) export class CoreModule { } diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index 5c2e8194..290ee0cc 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -15,8 +15,8 @@ export type CloneSetting = { export type CloneSettingPost = { export_settings: ExportSettingPost, - import_settings: ImportSettingPost, - advanced_settings: AdvancedSettingPost, + // Import_settings: ImportSettingPost, + // Advanced_settings: AdvancedSettingPost, employee_mappings: EmployeeSettingPost } @@ -27,15 +27,16 @@ export type CloneSettingExist = { export class CloneSettingModel { static constructPayload(cloneSettingsForm: FormGroup, customMappingSettings: MappingSetting[]): CloneSettingPost { + const exportSettingPayload = ExportSettingModel.constructPayload(cloneSettingsForm); const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); - const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); + // Const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm); const cloneSettingPayload: CloneSettingPost = { export_settings: exportSettingPayload, - import_settings: importSettingPayload, - advanced_settings: advancedSettingPayload, + // Import_settings: importSettingPayload, + // Advanced_settings: advancedSettingPayload, employee_mappings: employeeMappingPayload }; diff --git a/src/app/core/models/configuration/import-setting.model.ts b/src/app/core/models/configuration/import-setting.model.ts index 832e47b8..e5d4896c 100644 --- a/src/app/core/models/configuration/import-setting.model.ts +++ b/src/app/core/models/configuration/import-setting.model.ts @@ -53,8 +53,9 @@ export interface ImportSettingFormOption extends SelectFormOption { export class ImportSettingModel { static constructPayload(importSettingsForm: UntypedFormGroup, customMappingSettings: MappingSetting[]): ImportSettingPost { + const emptyDestinationAttribute = {id: null, name: null}; - const employeeSettingPayload: ImportSettingPost = { + const importSettingPayload: ImportSettingPost = { workspace_general_settings: { import_categories: importSettingsForm.get('chartOfAccount')?.value, import_items: importSettingsForm.get('importItems')?.value, @@ -67,7 +68,7 @@ export class ImportSettingModel { }, mapping_settings: ImportSettingModel.formatMappingSettings(importSettingsForm.get('expenseFields')?.value, customMappingSettings) }; - return employeeSettingPayload; + return importSettingPayload; } static formatChartOfAccounts(chartOfAccounts: {enabled: boolean, name: string}[]): string[] { diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 98ac6201..2abb6969 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -5,6 +5,7 @@ import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, ReimbursableExpensesObject } from '../../models/enum/enum.model'; +import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; @Injectable({ @@ -25,6 +26,27 @@ export class ExportSettingService { return this.apiService.put(`/v2/workspaces/${this.workspaceService.getWorkspaceId()}/export_settings/`, exportSettingsPayload); } + createReimbursableExpenseWatcher(form: FormGroup, exportSettings: ExportSettingGet): void { + form.controls.reimbursableExpense.valueChanges.subscribe((isReimbursableExpenseSelected) => { + if (isReimbursableExpenseSelected) { + form.controls.expenseState.setValidators(Validators.required); + form.controls.expenseState.setValue(exportSettings.expense_group_settings?.expense_state ? exportSettings.expense_group_settings?.expense_state : ExpenseState.PAYMENT_PROCESSING); + form.controls.reimbursableExportType.setValidators(Validators.required); + form.controls.reimbursableExportGroup.setValidators(Validators.required); + form.controls.reimbursableExportDate.setValidators(Validators.required); + } else { + form.controls.expenseState.clearValidators(); + form.controls.reimbursableExportType.clearValidators(); + form.controls.reimbursableExportGroup.clearValidators(); + form.controls.reimbursableExportDate.clearValidators(); + form.controls.expenseState.setValue(null); + form.controls.reimbursableExportType.setValue(null); + form.controls.reimbursableExportGroup.setValue(null); + form.controls.reimbursableExportDate.setValue(null); + } + }); + } + getReimbursableExportTypeOptions(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { return { EMPLOYEE: [ @@ -160,3 +182,4 @@ export class ExportSettingService { ]; } } + diff --git a/src/app/core/services/core/helper.service.ts b/src/app/core/services/core/helper.service.ts index 73a6bb65..df36682d 100644 --- a/src/app/core/services/core/helper.service.ts +++ b/src/app/core/services/core/helper.service.ts @@ -6,8 +6,8 @@ import { DefaultDestinationAttribute } from '../../models/db/general-mapping.mod import { WindowService } from './window.service'; import { ConfirmationDialog } from '../../models/misc/confirmation-dialog.model'; import { ConfirmationDialogComponent } from 'src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component'; -import { MatDialog } from '@angular/material/dialog'; import { Router } from '@angular/router'; +import { MatLegacyDialog as MatDialog} from '@angular/material/legacy-dialog'; @Injectable({ providedIn: 'root' diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 9c2c556f..be31ff1e 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -2,6 +2,8 @@
+ +
@@ -53,7 +55,7 @@
@@ -94,43 +96,72 @@
In this section, you c
-

To which Expense Account should the Expense - be posted to?

+ src="assets/images/svgs/general/document-disabled.svg"> +

Mode of Export

+ matTooltip="Reimbursable expense in Fyle will be exported to Quickbooks" + matTooltipPosition="above" matTooltipClass="clone-settings">
-
-
- -
-
+ +
- +
-

Mode of Export

+ src="assets/images/svgs/general/employee-disabled.svg"> +

To which Account should the Expense + be posted to?

+ matTooltip="All Entries will be posted to this account." matTooltipPosition="above" + matTooltipClass="clone-settings">
- +
+
+ + +
+ +
+ + +
+ +
+ + +
+
@@ -143,16 +174,18 @@
In this section, you c + matTooltipPosition="above" + matTooltipClass="clone-settings">
- + [phase]="ProgressPhase.ONBOARDING"> +
@@ -170,16 +203,44 @@
In this section, you c
- + [phase]="ProgressPhase.ONBOARDING"> +
+ +
+ +
diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 390a711a..9cc811ec 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -1,13 +1,20 @@ import { Component } from '@angular/core'; -import { FormGroup, FormBuilder } from '@angular/forms'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { forkJoin } from 'rxjs'; -import { CloneSetting } from 'src/app/core/models/configuration/clone-setting.model'; +import { CloneSetting, CloneSettingModel } from 'src/app/core/models/configuration/clone-setting.model'; import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; import { DestinationAttribute } from 'src/app/core/models/db/destination-attribute.model'; import { CloneSettingService } from 'src/app/core/services/configuration/clone-setting.service'; import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; +import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'; + import { HelperService } from 'src/app/core/services/core/helper.service'; -import { EmployeeFieldMapping, ReimbursableExpensesObject, ProgressPhase } from 'src/app/core/models/enum/enum.model'; +import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase } from 'src/app/core/models/enum/enum.model'; +import { MappingService } from 'src/app/core/services/misc/mapping.service'; +import { TrackingService } from 'src/app/core/services/integration/tracking.service'; +import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; +import { Router } from '@angular/router'; +import { MappingSetting } from 'src/app/core/models/db/mapping-setting.model'; @Component({ @@ -18,7 +25,9 @@ import { EmployeeFieldMapping, ReimbursableExpensesObject, ProgressPhase } from export class CloneSettingsComponent { isLoading: boolean = true; - + + isSaveInProgress: boolean = false; + cloneSettingsForm: FormGroup; autoMapEmployeeTypes: ExportSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); @@ -31,6 +40,16 @@ export class CloneSettingsComponent { bankAccounts: DestinationAttribute[]; + cccAccounts: DestinationAttribute[]; + + accountsPayables: DestinationAttribute[]; + + vendors: DestinationAttribute[]; + + employeeFieldMapping: EmployeeFieldMapping; + + expenseAccounts: DestinationAttribute[]; + cloneSettings: CloneSetting; reimbursableExpenseStateOptions: ExportSettingFormOption[]; @@ -39,6 +58,8 @@ export class CloneSettingsComponent { cccExpenseExportOptions: ExportSettingFormOption[]; + mappingSettings: MappingSetting[]; + ProgressPhase = ProgressPhase; constructor( @@ -46,8 +67,52 @@ export class CloneSettingsComponent { public helperService: HelperService, private formBuilder: FormBuilder, private cloneSettingService: CloneSettingService, + private mappingService: MappingService, + private trackingService: TrackingService, + private snackBar: MatSnackBar, + private router: Router ) { } + resetConfiguraions(): void { + const data: ConfirmationDialog = { + title: 'Are you sure?', + contents: `By resetting the configuration, you will be configuring each setting individually from the beginning.

+ Would you like to continue?`, + primaryCtaText: 'Yes' + }; + this.trackingService.onClickEvent(ClickEvent.CLONE_SETTINGS_RESET, {page: OnboardingStep.CLONE_SETTINGS}); + + this.helperService.openDialogAndSetupRedirection(data, '/workspaces/onboarding/employee_settings'); + } + + navigateToPreviousStep(): void { + this.trackingService.onClickEvent(ClickEvent.CLONE_SETTINGS_BACK, {page: OnboardingStep.CLONE_SETTINGS}); + this.router.navigate([`/workspaces/onboarding/qbo_connector`]); + } + + save(): void { + if (this.cloneSettingsForm.valid) { + this.isSaveInProgress = true; + const customMappingSettings = this.mappingSettings.filter(setting => !setting.import_to_fyle); + const cloneSettingPayload = CloneSettingModel.constructPayload(this.cloneSettingsForm, customMappingSettings); + + this.cloneSettingService.saveCloneSettings(cloneSettingPayload).subscribe((response) => { + this.isSaveInProgress = false; + this.snackBar.open('Cloned settings successfully'); + // This.trackingService.onCloneSettingsSave({ + // OldState: this.cloneSettings, + // NewState: response + // }); + // This.trackSessionTime(); + + this.router.navigate([`/workspaces/onboarding/done`]); + }, () => { + this.isSaveInProgress = false; + this.snackBar.open('Failed to clone settings'); + }); + } + } + getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { return { EMPLOYEE: [ @@ -81,30 +146,81 @@ export class CloneSettingsComponent { }[employeeFieldMapping]; } + getExportType(exportType: ReimbursableExpensesObject): string { + const lowerCaseWord = exportType.toLowerCase(); + + return lowerCaseWord.charAt(0).toUpperCase() + lowerCaseWord.slice(1); + } + + showExpenseAccountField(): boolean { + return this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.EXPENSE; + } + + showBankAccountField(): boolean { + return this.employeeFieldMapping === EmployeeFieldMapping.EMPLOYEE && this.cloneSettingsForm.controls.reimbursableExportType.value && this.cloneSettingsForm.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; + } + + showReimbursableAccountsPayableField(): boolean { + return (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && this.employeeFieldMapping === EmployeeFieldMapping.VENDOR); + } + + private setGeneralMappingsValidator(): void { + if (this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object) { + this.cloneSettingsForm.controls.bankAccount.setValidators(Validators.required); + } + } + + private setCustomValidatorsAndWatchers(): void { + this.exportSettingService.createReimbursableExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); + + this.setGeneralMappingsValidator(); + } + private setupForm(): void { this.cloneSettingsForm = this.formBuilder.group({ - reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], - autoMapEmployees: [this.cloneSettings.employee_mappings.workspace_general_settings.auto_map_employees], + // Employee Mapping + employeeMapping: [this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping], + autoMapEmployee: [this.cloneSettings.employee_mappings.workspace_general_settings.auto_map_employees], + + // Export Settings + reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object ? true : false], reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings.reimbursable_export_date_type], reimbursableExpenseState: [this.cloneSettings.export_settings.expense_group_settings.expense_state], - reimbursableExportTypes: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], - employeeFieldMapping: [this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping], + reimbursableExportType: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object], - cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings.ccc_expense_state] + cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings.ccc_expense_state], + qboExpenseAccount: [this.cloneSettings.export_settings.general_mappings.qbo_expense_account], + accountsPayable: [this.cloneSettings.export_settings.general_mappings.accounts_payable], + bankAccount: [this.cloneSettings.export_settings.general_mappings.bank_account] }); + + this.setCustomValidatorsAndWatchers(); + this.cloneSettingsForm.markAllAsTouched(); + this.isLoading = false; } private setupPage(): void { + const destinationAttributes = ['BANK_ACCOUNT', 'CREDIT_CARD_ACCOUNT', 'ACCOUNTS_PAYABLE', 'VENDOR']; + forkJoin([ - this.cloneSettingService.getCloneSettings() + this.cloneSettingService.getCloneSettings(), + this.mappingService.getGroupedQBODestinationAttributes(destinationAttributes), + this.mappingService.getMappingSettings() ]).subscribe(responses => { this.cloneSettings = responses[0]; + this.employeeFieldMapping = this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping; + this.mappingSettings = responses[2].results; + this.cccExpenseExportOptions = this.exportSettingService.getcreditCardExportTypes(); + this.bankAccounts = responses[1].BANK_ACCOUNT; + this.cccAccounts = responses[1].CREDIT_CARD_ACCOUNT; + this.accountsPayables = responses[1].ACCOUNTS_PAYABLE; + this.vendors = responses[1].VENDOR; + this.expenseAccounts = this.bankAccounts.concat(this.cccAccounts); this.reimbursableExpenseStateOptions = this.exportSettingService.getReimbursableExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); this.cccExpenseStateOptions = this.exportSettingService.getCCCExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); this.reimbursableExportOptions = this.getReimbursableExportTypes(EmployeeFieldMapping.EMPLOYEE); - this.cccExpenseExportOptions = this.exportSettingService.getcreditCardExportTypes(); this.setupForm(); }); } diff --git a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts index 1b1b3e2c..7b1a9db1 100644 --- a/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts +++ b/src/app/shared/components/core/confirmation-dialog/confirmation-dialog.component.ts @@ -1,6 +1,6 @@ import { Component, Inject, OnInit } from '@angular/core'; import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA, MatLegacyDialogRef as MatDialogRef} from '@angular/material/legacy-dialog'; @Component({ selector: 'app-confirmation-dialog', diff --git a/src/app/shared/components/core/select/select.component.ts b/src/app/shared/components/core/select/select.component.ts index 45dc25ca..1da2c752 100644 --- a/src/app/shared/components/core/select/select.component.ts +++ b/src/app/shared/components/core/select/select.component.ts @@ -6,7 +6,7 @@ import { DestinationAttribute } from 'src/app/core/models/db/destination-attribu import { ClickEvent, CorporateCreditCardExpensesObject, ProgressPhase, ReimbursableExpensesObject, SimpleSearchPage, SimpleSearchType } from 'src/app/core/models/enum/enum.model'; import { HelperService } from 'src/app/core/services/core/helper.service'; import { PreviewDialogComponent } from '../../configuration/preview-dialog/preview-dialog.component'; -import { MatDialog } from '@angular/material/dialog'; +import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog'; import { TrackingService } from 'src/app/core/services/integration/tracking.service'; @Component({ @@ -50,8 +50,8 @@ export class SelectComponent implements OnInit { showQboExportPreview(reimbursableExportType: ReimbursableExpensesObject | null, creditCardExportType: CorporateCreditCardExpensesObject | null): void { const data = { - QboReimburse: reimbursableExportType, - QboCCC: creditCardExportType + qboReimburse: reimbursableExportType, + qboCCC: creditCardExportType }; this.trackingService.onClickEvent(ClickEvent.PREVIEW_QBO_EXPORT, {phase: this.phase, exportType: reimbursableExportType || creditCardExportType}); diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 17fd026f..bb32a98d 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -24,6 +24,7 @@ import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/ import { MatLegacyInputModule as MatInputModule } from '@angular/material/legacy-input'; import { MatDatepickerModule } from '@angular/material/datepicker'; + // Pipes import { TrimCharacterPipe } from './pipes/trim-character.pipe'; import { SearchPipe } from './pipes/search.pipe'; From 72064918958f4a0ef4466d3b323f8095c52f2a49 Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Sat, 29 Jul 2023 19:49:09 +0000 Subject: [PATCH 10/47] [CodeFactor] Apply fixes --- src/app/core/models/configuration/clone-setting.model.ts | 4 ++-- .../onboarding/clone-settings/clone-settings.component.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index b7feb50b..ced29ea8 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -29,8 +29,8 @@ export class CloneSettingModel { static constructPayload(cloneSettingsForm: FormGroup, customMappingSettings: MappingSetting[]): CloneSettingPost { const exportSettingPayload = ExportSettingModel.constructPayload(cloneSettingsForm); - // const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); - // const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); + // Const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); + // Const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm); const cloneSettingPayload: CloneSettingPost = { diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index be1f8ca1..4bfdc8e5 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -61,7 +61,7 @@ export class CloneSettingsComponent implements OnInit { mappingSettings: MappingSetting[]; ProgressPhase = ProgressPhase; - + reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = [ { label: 'Report', @@ -190,7 +190,7 @@ export class CloneSettingsComponent implements OnInit { this.setGeneralMappingsValidator(); } - + private getExportGroup(exportGroups: string[] | null): string { if (exportGroups) { const exportGroup = exportGroups.find((exportGroup) => { From 5b569bf93b0a7b9d24f39add81a0ec5633170f9e Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 31 Jul 2023 15:38:05 +0530 Subject: [PATCH 11/47] lint fix --- .../core/models/configuration/clone-setting.model.ts | 12 ++++++------ .../clone-settings/clone-settings.component.ts | 4 ++-- .../qbo-connector/qbo-connector.component.spec.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index b7feb50b..990d1330 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -15,8 +15,8 @@ export type CloneSetting = { export type CloneSettingPost = { export_settings: ExportSettingPost, - // Import_settings: ImportSettingPost, - // Advanced_settings: AdvancedSettingPost, + Import_settings: ImportSettingPost, + Advanced_settings: AdvancedSettingPost, employee_mappings: EmployeeSettingPost } @@ -29,14 +29,14 @@ export class CloneSettingModel { static constructPayload(cloneSettingsForm: FormGroup, customMappingSettings: MappingSetting[]): CloneSettingPost { const exportSettingPayload = ExportSettingModel.constructPayload(cloneSettingsForm); - // const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); - // const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); + const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); + const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm); const cloneSettingPayload: CloneSettingPost = { export_settings: exportSettingPayload, - // Import_settings: importSettingPayload, - // Advanced_settings: advancedSettingPayload, + Import_settings: importSettingPayload, + Advanced_settings: advancedSettingPayload, employee_mappings: employeeMappingPayload }; diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index be1f8ca1..4bfdc8e5 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -61,7 +61,7 @@ export class CloneSettingsComponent implements OnInit { mappingSettings: MappingSetting[]; ProgressPhase = ProgressPhase; - + reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = [ { label: 'Report', @@ -190,7 +190,7 @@ export class CloneSettingsComponent implements OnInit { this.setGeneralMappingsValidator(); } - + private getExportGroup(exportGroups: string[] | null): string { if (exportGroups) { const exportGroup = exportGroups.find((exportGroup) => { diff --git a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.spec.ts b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.spec.ts index b9e1d882..e8a411a3 100644 --- a/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.spec.ts +++ b/src/app/shared/components/configuration/qbo-connector/qbo-connector.component.spec.ts @@ -43,7 +43,7 @@ describe('QboConnectorComponent', () => { service = { getQBOCredentials: () => of(response), connectQBO: () => of(response), - disconnectQBOConnection: () => of(response), + disconnectQBOConnection: () => of(response) }; service2 = { getExportSettings: () => of(exportResponse) From f831fc851300e1391213886469a8ece0aafd7f6d Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 31 Jul 2023 16:06:50 +0530 Subject: [PATCH 12/47] lint test fix --- .../configuration/clone-setting.service.spec.ts | 11 ----------- .../clone-settings/clone-settings.component.ts | 6 ------ 2 files changed, 17 deletions(-) diff --git a/src/app/core/services/configuration/clone-setting.service.spec.ts b/src/app/core/services/configuration/clone-setting.service.spec.ts index 08e67e8f..83d8d82f 100644 --- a/src/app/core/services/configuration/clone-setting.service.spec.ts +++ b/src/app/core/services/configuration/clone-setting.service.spec.ts @@ -37,15 +37,4 @@ describe('CloneSettingService', () => { }); req.flush(mockCloneSettingsGet); }); - - it('should post Clone Settings', () => { - service.saveCloneSettings(mockCloneSettingsGet).subscribe(value => { - expect(value).toEqual(mockCloneSettingsGet); - }); - const req = httpMock.expectOne({ - method: 'PUT', - url: `${API_BASE_URL}/v2/workspaces/${workspace_id}/clone_settings/` - }); - req.flush(mockCloneSettingsGet); - }); }); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 4bfdc8e5..6b7772fe 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -114,12 +114,6 @@ export class CloneSettingsComponent implements OnInit { this.cloneSettingService.saveCloneSettings(cloneSettingPayload).subscribe((response) => { this.isSaveInProgress = false; this.snackBar.open('Cloned settings successfully'); - // This.trackingService.onCloneSettingsSave({ - // OldState: this.cloneSettings, - // NewState: response - // }); - // This.trackSessionTime(); - this.router.navigate([`/workspaces/onboarding/done`]); }, () => { this.isSaveInProgress = false; From c2d35d42eb1dca87b2284f2a14f79f3ec70cfef0 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 31 Jul 2023 16:40:20 +0530 Subject: [PATCH 13/47] f --- .../core/services/configuration/clone-setting.service.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/core/services/configuration/clone-setting.service.spec.ts b/src/app/core/services/configuration/clone-setting.service.spec.ts index 83d8d82f..a911aec4 100644 --- a/src/app/core/services/configuration/clone-setting.service.spec.ts +++ b/src/app/core/services/configuration/clone-setting.service.spec.ts @@ -4,13 +4,14 @@ import { CloneSettingService } from './clone-setting.service'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { mockCloneSettingsGet } from 'src/app/integration/onboarding/clone-settings/clone-settings.fixture'; import { environment } from 'src/environments/environment'; +import { WorkspaceService } from '../workspace/workspace.service'; describe('CloneSettingService', () => { let service: CloneSettingService; let injector: TestBed; let httpMock: HttpTestingController; const API_BASE_URL = environment.api_url; - const workspace_id = 1; + const workspace_id = environment.tests.workspaceId; beforeEach(() => { TestBed.configureTestingModule({ From 3c88a389496bda546f256748f3e32c93a683ce42 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Tue, 1 Aug 2023 14:23:49 +0530 Subject: [PATCH 14/47] ccc export settings changes --- .../configuration/clone-setting.model.ts | 12 +- .../configuration/export-setting.service.ts | 61 +++- .../clone-settings.component.html | 159 ++++++++++- .../clone-settings.component.scss | 6 +- .../clone-settings.component.ts | 265 ++++++++++++++---- .../export-settings.component.ts | 1 + .../core/select/select.component.html | 3 +- 7 files changed, 444 insertions(+), 63 deletions(-) diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index 990d1330..ced29ea8 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -15,8 +15,8 @@ export type CloneSetting = { export type CloneSettingPost = { export_settings: ExportSettingPost, - Import_settings: ImportSettingPost, - Advanced_settings: AdvancedSettingPost, + // Import_settings: ImportSettingPost, + // Advanced_settings: AdvancedSettingPost, employee_mappings: EmployeeSettingPost } @@ -29,14 +29,14 @@ export class CloneSettingModel { static constructPayload(cloneSettingsForm: FormGroup, customMappingSettings: MappingSetting[]): CloneSettingPost { const exportSettingPayload = ExportSettingModel.constructPayload(cloneSettingsForm); - const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); - const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); + // Const importSettingPayload = ImportSettingModel.constructPayload(cloneSettingsForm, customMappingSettings); + // Const advancedSettingPayload = AdvancedSettingModel.constructPayload(cloneSettingsForm); const employeeMappingPayload = EmployeeSettingModel.constructPayload(cloneSettingsForm); const cloneSettingPayload: CloneSettingPost = { export_settings: exportSettingPayload, - Import_settings: importSettingPayload, - Advanced_settings: advancedSettingPayload, + // Import_settings: importSettingPayload, + // Advanced_settings: advancedSettingPayload, employee_mappings: employeeMappingPayload }; diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 2abb6969..5ca68b96 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -4,7 +4,7 @@ import { ExportSettingGet, ExportSettingPost, ExportSettingFormOption } from '.. import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; -import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, ReimbursableExpensesObject } from '../../models/enum/enum.model'; +import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseGroupingFieldOption, ExpenseState, ExportDateType, ReimbursableExpensesObject } from '../../models/enum/enum.model'; import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; @@ -47,6 +47,29 @@ export class ExportSettingService { }); } + + createCreditCardExpenseWatcher(form: FormGroup, exportSettings: ExportSettingGet, isCreditCardExpenseSelected: boolean): void { + form.controls.creditCardExpense.valueChanges.subscribe((isCreditCardExpenseSelected) => { + if (isCreditCardExpenseSelected) { + form.controls.cccExpenseState.setValidators(Validators.required); + form.controls.cccExpenseState.setValue(exportSettings.expense_group_settings?.ccc_expense_state ? exportSettings.expense_group_settings?.ccc_expense_state : exportSettings.workspace_general_settings.is_simplify_report_closure_enabled ? CCCExpenseState.APPROVED: CCCExpenseState.PAYMENT_PROCESSING); + form.controls.creditCardExportType.setValidators(Validators.required); + form.controls.creditCardExportGroup.setValidators(Validators.required); + form.controls.creditCardExportDate.setValidators(Validators.required); + } else { + form.controls.cccExpenseState.clearValidators(); + form.controls.creditCardExportType.clearValidators(); + form.controls.creditCardExportGroup.clearValidators(); + form.controls.creditCardExportDate.clearValidators(); + form.controls.cccExpenseState.setValue(null); + form.controls.creditCardExportType.setValue(null); + form.controls.creditCardExportGroup.setValue(null); + form.controls.creditCardExportDate.setValue(null); + } + }); + } + + getReimbursableExportTypeOptions(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { return { EMPLOYEE: [ @@ -181,5 +204,41 @@ export class ExportSettingService { } ]; } + + exportSelectionValidator(exportSettingsForm: FormGroup, isCloneSetting: boolean = false): ValidatorFn { + return (control: AbstractControl): {[key: string]: object} | null => { + let forbidden = true; + if (exportSettingsForm) { + if (typeof control.value === 'boolean') { + if (control.value) { + forbidden = false; + } else { + if (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value) { + forbidden = false; + } + } + } else if ((control.value === ExpenseState.PAID || control.value === ExpenseState.PAYMENT_PROCESSING || control.value === CCCExpenseState.APPROVED) + && (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value)) { + forbidden = false; + } else if (isCloneSetting && (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value)) { + forbidden = false; + } + + if (!forbidden) { + control.parent?.get('expenseState')?.setErrors(null); + control.parent?.get('cccExpenseState')?.setErrors(null); + control.parent?.get('reimbursableExpense')?.setErrors(null); + control.parent?.get('creditCardExpense')?.setErrors(null); + return null; + } + } + + return { + forbiddenOption: { + value: control.value + } + }; + }; + } } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 63060122..0bd72fed 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -71,7 +71,7 @@

Export Settings

In this section, you can configure how - and when expenses from Fyle need to be exported to Xero
+ and when expenses from Fyle need to be exported to Quickbooks Online
@@ -91,7 +91,6 @@
In this section, you c
-
@@ -105,7 +104,7 @@
In this section, you c
+ [formControllerName]="'expenseState'" [phase]="ProgressPhase.ONBOARDING">
@@ -199,13 +198,165 @@
In this section, you c matTooltipPosition="above" matTooltipClass="clone-settings">
- + +
+
+
+
+

Corporate Card Expense

+ +
+ +
+ +
+
+
+ +
+
+
+ +

State of export

+ +
+ + +
+
+ +
+
+
+ +

Mode of Export

+ +
+ + +
+
+ +
+
+
+ +

How should the expenses be grouped?

+ +
+ + + +
+
+ +
+
+
+ +

Date of export

+ +
+ + + +
+
+ +
+
+
+ +

Set Default Credit Card Account as

+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+
+
+ +

Date of export

+ +
+ + + +
+
+
+
+
+
diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.scss b/src/app/integration/onboarding/clone-settings/clone-settings.component.scss index f5d320c9..a5878024 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.scss +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.scss @@ -69,7 +69,7 @@ font-size: 14px; } - &--xero-header { + &--qbo-header { padding-left: 14px; padding-right: 280px; } @@ -78,7 +78,7 @@ padding: 20px 0px 12px 32px; } - &--xero-field { + &--qbo-field { height: 34px; width: 304px; background: #F5F5F5; @@ -88,7 +88,7 @@ color: #2C304E; } - &--xero-field-text { + &--qbo-field-text { padding-left: 14px; } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 6b7772fe..9230089a 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl } from '@angular/forms'; import { forkJoin } from 'rxjs'; import { CloneSetting, CloneSettingModel } from 'src/app/core/models/configuration/clone-setting.model'; import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; @@ -9,7 +9,7 @@ import { ExportSettingService } from 'src/app/core/services/configuration/export import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'; import { HelperService } from 'src/app/core/services/core/helper.service'; -import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption } from 'src/app/core/models/enum/enum.model'; +import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption, CorporateCreditCardExpensesObject, ExportDateType, ExpenseState, CCCExpenseState } from 'src/app/core/models/enum/enum.model'; import { MappingService } from 'src/app/core/services/misc/mapping.service'; import { TrackingService } from 'src/app/core/services/integration/tracking.service'; import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; @@ -60,9 +60,11 @@ export class CloneSettingsComponent implements OnInit { mappingSettings: MappingSetting[]; + cccExpenseGroupingDateOptions: ExportSettingFormOption[]; + ProgressPhase = ProgressPhase; - reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = [ + expenseGroupingFieldOptions: ExportSettingFormOption[] = [ { label: 'Report', value: ExpenseGroupingFieldOption.CLAIM_NUMBER @@ -88,40 +90,6 @@ export class CloneSettingsComponent implements OnInit { private router: Router ) { } - resetConfiguraions(): void { - const data: ConfirmationDialog = { - title: 'Are you sure?', - contents: `By resetting the configuration, you will be configuring each setting individually from the beginning.

- Would you like to continue?`, - primaryCtaText: 'Yes' - }; - this.trackingService.onClickEvent(ClickEvent.CLONE_SETTINGS_RESET, {page: OnboardingStep.CLONE_SETTINGS}); - - this.helperService.openDialogAndSetupRedirection(data, '/workspaces/onboarding/employee_settings'); - } - - navigateToPreviousStep(): void { - this.trackingService.onClickEvent(ClickEvent.CLONE_SETTINGS_BACK, {page: OnboardingStep.CLONE_SETTINGS}); - this.router.navigate([`/workspaces/onboarding/qbo_connector`]); - } - - save(): void { - if (this.cloneSettingsForm.valid) { - this.isSaveInProgress = true; - const customMappingSettings = this.mappingSettings.filter(setting => !setting.import_to_fyle); - const cloneSettingPayload = CloneSettingModel.constructPayload(this.cloneSettingsForm, customMappingSettings); - - this.cloneSettingService.saveCloneSettings(cloneSettingPayload).subscribe((response) => { - this.isSaveInProgress = false; - this.snackBar.open('Cloned settings successfully'); - this.router.navigate([`/workspaces/onboarding/done`]); - }, () => { - this.isSaveInProgress = false; - this.snackBar.open('Failed to clone settings'); - }); - } - } - getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { return { EMPLOYEE: [ @@ -161,6 +129,17 @@ export class CloneSettingsComponent implements OnInit { return lowerCaseWord.charAt(0).toUpperCase() + lowerCaseWord.slice(1); } + setCreditCardExpenseGroupingDateOptions(creditCardExportGroup: ExpenseGroupingFieldOption): void { + if (creditCardExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { + this.cccExpenseGroupingDateOptions = this.reimbursableExpenseGroupingDateOptions.concat([{ + label: 'Posted Date', + value: ExportDateType.POSTED_AT + }]); + } else { + this.cccExpenseGroupingDateOptions = this.reimbursableExpenseGroupingDateOptions.concat(); + } + } + showExpenseAccountField(): boolean { return this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.EXPENSE; } @@ -173,15 +152,197 @@ export class CloneSettingsComponent implements OnInit { return (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && this.employeeFieldMapping === EmployeeFieldMapping.VENDOR); } + showCreditCardAccountField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value && this.cloneSettingsForm.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.BILL && this.cloneSettingsForm.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } + + showDebitCardAccountField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value && this.cloneSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } + + showDefaultCreditCardVendorField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + showCCCAccountsPayableField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + navigateToPreviousStep(): void { + this.trackingService.onClickEvent(ClickEvent.CLONE_SETTINGS_BACK, {page: OnboardingStep.CLONE_SETTINGS}); + this.router.navigate([`/workspaces/onboarding/qbo_connector`]); + } + + resetConfiguraions(): void { + const data: ConfirmationDialog = { + title: 'Are you sure?', + contents: `By resetting the configuration, you will be configuring each setting individually from the beginning.

+ Would you like to continue?`, + primaryCtaText: 'Yes' + }; + this.trackingService.onClickEvent(ClickEvent.CLONE_SETTINGS_RESET, {page: OnboardingStep.CLONE_SETTINGS}); + + this.helperService.openDialogAndSetupRedirection(data, '/workspaces/onboarding/employee_settings'); + } + + save(): void { + if (this.cloneSettingsForm.valid) { + this.isSaveInProgress = true; + const customMappingSettings = this.mappingSettings.filter(setting => !setting.import_to_fyle); + const cloneSettingPayload = CloneSettingModel.constructPayload(this.cloneSettingsForm, customMappingSettings); + + this.cloneSettingService.saveCloneSettings(cloneSettingPayload).subscribe((response) => { + this.isSaveInProgress = false; + this.snackBar.open('Cloned settings successfully'); + this.router.navigate([`/workspaces/onboarding/done`]); + }, () => { + this.isSaveInProgress = false; + this.snackBar.open('Failed to clone settings'); + }); + } + } + private setGeneralMappingsValidator(): void { + if (this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object) { this.cloneSettingsForm.controls.bankAccount.setValidators(Validators.required); } + + if (this.showBankAccountField()) { + this.cloneSettingsForm.controls.bankAccount.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.bankAccount.clearValidators(); + this.cloneSettingsForm.controls.bankAccount.updateValueAndValidity(); + } + + if (this.showCreditCardAccountField()) { + this.cloneSettingsForm.controls.defaultCCCAccount.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.defaultCCCAccount.clearValidators(); + this.cloneSettingsForm.controls.defaultCCCAccount.updateValueAndValidity(); + } + + if (this.showDebitCardAccountField()) { + this.cloneSettingsForm.controls.defaultDebitCardAccount.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.defaultDebitCardAccount.clearValidators(); + this.cloneSettingsForm.controls.defaultDebitCardAccount.updateValueAndValidity(); + + } + + if (this.showReimbursableAccountsPayableField() || this.showCCCAccountsPayableField()) { + this.cloneSettingsForm.controls.accountsPayable.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.accountsPayable.clearValidators(); + this.cloneSettingsForm.controls.accountsPayable.updateValueAndValidity(); + } + + if (this.showDefaultCreditCardVendorField()) { + this.cloneSettingsForm.controls.defaultCreditCardVendor.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.defaultCreditCardVendor.clearValidators(); + this.cloneSettingsForm.controls.defaultCreditCardVendor.updateValueAndValidity(); + } + + if (this.showExpenseAccountField()) { + this.cloneSettingsForm.controls.qboExpenseAccount.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.qboExpenseAccount.clearValidators(); + this.cloneSettingsForm.controls.qboExpenseAccount.updateValueAndValidity(); + } + } + + private restrictExpenseGroupSetting(creditCardExportType: string | null) : void { + if (creditCardExportType === CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE || creditCardExportType === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE) { + this.cloneSettingsForm.controls.creditCardExportGroup.setValue(ExpenseGroupingFieldOption.EXPENSE_ID); + this.cloneSettingsForm.controls.creditCardExportGroup.disable(); + + this.cccExpenseGroupingDateOptions = [{ + label: 'Posted Date', + value: ExportDateType.POSTED_AT + }, + { + label: 'Spend Date', + value: ExportDateType.SPENT_AT + }]; + } else { + this.cloneSettingsForm.controls.creditCardExportGroup.enable(); + this.setCreditCardExpenseGroupingDateOptions(this.cloneSettingsForm.controls.creditCardExportGroup.value); + } + } + + private createCreditCardExportTypeWatcher(): void { + this.restrictExpenseGroupSetting(this.cloneSettingsForm.controls.creditCardExpense.value); + this.cloneSettingsForm.controls.creditCardExportType.valueChanges.subscribe((creditCardExportType: string) => { + this.setGeneralMappingsValidator(); + this.restrictExpenseGroupSetting(creditCardExportType); + }); + } + + private createReimbursableExportTypeWatcher(): void { + this.cloneSettingsForm.controls.reimbursableExportType.valueChanges.subscribe(() => { + this.setGeneralMappingsValidator(); + }); + } + + private createReimbursableExportGroupWatcher(): void { + this.cloneSettingsForm.controls.reimbursableExportGroup.valueChanges.subscribe((reimbursableExportGroup: ExpenseGroupingFieldOption) => { + if (reimbursableExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { + this.reimbursableExpenseGroupingDateOptions.pop(); + } else { + if (this.reimbursableExpenseGroupingDateOptions.length !== 5) { + this.reimbursableExpenseGroupingDateOptions.push({ + label: 'Last Spend Date', + value: ExportDateType.LAST_SPENT_AT + }); + } + } + }); + } + + private createCreditCardExportGroupWatcher(): void { + this.cloneSettingsForm.controls.creditCardExportGroup.valueChanges.subscribe((creditCardExportGroup: ExpenseGroupingFieldOption) => { + if (creditCardExportGroup && creditCardExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { + this.cccExpenseGroupingDateOptions = this.cccExpenseGroupingDateOptions.filter((option) => { + return option.value !== ExportDateType.LAST_SPENT_AT; + }); + this.setCreditCardExpenseGroupingDateOptions(creditCardExportGroup); + } else { + const lastSpentAt = this.cccExpenseGroupingDateOptions.filter((option) => { + return option.value === ExportDateType.LAST_SPENT_AT; + }); + if (!lastSpentAt.length) { + this.cccExpenseGroupingDateOptions.push({ + label: 'Last Spend Date', + value: ExportDateType.LAST_SPENT_AT + }); + } + this.setCreditCardExpenseGroupingDateOptions(creditCardExportGroup); + } + }); + } + + private setupExportWatchers(): void { + this.cloneSettingsForm?.controls.reimbursableExpense?.setValidators((this.exportSettingService.exportSelectionValidator(this.cloneSettingsForm, true))); + this.cloneSettingsForm?.controls.creditCardExpense?.setValidators(this.exportSettingService.exportSelectionValidator(this.cloneSettingsForm, true)); } private setCustomValidatorsAndWatchers(): void { + this.exportSettingService.createReimbursableExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); + this.exportSettingService.createCreditCardExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings, true); + + // Export select fields + this.createReimbursableExportTypeWatcher(); + this.createCreditCardExportTypeWatcher(); + + // Goruping fields + this.createReimbursableExportGroupWatcher(); + this.createCreditCardExportGroupWatcher(); + + this.setupExportWatchers(); + this.setCreditCardExpenseGroupingDateOptions(this.cloneSettingsForm.controls.creditCardExportGroup.value); this.setGeneralMappingsValidator(); } @@ -199,20 +360,28 @@ export class CloneSettingsComponent implements OnInit { private setupForm(): void { this.cloneSettingsForm = this.formBuilder.group({ // Employee Mapping - employeeMapping: [this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping], - autoMapEmployee: [this.cloneSettings.employee_mappings.workspace_general_settings.auto_map_employees], + employeeMapping: [this.cloneSettings.employee_mappings.workspace_general_settings?.employee_field_mapping], + autoMapEmployee: [this.cloneSettings.employee_mappings.workspace_general_settings?.auto_map_employees], // Export Settings - reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object ? true : false], - reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings.reimbursable_export_date_type], - reimbursableExpenseState: [this.cloneSettings.export_settings.expense_group_settings.expense_state], - reimbursableExportType: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], - creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object], + reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings?.reimbursable_expenses_object ? true : false], + reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings?.reimbursable_export_date_type], + expenseState: [this.cloneSettings.export_settings.expense_group_settings?.expense_state], reimbursableExportGroup: [this.getExportGroup(this.cloneSettings.export_settings.expense_group_settings?.reimbursable_expense_group_fields)], - cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings.ccc_expense_state], - qboExpenseAccount: [this.cloneSettings.export_settings.general_mappings.qbo_expense_account], - accountsPayable: [this.cloneSettings.export_settings.general_mappings.accounts_payable], - bankAccount: [this.cloneSettings.export_settings.general_mappings.bank_account] + reimbursableExportType: [this.cloneSettings.export_settings.workspace_general_settings?.reimbursable_expenses_object], + + creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings?.corporate_credit_card_expenses_object ? true : false], + creditCardExportDate: [this.cloneSettings.export_settings.expense_group_settings?.ccc_export_date_type], + cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings?.ccc_expense_state], + creditCardExportGroup: [this.getExportGroup(this.cloneSettings.export_settings.expense_group_settings?.corporate_credit_card_expense_group_fields)], + creditCardExportType: [this.cloneSettings.export_settings.workspace_general_settings?.corporate_credit_card_expenses_object], + + bankAccount: [this.cloneSettings.export_settings.general_mappings?.bank_account?.id ? this.cloneSettings.export_settings.general_mappings.bank_account : null], + qboExpenseAccount: [this.cloneSettings.export_settings.general_mappings?.qbo_expense_account?.id ? this.cloneSettings.export_settings.general_mappings.qbo_expense_account : null], + defaultCCCAccount: [this.cloneSettings.export_settings.general_mappings?.default_ccc_account?.id ? this.cloneSettings.export_settings.general_mappings.default_ccc_account : null], + accountsPayable: [this.cloneSettings.export_settings.general_mappings?.accounts_payable?.id ? this.cloneSettings.export_settings.general_mappings.accounts_payable : null], + defaultCreditCardVendor: [this.cloneSettings.export_settings.general_mappings?.default_ccc_vendor?.id ? this.cloneSettings.export_settings.general_mappings.default_ccc_vendor : null], + defaultDebitCardAccount: [this.cloneSettings.export_settings.general_mappings?.default_debit_card_account?.id ? this.cloneSettings.export_settings.general_mappings.default_debit_card_account : null] }); this.setCustomValidatorsAndWatchers(); diff --git a/src/app/shared/components/configuration/export-settings/export-settings.component.ts b/src/app/shared/components/configuration/export-settings/export-settings.component.ts index 2dc71295..cb992ef3 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.component.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.component.ts @@ -283,6 +283,7 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { }); } + private exportSelectionValidator(): ValidatorFn { return (control: AbstractControl): {[key: string]: object} | null => { let forbidden = true; diff --git a/src/app/shared/components/core/select/select.component.html b/src/app/shared/components/core/select/select.component.html index 1a052075..46761f87 100644 --- a/src/app/shared/components/core/select/select.component.html +++ b/src/app/shared/components/core/select/select.component.html @@ -27,7 +27,8 @@ + [listName]="mandatoryErrorListName" [customErrorMessage]="customErrorMessage"> +

Click Date: Tue, 1 Aug 2023 17:37:30 +0530 Subject: [PATCH 15/47] fix comments --- .../configuration/export-setting.model.ts | 2 +- .../configuration/clone-setting.service.ts | 2 +- .../configuration/export-setting.service.ts | 35 ++++++- .../clone-settings.component.spec.ts | 2 +- .../clone-settings.component.ts | 96 ++++++------------- src/styles.scss | 12 +-- 6 files changed, 70 insertions(+), 79 deletions(-) diff --git a/src/app/core/models/configuration/export-setting.model.ts b/src/app/core/models/configuration/export-setting.model.ts index b3c10062..6db282a7 100644 --- a/src/app/core/models/configuration/export-setting.model.ts +++ b/src/app/core/models/configuration/export-setting.model.ts @@ -36,7 +36,7 @@ export type ExportSettingGet = { } export interface ExportSettingFormOption extends SelectFormOption { - value: ExpenseState | CCCExpenseState | ReimbursableExpensesObject | CorporateCreditCardExpensesObject | ExpenseGroupingFieldOption | ExportDateType | AutoMapEmployee | EmployeeFieldMapping | null; + value: ExpenseState | CCCExpenseState | ReimbursableExpensesObject | CorporateCreditCardExpensesObject | ExpenseGroupingFieldOption | ExportDateType; } export class ExportSettingModel { diff --git a/src/app/core/services/configuration/clone-setting.service.ts b/src/app/core/services/configuration/clone-setting.service.ts index 6804b2d5..2748a0dd 100644 --- a/src/app/core/services/configuration/clone-setting.service.ts +++ b/src/app/core/services/configuration/clone-setting.service.ts @@ -25,7 +25,7 @@ export class CloneSettingService { return this.apiService.get(`/v2/workspaces/${this.workspaceId}/clone_settings/`, {}); } - saveCloneSettings(cloneSettingsPayload: CloneSettingPost): Observable { + postCloneSettings(cloneSettingsPayload: CloneSettingPost): Observable { return this.apiService.put(`/v2/workspaces/${this.workspaceId}/clone_settings/`, cloneSettingsPayload); } } diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 2abb6969..7cf19a9e 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -4,8 +4,9 @@ import { ExportSettingGet, ExportSettingPost, ExportSettingFormOption } from '.. import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; -import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, ReimbursableExpensesObject } from '../../models/enum/enum.model'; +import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseGroupingFieldOption, ExpenseState, ExportDateType, ReimbursableExpensesObject } from '../../models/enum/enum.model'; import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; +import { EmployeeSettingFormOption } from '../../models/configuration/employee-setting.model'; @Injectable({ @@ -47,6 +48,34 @@ export class ExportSettingService { }); } + getExportGroup(exportGroups: string[] | null): string { + if (exportGroups) { + const exportGroup = exportGroups.find((exportGroup) => { + return exportGroup === ExpenseGroupingFieldOption.EXPENSE_ID || exportGroup === ExpenseGroupingFieldOption.CLAIM_NUMBER || exportGroup === ExpenseGroupingFieldOption.SETTLEMENT_ID; + }); + return exportGroup ? exportGroup : ExpenseGroupingFieldOption.CLAIM_NUMBER; + } + + return ''; + } + + getReimbursableExpenseGroupingFieldOptions() { + return [ + { + label: 'Report', + value: ExpenseGroupingFieldOption.CLAIM_NUMBER + }, + { + label: 'Payment', + value: ExpenseGroupingFieldOption.SETTLEMENT_ID + }, + { + label: 'Expense', + value: ExpenseGroupingFieldOption.EXPENSE_ID + } + ]; + } + getReimbursableExportTypeOptions(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { return { EMPLOYEE: [ @@ -101,7 +130,7 @@ export class ExportSettingService { ]; } - getEmployeeFieldMappingOptions(): ExportSettingFormOption[] { + getEmployeeFieldMappingOptions(): EmployeeSettingFormOption[] { return [ { label: 'Employees', @@ -114,7 +143,7 @@ export class ExportSettingService { ]; } - getAutoMapEmployeeOptions(): ExportSettingFormOption[] { + getAutoMapEmployeeOptions(): EmployeeSettingFormOption[] { return [ { label: 'None', diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts index 0218da95..0d1fdca0 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -27,7 +27,7 @@ describe('CloneSettingsComponent', () => { beforeEach(async () => { service1 = { checkCloneSettingsExists: () => of(mockCloneSettingExist), - saveCloneSettings: () => of(mockCloneSettingsGet), + postCloneSettings: () => of(mockCloneSettingsGet), getCloneSettings: () => of(mockCloneSettingsGet) }; service2 = { diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 6b7772fe..4a49e89d 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -15,6 +15,7 @@ import { TrackingService } from 'src/app/core/services/integration/tracking.serv import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; import { Router } from '@angular/router'; import { MappingSetting } from 'src/app/core/models/db/mapping-setting.model'; +import { EmployeeSettingFormOption } from 'src/app/core/models/configuration/employee-setting.model'; @Component({ @@ -30,13 +31,15 @@ export class CloneSettingsComponent implements OnInit { cloneSettingsForm: FormGroup; - autoMapEmployeeTypes: ExportSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); + autoMapEmployeeTypes: EmployeeSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); reimbursableExportOptions: ExportSettingFormOption[]; reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingDateOptions(); - employeeFieldMappingOptions: ExportSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); + employeeFieldMappingOptions: EmployeeSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); + + reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions() bankAccounts: DestinationAttribute[]; @@ -62,21 +65,6 @@ export class CloneSettingsComponent implements OnInit { ProgressPhase = ProgressPhase; - reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = [ - { - label: 'Report', - value: ExpenseGroupingFieldOption.CLAIM_NUMBER - }, - { - label: 'Payment', - value: ExpenseGroupingFieldOption.SETTLEMENT_ID - }, - { - label: 'Expense', - value: ExpenseGroupingFieldOption.EXPENSE_ID - } - ]; - constructor( private exportSettingService: ExportSettingService, public helperService: HelperService, @@ -111,7 +99,7 @@ export class CloneSettingsComponent implements OnInit { const customMappingSettings = this.mappingSettings.filter(setting => !setting.import_to_fyle); const cloneSettingPayload = CloneSettingModel.constructPayload(this.cloneSettingsForm, customMappingSettings); - this.cloneSettingService.saveCloneSettings(cloneSettingPayload).subscribe((response) => { + this.cloneSettingService.postCloneSettings(cloneSettingPayload).subscribe((response) => { this.isSaveInProgress = false; this.snackBar.open('Cloned settings successfully'); this.router.navigate([`/workspaces/onboarding/done`]); @@ -122,39 +110,6 @@ export class CloneSettingsComponent implements OnInit { } } - getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { - return { - EMPLOYEE: [ - { - label: 'Check', - value: ReimbursableExpensesObject.CHECK - }, - { - label: 'Expense', - value: ReimbursableExpensesObject.EXPENSE - }, - { - label: 'Journal Entry', - value: ReimbursableExpensesObject.JOURNAL_ENTRY - } - ], - VENDOR: [ - { - label: 'Bill', - value: ReimbursableExpensesObject.BILL - }, - { - label: 'Expense', - value: ReimbursableExpensesObject.EXPENSE - }, - { - label: 'Journal Entry', - value: ReimbursableExpensesObject.JOURNAL_ENTRY - } - ] - }[employeeFieldMapping]; - } - getExportType(exportType: ReimbursableExpensesObject): string { const lowerCaseWord = exportType.toLowerCase(); @@ -174,8 +129,25 @@ export class CloneSettingsComponent implements OnInit { } private setGeneralMappingsValidator(): void { - if (this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object) { + if (this.showBankAccountField()) { this.cloneSettingsForm.controls.bankAccount.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.bankAccount.clearValidators(); + this.cloneSettingsForm.controls.bankAccount.updateValueAndValidity(); + } + + if (this.showExpenseAccountField()) { + this.cloneSettingsForm.controls.qboExpenseAccount.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.qboExpenseAccount.clearValidators(); + this.cloneSettingsForm.controls.qboExpenseAccount.updateValueAndValidity(); + } + + if (this.showReimbursableAccountsPayableField()) { + this.cloneSettingsForm.controls.accountsPayable.setValidators(Validators.required); + } else { + this.cloneSettingsForm.controls.accountsPayable.clearValidators(); + this.cloneSettingsForm.controls.accountsPayable.updateValueAndValidity(); } } @@ -185,17 +157,6 @@ export class CloneSettingsComponent implements OnInit { this.setGeneralMappingsValidator(); } - private getExportGroup(exportGroups: string[] | null): string { - if (exportGroups) { - const exportGroup = exportGroups.find((exportGroup) => { - return exportGroup === ExpenseGroupingFieldOption.EXPENSE_ID || exportGroup === ExpenseGroupingFieldOption.CLAIM_NUMBER || exportGroup === ExpenseGroupingFieldOption.SETTLEMENT_ID; - }); - return exportGroup ? exportGroup : ExpenseGroupingFieldOption.CLAIM_NUMBER; - } - - return ''; - } - private setupForm(): void { this.cloneSettingsForm = this.formBuilder.group({ // Employee Mapping @@ -207,12 +168,13 @@ export class CloneSettingsComponent implements OnInit { reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings.reimbursable_export_date_type], reimbursableExpenseState: [this.cloneSettings.export_settings.expense_group_settings.expense_state], reimbursableExportType: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], - creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object], - reimbursableExportGroup: [this.getExportGroup(this.cloneSettings.export_settings.expense_group_settings?.reimbursable_expense_group_fields)], + creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object ? true : false], + reimbursableExportGroup: [this.exportSettingService.getExportGroup(this.cloneSettings.export_settings.expense_group_settings?.reimbursable_expense_group_fields)], cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings.ccc_expense_state], qboExpenseAccount: [this.cloneSettings.export_settings.general_mappings.qbo_expense_account], accountsPayable: [this.cloneSettings.export_settings.general_mappings.accounts_payable], - bankAccount: [this.cloneSettings.export_settings.general_mappings.bank_account] + bankAccount: [this.cloneSettings.export_settings.general_mappings.bank_account], + searchOption: [] }); this.setCustomValidatorsAndWatchers(); @@ -241,7 +203,7 @@ export class CloneSettingsComponent implements OnInit { this.expenseAccounts = this.bankAccounts.concat(this.cccAccounts); this.reimbursableExpenseStateOptions = this.exportSettingService.getReimbursableExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); this.cccExpenseStateOptions = this.exportSettingService.getCCCExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); - this.reimbursableExportOptions = this.getReimbursableExportTypes(EmployeeFieldMapping.EMPLOYEE); + this.reimbursableExportOptions = this.exportSettingService.getReimbursableExportTypeOptions(EmployeeFieldMapping.EMPLOYEE); this.setupForm(); }); } diff --git a/src/styles.scss b/src/styles.scss index cf86df58..6dcca97d 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -259,12 +259,6 @@ th.mat-header-cell:last-of-type { .mat-option.mat-active { background: none !important; - - &.clone-settings { - @extend .mat-tooltip, .above, .align-center; - white-space: normal !important; - margin-right: 6px !important; - } } .mat-form-field-appearance-outline.mat-focused .mat-form-field-outline-thick { @@ -342,6 +336,12 @@ th.mat-header-cell:last-of-type { transform: rotate(270deg); } } + + &.clone-settings { + @extend .mat-tooltip, .above, .align-center; + white-space: normal !important; + margin-right: 6px !important; + } &.left { overflow: initial; From 62f480938521742041661650175a2732c711e18c Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Tue, 1 Aug 2023 12:13:52 +0000 Subject: [PATCH 16/47] [CodeFactor] Apply fixes --- .../onboarding/clone-settings/clone-settings.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 4a49e89d..e361585e 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -39,7 +39,7 @@ export class CloneSettingsComponent implements OnInit { employeeFieldMappingOptions: EmployeeSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); - reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions() + reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions(); bankAccounts: DestinationAttribute[]; From e0f66fdc7c87806dab33745c0d13180498033bf3 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Tue, 1 Aug 2023 18:31:46 +0530 Subject: [PATCH 17/47] lint fix --- src/app/app.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7949b807..02f2334d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -26,7 +26,7 @@ import { GlobalErrorHandler } from './app.errorhandling'; FormsModule, ReactiveFormsModule, MatSnackBarModule, - MatDialogModule, + MatDialogModule ], providers: [ { From 236296a9b3946794ab96976fc6053646a31e2f2a Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Tue, 1 Aug 2023 18:38:43 +0530 Subject: [PATCH 18/47] df --- .../clone-advanced-settings.component.html | 1 - .../clone-advanced-settings.component.scss | 0 .../clone-advanced-settings.component.spec.ts | 23 ------------------- .../clone-advanced-settings.component.ts | 10 -------- .../clone-export-settings.component.html | 1 - .../clone-export-settings.component.scss | 0 .../clone-export-settings.component.spec.ts | 23 ------------------- .../clone-export-settings.component.ts | 10 -------- .../clone-import-settings.component.html | 1 - .../clone-import-settings.component.scss | 0 .../clone-import-settings.component.spec.ts | 23 ------------------- .../clone-import-settings.component.ts | 10 -------- 12 files changed, 102 deletions(-) delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html deleted file mode 100644 index 86d05cca..00000000 --- a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html +++ /dev/null @@ -1 +0,0 @@ -

clone-advanced-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts deleted file mode 100644 index 5a90fabf..00000000 --- a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CloneAdvancedSettingsComponent } from './clone-advanced-settings.component'; - -describe('CloneAdvancedSettingsComponent', () => { - let component: CloneAdvancedSettingsComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CloneAdvancedSettingsComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(CloneAdvancedSettingsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts deleted file mode 100644 index 8dfbfaca..00000000 --- a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-clone-advanced-settings', - templateUrl: './clone-advanced-settings.component.html', - styleUrls: ['./clone-advanced-settings.component.scss'] -}) -export class CloneAdvancedSettingsComponent { - -} diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html deleted file mode 100644 index f3325808..00000000 --- a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html +++ /dev/null @@ -1 +0,0 @@ -

clone-export-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts deleted file mode 100644 index 6229e2e6..00000000 --- a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CloneExportSettingsComponent } from './clone-export-settings.component'; - -describe('CloneExportSettingsComponent', () => { - let component: CloneExportSettingsComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CloneExportSettingsComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(CloneExportSettingsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts deleted file mode 100644 index 52f20f47..00000000 --- a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-clone-export-settings', - templateUrl: './clone-export-settings.component.html', - styleUrls: ['./clone-export-settings.component.scss'] -}) -export class CloneExportSettingsComponent { - -} diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html deleted file mode 100644 index c9238948..00000000 --- a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html +++ /dev/null @@ -1 +0,0 @@ -

clone-import-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts deleted file mode 100644 index 5f078b48..00000000 --- a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CloneImportSettingsComponent } from './clone-import-settings.component'; - -describe('CloneImportSettingsComponent', () => { - let component: CloneImportSettingsComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CloneImportSettingsComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(CloneImportSettingsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts deleted file mode 100644 index 233f684f..00000000 --- a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-clone-import-settings', - templateUrl: './clone-import-settings.component.html', - styleUrls: ['./clone-import-settings.component.scss'] -}) -export class CloneImportSettingsComponent { - -} From 3ca82d81d989b10f98e788827a90a0188d521267 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Tue, 1 Aug 2023 19:08:34 +0530 Subject: [PATCH 19/47] add fix --- src/app/shared/shared.module.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index bb32a98d..984feec5 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -65,9 +65,6 @@ import { MandatoryErrorMessageComponent } from './components/helpers/mandatory-e import { AddEmailDialogComponent } from './components/configuration/advanced-settings/add-email-dialog/add-email-dialog.component'; import { EmailMultiSelectFieldComponent } from './components/configuration/email-multi-select-field/email-multi-select-field.component'; import { SkipExportLogTableComponent } from './components/export-log/skip-export-log-table/skip-export-log-table.component'; -import { CloneAdvancedSettingsComponent } from './components/clone-settings/clone-advanced-settings/clone-advanced-settings.component'; -import { CloneExportSettingsComponent } from './components/clone-settings/clone-export-settings/clone-export-settings.component'; -import { CloneImportSettingsComponent } from './components/clone-settings/clone-import-settings/clone-import-settings.component'; import { ToggleComponent } from './components/core/toggle/toggle.component'; import { SelectComponent } from './components/core/select/select.component'; @@ -111,9 +108,6 @@ import { SelectComponent } from './components/core/select/select.component'; AddEmailDialogComponent, EmailMultiSelectFieldComponent, SkipExportLogTableComponent, - CloneAdvancedSettingsComponent, - CloneExportSettingsComponent, - CloneImportSettingsComponent, ToggleComponent, SelectComponent ], From 7d394fabd7c4d614bb29797b47609c5253530fcc Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Tue, 1 Aug 2023 21:12:39 +0530 Subject: [PATCH 20/47] fix --- .../configuration/export-setting.service.ts | 3 +- .../clone-settings.component.html | 73 ++++++++++--------- .../clone-settings.component.ts | 2 +- .../clone-advanced-settings.component.html | 1 - .../clone-advanced-settings.component.scss | 0 .../clone-advanced-settings.component.spec.ts | 23 ------ .../clone-advanced-settings.component.ts | 10 --- .../clone-export-settings.component.html | 1 - .../clone-export-settings.component.scss | 0 .../clone-export-settings.component.spec.ts | 23 ------ .../clone-export-settings.component.ts | 10 --- .../clone-import-settings.component.html | 1 - .../clone-import-settings.component.scss | 0 .../clone-import-settings.component.spec.ts | 23 ------ .../clone-import-settings.component.ts | 10 --- .../export-settings.component.ts | 1 - src/app/shared/shared.module.ts | 6 -- 17 files changed, 39 insertions(+), 148 deletions(-) delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts delete mode 100644 src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts delete mode 100644 src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts delete mode 100644 src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 5efd54c4..838bcfef 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -48,8 +48,7 @@ export class ExportSettingService { }); } - - createCreditCardExpenseWatcher(form: FormGroup, exportSettings: ExportSettingGet, isCreditCardExpenseSelected: boolean): void { + createCreditCardExpenseWatcher(form: FormGroup, exportSettings: ExportSettingGet): void { form.controls.creditCardExpense.valueChanges.subscribe((isCreditCardExpenseSelected) => { if (isCreditCardExpenseSelected) { form.controls.cccExpenseState.setValidators(Validators.required); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 0bd72fed..090e9054 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -205,25 +205,26 @@
In this section, you c
+ +
+
+
+

Corporate Card Expense

+ +
-
-
-
-
-

Corporate Card Expense

- -
- -
- -
+
+
+
+ +
@@ -331,28 +332,28 @@
In this section, you c [formControllerName]="'defaultCreditCardVendor'" [phase]="ProgressPhase.ONBOARDING">
- -
-
-
-
- -

Date of export

- -
- - - -
+
+
+ +
+
+
+
+ +

Select Accounts Payable Account

+
+ + +
diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 5d229bf5..5bd375d6 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -280,7 +280,7 @@ export class CloneSettingsComponent implements OnInit { private setCustomValidatorsAndWatchers(): void { this.exportSettingService.createReimbursableExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); - this.exportSettingService.createCreditCardExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings, true); + this.exportSettingService.createCreditCardExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); // Export select fields this.createReimbursableExportTypeWatcher(); diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html deleted file mode 100644 index 86d05cca..00000000 --- a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.html +++ /dev/null @@ -1 +0,0 @@ -

clone-advanced-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts deleted file mode 100644 index 5a90fabf..00000000 --- a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CloneAdvancedSettingsComponent } from './clone-advanced-settings.component'; - -describe('CloneAdvancedSettingsComponent', () => { - let component: CloneAdvancedSettingsComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CloneAdvancedSettingsComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(CloneAdvancedSettingsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts b/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts deleted file mode 100644 index 8dfbfaca..00000000 --- a/src/app/shared/components/clone-settings/clone-advanced-settings/clone-advanced-settings.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-clone-advanced-settings', - templateUrl: './clone-advanced-settings.component.html', - styleUrls: ['./clone-advanced-settings.component.scss'] -}) -export class CloneAdvancedSettingsComponent { - -} diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html deleted file mode 100644 index f3325808..00000000 --- a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.html +++ /dev/null @@ -1 +0,0 @@ -

clone-export-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts deleted file mode 100644 index 6229e2e6..00000000 --- a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CloneExportSettingsComponent } from './clone-export-settings.component'; - -describe('CloneExportSettingsComponent', () => { - let component: CloneExportSettingsComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CloneExportSettingsComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(CloneExportSettingsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts b/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts deleted file mode 100644 index 52f20f47..00000000 --- a/src/app/shared/components/clone-settings/clone-export-settings/clone-export-settings.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-clone-export-settings', - templateUrl: './clone-export-settings.component.html', - styleUrls: ['./clone-export-settings.component.scss'] -}) -export class CloneExportSettingsComponent { - -} diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html deleted file mode 100644 index c9238948..00000000 --- a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.html +++ /dev/null @@ -1 +0,0 @@ -

clone-import-settings works!

diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts deleted file mode 100644 index 5f078b48..00000000 --- a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CloneImportSettingsComponent } from './clone-import-settings.component'; - -describe('CloneImportSettingsComponent', () => { - let component: CloneImportSettingsComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CloneImportSettingsComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(CloneImportSettingsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts b/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts deleted file mode 100644 index 233f684f..00000000 --- a/src/app/shared/components/clone-settings/clone-import-settings/clone-import-settings.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-clone-import-settings', - templateUrl: './clone-import-settings.component.html', - styleUrls: ['./clone-import-settings.component.scss'] -}) -export class CloneImportSettingsComponent { - -} diff --git a/src/app/shared/components/configuration/export-settings/export-settings.component.ts b/src/app/shared/components/configuration/export-settings/export-settings.component.ts index cb992ef3..2dc71295 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.component.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.component.ts @@ -283,7 +283,6 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { }); } - private exportSelectionValidator(): ValidatorFn { return (control: AbstractControl): {[key: string]: object} | null => { let forbidden = true; diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index bb32a98d..984feec5 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -65,9 +65,6 @@ import { MandatoryErrorMessageComponent } from './components/helpers/mandatory-e import { AddEmailDialogComponent } from './components/configuration/advanced-settings/add-email-dialog/add-email-dialog.component'; import { EmailMultiSelectFieldComponent } from './components/configuration/email-multi-select-field/email-multi-select-field.component'; import { SkipExportLogTableComponent } from './components/export-log/skip-export-log-table/skip-export-log-table.component'; -import { CloneAdvancedSettingsComponent } from './components/clone-settings/clone-advanced-settings/clone-advanced-settings.component'; -import { CloneExportSettingsComponent } from './components/clone-settings/clone-export-settings/clone-export-settings.component'; -import { CloneImportSettingsComponent } from './components/clone-settings/clone-import-settings/clone-import-settings.component'; import { ToggleComponent } from './components/core/toggle/toggle.component'; import { SelectComponent } from './components/core/select/select.component'; @@ -111,9 +108,6 @@ import { SelectComponent } from './components/core/select/select.component'; AddEmailDialogComponent, EmailMultiSelectFieldComponent, SkipExportLogTableComponent, - CloneAdvancedSettingsComponent, - CloneExportSettingsComponent, - CloneImportSettingsComponent, ToggleComponent, SelectComponent ], From e592677113ef2a61661d1c37a247dc3153af684a Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Tue, 1 Aug 2023 15:45:18 +0000 Subject: [PATCH 21/47] [CodeFactor] Apply fixes --- .../onboarding/clone-settings/clone-settings.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 5bd375d6..9f93beb9 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -39,7 +39,7 @@ export class CloneSettingsComponent implements OnInit { employeeFieldMappingOptions: EmployeeSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); - expenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions() + expenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions(); bankAccounts: DestinationAttribute[]; From e05a557af2ba8d7d7e4434af2b8221c2e50744bd Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Tue, 1 Aug 2023 23:25:28 +0530 Subject: [PATCH 22/47] lint fix --- .../core/services/configuration/clone-setting.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/services/configuration/clone-setting.service.spec.ts b/src/app/core/services/configuration/clone-setting.service.spec.ts index 202d5dc3..0084e9c9 100644 --- a/src/app/core/services/configuration/clone-setting.service.spec.ts +++ b/src/app/core/services/configuration/clone-setting.service.spec.ts @@ -38,7 +38,7 @@ describe('CloneSettingService', () => { }); req.flush(mockCloneSettingsGet); }); - + it('should post Clone Settings', () => { service.postCloneSettings(mockCloneSettingsGet).subscribe(value => { expect(value).toEqual(mockCloneSettingsGet); From 52948183bfaefb08b6ae8a26fb5b55aee330d60e Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 2 Aug 2023 15:50:28 +0530 Subject: [PATCH 23/47] initial draft --- .../configuration/import-setting.service.ts | 28 +- src/app/core/services/misc/mapping.service.ts | 5 +- .../clone-settings.component.html | 138 +++++++ .../clone-settings.component.scss | 350 +++++++++--------- .../clone-settings.component.ts | 180 ++++++++- .../import-settings.component.scss | 129 ------- src/styles.scss | 140 ++++++- 7 files changed, 658 insertions(+), 312 deletions(-) diff --git a/src/app/core/services/configuration/import-setting.service.ts b/src/app/core/services/configuration/import-setting.service.ts index 63397c16..74c9bcd0 100644 --- a/src/app/core/services/configuration/import-setting.service.ts +++ b/src/app/core/services/configuration/import-setting.service.ts @@ -1,7 +1,9 @@ import { Injectable } from '@angular/core'; -import { ImportSettingPost } from '../../models/configuration/import-setting.model'; +import { ExpenseFieldsFormOption, ImportSettingPost } from '../../models/configuration/import-setting.model'; import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; +import { ExpenseField } from '../../models/misc/expense-field.model'; +import { MappingSetting } from '../../models/db/mapping-setting.model'; @Injectable({ providedIn: 'root' @@ -20,4 +22,28 @@ export class ImportSettingService { postImportSettings(exportSettingsPayload: ImportSettingPost){ return this.apiService.put(`/v2/workspaces/${this.workspaceService.getWorkspaceId()}/import_settings/`, exportSettingsPayload); } + + getQboExpenseFields(xeroAttributes: ExpenseField[], mappingSettings: MappingSetting[], isCloneSettings: boolean = false, fyleFields: string[] = []): ExpenseFieldsFormOption[] { + return xeroAttributes.map(attribute => { + const mappingSetting = mappingSettings.filter((mappingSetting: MappingSetting) => { + if (mappingSetting.destination_field.toUpperCase() === attribute.attribute_type) { + if (isCloneSettings) { + return fyleFields.includes(mappingSetting.source_field.toUpperCase()) ? mappingSetting : false; + } + + return mappingSetting; + } + + return false; + }); + + return { + source_field: mappingSetting.length > 0 ? mappingSetting[0].source_field : '', + destination_field: attribute.display_name, + import_to_fyle: mappingSetting.length > 0 ? mappingSetting[0].import_to_fyle : false, + disable_import_to_fyle: false, + source_placeholder: '' + }; + }); + } } diff --git a/src/app/core/services/misc/mapping.service.ts b/src/app/core/services/misc/mapping.service.ts index b4f28fa6..544b9a73 100644 --- a/src/app/core/services/misc/mapping.service.ts +++ b/src/app/core/services/misc/mapping.service.ts @@ -215,5 +215,8 @@ export class MappingService { } return undefined; } - + + getQboField(): Observable { + return this.apiService.get(`/workspaces/${this.workspaceId}/qbo/qbo_fields/`, {}); + } } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 090e9054..5843f079 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -5,6 +5,7 @@
+
@@ -62,6 +63,7 @@
+
@@ -360,6 +362,142 @@
In this section, you c
+ +
+
+
+ +
+
+

Import Settings

+
In this section, you can configure how + the dimensions you import from Quickbooks should be mapped in Fyle
+
+
+ +
+
+
+ Quickbooks Field +
+
+ Fyle Field +
+
+
+ +
+
+
+
+

+ Chart of Accounts +

+
+ + + +
+

+ Category +

+
+ +
+ View Accounts + +
+ +
+ + {{ chartOfAccountType.value.name }} + +
+
+
+
+ +
+
+ +
+
+
+
+
+

+ {{ expenseField.value.destination_field | titlecase }} +

+
+ + + + + + + {{ fyleExpenseField.split('_').join(' ') | titlecase }} + + + +
+ + +
+
+
+ +

or

+

+ Create a new field in Fyle +

+
+
+ +
+ +
+
+
+ +
+

Add Fields

+ +
+ + + + + +
+
+
@@ -466,7 +469,7 @@
In this section, you c class="clone-settings--coa-list sub-text-color">or

+ (click)="createExpenseField(expenseField.value.destination_field)"> Create a new field in Fyle

@@ -480,6 +483,55 @@
In this section, you c
+
+
+
+

+ Tax Code +

+
+ + + +
+

+ Tax Group +

+
+ + + + +
+ +

{{ option.value }}

+

{{ option.value }}

+ +
+
+
+
+ +
+
+
+
+
+ +
+
+

Add Fields

@@ -488,8 +540,8 @@
In this section, you c -
-
@@ -210,13 +208,12 @@
In this section, you c
- +

Corporate Card Expense

-
@@ -339,12 +336,11 @@
In this section, you c
- +
-
+

Select Accounts Payable Account

@@ -379,6 +375,49 @@
In this section, you c
+
+
+
+ +

Import Products/Services from QuickBooks Online +

+ +
+ +
+ + +
+
+
+ +
+
+
+ +

Import Vendors from QuickBooks Online

+ +
+ +
+ + +
+
+
+
@@ -389,10 +428,11 @@
In this section, you c
- +
-
+

@@ -430,7 +470,7 @@

In this section, you c class="clone-settings--delete-icon pointer" (click)="disableImportCoa()">
- +
In this section, you c class="selected-value-check-mark"> -
- - +
+ +
@@ -478,76 +523,92 @@
In this section, you c
+ class="clone-settings--delete-icon pointer" + (click)="deleteExpenseField(i, expenseField)">
- -
-
-
-

- Tax Code -

-
- +
+
+
+

+ Tax Code +

+
+ + -
-

- Tax Group -

-
+
+

+ Tax Group +

+
- - - -
- -

{{ option.value }}

-

{{ option.value }}

- -
+ + + +
+ +

+ {{ option.value }}

+

{{ option.value }}

+ +
+
+
+
+
- -
- -
-
-
-
-
- +
+ +
+
+ +
-
- -
+ +

Add Fields

- - -
+
From 0fddde64b2691a1e9d3f60b99a7fc60c1330dbc6 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Fri, 11 Aug 2023 12:44:19 +0530 Subject: [PATCH 36/47] asd --- .../configuration/import-setting.service.ts | 6 +- .../clone-settings.component.spec.ts | 98 ++++++++++++++++++- .../clone-settings.component.ts | 7 -- .../clone-settings/clone-settings.fixture.ts | 2 +- 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/src/app/core/services/configuration/import-setting.service.ts b/src/app/core/services/configuration/import-setting.service.ts index 7bce15aa..67aff13c 100644 --- a/src/app/core/services/configuration/import-setting.service.ts +++ b/src/app/core/services/configuration/import-setting.service.ts @@ -32,8 +32,8 @@ export class ImportSettingService { return this.apiService.put(`/v2/workspaces/${this.workspaceId}/import_settings/`, exportSettingsPayload); } - getQboExpenseFields(xeroAttributes: ExpenseField[], mappingSettings: MappingSetting[], isCloneSettings: boolean = false, fyleFields: string[] = []): ExpenseFieldsFormOption[] { - return xeroAttributes.map(attribute => { + getQboExpenseFields(qboAttributes: ExpenseField[], mappingSettings: MappingSetting[], isCloneSettings: boolean = false, fyleFields: string[] = []): ExpenseFieldsFormOption[] { + return qboAttributes.map(attribute => { const mappingSetting = mappingSettings.filter((mappingSetting: MappingSetting) => { if (mappingSetting.destination_field.toUpperCase() === attribute.attribute_type) { if (isCloneSettings) { @@ -42,10 +42,8 @@ export class ImportSettingService { return mappingSetting; } - return false; }); - return { source_field: mappingSetting.length > 0 ? mappingSetting[0].source_field : '', destination_field: attribute.display_name, diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts index f92c632c..d2192e63 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -2,7 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CloneSettingsComponent } from './clone-settings.component'; import { HttpClientModule } from '@angular/common/http'; -import { FormBuilder } from '@angular/forms'; +import { FormBuilder, UntypedFormBuilder, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { of } from 'rxjs'; import { mockCloneSettingExist, mockCloneSettingsGet, mockGroupedDestinationAttribtues } from './clone-settings.fixture'; @@ -14,12 +14,17 @@ import { AdvancedSettingService } from 'src/app/core/services/configuration/adva import { MatMenuModule } from '@angular/material/menu'; import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; import { MatLegacySnackBarModule as MatSnackBarModule } from '@angular/material/legacy-snack-bar'; -import { ReimbursableExpensesObject } from 'src/app/core/models/enum/enum.model'; +import { CorporateCreditCardExpensesObject, EmployeeFieldMapping, ReimbursableExpensesObject } from 'src/app/core/models/enum/enum.model'; +import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; describe('CloneSettingsComponent', () => { let component: CloneSettingsComponent; let fixture: ComponentFixture; + let router: Router; + let formbuilder: UntypedFormBuilder; + let exportSettingService: ExportSettingService; + let cloneSettingService: CloneSettingService; const routerSpy = { navigate: jasmine.createSpy('navigate'), url: '/path' }; let service1: any; let service2: any; @@ -57,6 +62,45 @@ describe('CloneSettingsComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(CloneSettingsComponent); component = fixture.componentInstance; + router = TestBed.inject(Router); + formbuilder = TestBed.inject(UntypedFormBuilder); + exportSettingService = TestBed.inject(ExportSettingService); + component.cloneSettings = mockCloneSettingsGet; + + component.cloneSettingsForm = formbuilder.group({ + employeeMapping: [component.cloneSettings.employee_mappings.workspace_general_settings?.employee_field_mapping, Validators.required], + autoMapEmployee: [component.cloneSettings.employee_mappings.workspace_general_settings?.auto_map_employees, Validators.nullValidator], + + // Export Settings + reimbursableExpense: [component.cloneSettings.export_settings.workspace_general_settings?.reimbursable_expenses_object ? true : false], + reimbursableExportDate: [component.cloneSettings.export_settings.expense_group_settings?.reimbursable_export_date_type], + expenseState: [component.cloneSettings.export_settings.expense_group_settings?.expense_state], + reimbursableExportGroup: [exportSettingService.getExportGroup(component.cloneSettings.export_settings.expense_group_settings?.reimbursable_expense_group_fields)], + reimbursableExportType: [component.cloneSettings.export_settings.workspace_general_settings?.reimbursable_expenses_object], + + creditCardExpense: [component.cloneSettings.export_settings.workspace_general_settings?.corporate_credit_card_expenses_object ? true : false], + creditCardExportDate: [component.cloneSettings.export_settings.expense_group_settings?.ccc_export_date_type], + cccExpenseState: [component.cloneSettings.export_settings.expense_group_settings?.ccc_expense_state], + creditCardExportGroup: [exportSettingService.getExportGroup(component.cloneSettings.export_settings.expense_group_settings?.corporate_credit_card_expense_group_fields)], + creditCardExportType: [component.cloneSettings.export_settings.workspace_general_settings?.corporate_credit_card_expenses_object], + + bankAccount: [component.cloneSettings.export_settings.general_mappings?.bank_account?.id ? component.cloneSettings.export_settings.general_mappings.bank_account : null], + qboExpenseAccount: [component.cloneSettings.export_settings.general_mappings?.qbo_expense_account?.id ? component.cloneSettings.export_settings.general_mappings.qbo_expense_account : null], + defaultCCCAccount: [component.cloneSettings.export_settings.general_mappings?.default_ccc_account?.id ? component.cloneSettings.export_settings.general_mappings.default_ccc_account : null], + accountsPayable: [component.cloneSettings.export_settings.general_mappings?.accounts_payable?.id ? component.cloneSettings.export_settings.general_mappings.accounts_payable : null], + defaultCreditCardVendor: [component.cloneSettings.export_settings.general_mappings?.default_ccc_vendor?.id ? component.cloneSettings.export_settings.general_mappings.default_ccc_vendor : null], + defaultDebitCardAccount: [component.cloneSettings.export_settings.general_mappings?.default_debit_card_account?.id ? component.cloneSettings.export_settings.general_mappings.default_debit_card_account : null], + searchOption: [], + + // Import Settings + chartOfAccount: [component.cloneSettings.import_settings.workspace_general_settings.import_categories], + importItems: [component.cloneSettings.import_settings.workspace_general_settings.import_items], + //chartOfAccountTypes: this.formBuilder.array(chartOfAccountTypeFormArray), + //expenseFields: this.formBuilder.array(expenseFieldsFormArray), + taxCode: [component.cloneSettings.import_settings.workspace_general_settings.import_tax_codes], + defaultTaxCode: [component.cloneSettings.import_settings.general_mappings?.default_tax_code?.id ? component.cloneSettings.import_settings.general_mappings.default_tax_code : null], + importVendorsAsMerchants: [component.cloneSettings.import_settings.workspace_general_settings.import_vendors_as_merchants] + }) fixture.detectChanges(); }); @@ -83,4 +127,54 @@ describe('CloneSettingsComponent', () => { component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(!component.cloneSettingsForm.controls.reimbursableExportGroup.value); expect((component as any).createReimbursableExportGroupWatcher()).toBeUndefined(); }); + + + it('showBankAccountField function check', () => { + component.employeeFieldMapping = EmployeeFieldMapping.EMPLOYEE; + component.cloneSettingsForm.controls.reimbursableExportType.patchValue(ReimbursableExpensesObject.BILL); + fixture.detectChanges(); + expect(component.showBankAccountField()).toBeTrue(); + }); + + it('showReimbursableAccountsPayableField function check', () => { + component.cloneSettingsForm.controls.employeeMapping.patchValue(EmployeeFieldMapping.VENDOR); + component.cloneSettingsForm.controls.reimbursableExportType.patchValue(ReimbursableExpensesObject.JOURNAL_ENTRY); + fixture.detectChanges(); + expect(component.showReimbursableAccountsPayableField()).toBeTrue(); + }); + + it('showCCCAccountsPayableField function check', () => { + component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.BILL); + fixture.detectChanges(); + expect(component.showCCCAccountsPayableField()).toBeTrue(); + }) + + it('showDefaultCreditCardVendorField function check', () => { + component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.BILL); + fixture.detectChanges(); + expect(component.showCCCAccountsPayableField()).toBeTrue(); + }) + + it('setGeneralMappingsValidator function check', () => { + component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); + fixture.detectChanges(); + expect((component as any).setGeneralMappingsValidator()).toBeUndefined(); + }); + + it('show') + + it('Save Function check', () => { + component.isSaveInProgress = false; + component.mappingSettings = []; + spyOn(cloneSettingService, 'postCloneSettings').and.callThrough() + + expect(component.save()).toBeUndefined(); + fixture.detectChanges(); + expect(cloneSettingService.postCloneSettings).toHaveBeenCalled(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/workspaces/onboarding/done']); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index b55af2f7..cf246a09 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -266,12 +266,6 @@ export class CloneSettingsComponent implements OnInit { }); } - private setupEmployeeMappingWatcher(): void { - this.cloneSettingsForm.controls.employeeMapping.valueChanges.subscribe((employeeMapping: EmployeeFieldMapping) => { - this.reimbursableExportOptions = this.exportSettingService.getReimbursableExportTypeOptions(employeeMapping); - }); - } - private createReimbursableExportGroupWatcher(): void { this.cloneSettingsForm.controls.reimbursableExportGroup.valueChanges.subscribe((reimbursableExportGroup: ExpenseGroupingFieldOption) => { if (reimbursableExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { @@ -368,7 +362,6 @@ export class CloneSettingsComponent implements OnInit { this.setGeneralMappingsValidator(); this.setupExpenseFieldWatcher(); - this.setupEmployeeMappingWatcher(); } createChartOfAccountField(type: string): UntypedFormGroup { diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts b/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts index f1ae96d2..98a87f82 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts @@ -1,4 +1,4 @@ -import { CloneSetting, CloneSettingExist } from "src/app/core/models/configuration/clone-setting.model"; +import { CloneSetting, CloneSettingExist, CloneSettingPost } from "src/app/core/models/configuration/clone-setting.model"; import { GroupedDestinationAttribute } from "src/app/core/models/db/destination-attribute.model"; import {AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, MappingDestinationField, MappingSourceField, ReimbursableExpensesObject } from "src/app/core/models/enum/enum.model"; From 9f936254efcbb32b05832b94c86b50c52e5d15dd Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Fri, 11 Aug 2023 16:04:01 +0530 Subject: [PATCH 37/47] add more tests --- .../clone-settings.component.spec.ts | 142 +++++++++++++++--- .../clone-settings.component.ts | 11 +- 2 files changed, 130 insertions(+), 23 deletions(-) diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts index d2192e63..f8b78cfe 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -1,5 +1,5 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; - +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { CloneSettingsComponent } from './clone-settings.component'; import { HttpClientModule } from '@angular/common/http'; import { FormBuilder, UntypedFormBuilder, Validators } from '@angular/forms'; @@ -14,8 +14,9 @@ import { AdvancedSettingService } from 'src/app/core/services/configuration/adva import { MatMenuModule } from '@angular/material/menu'; import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; import { MatLegacySnackBarModule as MatSnackBarModule } from '@angular/material/legacy-snack-bar'; -import { CorporateCreditCardExpensesObject, EmployeeFieldMapping, ReimbursableExpensesObject } from 'src/app/core/models/enum/enum.model'; +import { CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseGroupingFieldOption, ExportDateType, ReimbursableExpensesObject } from 'src/app/core/models/enum/enum.model'; import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; +import { ImportSettingService } from 'src/app/core/services/configuration/import-setting.service'; describe('CloneSettingsComponent', () => { @@ -24,6 +25,7 @@ describe('CloneSettingsComponent', () => { let router: Router; let formbuilder: UntypedFormBuilder; let exportSettingService: ExportSettingService; + let importSettingService: ImportSettingService; let cloneSettingService: CloneSettingService; const routerSpy = { navigate: jasmine.createSpy('navigate'), url: '/path' }; let service1: any; @@ -46,7 +48,7 @@ describe('CloneSettingsComponent', () => { await TestBed.configureTestingModule({ declarations: [ CloneSettingsComponent ], imports: [ - HttpClientModule, MatDialogModule, MatSnackBarModule, MatMenuModule + HttpClientModule, MatDialogModule, MatSnackBarModule, MatMenuModule, NoopAnimationsModule ], providers: [ FormBuilder, @@ -65,6 +67,7 @@ describe('CloneSettingsComponent', () => { router = TestBed.inject(Router); formbuilder = TestBed.inject(UntypedFormBuilder); exportSettingService = TestBed.inject(ExportSettingService); + importSettingService = TestBed.inject(ImportSettingService); component.cloneSettings = mockCloneSettingsGet; component.cloneSettingsForm = formbuilder.group({ @@ -95,12 +98,14 @@ describe('CloneSettingsComponent', () => { // Import Settings chartOfAccount: [component.cloneSettings.import_settings.workspace_general_settings.import_categories], importItems: [component.cloneSettings.import_settings.workspace_general_settings.import_items], - //chartOfAccountTypes: this.formBuilder.array(chartOfAccountTypeFormArray), - //expenseFields: this.formBuilder.array(expenseFieldsFormArray), + chartOfAccountTypes: formbuilder.array([]), + expenseFields: formbuilder.array([]), taxCode: [component.cloneSettings.import_settings.workspace_general_settings.import_tax_codes], defaultTaxCode: [component.cloneSettings.import_settings.general_mappings?.default_tax_code?.id ? component.cloneSettings.import_settings.general_mappings.default_tax_code : null], importVendorsAsMerchants: [component.cloneSettings.import_settings.workspace_general_settings.import_vendors_as_merchants] }) + + cloneSettingService = TestBed.inject(CloneSettingService); fixture.detectChanges(); }); @@ -115,16 +120,25 @@ describe('CloneSettingsComponent', () => { }); it('createCreditCardExportGroupWatcher function check', () => { - component.cloneSettingsForm.controls.creditCardExportGroup.patchValue(!component.cloneSettingsForm.controls.creditCardExportGroup.value); + component.cccExpenseGroupingDateOptions = [{ + 'label': 'Posted Date', + 'value': ExportDateType.POSTED_AT + }, + { + 'label': 'Spend Date', + 'value': ExportDateType.SPENT_AT + }] + + component.cloneSettingsForm.controls.creditCardExportGroup.patchValue(ExpenseGroupingFieldOption.EXPENSE_ID); expect((component as any).createCreditCardExportGroupWatcher()).toBeUndefined(); - component.cloneSettingsForm.controls.creditCardExpense.patchValue(!component.cloneSettingsForm.controls.creditCardExportGroup.value); + component.cloneSettingsForm.controls.creditCardExportGroup.patchValue(ExpenseGroupingFieldOption.CLAIM_NUMBER); expect((component as any).createCreditCardExportGroupWatcher()).toBeUndefined(); }); it('createReimbursableExportGroupWatcher function check', () => { - component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(!component.cloneSettingsForm.controls.reimbursableExportGroup.value); + component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(ExpenseGroupingFieldOption.EXPENSE_ID); expect((component as any).createReimbursableExportGroupWatcher()).toBeUndefined(); - component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(!component.cloneSettingsForm.controls.reimbursableExportGroup.value); + component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(ExpenseGroupingFieldOption.SETTLEMENT_ID); expect((component as any).createReimbursableExportGroupWatcher()).toBeUndefined(); }); @@ -160,21 +174,113 @@ describe('CloneSettingsComponent', () => { fixture.detectChanges(); expect((component as any).setGeneralMappingsValidator()).toBeUndefined(); }); - - it('show') - + it('Save Function check', () => { component.isSaveInProgress = false; - component.mappingSettings = []; + component.mappingSettings = [] + component.qboExpenseFields = [ + { + "source_field": "COST_CENTER", + "destination_field": "CUSTOMER", + "import_to_fyle": true, + "disable_import_to_fyle": false, + "source_placeholder": "" + } + ] + component.chartOfAccountTypesList = [ + 'Expense', 'Other Expense', 'Fixed Asset', 'Cost of Goods Sold', 'Current Liability', 'Equity', + 'Other Current Asset', 'Other Current Liability', 'Long Term Liability', 'Current Asset', 'Income', 'Other Income' + ]; spyOn(cloneSettingService, 'postCloneSettings').and.callThrough() - expect(component.save()).toBeUndefined(); fixture.detectChanges(); expect(cloneSettingService.postCloneSettings).toHaveBeenCalled(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/workspaces/onboarding/done']); }); - - it('should create', () => { - expect(component).toBeTruthy(); + + it('navigateToPreviousStep Function check', () => { + component.navigateToPreviousStep(); + expect(routerSpy.navigate).toHaveBeenCalledWith(([`/workspaces/onboarding/qbo_connector`])); + }) + + it('enableTaxImport Function check', () => { + component.enableTaxImport(); + expect(component.cloneSettingsForm.controls.taxCode.value).toBeTrue(); + }) + + it('disableImportTax Function check', () => { + component.disableImportTax(); + expect(component.cloneSettingsForm.controls.taxCode.value).toBeFalse(); + expect(component.cloneSettingsForm.controls.defaultTaxCode.value).toEqual(null); + }) + + it('disableImportCoa Function check', () => { + component.disableImportCoa(); + expect(component.cloneSettingsForm.controls.chartOfAccount.value).toBeFalse(); + }) + + it('restrictExpenseGroupSetting function check', () => { + expect((component as any).restrictExpenseGroupSetting('CREDIT CARD PURCHASE')).toBeUndefined(); + }); + + it('enableAccountImport function check', () => { + component.enableAccountImport(); + expect(component.cloneSettingsForm.controls.chartOfAccount.value).toBeTrue(); + }); + + it('setImportFields function check', () => { + component.enableAccountImport(); + expect(component.cloneSettingsForm.controls.chartOfAccount.value).toBeTrue(); + }); + + it('getQboExpenseFields function check', () => { + const qboAttributes = ['CUSTOMER']; + const mappingSettings = [ + { + "source_field": "COST_CENTER", + "destination_field": "CUSTOMER", + "import_to_fyle": true, + "is_custom": false, + "source_placeholder": null + } + ]; + const fyleFields = ['COST_CENTER', 'PROJECT']; + + expect((component as any).getQboExpenseFields(qboAttributes, mappingSettings, true, fyleFields)); + }); + + it('setImportFields function check', () => { + component.mappingSettings = []; + + const fyleFields = ['COST_CENTER', 'PROJECT']; + spyOn(importSettingService, 'getQboExpenseFields').and.returnValue([]); + expect((component as any).setImportFields(fyleFields)); + }); + + it('setupEmployeeMappingWatcher function check', () => { + component.cloneSettingsForm.controls.employeeMapping.patchValue(EmployeeFieldMapping.VENDOR); + expect((component as any).setupEmployeeMappingWatcher()).toBeUndefined(); + fixture.detectChanges(); + component.cloneSettingsForm.controls.employeeMapping.patchValue(EmployeeFieldMapping.EMPLOYEE); + expect((component as any).setupEmployeeMappingWatcher()).toBeUndefined(); + }); + + it('createReimbursableExportTypeWatcher function check', () => { + component.cloneSettingsForm.controls.reimbursableExportType.patchValue(ReimbursableExpensesObject.EXPENSE); + expect((component as any).createReimbursableExportTypeWatcher()).toBeUndefined(); + fixture.detectChanges(); + component.cloneSettingsForm.controls.reimbursableExportType.patchValue(ReimbursableExpensesObject.BILL); + expect((component as any).createReimbursableExportTypeWatcher()).toBeUndefined(); + }); + + it('createCreditCardExportTypeWatcher function check', () => { + component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); + expect((component as any).createCreditCardExportTypeWatcher()).toBeUndefined(); + fixture.detectChanges(); + component.cloneSettingsForm.controls.employeeMapping.patchValue(CorporateCreditCardExpensesObject.JOURNAL_ENTRY); + expect((component as any).createCreditCardExportTypeWatcher()).toBeUndefined(); + }); + + it('setCustomValidatorsAndWatchers function check', () => { + expect((component as any).setCustomValidatorsAndWatchers()).toBeUndefined(); }); }); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index cf246a09..e8b37027 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl, UntypedFormGroup, FormArray } from '@angular/forms'; +import { FormGroup, FormBuilder, Validators, AbstractControl, UntypedFormGroup, FormArray } from '@angular/forms'; import { forkJoin } from 'rxjs'; import { CloneSetting, CloneSettingModel } from 'src/app/core/models/configuration/clone-setting.model'; import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; @@ -9,7 +9,7 @@ import { ExportSettingService } from 'src/app/core/services/configuration/export import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'; import { HelperService } from 'src/app/core/services/core/helper.service'; -import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption, CorporateCreditCardExpensesObject, ExportDateType, ExpenseState, CCCExpenseState, MappingDestinationField, SimpleSearchType, SimpleSearchPage } from 'src/app/core/models/enum/enum.model'; +import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption, CorporateCreditCardExpensesObject, ExportDateType, MappingDestinationField, SimpleSearchType, SimpleSearchPage } from 'src/app/core/models/enum/enum.model'; import { MappingService } from 'src/app/core/services/misc/mapping.service'; import { TrackingService } from 'src/app/core/services/integration/tracking.service'; import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; @@ -412,6 +412,9 @@ export class CloneSettingsComponent implements OnInit { const chartOfAccountTypeFormArray = this.chartOfAccountTypesList.map((type) => this.createChartOfAccountField(type)); const expenseFieldsFormArray = this.importSettingService.getExpenseFieldsFormArray(this.qboExpenseFields, false); + + console.log('sdfsdf', this.chartOfAccountTypesList) + console.log('sdfsdf', this.qboExpenseFields) this.cloneSettingsForm = this.formBuilder.group({ // Employee Mapping @@ -456,17 +459,15 @@ export class CloneSettingsComponent implements OnInit { this.isLoading = false; } - private getQboExpenseFields(qboAttributes: string[], mappingSettings: MappingSetting[], isCloneSettings: boolean = false, fyleFields: string[] = []): ExpenseFieldsFormOption[] { + private getQboExpenseFields(qboAttributes: string[], mappingSettings: MappingSetting[], isCloneSettings: boolean = false, fyleFields: string[] = []): ExpenseFieldsFormOption[] { return qboAttributes.map(attribute => { const mappingSetting = mappingSettings.filter((mappingSetting: MappingSetting) => { if (mappingSetting.destination_field.toUpperCase() === attribute) { if (isCloneSettings) { return fyleFields.includes(mappingSetting.source_field.toUpperCase()) ? mappingSetting : false; } - return mappingSetting; } - return false; }); From 1bf7548ca2e5b8e578fc46ccde69c34b0748e8d6 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Fri, 11 Aug 2023 16:11:16 +0530 Subject: [PATCH 38/47] add fix --- .../clone-settings.component.spec.ts | 32 +++++++++---------- .../clone-settings.component.ts | 6 +--- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts index f8b78cfe..e0584bb6 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -103,8 +103,8 @@ describe('CloneSettingsComponent', () => { taxCode: [component.cloneSettings.import_settings.workspace_general_settings.import_tax_codes], defaultTaxCode: [component.cloneSettings.import_settings.general_mappings?.default_tax_code?.id ? component.cloneSettings.import_settings.general_mappings.default_tax_code : null], importVendorsAsMerchants: [component.cloneSettings.import_settings.workspace_general_settings.import_vendors_as_merchants] - }) - + }); + cloneSettingService = TestBed.inject(CloneSettingService); fixture.detectChanges(); }); @@ -127,7 +127,7 @@ describe('CloneSettingsComponent', () => { { 'label': 'Spend Date', 'value': ExportDateType.SPENT_AT - }] + }]; component.cloneSettingsForm.controls.creditCardExportGroup.patchValue(ExpenseGroupingFieldOption.EXPENSE_ID); expect((component as any).createCreditCardExportGroupWatcher()).toBeUndefined(); @@ -141,8 +141,8 @@ describe('CloneSettingsComponent', () => { component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(ExpenseGroupingFieldOption.SETTLEMENT_ID); expect((component as any).createReimbursableExportGroupWatcher()).toBeUndefined(); }); - - + + it('showBankAccountField function check', () => { component.employeeFieldMapping = EmployeeFieldMapping.EMPLOYEE; component.cloneSettingsForm.controls.reimbursableExportType.patchValue(ReimbursableExpensesObject.BILL); @@ -156,18 +156,18 @@ describe('CloneSettingsComponent', () => { fixture.detectChanges(); expect(component.showReimbursableAccountsPayableField()).toBeTrue(); }); - + it('showCCCAccountsPayableField function check', () => { component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.BILL); fixture.detectChanges(); expect(component.showCCCAccountsPayableField()).toBeTrue(); - }) - + }); + it('showDefaultCreditCardVendorField function check', () => { component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.BILL); fixture.detectChanges(); expect(component.showCCCAccountsPayableField()).toBeTrue(); - }) + }); it('setGeneralMappingsValidator function check', () => { component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); @@ -177,7 +177,7 @@ describe('CloneSettingsComponent', () => { it('Save Function check', () => { component.isSaveInProgress = false; - component.mappingSettings = [] + component.mappingSettings = []; component.qboExpenseFields = [ { "source_field": "COST_CENTER", @@ -186,12 +186,12 @@ describe('CloneSettingsComponent', () => { "disable_import_to_fyle": false, "source_placeholder": "" } - ] + ]; component.chartOfAccountTypesList = [ 'Expense', 'Other Expense', 'Fixed Asset', 'Cost of Goods Sold', 'Current Liability', 'Equity', 'Other Current Asset', 'Other Current Liability', 'Long Term Liability', 'Current Asset', 'Income', 'Other Income' ]; - spyOn(cloneSettingService, 'postCloneSettings').and.callThrough() + spyOn(cloneSettingService, 'postCloneSettings').and.callThrough(); expect(component.save()).toBeUndefined(); fixture.detectChanges(); expect(cloneSettingService.postCloneSettings).toHaveBeenCalled(); @@ -200,23 +200,23 @@ describe('CloneSettingsComponent', () => { it('navigateToPreviousStep Function check', () => { component.navigateToPreviousStep(); expect(routerSpy.navigate).toHaveBeenCalledWith(([`/workspaces/onboarding/qbo_connector`])); - }) + }); it('enableTaxImport Function check', () => { component.enableTaxImport(); expect(component.cloneSettingsForm.controls.taxCode.value).toBeTrue(); - }) + }); it('disableImportTax Function check', () => { component.disableImportTax(); expect(component.cloneSettingsForm.controls.taxCode.value).toBeFalse(); expect(component.cloneSettingsForm.controls.defaultTaxCode.value).toEqual(null); - }) + }); it('disableImportCoa Function check', () => { component.disableImportCoa(); expect(component.cloneSettingsForm.controls.chartOfAccount.value).toBeFalse(); - }) + }); it('restrictExpenseGroupSetting function check', () => { expect((component as any).restrictExpenseGroupSetting('CREDIT CARD PURCHASE')).toBeUndefined(); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index e8b37027..2ea9f980 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -412,10 +412,6 @@ export class CloneSettingsComponent implements OnInit { const chartOfAccountTypeFormArray = this.chartOfAccountTypesList.map((type) => this.createChartOfAccountField(type)); const expenseFieldsFormArray = this.importSettingService.getExpenseFieldsFormArray(this.qboExpenseFields, false); - - console.log('sdfsdf', this.chartOfAccountTypesList) - console.log('sdfsdf', this.qboExpenseFields) - this.cloneSettingsForm = this.formBuilder.group({ // Employee Mapping employeeMapping: [this.cloneSettings.employee_mappings.workspace_general_settings?.employee_field_mapping, Validators.required], @@ -459,7 +455,7 @@ export class CloneSettingsComponent implements OnInit { this.isLoading = false; } - private getQboExpenseFields(qboAttributes: string[], mappingSettings: MappingSetting[], isCloneSettings: boolean = false, fyleFields: string[] = []): ExpenseFieldsFormOption[] { + private getQboExpenseFields(qboAttributes: string[], mappingSettings: MappingSetting[], isCloneSettings: boolean = false, fyleFields: string[] = []): ExpenseFieldsFormOption[] { return qboAttributes.map(attribute => { const mappingSetting = mappingSettings.filter((mappingSetting: MappingSetting) => { if (mappingSetting.destination_field.toUpperCase() === attribute) { From dd1287c3cb162d7ad23502b2a9a9fa00044550eb Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 16 Aug 2023 13:57:39 +0530 Subject: [PATCH 39/47] comments resolved --- .../configuration/clone-setting.service.ts | 1 + .../export-setting.service.spec.ts | 13 +++ .../configuration/export-setting.service.ts | 107 ++++++++++++------ .../clone-settings.component.html | 47 ++++---- .../clone-settings.component.ts | 63 ++--------- .../export-settings.component.spec.ts | 9 +- .../export-settings.component.ts | 52 +-------- 7 files changed, 127 insertions(+), 165 deletions(-) diff --git a/src/app/core/services/configuration/clone-setting.service.ts b/src/app/core/services/configuration/clone-setting.service.ts index 2748a0dd..df8f4d8e 100644 --- a/src/app/core/services/configuration/clone-setting.service.ts +++ b/src/app/core/services/configuration/clone-setting.service.ts @@ -3,6 +3,7 @@ import { Observable } from 'rxjs'; import { CloneSetting, CloneSettingExist, CloneSettingPost } from '../../models/configuration/clone-setting.model'; import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; +import { FormControl, FormGroup } from '@angular/forms'; @Injectable({ providedIn: 'root' diff --git a/src/app/core/services/configuration/export-setting.service.spec.ts b/src/app/core/services/configuration/export-setting.service.spec.ts index 3e42cd96..a2b353cf 100644 --- a/src/app/core/services/configuration/export-setting.service.spec.ts +++ b/src/app/core/services/configuration/export-setting.service.spec.ts @@ -173,6 +173,19 @@ describe('ExportSettingService', () => { expect((service as any).createCreditCardExpenseWatcher(form, exportResponse)).toBeUndefined(); }); + it('setGeneralMappingsValidator function check', () => { + const form = formbuilder.group({ + creditCardExpense: false, + cccExpenseState: ExpenseState.PAID, + creditCardExportType: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE, + creditCardExportGroup: ExpenseGroupingFieldOption.EXPENSE_ID, + creditCardExportDate: ExportDateType.POSTED_AT + }); + form.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); + fixture.detectChanges(); + expect((service as any).setGeneralMappingsValidator()).toBeUndefined(); + }); + it('function check', () => { expect((service as any).getExportGroup([ExpenseGroupingFieldOption.EXPENSE_ID])).toEqual('expense_id'); expect((service as any).getExportGroup(null)).toEqual(''); diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 0ef3ffdd..eaf6f21c 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -151,40 +151,6 @@ export class ExportSettingService { ]; } - getEmployeeFieldMappingOptions(): EmployeeSettingFormOption[] { - return [ - { - label: 'Employees', - value: EmployeeFieldMapping.EMPLOYEE - }, - { - label: 'Vendor', - value: EmployeeFieldMapping.VENDOR - } - ]; - } - - getAutoMapEmployeeOptions(): EmployeeSettingFormOption[] { - return [ - { - label: 'None', - value: null - }, - { - label: 'Employee name on Fyle to contact name on Quickbooks', - value: AutoMapEmployee.NAME - }, - { - label: 'Employee email on Fyle to contact email on Quickbooks', - value: AutoMapEmployee.EMAIL - }, - { - label: 'Fyle Employee Code to QuickBooks Online Display name on Quickbooks', - value: AutoMapEmployee.EMPLOYEE_CODE - } - ]; - } - getReimbursableExpenseGroupingDateOptions(): ExportSettingFormOption[] { return [ { @@ -271,5 +237,78 @@ export class ExportSettingService { }; }; } + + showExpenseAccountField(form: FormGroup): boolean { + return form.controls.reimbursableExportType.value === ReimbursableExpensesObject.EXPENSE; + } + + showBankAccountField(form: FormGroup): boolean { + return form.value.employeeMapping === EmployeeFieldMapping.EMPLOYEE && form.controls.reimbursableExportType.value && form.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; + } + + showReimbursableAccountsPayableField(form: FormGroup): boolean { + return (form.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (form.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && form.value.employeeMapping === EmployeeFieldMapping.VENDOR); + } + + showCreditCardAccountField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value && form.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.BILL && form.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } + + showDebitCardAccountField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value && form.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } + + showDefaultCreditCardVendorField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + showCCCAccountsPayableField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + setGeneralMappingsValidator(form: FormGroup): void { + if (this.showBankAccountField(form)) { + form.controls.bankAccount.setValidators(Validators.required); + } else { + form.controls.bankAccount.clearValidators(); + form.controls.bankAccount.updateValueAndValidity(); + } + + if (this.showCreditCardAccountField(form)) { + form.controls.defaultCCCAccount.setValidators(Validators.required); + } else { + form.controls.defaultCCCAccount.clearValidators(); + form.controls.defaultCCCAccount.updateValueAndValidity(); + } + + if (this.showDebitCardAccountField(form)) { + form.controls.defaultDebitCardAccount.setValidators(Validators.required); + } else { + form.controls.defaultDebitCardAccount.clearValidators(); + form.controls.defaultDebitCardAccount.updateValueAndValidity(); + + } + + if (this.showReimbursableAccountsPayableField(form) || this.showCCCAccountsPayableField(form)) { + form.controls.accountsPayable.setValidators(Validators.required); + } else { + form.controls.accountsPayable.clearValidators(); + form.controls.accountsPayable.updateValueAndValidity(); + } + + if (this.showDefaultCreditCardVendorField(form)) { + form.controls.defaultCreditCardVendor.setValidators(Validators.required); + } else { + form.controls.defaultCreditCardVendor.clearValidators(); + form.controls.defaultCreditCardVendor.updateValueAndValidity(); + } + + if (this.showExpenseAccountField(form)) { + form.controls.qboExpenseAccount.setValidators(Validators.required); + } else { + form.controls.qboExpenseAccount.clearValidators(); + form.controls.qboExpenseAccount.updateValueAndValidity(); + } + } } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 090e9054..86338157 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -14,7 +14,7 @@

Employee Mappings

- In this section, you can configure how map fyle employees to Quickbooks Vendor / Employee + In this section, you can configure how map fyle employees to QuickBooks Online Vendor / Employee
@@ -26,14 +26,15 @@
src="assets/images/svgs/general/calendar-disabled.svg">

Employee Field Mapping

@@ -46,14 +47,14 @@
src="assets/images/svgs/general/employee-disabled.svg">

Auto Map Employee

@@ -71,7 +72,7 @@

Export Settings

In this section, you can configure how - and when expenses from Fyle need to be exported to Quickbooks Online
+ and when expenses from Fyle need to be exported to QuickBooks Online
@@ -79,7 +80,7 @@
In this section, you c

Reimbursable Expense

@@ -117,12 +118,12 @@
In this section, you c

Mode of Export

@@ -175,12 +176,12 @@
In this section, you c

Date of export

@@ -194,7 +195,7 @@
In this section, you c

How should the expenses be grouped?

@@ -212,7 +213,7 @@
In this section, you c

Corporate Card Expense

@@ -251,12 +252,12 @@
In this section, you c

Mode of Export

@@ -270,7 +271,7 @@
In this section, you c

How should the expenses be grouped?

@@ -289,12 +290,12 @@
In this section, you c

Date of export

@@ -308,7 +309,7 @@
In this section, you c

Set Default Credit Card Account as

@@ -345,7 +346,7 @@
In this section, you c

Select Accounts Payable Account

diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 1f1be209..462f460d 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -16,6 +16,7 @@ import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog import { Router } from '@angular/router'; import { MappingSetting } from 'src/app/core/models/db/mapping-setting.model'; import { EmployeeSettingFormOption } from 'src/app/core/models/configuration/employee-setting.model'; +import { EmployeeSettingService } from 'src/app/core/services/configuration/employee-setting.service'; @Component({ @@ -31,13 +32,13 @@ export class CloneSettingsComponent implements OnInit { cloneSettingsForm: FormGroup; - autoMapEmployeeTypes: EmployeeSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); + autoMapEmployeeTypes: EmployeeSettingFormOption[] = this.employeeSettingService.getAutoMapEmployeeOptions(); reimbursableExportOptions: ExportSettingFormOption[]; reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingDateOptions(); - employeeFieldMappingOptions: EmployeeSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); + employeeFieldMappingOptions: EmployeeSettingFormOption[] = this.employeeSettingService.getEmployeeFieldMappingOptions(); expenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions(); @@ -69,6 +70,7 @@ export class CloneSettingsComponent implements OnInit { constructor( private exportSettingService: ExportSettingService, + private employeeSettingService: EmployeeSettingService, public helperService: HelperService, private formBuilder: FormBuilder, private cloneSettingService: CloneSettingService, @@ -117,7 +119,7 @@ export class CloneSettingsComponent implements OnInit { return lowerCaseWord.charAt(0).toUpperCase() + lowerCaseWord.slice(1); } - setCreditCardExpenseGroupingDateOptions(creditCardExportGroup: ExpenseGroupingFieldOption): void { + private setCreditCardExpenseGroupingDateOptions(creditCardExportGroup: ExpenseGroupingFieldOption): void { if (creditCardExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { this.cccExpenseGroupingDateOptions = this.reimbursableExpenseGroupingDateOptions.concat([{ label: 'Posted Date', @@ -133,11 +135,11 @@ export class CloneSettingsComponent implements OnInit { } showBankAccountField(): boolean { - return this.cloneSettingsForm.controls.employeeMapping.value === EmployeeFieldMapping.EMPLOYEE && this.cloneSettingsForm.controls.reimbursableExportType.value && this.cloneSettingsForm.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; + return this.cloneSettingsForm.value.employeeMapping === EmployeeFieldMapping.EMPLOYEE && this.cloneSettingsForm.controls.reimbursableExportType.value && this.cloneSettingsForm.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; } showReimbursableAccountsPayableField(): boolean { - return (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && this.cloneSettingsForm.controls.employeeMapping.value === EmployeeFieldMapping.VENDOR); + return (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && this.cloneSettingsForm.value.employeeMapping === EmployeeFieldMapping.VENDOR); } showCreditCardAccountField(): boolean { @@ -156,51 +158,6 @@ export class CloneSettingsComponent implements OnInit { return this.cloneSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; } - private setGeneralMappingsValidator(): void { - if (this.showBankAccountField()) { - this.cloneSettingsForm.controls.bankAccount.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.bankAccount.clearValidators(); - this.cloneSettingsForm.controls.bankAccount.updateValueAndValidity(); - } - - if (this.showCreditCardAccountField()) { - this.cloneSettingsForm.controls.defaultCCCAccount.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.defaultCCCAccount.clearValidators(); - this.cloneSettingsForm.controls.defaultCCCAccount.updateValueAndValidity(); - } - - if (this.showDebitCardAccountField()) { - this.cloneSettingsForm.controls.defaultDebitCardAccount.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.defaultDebitCardAccount.clearValidators(); - this.cloneSettingsForm.controls.defaultDebitCardAccount.updateValueAndValidity(); - - } - - if (this.showReimbursableAccountsPayableField() || this.showCCCAccountsPayableField()) { - this.cloneSettingsForm.controls.accountsPayable.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.accountsPayable.clearValidators(); - this.cloneSettingsForm.controls.accountsPayable.updateValueAndValidity(); - } - - if (this.showDefaultCreditCardVendorField()) { - this.cloneSettingsForm.controls.defaultCreditCardVendor.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.defaultCreditCardVendor.clearValidators(); - this.cloneSettingsForm.controls.defaultCreditCardVendor.updateValueAndValidity(); - } - - if (this.showExpenseAccountField()) { - this.cloneSettingsForm.controls.qboExpenseAccount.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.qboExpenseAccount.clearValidators(); - this.cloneSettingsForm.controls.qboExpenseAccount.updateValueAndValidity(); - } - } - private restrictExpenseGroupSetting(creditCardExportType: string | null) : void { if (creditCardExportType === CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE || creditCardExportType === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE) { this.cloneSettingsForm.controls.creditCardExportGroup.setValue(ExpenseGroupingFieldOption.EXPENSE_ID); @@ -223,14 +180,14 @@ export class CloneSettingsComponent implements OnInit { private createCreditCardExportTypeWatcher(): void { this.restrictExpenseGroupSetting(this.cloneSettingsForm.controls.creditCardExpense.value); this.cloneSettingsForm.controls.creditCardExportType.valueChanges.subscribe((creditCardExportType: string) => { - this.setGeneralMappingsValidator(); + this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); this.restrictExpenseGroupSetting(creditCardExportType); }); } private createReimbursableExportTypeWatcher(): void { this.cloneSettingsForm.controls.reimbursableExportType.valueChanges.subscribe(() => { - this.setGeneralMappingsValidator(); + this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); }); } @@ -299,7 +256,7 @@ export class CloneSettingsComponent implements OnInit { this.setupEmployeeMappingWatcher(); this.setCreditCardExpenseGroupingDateOptions(this.cloneSettingsForm.controls.creditCardExportGroup.value); - this.setGeneralMappingsValidator(); + this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); } private setupForm(): void { diff --git a/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts b/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts index 45d16ae8..41dbfd19 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts @@ -43,7 +43,8 @@ describe('ExportSettingsComponent', () => { getReimbursableExportTypeOptions: () => undefined, getCCCExpenseStateOptions: () => undefined, getExportGroup: () => undefined, - getReimbursableExpenseStateOptions: () => mockReimbursableExpenseStateOptions + getReimbursableExpenseStateOptions: () => mockReimbursableExpenseStateOptions, + setGeneralMappingsValidator: () => undefined }; service2 = { getGroupedQBODestinationAttributes: () => of(destinationAttribute), @@ -168,12 +169,6 @@ describe('ExportSettingsComponent', () => { expect(component.showReimbursableAccountsPayableField()).toBeTrue(); }); - it('setGeneralMappingsValidator function check', () => { - component.exportSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); - fixture.detectChanges(); - expect((component as any).setGeneralMappingsValidator()).toBeUndefined(); - }); - it('createReimbursableExportGroupWatcher function check', () => { const reimbursable = component.exportSettingsForm.controls.reimbursableExportGroup.value; component.exportSettingsForm.controls.reimbursableExportGroup.patchValue('expense_id'); diff --git a/src/app/shared/components/configuration/export-settings/export-settings.component.ts b/src/app/shared/components/configuration/export-settings/export-settings.component.ts index 9f9a43dd..3ecdefc6 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.component.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.component.ts @@ -142,14 +142,14 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { private createReimbursableExportTypeWatcher(): void { this.exportSettingsForm.controls.reimbursableExportType.valueChanges.subscribe(() => { - this.setGeneralMappingsValidator(); - }); + this.exportSettingService.setGeneralMappingsValidator(this.exportSettingsForm); +}); } private createCreditCardExportTypeWatcher(): void { this.restrictExpenseGroupSetting(this.exportSettings.workspace_general_settings.corporate_credit_card_expenses_object); this.exportSettingsForm.controls.creditCardExportType.valueChanges.subscribe((creditCardExportType: string) => { - this.setGeneralMappingsValidator(); + this.exportSettingService.setGeneralMappingsValidator(this.exportSettingsForm); this.restrictExpenseGroupSetting(creditCardExportType); }); } @@ -186,50 +186,6 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { return (this.exportSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL || this.exportSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL) ? ReimbursableExpensesObject.BILL : ReimbursableExpensesObject.JOURNAL_ENTRY; } - private setGeneralMappingsValidator(): void { - if (this.showBankAccountField()) { - this.exportSettingsForm.controls.bankAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.bankAccount.clearValidators(); - this.exportSettingsForm.controls.bankAccount.updateValueAndValidity(); - } - - if (this.showCreditCardAccountField()) { - this.exportSettingsForm.controls.defaultCCCAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.defaultCCCAccount.clearValidators(); - this.exportSettingsForm.controls.defaultCCCAccount.updateValueAndValidity(); - } - - if (this.showDebitCardAccountField()) { - this.exportSettingsForm.controls.defaultDebitCardAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.defaultDebitCardAccount.clearValidators(); - this.exportSettingsForm.controls.defaultDebitCardAccount.updateValueAndValidity(); - } - - if (this.showReimbursableAccountsPayableField() || this.showCCCAccountsPayableField()) { - this.exportSettingsForm.controls.accountsPayable.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.accountsPayable.clearValidators(); - this.exportSettingsForm.controls.accountsPayable.updateValueAndValidity(); - } - - if (this.showDefaultCreditCardVendorField()) { - this.exportSettingsForm.controls.defaultCreditCardVendor.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.defaultCreditCardVendor.clearValidators(); - this.exportSettingsForm.controls.defaultCreditCardVendor.updateValueAndValidity(); - } - - if (this.showExpenseAccountField()) { - this.exportSettingsForm.controls.qboExpenseAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.qboExpenseAccount.clearValidators(); - this.exportSettingsForm.controls.qboExpenseAccount.updateValueAndValidity(); - } - } - private createReimbursableExportGroupWatcher(): void { this.exportSettingsForm.controls.reimbursableExportGroup.valueChanges.subscribe((reimbursableExportGroup: ExpenseGroupingFieldOption) => { if (reimbursableExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { @@ -291,7 +247,7 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { this.createReimbursableExportGroupWatcher(); this.createCreditCardExportGroupWatcher(); - this.setGeneralMappingsValidator(); + this.exportSettingService.setGeneralMappingsValidator(this.exportSettingsForm); } private getSettingsAndSetupForm(): void { From 7495e8d8c81e796739011e8d16704a9ae235e32e Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 16 Aug 2023 14:15:20 +0530 Subject: [PATCH 40/47] oioi --- .../core/services/configuration/export-setting.service.spec.ts | 1 - .../onboarding/clone-settings/clone-settings.component.ts | 2 +- .../employee-settings/employee-settings.component.ts | 3 +-- .../configuration/export-settings/export-settings.fixture.ts | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/app/core/services/configuration/export-setting.service.spec.ts b/src/app/core/services/configuration/export-setting.service.spec.ts index a2b353cf..c18b9a99 100644 --- a/src/app/core/services/configuration/export-setting.service.spec.ts +++ b/src/app/core/services/configuration/export-setting.service.spec.ts @@ -182,7 +182,6 @@ describe('ExportSettingService', () => { creditCardExportDate: ExportDateType.POSTED_AT }); form.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); - fixture.detectChanges(); expect((service as any).setGeneralMappingsValidator()).toBeUndefined(); }); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index 462f460d..db89207d 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -263,7 +263,7 @@ export class CloneSettingsComponent implements OnInit { this.cloneSettingsForm = this.formBuilder.group({ // Employee Mapping employeeMapping: [this.cloneSettings.employee_mappings.workspace_general_settings?.employee_field_mapping, Validators.required], - autoMapEmployee: [this.cloneSettings.employee_mappings.workspace_general_settings?.auto_map_employees, Validators.nullValidator], + autoMapEmployee: [this.cloneSettings.employee_mappings.workspace_general_settings?.auto_map_employees], // Export Settings reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings?.reimbursable_expenses_object ? true : false], diff --git a/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts b/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts index 4cd2374e..35af4b15 100644 --- a/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts +++ b/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts @@ -176,7 +176,7 @@ export class EmployeeSettingsComponent implements OnInit, OnDestroy { this.setLiveEntityExample(responses[1]); this.employeeSettingsForm = this.formBuilder.group({ employeeMapping: [this.existingEmployeeFieldMapping, Validators.required], - autoMapEmployee: [responses[0].workspace_general_settings?.auto_map_employees, Validators.nullValidator] + autoMapEmployee: [responses[0].workspace_general_settings?.auto_map_employees] }); this.reimbursableExportType = responses[2].workspace_general_settings?.reimbursable_expenses_object; this.isLoading = false; @@ -192,5 +192,4 @@ export class EmployeeSettingsComponent implements OnInit, OnDestroy { ngOnInit(): void { this.setupForm(); } - } diff --git a/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts b/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts index 4a72edab..87b0e46b 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts @@ -335,4 +335,4 @@ export const mockReimbursableExpenseStateOptions = [ label: 'Closed', value: ExpenseState.PAID } -]; \ No newline at end of file +]; From fcc4898e21cd4d6c8aee8f96c2bf0b2ff701bdfd Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 16 Aug 2023 16:59:56 +0530 Subject: [PATCH 41/47] comment resolved --- .../export-setting.service.spec.ts | 50 +++++++++++++++---- src/app/core/services/misc/mapping.service.ts | 4 -- .../clone-settings.component.html | 7 ++- .../clone-settings.component.spec.ts | 26 +++++++--- .../clone-settings.component.ts | 5 +- 5 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/app/core/services/configuration/export-setting.service.spec.ts b/src/app/core/services/configuration/export-setting.service.spec.ts index c18b9a99..e957f043 100644 --- a/src/app/core/services/configuration/export-setting.service.spec.ts +++ b/src/app/core/services/configuration/export-setting.service.spec.ts @@ -1,10 +1,10 @@ import { getTestBed, TestBed } from '@angular/core/testing'; import { ExportSettingService } from './export-setting.service'; import { ExportSettingGet, ExportSettingPost } from '../../models/configuration/export-setting.model'; -import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCreditCardExpensesObject, ExportDateType, ExpenseGroupingFieldOption } from '../../models/enum/enum.model'; +import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCreditCardExpensesObject, ExportDateType, ExpenseGroupingFieldOption, EmployeeFieldMapping } from '../../models/enum/enum.model'; import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; import { environment } from 'src/environments/environment'; -import { AbstractControl, FormBuilder } from '@angular/forms'; +import { AbstractControl, FormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { exportResponse } from 'src/app/shared/components/configuration/export-settings/export-settings.fixture'; describe('ExportSettingService', () => { @@ -174,15 +174,47 @@ describe('ExportSettingService', () => { }); it('setGeneralMappingsValidator function check', () => { - const form = formbuilder.group({ - creditCardExpense: false, - cccExpenseState: ExpenseState.PAID, - creditCardExportType: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE, - creditCardExportGroup: ExpenseGroupingFieldOption.EXPENSE_ID, - creditCardExportDate: ExportDateType.POSTED_AT + const form= new UntypedFormGroup({ + employeeMapping: new UntypedFormControl('EMPLOYEE'), + autoMapEmployee: new UntypedFormControl('EMPLOYEE_CODE'), + expenseState: new UntypedFormControl('PAID'), + cccExpenseState: new UntypedFormControl('PAID'), + reimbursableExpense: new UntypedFormControl(true), + reimbursableExportType: new UntypedFormControl('BILL'), + reimbursableExportGroup: new UntypedFormControl('sample'), + reimbursableExportDate: new UntypedFormControl(null), + creditCardExpense: new UntypedFormControl(true), + creditCardExportType: new UntypedFormControl('BILL'), + creditCardExportGroup: new UntypedFormControl('sipper'), + creditCardExportDate: new UntypedFormControl(null), + bankAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + defaultCCCAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + accountsPayable: new UntypedFormControl({id: '1', name: 'Fyle'}), + defaultCreditCardVendor: new UntypedFormControl({id: '1', name: 'Fyle'}), + qboExpenseAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + defaultDebitCardAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + searchOption: new UntypedFormControl([]), + chartOfAccount: new UntypedFormControl(true), + chartOfAccountTypes: new UntypedFormControl([{enabled: true, name: 'expence'}]), + importItems: new UntypedFormControl(true), + taxCode: new UntypedFormControl(true), + defaultTaxCode: new UntypedFormControl({id: '1', name: 'Fyle'}), + importVendorsAsMerchants: new UntypedFormControl(true), + paymentSync: new UntypedFormControl(true), + billPaymentAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + changeAccountingPeriod: new UntypedFormControl(true), + singleCreditLineJE: new UntypedFormControl(true), + autoCreateVendors: new UntypedFormControl(true), + autoCreateMerchantsAsVendors: new UntypedFormControl(true), + exportSchedule: new UntypedFormControl(true), + exportScheduleFrequency: new UntypedFormControl(10), + memoStructure: new UntypedFormControl(['Fyle']), + emails: new UntypedFormControl([]), + addedEmail: new UntypedFormControl([]), + skipExport: new UntypedFormControl(true) }); form.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); - expect((service as any).setGeneralMappingsValidator()).toBeUndefined(); + expect((service as any).setGeneralMappingsValidator(form)).toBeUndefined(); }); it('function check', () => { diff --git a/src/app/core/services/misc/mapping.service.ts b/src/app/core/services/misc/mapping.service.ts index 9373f065..04cc3c12 100644 --- a/src/app/core/services/misc/mapping.service.ts +++ b/src/app/core/services/misc/mapping.service.ts @@ -215,8 +215,4 @@ export class MappingService { } return undefined; } - - getQboField(): Observable { - return this.apiService.get(`/workspaces/${this.workspaceId}/qbo/qbo_fields/`, {}); - } } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 8658ac38..f7859f77 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -227,7 +227,6 @@
In this section, you c -
@@ -373,7 +372,7 @@
In this section, you c

Import Settings

In this section, you can configure how - the dimensions you import from Quickbooks should be mapped in Fyle
+ the dimensions you import from QuickBooks Online should be mapped in Fyle
@@ -414,7 +413,7 @@
In this section, you c + [formControllerName]="'importVendorsAsMerchants'">
@@ -423,7 +422,7 @@
In this section, you c
- Quickbooks Field + QuickBooks Online Field
Fyle Field diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts index e0584bb6..af46f9e6 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -17,6 +17,7 @@ import { MatLegacySnackBarModule as MatSnackBarModule } from '@angular/material/ import { CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseGroupingFieldOption, ExportDateType, ReimbursableExpensesObject } from 'src/app/core/models/enum/enum.model'; import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; import { ImportSettingService } from 'src/app/core/services/configuration/import-setting.service'; +import { mockReimbursableExpenseGroupingDateOptions, mockReimbursableExpenseGroupingFieldOptions, mockReimbursableExpenseStateOptions } from 'src/app/shared/components/configuration/export-settings/export-settings.fixture'; describe('CloneSettingsComponent', () => { @@ -31,6 +32,7 @@ describe('CloneSettingsComponent', () => { let service1: any; let service2: any; let service3: any; + let service4: any; beforeEach(async () => { service1 = { @@ -45,6 +47,20 @@ describe('CloneSettingsComponent', () => { getQBODestinationAttributes: () => null, getExpenseFieldsFormArray: () => null }; + + service4 = { + exportSelectionValidator: () => undefined, + createCreditCardExpenseWatcher: () => undefined, + createReimbursableExpenseWatcher: () => undefined, + getReimbursableExpenseGroupingFieldOptions: () => mockReimbursableExpenseGroupingFieldOptions, + getReimbursableExpenseGroupingDateOptions: () => mockReimbursableExpenseGroupingDateOptions, + getcreditCardExportTypes: () => undefined, + getReimbursableExportTypeOptions: () => undefined, + getCCCExpenseStateOptions: () => undefined, + getExportGroup: () => undefined, + getReimbursableExpenseStateOptions: () => mockReimbursableExpenseStateOptions, + setGeneralMappingsValidator: () => undefined + }; await TestBed.configureTestingModule({ declarations: [ CloneSettingsComponent ], imports: [ @@ -53,9 +69,11 @@ describe('CloneSettingsComponent', () => { providers: [ FormBuilder, { provide: Router, useValue: routerSpy }, + { provide: ExportSettingService, useValue: service4}, { provide: CloneSettingService, useValue: service1 }, { provide: MappingService, useValue: service2 }, - { provide: AdvancedSettingService, useValue: service3 } + { provide: AdvancedSettingService, useValue: service3 }, + { provide: ExportSettingService, useValue: service4} ] }) .compileComponents(); @@ -169,12 +187,6 @@ describe('CloneSettingsComponent', () => { expect(component.showCCCAccountsPayableField()).toBeTrue(); }); - it('setGeneralMappingsValidator function check', () => { - component.cloneSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); - fixture.detectChanges(); - expect((component as any).setGeneralMappingsValidator()).toBeUndefined(); - }); - it('Save Function check', () => { component.isSaveInProgress = false; component.mappingSettings = []; diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index f78ede25..b11d3cc5 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -9,7 +9,7 @@ import { ExportSettingService } from 'src/app/core/services/configuration/export import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'; import { HelperService } from 'src/app/core/services/core/helper.service'; -import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption, CorporateCreditCardExpensesObject, ExportDateType, MappingDestinationField, SimpleSearchType, SimpleSearchPage } from 'src/app/core/models/enum/enum.model'; +import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption, CorporateCreditCardExpensesObject, ExportDateType, MappingDestinationField, SimpleSearchType, SimpleSearchPage, QBOField } from 'src/app/core/models/enum/enum.model'; import { MappingService } from 'src/app/core/services/misc/mapping.service'; import { TrackingService } from 'src/app/core/services/integration/tracking.service'; import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; @@ -316,7 +316,6 @@ export class CloneSettingsComponent implements OnInit { this.setupEmployeeMappingWatcher(); this.setCreditCardExpenseGroupingDateOptions(this.cloneSettingsForm.controls.creditCardExportGroup.value); - this.setupExpenseFieldWatcher(); this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); } @@ -473,7 +472,7 @@ export class CloneSettingsComponent implements OnInit { this.mappingService.getGroupedQBODestinationAttributes(destinationAttributes), this.mappingService.getMappingSettings(), this.mappingService.getFyleExpenseFields(), - this.mappingService.getQBODestinationAttributes('TAX_CODE') + this.mappingService.getQBODestinationAttributes(QBOField.TAX_CODE) ]).subscribe(responses => { this.cloneSettings = responses[0]; this.fyleExpenseFields = responses[3].map(field => field.attribute_type); From a9700330ce1f2639f0c97241a8f777063cac8938 Mon Sep 17 00:00:00 2001 From: Nilesh Pant <58652823+NileshPant1999@users.noreply.github.com> Date: Fri, 18 Aug 2023 12:04:45 +0530 Subject: [PATCH 42/47] clone settings corporate credit card export settings (#286) --- .../configuration/clone-setting.model.spec.ts | 159 ++++++++++ .../configuration/clone-setting.model.ts | 8 +- .../clone-setting.service.spec.ts | 11 + .../configuration/clone-setting.service.ts | 1 + .../configuration/employee-setting.service.ts | 37 ++- .../export-setting.service.spec.ts | 70 ++++- .../configuration/export-setting.service.ts | 160 ++++++++-- .../clone-settings.component.html | 187 ++++++++++-- .../clone-settings.component.scss | 6 +- .../clone-settings.component.spec.ts | 21 ++ .../clone-settings.component.ts | 193 +++++++++--- .../employee-settings.component.spec.ts | 4 +- .../employee-settings.component.ts | 35 +-- .../export-settings.component.spec.ts | 64 ++-- .../export-settings.component.ts | 278 ++---------------- .../export-settings.fixture.ts | 115 +++++++- .../core/select/select.component.html | 3 +- 17 files changed, 921 insertions(+), 431 deletions(-) create mode 100644 src/app/core/models/configuration/clone-setting.model.spec.ts diff --git a/src/app/core/models/configuration/clone-setting.model.spec.ts b/src/app/core/models/configuration/clone-setting.model.spec.ts new file mode 100644 index 00000000..768325fd --- /dev/null +++ b/src/app/core/models/configuration/clone-setting.model.spec.ts @@ -0,0 +1,159 @@ +import { TestBed } from '@angular/core/testing'; +import { UntypedFormControl, UntypedFormGroup} from '@angular/forms'; +import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, MappingDestinationField, MappingSourceField, ReimbursableExpensesObject } from '../enum/enum.model'; +import { CloneSettingModel, CloneSettingPost } from './clone-setting.model'; +import { ImportSettingModel } from './import-setting.model'; +import { MappingSetting } from '../db/mapping-setting.model'; +describe('CloneSettingModel', () => { + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [UntypedFormGroup], + declarations: [ CloneSettingModel ] + }) + .compileComponents(); + }); + + it('Should return CloneSettingModel[]', () => { + const expence_Field = [{ + source_field: 'PROJECT', + destination_field: 'CLASS', + import_to_fyle: true, + is_custom: true, + source_placeholder: 'Fyle' + }]; + + const cloneSettingForm= new UntypedFormGroup({ + employeeMapping: new UntypedFormControl('EMPLOYEE'), + autoMapEmployee: new UntypedFormControl('EMPLOYEE_CODE'), + expenseState: new UntypedFormControl('PAID'), + cccExpenseState: new UntypedFormControl('PAID'), + reimbursableExpense: new UntypedFormControl(true), + reimbursableExportType: new UntypedFormControl('BILL'), + reimbursableExportGroup: new UntypedFormControl('sample'), + reimbursableExportDate: new UntypedFormControl(null), + creditCardExpense: new UntypedFormControl(true), + creditCardExportType: new UntypedFormControl('BILL'), + creditCardExportGroup: new UntypedFormControl('sipper'), + creditCardExportDate: new UntypedFormControl(null), + bankAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + defaultCCCAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + accountsPayable: new UntypedFormControl({id: '1', name: 'Fyle'}), + defaultCreditCardVendor: new UntypedFormControl({id: '1', name: 'Fyle'}), + qboExpenseAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + defaultDebitCardAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + searchOption: new UntypedFormControl([]), + chartOfAccount: new UntypedFormControl(true), + chartOfAccountTypes: new UntypedFormControl([{enabled: true, name: 'expence'}]), + expenseFields: new UntypedFormControl(expence_Field), + importItems: new UntypedFormControl(true), + taxCode: new UntypedFormControl(true), + defaultTaxCode: new UntypedFormControl({id: '1', name: 'Fyle'}), + importVendorsAsMerchants: new UntypedFormControl(true), + paymentSync: new UntypedFormControl(true), + billPaymentAccount: new UntypedFormControl({id: '1', name: 'Fyle'}), + changeAccountingPeriod: new UntypedFormControl(true), + singleCreditLineJE: new UntypedFormControl(true), + autoCreateVendors: new UntypedFormControl(true), + autoCreateMerchantsAsVendors: new UntypedFormControl(true), + exportSchedule: new UntypedFormControl(true), + exportScheduleFrequency: new UntypedFormControl(10), + memoStructure: new UntypedFormControl(['Fyle']), + emails: new UntypedFormControl([]), + addedEmail: new UntypedFormControl([]), + skipExport: new UntypedFormControl(true) + + }); + + const cloneSettingPayload: CloneSettingPost= { + employee_mappings: { + workspace_general_settings: { + employee_field_mapping: EmployeeFieldMapping.EMPLOYEE, + auto_map_employees: AutoMapEmployee.EMPLOYEE_CODE + } + }, + import_settings: { + workspace_general_settings: { + import_categories: true, + import_items: true, + charts_of_accounts: ImportSettingModel.formatChartOfAccounts([{enabled: true, name: 'expence'}]), + import_tax_codes: true, + import_vendors_as_merchants: true + }, + general_mappings: { + default_tax_code: {id: '1', name: 'Fyle'} + }, + mapping_settings: [{ + source_field: MappingSourceField.PROJECT, + destination_field: MappingDestinationField.CLASS, + import_to_fyle: true, + is_custom: false, + source_placeholder: 'Fyle' + }, + { + source_field: MappingSourceField.COST_CENTER, + destination_field: MappingDestinationField.CUSTOMER, + import_to_fyle: false, + is_custom: false, + source_placeholder: null + }] + }, + export_settings: { + expense_group_settings: { + expense_state: ExpenseState.PAID, + ccc_expense_state: CCCExpenseState.PAID, + reimbursable_expense_group_fields: ['sample'], + reimbursable_export_date_type: null, + corporate_credit_card_expense_group_fields: ['sipper'], + ccc_export_date_type: null + }, + workspace_general_settings: { + reimbursable_expenses_object: ReimbursableExpensesObject.BILL, + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL + }, + general_mappings: { + bank_account: {id: '1', name: 'Fyle'}, + default_ccc_account: {id: '1', name: 'Fyle'}, + accounts_payable: {id: '1', name: 'Fyle'}, + default_ccc_vendor: {id: '1', name: 'Fyle'}, + qbo_expense_account: {id: '1', name: 'Fyle'}, + default_debit_card_account: {id: '1', name: 'Fyle'} + } + }, + advanced_settings: { + workspace_general_settings: { + sync_fyle_to_qbo_payments: false, + sync_qbo_to_fyle_payments: false, + auto_create_destination_entity: true, + auto_create_merchants_as_vendors: true, + je_single_credit_line: true, + change_accounting_period: true, + memo_structure: ['Fyle'] + }, + general_mappings: { + bill_payment_account: {id: '1', name: 'Fyle'} + }, + workspace_schedules: { + enabled: true, + interval_hours: 10, + emails_selected: [], + additional_email_options: [] + } + } + }; + + const existingMappingSettings: MappingSetting[] = [{ + id: 21, + created_at: new Date(), + updated_at: new Date(), + workspace: 1, + source_field: MappingSourceField.COST_CENTER, + destination_field: MappingDestinationField.CUSTOMER, + import_to_fyle: false, + is_custom: false, + source_placeholder: null + }]; + + expect(CloneSettingModel.constructPayload(cloneSettingForm, existingMappingSettings)).toEqual(cloneSettingPayload); + }); +}); diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index 990d1330..2fd9b470 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -15,8 +15,8 @@ export type CloneSetting = { export type CloneSettingPost = { export_settings: ExportSettingPost, - Import_settings: ImportSettingPost, - Advanced_settings: AdvancedSettingPost, + import_settings: ImportSettingPost, + advanced_settings: AdvancedSettingPost, employee_mappings: EmployeeSettingPost } @@ -35,8 +35,8 @@ export class CloneSettingModel { const cloneSettingPayload: CloneSettingPost = { export_settings: exportSettingPayload, - Import_settings: importSettingPayload, - Advanced_settings: advancedSettingPayload, + import_settings: importSettingPayload, + advanced_settings: advancedSettingPayload, employee_mappings: employeeMappingPayload }; diff --git a/src/app/core/services/configuration/clone-setting.service.spec.ts b/src/app/core/services/configuration/clone-setting.service.spec.ts index a911aec4..0084e9c9 100644 --- a/src/app/core/services/configuration/clone-setting.service.spec.ts +++ b/src/app/core/services/configuration/clone-setting.service.spec.ts @@ -38,4 +38,15 @@ describe('CloneSettingService', () => { }); req.flush(mockCloneSettingsGet); }); + + it('should post Clone Settings', () => { + service.postCloneSettings(mockCloneSettingsGet).subscribe(value => { + expect(value).toEqual(mockCloneSettingsGet); + }); + const req = httpMock.expectOne({ + method: 'PUT', + url: `${API_BASE_URL}/v2/workspaces/${workspace_id}/clone_settings/` + }); + req.flush(mockCloneSettingsGet); + }); }); diff --git a/src/app/core/services/configuration/clone-setting.service.ts b/src/app/core/services/configuration/clone-setting.service.ts index 2748a0dd..df8f4d8e 100644 --- a/src/app/core/services/configuration/clone-setting.service.ts +++ b/src/app/core/services/configuration/clone-setting.service.ts @@ -3,6 +3,7 @@ import { Observable } from 'rxjs'; import { CloneSetting, CloneSettingExist, CloneSettingPost } from '../../models/configuration/clone-setting.model'; import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; +import { FormControl, FormGroup } from '@angular/forms'; @Injectable({ providedIn: 'root' diff --git a/src/app/core/services/configuration/employee-setting.service.ts b/src/app/core/services/configuration/employee-setting.service.ts index 1f2c7585..432893b7 100644 --- a/src/app/core/services/configuration/employee-setting.service.ts +++ b/src/app/core/services/configuration/employee-setting.service.ts @@ -1,9 +1,10 @@ import { Injectable } from '@angular/core'; import { Observable, Subject } from 'rxjs'; import { Cacheable, CacheBuster } from 'ts-cacheable'; -import { EmployeeSettingGet, EmployeeSettingPost } from '../../models/configuration/employee-setting.model'; +import { EmployeeSettingFormOption, EmployeeSettingGet, EmployeeSettingPost } from '../../models/configuration/employee-setting.model'; import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; +import { AutoMapEmployee, EmployeeFieldMapping } from '../../models/enum/enum.model'; const employeeSettingsCache$ = new Subject(); @@ -32,4 +33,38 @@ export class EmployeeSettingService { postEmployeeSettings(employeeSettingsPayload: EmployeeSettingPost): Observable { return this.apiService.put(`/v2/workspaces/${this.workspaceService.getWorkspaceId()}/map_employees/`, employeeSettingsPayload); } + + getEmployeeFieldMappingOptions(): EmployeeSettingFormOption[] { + return [ + { + label: 'Employees', + value: EmployeeFieldMapping.EMPLOYEE + }, + { + label: 'Vendor', + value: EmployeeFieldMapping.VENDOR + } + ]; + } + + getAutoMapEmployeeOptions(): EmployeeSettingFormOption[] { + return [ + { + value: null, + label: 'None' + }, + { + value: AutoMapEmployee.NAME, + label: 'Fyle Name to QuickBooks Online Display name' + }, + { + value: AutoMapEmployee.EMAIL, + label: 'Fyle Email to QuickBooks Online Email' + }, + { + value: AutoMapEmployee.EMPLOYEE_CODE, + label: 'Fyle Employee Code to QuickBooks Online Display name' + } + ]; + } } diff --git a/src/app/core/services/configuration/export-setting.service.spec.ts b/src/app/core/services/configuration/export-setting.service.spec.ts index a080e0e9..c18b9a99 100644 --- a/src/app/core/services/configuration/export-setting.service.spec.ts +++ b/src/app/core/services/configuration/export-setting.service.spec.ts @@ -1,9 +1,11 @@ import { getTestBed, TestBed } from '@angular/core/testing'; import { ExportSettingService } from './export-setting.service'; import { ExportSettingGet, ExportSettingPost } from '../../models/configuration/export-setting.model'; -import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCreditCardExpensesObject, ExportDateType } from '../../models/enum/enum.model'; +import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCreditCardExpensesObject, ExportDateType, ExpenseGroupingFieldOption } from '../../models/enum/enum.model'; import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; import { environment } from 'src/environments/environment'; +import { AbstractControl, FormBuilder } from '@angular/forms'; +import { exportResponse } from 'src/app/shared/components/configuration/export-settings/export-settings.fixture'; describe('ExportSettingService', () => { let service: ExportSettingService; @@ -11,6 +13,8 @@ describe('ExportSettingService', () => { let httpMock: HttpTestingController; const API_BASE_URL = environment.api_url; const workspace_id = environment.tests.workspaceId; + let formbuilder: FormBuilder; + beforeEach(() => { TestBed.configureTestingModule({ @@ -18,6 +22,7 @@ describe('ExportSettingService', () => { providers: [ExportSettingService] }); injector = getTestBed(); + formbuilder = TestBed.inject(FormBuilder); service = injector.inject(ExportSettingService); httpMock = injector.inject(HttpTestingController); }); @@ -121,4 +126,67 @@ describe('ExportSettingService', () => { }); + it('exportSelectionValidator function check', () => { + const control = { value: ExpenseState.PAID, parent: formbuilder.group({ + reimbursableExpense: ReimbursableExpensesObject.BILL + }) }; + expect((service as any).exportSelectionValidator()(control as AbstractControl)).toEqual({forbiddenOption: { value: 'PAID' }}); + const control1 = { value: ExpenseState.PAYMENT_PROCESSING, parent: formbuilder.group({ + creditCardExpense: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE + }) }; + expect((service as any).exportSelectionValidator()(control1 as AbstractControl)).toEqual({forbiddenOption: { value: 'PAYMENT_PROCESSING' }}); + }); + + it('createReimbursableExpenseWatcher function check', () => { + const form = formbuilder.group({ + reimbursableExpense: false, + expenseState: ExpenseState.PAID, + reimbursableExportType: ReimbursableExpensesObject.BILL, + reimbursableExportDate: ExportDateType.APPROVED_AT, + reimbursableExportGroup: ExpenseGroupingFieldOption.EXPENSE_ID + }); + + expect((service as any).createReimbursableExpenseWatcher(form, exportResponse)).toBeUndefined(); + + form.controls.reimbursableExpense.patchValue(true); + expect((service as any).createReimbursableExpenseWatcher(form, exportResponse)).toBeUndefined(); + + form.controls.reimbursableExpense.patchValue(false); + expect((service as any).createReimbursableExpenseWatcher(form, exportResponse)).toBeUndefined(); + }); + + it('createCreditCardExpenseWatcher function check', () => { + const form = formbuilder.group({ + creditCardExpense: false, + cccExpenseState: ExpenseState.PAID, + creditCardExportType: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE, + creditCardExportGroup: ExpenseGroupingFieldOption.EXPENSE_ID, + creditCardExportDate: ExportDateType.POSTED_AT + }); + + expect((service as any).createCreditCardExpenseWatcher(form, exportResponse)).toBeUndefined(); + + form.controls.creditCardExpense.patchValue(true); + expect((service as any).createCreditCardExpenseWatcher(form, exportResponse)).toBeUndefined(); + + form.controls.creditCardExpense.patchValue(false); + expect((service as any).createCreditCardExpenseWatcher(form, exportResponse)).toBeUndefined(); + }); + + it('setGeneralMappingsValidator function check', () => { + const form = formbuilder.group({ + creditCardExpense: false, + cccExpenseState: ExpenseState.PAID, + creditCardExportType: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE, + creditCardExportGroup: ExpenseGroupingFieldOption.EXPENSE_ID, + creditCardExportDate: ExportDateType.POSTED_AT + }); + form.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); + expect((service as any).setGeneralMappingsValidator()).toBeUndefined(); + }); + + it('function check', () => { + expect((service as any).getExportGroup([ExpenseGroupingFieldOption.EXPENSE_ID])).toEqual('expense_id'); + expect((service as any).getExportGroup(null)).toEqual(''); + }); }); diff --git a/src/app/core/services/configuration/export-setting.service.ts b/src/app/core/services/configuration/export-setting.service.ts index 7cf19a9e..eaf6f21c 100644 --- a/src/app/core/services/configuration/export-setting.service.ts +++ b/src/app/core/services/configuration/export-setting.service.ts @@ -48,6 +48,27 @@ export class ExportSettingService { }); } + createCreditCardExpenseWatcher(form: FormGroup, exportSettings: ExportSettingGet): void { + form.controls.creditCardExpense.valueChanges.subscribe((isCreditCardExpenseSelected) => { + if (isCreditCardExpenseSelected) { + form.controls.cccExpenseState.setValidators(Validators.required); + form.controls.cccExpenseState.setValue(exportSettings.expense_group_settings?.ccc_expense_state ? exportSettings.expense_group_settings?.ccc_expense_state : exportSettings.workspace_general_settings.is_simplify_report_closure_enabled ? CCCExpenseState.APPROVED: CCCExpenseState.PAYMENT_PROCESSING); + form.controls.creditCardExportType.setValidators(Validators.required); + form.controls.creditCardExportGroup.setValidators(Validators.required); + form.controls.creditCardExportDate.setValidators(Validators.required); + } else { + form.controls.cccExpenseState.clearValidators(); + form.controls.creditCardExportType.clearValidators(); + form.controls.creditCardExportGroup.clearValidators(); + form.controls.creditCardExportDate.clearValidators(); + form.controls.cccExpenseState.setValue(null); + form.controls.creditCardExportType.setValue(null); + form.controls.creditCardExportGroup.setValue(null); + form.controls.creditCardExportDate.setValue(null); + } + }); + } + getExportGroup(exportGroups: string[] | null): string { if (exportGroups) { const exportGroup = exportGroups.find((exportGroup) => { @@ -130,36 +151,6 @@ export class ExportSettingService { ]; } - getEmployeeFieldMappingOptions(): EmployeeSettingFormOption[] { - return [ - { - label: 'Employees', - value: EmployeeFieldMapping.EMPLOYEE - }, - { - label: 'Vendor', - value: EmployeeFieldMapping.VENDOR - } - ]; - } - - getAutoMapEmployeeOptions(): EmployeeSettingFormOption[] { - return [ - { - label: 'None', - value: null - }, - { - label: 'Employee name on Fyle to contact name on Quickbooks', - value: AutoMapEmployee.NAME - }, - { - label: 'Employee email on Fyle to contact email on Quickbooks', - value: AutoMapEmployee.EMAIL - } - ]; - } - getReimbursableExpenseGroupingDateOptions(): ExportSettingFormOption[] { return [ { @@ -210,5 +201,114 @@ export class ExportSettingService { } ]; } + + exportSelectionValidator(exportSettingsForm: FormGroup, isCloneSetting: boolean = false): ValidatorFn { + return (control: AbstractControl): {[key: string]: object} | null => { + let forbidden = true; + if (exportSettingsForm) { + if (typeof control.value === 'boolean') { + if (control.value) { + forbidden = false; + } else { + if (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value) { + forbidden = false; + } + } + } else if ((control.value === ExpenseState.PAID || control.value === ExpenseState.PAYMENT_PROCESSING || control.value === CCCExpenseState.APPROVED) + && (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value)) { + forbidden = false; + } else if (isCloneSetting && (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value)) { + forbidden = false; + } + + if (!forbidden) { + control.parent?.get('expenseState')?.setErrors(null); + control.parent?.get('cccExpenseState')?.setErrors(null); + control.parent?.get('reimbursableExpense')?.setErrors(null); + control.parent?.get('creditCardExpense')?.setErrors(null); + return null; + } + } + + return { + forbiddenOption: { + value: control.value + } + }; + }; + } + + showExpenseAccountField(form: FormGroup): boolean { + return form.controls.reimbursableExportType.value === ReimbursableExpensesObject.EXPENSE; + } + + showBankAccountField(form: FormGroup): boolean { + return form.value.employeeMapping === EmployeeFieldMapping.EMPLOYEE && form.controls.reimbursableExportType.value && form.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; + } + + showReimbursableAccountsPayableField(form: FormGroup): boolean { + return (form.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (form.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && form.value.employeeMapping === EmployeeFieldMapping.VENDOR); + } + + showCreditCardAccountField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value && form.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.BILL && form.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } + + showDebitCardAccountField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value && form.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } + + showDefaultCreditCardVendorField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + showCCCAccountsPayableField(form: FormGroup): boolean { + return form.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + setGeneralMappingsValidator(form: FormGroup): void { + if (this.showBankAccountField(form)) { + form.controls.bankAccount.setValidators(Validators.required); + } else { + form.controls.bankAccount.clearValidators(); + form.controls.bankAccount.updateValueAndValidity(); + } + + if (this.showCreditCardAccountField(form)) { + form.controls.defaultCCCAccount.setValidators(Validators.required); + } else { + form.controls.defaultCCCAccount.clearValidators(); + form.controls.defaultCCCAccount.updateValueAndValidity(); + } + + if (this.showDebitCardAccountField(form)) { + form.controls.defaultDebitCardAccount.setValidators(Validators.required); + } else { + form.controls.defaultDebitCardAccount.clearValidators(); + form.controls.defaultDebitCardAccount.updateValueAndValidity(); + + } + + if (this.showReimbursableAccountsPayableField(form) || this.showCCCAccountsPayableField(form)) { + form.controls.accountsPayable.setValidators(Validators.required); + } else { + form.controls.accountsPayable.clearValidators(); + form.controls.accountsPayable.updateValueAndValidity(); + } + + if (this.showDefaultCreditCardVendorField(form)) { + form.controls.defaultCreditCardVendor.setValidators(Validators.required); + } else { + form.controls.defaultCreditCardVendor.clearValidators(); + form.controls.defaultCreditCardVendor.updateValueAndValidity(); + } + + if (this.showExpenseAccountField(form)) { + form.controls.qboExpenseAccount.setValidators(Validators.required); + } else { + form.controls.qboExpenseAccount.clearValidators(); + form.controls.qboExpenseAccount.updateValueAndValidity(); + } + } } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 63060122..86338157 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -14,7 +14,7 @@

Employee Mappings

- In this section, you can configure how map fyle employees to Quickbooks Vendor / Employee + In this section, you can configure how map fyle employees to QuickBooks Online Vendor / Employee
@@ -26,14 +26,15 @@
src="assets/images/svgs/general/calendar-disabled.svg">

Employee Field Mapping

@@ -46,14 +47,14 @@
src="assets/images/svgs/general/employee-disabled.svg">

Auto Map Employee

@@ -71,7 +72,7 @@

Export Settings

In this section, you can configure how - and when expenses from Fyle need to be exported to Xero
+ and when expenses from Fyle need to be exported to QuickBooks Online
@@ -79,7 +80,7 @@
In this section, you c

Reimbursable Expense

@@ -91,7 +92,6 @@
In this section, you c
-
@@ -105,7 +105,7 @@
In this section, you c
+ [formControllerName]="'expenseState'" [phase]="ProgressPhase.ONBOARDING">
@@ -118,12 +118,12 @@
In this section, you c

Mode of Export

@@ -176,12 +176,12 @@
In this section, you c

Date of export

@@ -195,17 +195,170 @@
In this section, you c

How should the expenses be grouped?

- + +
+
+
+

Corporate Card Expense

+ +
+ +
+ +
+
+
+ + +
+
+
+
+ +

State of export

+ +
+ + +
+
+ +
+
+
+ +

Mode of Export

+ +
+ + +
+
+ +
+
+
+ +

How should the expenses be grouped?

+ +
+ + + +
+
+ +
+
+
+ +

Date of export

+ +
+ + + +
+
+ +
+
+
+ +

Set Default Credit Card Account as

+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+
+
+
+ +

Select Accounts Payable Account

+ +
+ + + +
+
+
+
diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.scss b/src/app/integration/onboarding/clone-settings/clone-settings.component.scss index f5d320c9..a5878024 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.scss +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.scss @@ -69,7 +69,7 @@ font-size: 14px; } - &--xero-header { + &--qbo-header { padding-left: 14px; padding-right: 280px; } @@ -78,7 +78,7 @@ padding: 20px 0px 12px 32px; } - &--xero-field { + &--qbo-field { height: 34px; width: 304px; background: #F5F5F5; @@ -88,7 +88,7 @@ color: #2C304E; } - &--xero-field-text { + &--qbo-field-text { padding-left: 14px; } diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts index 0d1fdca0..57c97f5d 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.spec.ts @@ -14,6 +14,7 @@ import { AdvancedSettingService } from 'src/app/core/services/configuration/adva import { MatMenuModule } from '@angular/material/menu'; import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; import { MatLegacySnackBarModule as MatSnackBarModule } from '@angular/material/legacy-snack-bar'; +import { ReimbursableExpensesObject } from 'src/app/core/models/enum/enum.model'; describe('CloneSettingsComponent', () => { @@ -60,4 +61,24 @@ describe('CloneSettingsComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('getExportType function check', () => { + const response = ReimbursableExpensesObject.JOURNAL_ENTRY; + const output = response.toLowerCase().charAt(0).toUpperCase() + response.toLowerCase().slice(1); + expect(component.getExportType(ReimbursableExpensesObject.JOURNAL_ENTRY)).toEqual(output); + }); + + it('createCreditCardExportGroupWatcher function check', () => { + component.cloneSettingsForm.controls.creditCardExportGroup.patchValue(!component.cloneSettingsForm.controls.creditCardExportGroup.value); + expect((component as any).createCreditCardExportGroupWatcher()).toBeUndefined(); + component.cloneSettingsForm.controls.creditCardExpense.patchValue(!component.cloneSettingsForm.controls.creditCardExportGroup.value); + expect((component as any).createCreditCardExportGroupWatcher()).toBeUndefined(); + }); + + it('createReimbursableExportGroupWatcher function check', () => { + component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(!component.cloneSettingsForm.controls.reimbursableExportGroup.value); + expect((component as any).createReimbursableExportGroupWatcher()).toBeUndefined(); + component.cloneSettingsForm.controls.reimbursableExportGroup.patchValue(!component.cloneSettingsForm.controls.reimbursableExportGroup.value); + expect((component as any).createReimbursableExportGroupWatcher()).toBeUndefined(); + }); }); diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index e361585e..db89207d 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl } from '@angular/forms'; import { forkJoin } from 'rxjs'; import { CloneSetting, CloneSettingModel } from 'src/app/core/models/configuration/clone-setting.model'; import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; @@ -9,13 +9,14 @@ import { ExportSettingService } from 'src/app/core/services/configuration/export import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'; import { HelperService } from 'src/app/core/services/core/helper.service'; -import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption } from 'src/app/core/models/enum/enum.model'; +import { EmployeeFieldMapping, ReimbursableExpensesObject, ClickEvent, OnboardingStep, ProgressPhase, ExpenseGroupingFieldOption, CorporateCreditCardExpensesObject, ExportDateType, ExpenseState, CCCExpenseState } from 'src/app/core/models/enum/enum.model'; import { MappingService } from 'src/app/core/services/misc/mapping.service'; import { TrackingService } from 'src/app/core/services/integration/tracking.service'; import { ConfirmationDialog } from 'src/app/core/models/misc/confirmation-dialog.model'; import { Router } from '@angular/router'; import { MappingSetting } from 'src/app/core/models/db/mapping-setting.model'; import { EmployeeSettingFormOption } from 'src/app/core/models/configuration/employee-setting.model'; +import { EmployeeSettingService } from 'src/app/core/services/configuration/employee-setting.service'; @Component({ @@ -31,15 +32,15 @@ export class CloneSettingsComponent implements OnInit { cloneSettingsForm: FormGroup; - autoMapEmployeeTypes: EmployeeSettingFormOption[] = this.exportSettingService.getAutoMapEmployeeOptions(); + autoMapEmployeeTypes: EmployeeSettingFormOption[] = this.employeeSettingService.getAutoMapEmployeeOptions(); reimbursableExportOptions: ExportSettingFormOption[]; reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingDateOptions(); - employeeFieldMappingOptions: EmployeeSettingFormOption[] = this.exportSettingService.getEmployeeFieldMappingOptions(); + employeeFieldMappingOptions: EmployeeSettingFormOption[] = this.employeeSettingService.getEmployeeFieldMappingOptions(); - reimbursableExpenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions(); + expenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions(); bankAccounts: DestinationAttribute[]; @@ -63,10 +64,13 @@ export class CloneSettingsComponent implements OnInit { mappingSettings: MappingSetting[]; + cccExpenseGroupingDateOptions: ExportSettingFormOption[]; + ProgressPhase = ProgressPhase; constructor( private exportSettingService: ExportSettingService, + private employeeSettingService: EmployeeSettingService, public helperService: HelperService, private formBuilder: FormBuilder, private cloneSettingService: CloneSettingService, @@ -112,68 +116,174 @@ export class CloneSettingsComponent implements OnInit { getExportType(exportType: ReimbursableExpensesObject): string { const lowerCaseWord = exportType.toLowerCase(); - return lowerCaseWord.charAt(0).toUpperCase() + lowerCaseWord.slice(1); } + private setCreditCardExpenseGroupingDateOptions(creditCardExportGroup: ExpenseGroupingFieldOption): void { + if (creditCardExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { + this.cccExpenseGroupingDateOptions = this.reimbursableExpenseGroupingDateOptions.concat([{ + label: 'Posted Date', + value: ExportDateType.POSTED_AT + }]); + } else { + this.cccExpenseGroupingDateOptions = this.reimbursableExpenseGroupingDateOptions.concat(); + } + } + showExpenseAccountField(): boolean { return this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.EXPENSE; } showBankAccountField(): boolean { - return this.employeeFieldMapping === EmployeeFieldMapping.EMPLOYEE && this.cloneSettingsForm.controls.reimbursableExportType.value && this.cloneSettingsForm.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; + return this.cloneSettingsForm.value.employeeMapping === EmployeeFieldMapping.EMPLOYEE && this.cloneSettingsForm.controls.reimbursableExportType.value && this.cloneSettingsForm.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; } showReimbursableAccountsPayableField(): boolean { - return (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && this.employeeFieldMapping === EmployeeFieldMapping.VENDOR); + return (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL) || (this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.JOURNAL_ENTRY && this.cloneSettingsForm.value.employeeMapping === EmployeeFieldMapping.VENDOR); } - private setGeneralMappingsValidator(): void { - if (this.showBankAccountField()) { - this.cloneSettingsForm.controls.bankAccount.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.bankAccount.clearValidators(); - this.cloneSettingsForm.controls.bankAccount.updateValueAndValidity(); - } + showCreditCardAccountField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value && this.cloneSettingsForm.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.BILL && this.cloneSettingsForm.controls.creditCardExportType.value !== CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } - if (this.showExpenseAccountField()) { - this.cloneSettingsForm.controls.qboExpenseAccount.setValidators(Validators.required); - } else { - this.cloneSettingsForm.controls.qboExpenseAccount.clearValidators(); - this.cloneSettingsForm.controls.qboExpenseAccount.updateValueAndValidity(); - } + showDebitCardAccountField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value && this.cloneSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE; + } - if (this.showReimbursableAccountsPayableField()) { - this.cloneSettingsForm.controls.accountsPayable.setValidators(Validators.required); + showDefaultCreditCardVendorField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + showCCCAccountsPayableField(): boolean { + return this.cloneSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL; + } + + private restrictExpenseGroupSetting(creditCardExportType: string | null) : void { + if (creditCardExportType === CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE || creditCardExportType === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE) { + this.cloneSettingsForm.controls.creditCardExportGroup.setValue(ExpenseGroupingFieldOption.EXPENSE_ID); + this.cloneSettingsForm.controls.creditCardExportGroup.disable(); + + this.cccExpenseGroupingDateOptions = [{ + label: 'Posted Date', + value: ExportDateType.POSTED_AT + }, + { + label: 'Spend Date', + value: ExportDateType.SPENT_AT + }]; } else { - this.cloneSettingsForm.controls.accountsPayable.clearValidators(); - this.cloneSettingsForm.controls.accountsPayable.updateValueAndValidity(); + this.cloneSettingsForm.controls.creditCardExportGroup.enable(); + this.setCreditCardExpenseGroupingDateOptions(this.cloneSettingsForm.controls.creditCardExportGroup.value); } } + private createCreditCardExportTypeWatcher(): void { + this.restrictExpenseGroupSetting(this.cloneSettingsForm.controls.creditCardExpense.value); + this.cloneSettingsForm.controls.creditCardExportType.valueChanges.subscribe((creditCardExportType: string) => { + this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); + this.restrictExpenseGroupSetting(creditCardExportType); + }); + } + + private createReimbursableExportTypeWatcher(): void { + this.cloneSettingsForm.controls.reimbursableExportType.valueChanges.subscribe(() => { + this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); + }); + } + + private setupEmployeeMappingWatcher(): void { + this.cloneSettingsForm.controls.employeeMapping.valueChanges.subscribe((employeeMapping: EmployeeFieldMapping) => { + this.reimbursableExportOptions = this.exportSettingService.getReimbursableExportTypeOptions(employeeMapping); + }); + } + + private createReimbursableExportGroupWatcher(): void { + this.cloneSettingsForm.controls.reimbursableExportGroup.valueChanges.subscribe((reimbursableExportGroup: ExpenseGroupingFieldOption) => { + if (reimbursableExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { + this.reimbursableExpenseGroupingDateOptions.pop(); + } else { + if (this.reimbursableExpenseGroupingDateOptions.length !== 5) { + this.reimbursableExpenseGroupingDateOptions.push({ + label: 'Last Spend Date', + value: ExportDateType.LAST_SPENT_AT + }); + } + } + }); + } + + private createCreditCardExportGroupWatcher(): void { + this.cloneSettingsForm.controls.creditCardExportGroup.valueChanges.subscribe((creditCardExportGroup: ExpenseGroupingFieldOption) => { + if (creditCardExportGroup && creditCardExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { + this.cccExpenseGroupingDateOptions = this.cccExpenseGroupingDateOptions.filter((option) => { + return option.value !== ExportDateType.LAST_SPENT_AT; + }); + this.setCreditCardExpenseGroupingDateOptions(creditCardExportGroup); + } else { + const lastSpentAt = this.cccExpenseGroupingDateOptions.filter((option) => { + return option.value === ExportDateType.LAST_SPENT_AT; + }); + if (!lastSpentAt.length) { + this.cccExpenseGroupingDateOptions.push({ + label: 'Last Spend Date', + value: ExportDateType.LAST_SPENT_AT + }); + } + this.setCreditCardExpenseGroupingDateOptions(creditCardExportGroup); + } + }); + } + + private setupExportWatchers(): void { + this.cloneSettingsForm?.controls.reimbursableExpense?.setValidators((this.exportSettingService.exportSelectionValidator(this.cloneSettingsForm, true))); + this.cloneSettingsForm?.controls.creditCardExpense?.setValidators(this.exportSettingService.exportSelectionValidator(this.cloneSettingsForm, true)); + } + private setCustomValidatorsAndWatchers(): void { + this.exportSettingService.createReimbursableExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); + this.exportSettingService.createCreditCardExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); + + // Export select fields + this.createReimbursableExportTypeWatcher(); + this.createCreditCardExportTypeWatcher(); - this.setGeneralMappingsValidator(); + // Goruping fields + this.createReimbursableExportGroupWatcher(); + this.createCreditCardExportGroupWatcher(); + + this.setupExportWatchers(); + this.setupEmployeeMappingWatcher(); + + this.setCreditCardExpenseGroupingDateOptions(this.cloneSettingsForm.controls.creditCardExportGroup.value); + this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); } private setupForm(): void { this.cloneSettingsForm = this.formBuilder.group({ // Employee Mapping - employeeMapping: [this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping], - autoMapEmployee: [this.cloneSettings.employee_mappings.workspace_general_settings.auto_map_employees], + employeeMapping: [this.cloneSettings.employee_mappings.workspace_general_settings?.employee_field_mapping, Validators.required], + autoMapEmployee: [this.cloneSettings.employee_mappings.workspace_general_settings?.auto_map_employees], // Export Settings - reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object ? true : false], - reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings.reimbursable_export_date_type], - reimbursableExpenseState: [this.cloneSettings.export_settings.expense_group_settings.expense_state], - reimbursableExportType: [this.cloneSettings.export_settings.workspace_general_settings.reimbursable_expenses_object], - creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings.corporate_credit_card_expenses_object ? true : false], + reimbursableExpense: [this.cloneSettings.export_settings.workspace_general_settings?.reimbursable_expenses_object ? true : false], + reimbursableExportDate: [this.cloneSettings.export_settings.expense_group_settings?.reimbursable_export_date_type], + expenseState: [this.cloneSettings.export_settings.expense_group_settings?.expense_state], reimbursableExportGroup: [this.exportSettingService.getExportGroup(this.cloneSettings.export_settings.expense_group_settings?.reimbursable_expense_group_fields)], - cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings.ccc_expense_state], - qboExpenseAccount: [this.cloneSettings.export_settings.general_mappings.qbo_expense_account], - accountsPayable: [this.cloneSettings.export_settings.general_mappings.accounts_payable], - bankAccount: [this.cloneSettings.export_settings.general_mappings.bank_account], + reimbursableExportType: [this.cloneSettings.export_settings.workspace_general_settings?.reimbursable_expenses_object], + + creditCardExpense: [this.cloneSettings.export_settings.workspace_general_settings?.corporate_credit_card_expenses_object ? true : false], + creditCardExportDate: [this.cloneSettings.export_settings.expense_group_settings?.ccc_export_date_type], + cccExpenseState: [this.cloneSettings.export_settings.expense_group_settings?.ccc_expense_state], + creditCardExportGroup: [this.exportSettingService.getExportGroup(this.cloneSettings.export_settings.expense_group_settings?.corporate_credit_card_expense_group_fields)], + creditCardExportType: [this.cloneSettings.export_settings.workspace_general_settings?.corporate_credit_card_expenses_object], + + bankAccount: [this.cloneSettings.export_settings.general_mappings?.bank_account?.id ? this.cloneSettings.export_settings.general_mappings.bank_account : null], + qboExpenseAccount: [this.cloneSettings.export_settings.general_mappings?.qbo_expense_account?.id ? this.cloneSettings.export_settings.general_mappings.qbo_expense_account : null], + defaultCCCAccount: [this.cloneSettings.export_settings.general_mappings?.default_ccc_account?.id ? this.cloneSettings.export_settings.general_mappings.default_ccc_account : null], + accountsPayable: [this.cloneSettings.export_settings.general_mappings?.accounts_payable?.id ? this.cloneSettings.export_settings.general_mappings.accounts_payable : null], + defaultCreditCardVendor: [this.cloneSettings.export_settings.general_mappings?.default_ccc_vendor?.id ? this.cloneSettings.export_settings.general_mappings.default_ccc_vendor : null], + defaultDebitCardAccount: [this.cloneSettings.export_settings.general_mappings?.default_debit_card_account?.id ? this.cloneSettings.export_settings.general_mappings.default_debit_card_account : null], searchOption: [] }); @@ -193,17 +303,22 @@ export class CloneSettingsComponent implements OnInit { this.mappingService.getMappingSettings() ]).subscribe(responses => { this.cloneSettings = responses[0]; + this.employeeFieldMapping = this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping; this.mappingSettings = responses[2].results; - this.cccExpenseExportOptions = this.exportSettingService.getcreditCardExportTypes(); + this.bankAccounts = responses[1].BANK_ACCOUNT; this.cccAccounts = responses[1].CREDIT_CARD_ACCOUNT; this.accountsPayables = responses[1].ACCOUNTS_PAYABLE; this.vendors = responses[1].VENDOR; this.expenseAccounts = this.bankAccounts.concat(this.cccAccounts); + + this.reimbursableExportOptions = this.exportSettingService.getReimbursableExportTypeOptions(EmployeeFieldMapping.EMPLOYEE); + this.cccExpenseExportOptions = this.exportSettingService.getcreditCardExportTypes(); + this.reimbursableExpenseStateOptions = this.exportSettingService.getReimbursableExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); this.cccExpenseStateOptions = this.exportSettingService.getCCCExpenseStateOptions(this.cloneSettings.export_settings.workspace_general_settings.is_simplify_report_closure_enabled); - this.reimbursableExportOptions = this.exportSettingService.getReimbursableExportTypeOptions(EmployeeFieldMapping.EMPLOYEE); + this.setupForm(); }); } diff --git a/src/app/shared/components/configuration/employee-settings/employee-settings.component.spec.ts b/src/app/shared/components/configuration/employee-settings/employee-settings.component.spec.ts index 90e10f03..7dfd21b6 100644 --- a/src/app/shared/components/configuration/employee-settings/employee-settings.component.spec.ts +++ b/src/app/shared/components/configuration/employee-settings/employee-settings.component.spec.ts @@ -46,7 +46,9 @@ describe('EmployeeSettingsComponent', () => { service1 = { getEmployeeSettings: () => of(response), - postEmployeeSettings: () => of(response) + postEmployeeSettings: () => of(response), + getEmployeeFieldMappingOptions: () => null, + getAutoMapEmployeeOptions: () => null }; service2 = { diff --git a/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts b/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts index ea65ebbe..35af4b15 100644 --- a/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts +++ b/src/app/shared/components/configuration/employee-settings/employee-settings.component.ts @@ -37,35 +37,9 @@ export class EmployeeSettingsComponent implements OnInit, OnDestroy { existingEmployeeFieldMapping: EmployeeFieldMapping | undefined; - employeeMappingOptions: EmployeeSettingFormOption[] = [ - { - value: EmployeeFieldMapping.EMPLOYEE, - label: 'Employees' - }, - { - value: EmployeeFieldMapping.VENDOR, - label: 'Vendors' - } - ]; - - autoMapEmployeeOptions: EmployeeSettingFormOption[] = [ - { - value: null, - label: 'None' - }, - { - value: AutoMapEmployee.NAME, - label: 'Fyle Name to QuickBooks Online Display name' - }, - { - value: AutoMapEmployee.EMAIL, - label: 'Fyle Email to QuickBooks Online Email' - }, - { - value: AutoMapEmployee.EMPLOYEE_CODE, - label: 'Fyle Employee Code to QuickBooks Online Display name' - } - ]; + employeeMappingOptions: EmployeeSettingFormOption[] = this.employeeSettingService.getEmployeeFieldMappingOptions(); + + autoMapEmployeeOptions: EmployeeSettingFormOption[] = this.employeeSettingService.getAutoMapEmployeeOptions(); windowReference: Window; @@ -202,7 +176,7 @@ export class EmployeeSettingsComponent implements OnInit, OnDestroy { this.setLiveEntityExample(responses[1]); this.employeeSettingsForm = this.formBuilder.group({ employeeMapping: [this.existingEmployeeFieldMapping, Validators.required], - autoMapEmployee: [responses[0].workspace_general_settings?.auto_map_employees, Validators.nullValidator] + autoMapEmployee: [responses[0].workspace_general_settings?.auto_map_employees] }); this.reimbursableExportType = responses[2].workspace_general_settings?.reimbursable_expenses_object; this.isLoading = false; @@ -218,5 +192,4 @@ export class EmployeeSettingsComponent implements OnInit, OnDestroy { ngOnInit(): void { this.setupForm(); } - } diff --git a/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts b/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts index 90277a70..41dbfd19 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.component.spec.ts @@ -6,7 +6,7 @@ import { ExportSettingsComponent } from './export-settings.component'; import { HttpClientModule } from '@angular/common/http'; import { SharedModule } from 'src/app/shared/shared.module'; import { CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseGroupingFieldOption, ExpenseState, ExportDateType, OnboardingState, ReimbursableExpensesObject } from 'src/app/core/models/enum/enum.model'; -import { destinationAttribute, errorResponse, exportResponse, exportResponse1, export_settings, replacecontent1, replacecontent2, replacecontent3, workspaceResponse, workspaceResponse1 } from './export-settings.fixture'; +import { destinationAttribute, errorResponse, exportResponse, exportResponse1, export_settings, mockCCCExpenseStateOptions, mockCreditCardExportType, mockReimbursableExpenseGroupingDateOptions, mockReimbursableExpenseGroupingFieldOptions, mockReimbursableExpenseStateOptions, mockReimbursableExportTypeOptions, replacecontent1, replacecontent2, replacecontent3, workspaceResponse, workspaceResponse1 } from './export-settings.fixture'; import { MappingService } from 'src/app/core/services/misc/mapping.service'; import { WorkspaceService } from 'src/app/core/services/workspace/workspace.service'; import { ExportSettingService } from 'src/app/core/services/configuration/export-setting.service'; @@ -33,7 +33,18 @@ describe('ExportSettingsComponent', () => { beforeEach(async () => { service1 = { getExportSettings: () => of(exportResponse), - postExportSettings: () => of(exportResponse) + postExportSettings: () => of(exportResponse), + exportSelectionValidator: () => undefined, + createCreditCardExpenseWatcher: () => undefined, + createReimbursableExpenseWatcher: () => undefined, + getReimbursableExpenseGroupingFieldOptions: () => mockReimbursableExpenseGroupingFieldOptions, + getReimbursableExpenseGroupingDateOptions: () => mockReimbursableExpenseGroupingDateOptions, + getcreditCardExportTypes: () => undefined, + getReimbursableExportTypeOptions: () => undefined, + getCCCExpenseStateOptions: () => undefined, + getExportGroup: () => undefined, + getReimbursableExpenseStateOptions: () => mockReimbursableExpenseStateOptions, + setGeneralMappingsValidator: () => undefined }; service2 = { getGroupedQBODestinationAttributes: () => of(destinationAttribute), @@ -69,13 +80,13 @@ describe('ExportSettingsComponent', () => { component.exportSettings = exportResponse; component.exportSettingsForm = formbuilder.group({ expenseState: [component.exportSettings.expense_group_settings?.expense_state, Validators.required], - reimbursableExpense: [component.exportSettings.workspace_general_settings?.reimbursable_expenses_object ? true : false, (component as any).exportSelectionValidator()], + reimbursableExpense: [component.exportSettings.workspace_general_settings?.reimbursable_expenses_object ? true : false], reimbursableExportType: [component.exportSettings.workspace_general_settings?.reimbursable_expenses_object], - reimbursableExportGroup: [(component as any).getExportGroup(component.exportSettings.expense_group_settings?.reimbursable_expense_group_fields)], + reimbursableExportGroup: [exportSettingService.getExportGroup(component.exportSettings.expense_group_settings?.reimbursable_expense_group_fields)], reimbursableExportDate: [component.exportSettings.expense_group_settings?.reimbursable_export_date_type], - creditCardExpense: [component.exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object ? true : false, (component as any).exportSelectionValidator()], + creditCardExpense: [component.exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object ? true : false], creditCardExportType: [component.exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object], - creditCardExportGroup: [(component as any).getExportGroup(component.exportSettings.expense_group_settings?.corporate_credit_card_expense_group_fields)], + creditCardExportGroup: [exportSettingService.getExportGroup(component.exportSettings.expense_group_settings?.corporate_credit_card_expense_group_fields)], creditCardExportDate: [component.exportSettings.expense_group_settings?.ccc_export_date_type], bankAccount: [component.exportSettings.general_mappings?.bank_account?.id ? component.exportSettings.general_mappings.bank_account : null], defaultCCCAccount: [component.exportSettings.general_mappings?.default_ccc_account?.id ? component.exportSettings.general_mappings.default_ccc_account : null], @@ -105,9 +116,6 @@ describe('ExportSettingsComponent', () => { expect(component.getExportType(ReimbursableExpensesObject.JOURNAL_ENTRY)).toEqual(output); }); - it('getReimbursableExportTypes function check', () => { - expect(component.getReimbursableExportTypes(EmployeeFieldMapping.EMPLOYEE)).toEqual(export_settings); - }); it('navigateToPreviousStep function check', () => { expect(component.navigateToPreviousStep()).toBeUndefined(); @@ -126,22 +134,6 @@ describe('ExportSettingsComponent', () => { expect(component.generateGroupingLabel('reimbursable')).toEqual('How should the expenses be grouped?'); }); - it('createReimbursableExpenseWatcher function check', () => { - component.ngOnInit(); - component.exportSettingsForm.controls.reimbursableExpense.patchValue(true); - expect((component as any).createReimbursableExpenseWatcher()).toBeUndefined(); - fixture.detectChanges(); - component.exportSettingsForm.controls.reimbursableExpense.patchValue(false); - expect((component as any).createReimbursableExpenseWatcher()).toBeUndefined(); - }); - - it('createCreditCardExpenseWatcher function check', () => { - component.exportSettingsForm.controls.creditCardExpense.patchValue(!component.exportSettingsForm.controls.creditCardExpense.value); - expect((component as any).createCreditCardExpenseWatcher()).toBeUndefined(); - // Fixture.detectChanges(); - component.exportSettingsForm.controls.creditCardExpense.patchValue(!component.exportSettingsForm.controls.creditCardExpense.value); - expect((component as any).createCreditCardExpenseWatcher()).toBeUndefined(); - }); it('restrictExpenseGroupSetting function check', () => { expect((component as any).restrictExpenseGroupSetting('CREDIT CARD PURCHASE')).toBeUndefined(); @@ -177,12 +169,6 @@ describe('ExportSettingsComponent', () => { expect(component.showReimbursableAccountsPayableField()).toBeTrue(); }); - it('setGeneralMappingsValidator function check', () => { - component.exportSettingsForm.controls.creditCardExportType.patchValue(CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE); - fixture.detectChanges(); - expect((component as any).setGeneralMappingsValidator()).toBeUndefined(); - }); - it('createReimbursableExportGroupWatcher function check', () => { const reimbursable = component.exportSettingsForm.controls.reimbursableExportGroup.value; component.exportSettingsForm.controls.reimbursableExportGroup.patchValue('expense_id'); @@ -201,11 +187,6 @@ describe('ExportSettingsComponent', () => { expect((component as any).createCreditCardExportGroupWatcher()).toBeUndefined(); }); - it('function check', () => { - expect((component as any).getExportGroup([ExpenseGroupingFieldOption.EXPENSE_ID])).toEqual('expense_id'); - expect((component as any).getExportGroup(null)).toEqual(''); - }); - it('advancedSettingAffected function check', () => { component.exportSettings.workspace_general_settings.corporate_credit_card_expenses_object = CorporateCreditCardExpensesObject.BILL; component.exportSettings.workspace_general_settings.reimbursable_expenses_object = ReimbursableExpensesObject.CHECK; @@ -272,15 +253,4 @@ describe('ExportSettingsComponent', () => { expect(exportSettingService.postExportSettings).toHaveBeenCalled(); expect(component.isLoading).toBeFalse(); }); - - it('exportSelectionValidator function check', () => { - const control = { value: ExpenseState.PAID, parent: formbuilder.group({ - reimbursableExpense: ReimbursableExpensesObject.BILL - }) }; - expect((component as any).exportSelectionValidator()(control as AbstractControl)).toBeNull(); - const control1 = { value: ExpenseState.PAYMENT_PROCESSING, parent: formbuilder.group({ - creditCardExpense: CorporateCreditCardExpensesObject.BILL - }) }; - expect((component as any).exportSelectionValidator()(control1 as AbstractControl)).toBeNull(); - }); }); diff --git a/src/app/shared/components/configuration/export-settings/export-settings.component.ts b/src/app/shared/components/configuration/export-settings/export-settings.component.ts index 2dc71295..3ecdefc6 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.component.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.component.ts @@ -55,64 +55,13 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { cccExpenseStateOptions: ExportSettingFormOption[]; - expenseGroupingFieldOptions: ExportSettingFormOption[] = [ - { - label: 'Report', - value: ExpenseGroupingFieldOption.CLAIM_NUMBER - }, - { - label: 'Payment', - value: ExpenseGroupingFieldOption.SETTLEMENT_ID - }, - { - label: 'Expense', - value: ExpenseGroupingFieldOption.EXPENSE_ID - } - ]; - - reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = [ - { - label: 'Current Date', - value: ExportDateType.CURRENT_DATE - }, - { - label: 'Verification Date', - value: ExportDateType.VERIFIED_AT - }, - { - label: 'Spend Date', - value: ExportDateType.SPENT_AT - }, - { - label: 'Approval Date', - value: ExportDateType.APPROVED_AT - }, - { - label: 'Last Spend Date', - value: ExportDateType.LAST_SPENT_AT - } - ]; + expenseGroupingFieldOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingFieldOptions(); + + reimbursableExpenseGroupingDateOptions: ExportSettingFormOption[] = this.exportSettingService.getReimbursableExpenseGroupingDateOptions(); cccExpenseGroupingDateOptions: ExportSettingFormOption[]; - creditCardExportTypes: ExportSettingFormOption[] = [ - { - label: 'Bill', - value: CorporateCreditCardExpensesObject.BILL - }, - { - label: 'Credit Card Purchase', - value: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE - }, - { - label: 'Journal Entry', - value: CorporateCreditCardExpensesObject.JOURNAL_ENTRY - }, - { - label: 'Debit Card Expense', - value: CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE - } - ]; + creditCardExportTypes: ExportSettingFormOption[] = this.exportSettingService.getcreditCardExportTypes(); reimbursableExportTypes: ExportSettingFormOption[]; @@ -160,84 +109,6 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { return `How should the expense in ${this.getExportType(exportType)} be grouped?`; } - getReimbursableExportTypes(employeeFieldMapping: EmployeeFieldMapping): ExportSettingFormOption[] { - return { - EMPLOYEE: [ - { - label: 'Check', - value: ReimbursableExpensesObject.CHECK - }, - { - label: 'Expense', - value: ReimbursableExpensesObject.EXPENSE - }, - { - label: 'Journal Entry', - value: ReimbursableExpensesObject.JOURNAL_ENTRY - } - ], - VENDOR: [ - { - label: 'Bill', - value: ReimbursableExpensesObject.BILL - }, - { - label: 'Expense', - value: ReimbursableExpensesObject.EXPENSE - }, - { - label: 'Journal Entry', - value: ReimbursableExpensesObject.JOURNAL_ENTRY - } - ] - }[employeeFieldMapping]; - } - - private createReimbursableExpenseWatcher(): void { - this.exportSettingsForm.controls.reimbursableExpense.valueChanges.subscribe((isReimbursableExpenseSelected) => { - if (isReimbursableExpenseSelected) { - this.exportSettingsForm.controls.expenseState.setValidators(Validators.required); - this.exportSettingsForm.controls.expenseState.setValue(this.exportSettings.expense_group_settings?.expense_state ? this.exportSettings.expense_group_settings?.expense_state : ExpenseState.PAYMENT_PROCESSING); - this.exportSettingsForm.controls.reimbursableExportType.setValidators(Validators.required); - this.exportSettingsForm.controls.reimbursableExportGroup.setValidators(Validators.required); - this.exportSettingsForm.controls.reimbursableExportDate.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.expenseState.clearValidators(); - this.exportSettingsForm.controls.reimbursableExportType.clearValidators(); - this.exportSettingsForm.controls.reimbursableExportGroup.clearValidators(); - this.exportSettingsForm.controls.reimbursableExportDate.clearValidators(); - this.exportSettingsForm.controls.expenseState.setValue(null); - this.exportSettingsForm.controls.reimbursableExportType.setValue(null); - this.exportSettingsForm.controls.reimbursableExportGroup.setValue(null); - this.exportSettingsForm.controls.reimbursableExportDate.setValue(null); - } - - this.setGeneralMappingsValidator(); - }); - } - - private createCreditCardExpenseWatcher(): void { - this.exportSettingsForm.controls.creditCardExpense.valueChanges.subscribe((isCreditCardExpenseSelected) => { - if (isCreditCardExpenseSelected) { - this.exportSettingsForm.controls.cccExpenseState.setValidators(Validators.required); - this.exportSettingsForm.controls.cccExpenseState.setValue(this.exportSettings.expense_group_settings?.ccc_expense_state ? this.exportSettings.expense_group_settings?.ccc_expense_state : this.is_simplify_report_closure_enabled ? CCCExpenseState.APPROVED: CCCExpenseState.PAYMENT_PROCESSING); - this.exportSettingsForm.controls.creditCardExportType.setValidators(Validators.required); - this.exportSettingsForm.controls.creditCardExportGroup.setValidators(Validators.required); - this.exportSettingsForm.controls.creditCardExportDate.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.cccExpenseState.clearValidators(); - this.exportSettingsForm.controls.creditCardExportType.clearValidators(); - this.exportSettingsForm.controls.creditCardExportGroup.clearValidators(); - this.exportSettingsForm.controls.creditCardExportDate.clearValidators(); - this.exportSettingsForm.controls.cccExpenseState.setValue(null); - this.exportSettingsForm.controls.creditCardExportType.setValue(null); - this.exportSettingsForm.controls.creditCardExportGroup.setValue(null); - this.exportSettingsForm.controls.creditCardExportDate.setValue(null); - } - - this.setGeneralMappingsValidator(); - }); - } private restrictExpenseGroupSetting(creditCardExportType: string | null) : void { if (creditCardExportType === CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE || creditCardExportType === CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE) { @@ -271,52 +142,18 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { private createReimbursableExportTypeWatcher(): void { this.exportSettingsForm.controls.reimbursableExportType.valueChanges.subscribe(() => { - this.setGeneralMappingsValidator(); - }); + this.exportSettingService.setGeneralMappingsValidator(this.exportSettingsForm); +}); } private createCreditCardExportTypeWatcher(): void { this.restrictExpenseGroupSetting(this.exportSettings.workspace_general_settings.corporate_credit_card_expenses_object); this.exportSettingsForm.controls.creditCardExportType.valueChanges.subscribe((creditCardExportType: string) => { - this.setGeneralMappingsValidator(); + this.exportSettingService.setGeneralMappingsValidator(this.exportSettingsForm); this.restrictExpenseGroupSetting(creditCardExportType); }); } - private exportSelectionValidator(): ValidatorFn { - return (control: AbstractControl): {[key: string]: object} | null => { - let forbidden = true; - if (this.exportSettingsForm) { - if (typeof control.value === 'boolean') { - if (control.value) { - forbidden = false; - } else { - if (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value) { - forbidden = false; - } - } - } else if ((control.value === ExpenseState.PAID || control.value === ExpenseState.PAYMENT_PROCESSING || control.value === CCCExpenseState.APPROVED) - && (control.parent?.get('reimbursableExpense')?.value || control.parent?.get('creditCardExpense')?.value)) { - forbidden = false; - } - - if (!forbidden) { - control.parent?.get('expenseState')?.setErrors(null); - control.parent?.get('cccExpenseState')?.setErrors(null); - control.parent?.get('reimbursableExpense')?.setErrors(null); - control.parent?.get('creditCardExpense')?.setErrors(null); - return null; - } - } - - return { - forbiddenOption: { - value: control.value - } - }; - }; - } - showBankAccountField(): boolean { return this.employeeFieldMapping === EmployeeFieldMapping.EMPLOYEE && this.exportSettingsForm.controls.reimbursableExportType.value && this.exportSettingsForm.controls.reimbursableExportType.value !== ReimbursableExpensesObject.EXPENSE; } @@ -349,50 +186,6 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { return (this.exportSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.BILL || this.exportSettingsForm.controls.creditCardExportType.value === CorporateCreditCardExpensesObject.BILL) ? ReimbursableExpensesObject.BILL : ReimbursableExpensesObject.JOURNAL_ENTRY; } - private setGeneralMappingsValidator(): void { - if (this.showBankAccountField()) { - this.exportSettingsForm.controls.bankAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.bankAccount.clearValidators(); - this.exportSettingsForm.controls.bankAccount.updateValueAndValidity(); - } - - if (this.showCreditCardAccountField()) { - this.exportSettingsForm.controls.defaultCCCAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.defaultCCCAccount.clearValidators(); - this.exportSettingsForm.controls.defaultCCCAccount.updateValueAndValidity(); - } - - if (this.showDebitCardAccountField()) { - this.exportSettingsForm.controls.defaultDebitCardAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.defaultDebitCardAccount.clearValidators(); - this.exportSettingsForm.controls.defaultDebitCardAccount.updateValueAndValidity(); - } - - if (this.showReimbursableAccountsPayableField() || this.showCCCAccountsPayableField()) { - this.exportSettingsForm.controls.accountsPayable.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.accountsPayable.clearValidators(); - this.exportSettingsForm.controls.accountsPayable.updateValueAndValidity(); - } - - if (this.showDefaultCreditCardVendorField()) { - this.exportSettingsForm.controls.defaultCreditCardVendor.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.defaultCreditCardVendor.clearValidators(); - this.exportSettingsForm.controls.defaultCreditCardVendor.updateValueAndValidity(); - } - - if (this.showExpenseAccountField()) { - this.exportSettingsForm.controls.qboExpenseAccount.setValidators(Validators.required); - } else { - this.exportSettingsForm.controls.qboExpenseAccount.clearValidators(); - this.exportSettingsForm.controls.qboExpenseAccount.updateValueAndValidity(); - } - } - private createReimbursableExportGroupWatcher(): void { this.exportSettingsForm.controls.reimbursableExportGroup.valueChanges.subscribe((reimbursableExportGroup: ExpenseGroupingFieldOption) => { if (reimbursableExportGroup === ExpenseGroupingFieldOption.EXPENSE_ID) { @@ -430,14 +223,21 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { }); } + private setupExportWatchers(): void { + this.exportSettingsForm?.controls.reimbursableExpense?.setValidators(this.exportSettingService.exportSelectionValidator(this.exportSettingsForm)); + this.exportSettingsForm?.controls.creditCardExpense?.setValidators(this.exportSettingService.exportSelectionValidator(this.exportSettingsForm)); + } + private setCustomValidatorsAndWatchers(): void { + this.setupExportWatchers(); + // Date grouping this.setCreditCardExpenseGroupingDateOptions(this.exportSettingsForm.controls.creditCardExportGroup.value); // Toggles - this.createReimbursableExpenseWatcher(); - this.createCreditCardExpenseWatcher(); + this.exportSettingService.createReimbursableExpenseWatcher(this.exportSettingsForm, this.exportSettings); + this.exportSettingService.createCreditCardExpenseWatcher(this.exportSettingsForm, this.exportSettings); // Export select fields this.createReimbursableExportTypeWatcher(); @@ -447,18 +247,7 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { this.createReimbursableExportGroupWatcher(); this.createCreditCardExportGroupWatcher(); - this.setGeneralMappingsValidator(); - } - - private getExportGroup(exportGroups: string[] | null): string { - if (exportGroups) { - const exportGroup = exportGroups.find((exportGroup) => { - return exportGroup === ExpenseGroupingFieldOption.EXPENSE_ID || exportGroup === ExpenseGroupingFieldOption.CLAIM_NUMBER || exportGroup === ExpenseGroupingFieldOption.SETTLEMENT_ID; - }); - return exportGroup ? exportGroup : ExpenseGroupingFieldOption.CLAIM_NUMBER; - } - - return ''; + this.exportSettingService.setGeneralMappingsValidator(this.exportSettingsForm); } private getSettingsAndSetupForm(): void { @@ -471,7 +260,6 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { ]).subscribe(response => { this.exportSettings = response[0]; this.employeeFieldMapping = response[2].employee_field_mapping; - this.reimbursableExportTypes = this.getReimbursableExportTypes(this.employeeFieldMapping); this.bankAccounts = response[1].BANK_ACCOUNT; this.cccAccounts = response[1].CREDIT_CARD_ACCOUNT; @@ -481,27 +269,9 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { this.is_simplify_report_closure_enabled = response[2].is_simplify_report_closure_enabled; this.import_items = response[2].import_items; - this.cccExpenseStateOptions = [ - { - label: this.is_simplify_report_closure_enabled ? 'Approved' : 'Payment Processing', - value: this.is_simplify_report_closure_enabled ? CCCExpenseState.APPROVED: CCCExpenseState.PAYMENT_PROCESSING - }, - { - label: this.is_simplify_report_closure_enabled ? 'Closed' : 'Paid', - value: CCCExpenseState.PAID - } - ]; - - this.expenseStateOptions = [ - { - label: this.is_simplify_report_closure_enabled ? 'Processing' : 'Payment Processing', - value: ExpenseState.PAYMENT_PROCESSING - }, - { - label: this.is_simplify_report_closure_enabled ? 'Closed' : 'Paid', - value: ExpenseState.PAID - } - ]; + this.reimbursableExportTypes = this.exportSettingService.getReimbursableExportTypeOptions(this.employeeFieldMapping); + this.cccExpenseStateOptions = this.exportSettingService.getCCCExpenseStateOptions(this.is_simplify_report_closure_enabled); + this.expenseStateOptions = this.exportSettingService.getReimbursableExpenseStateOptions(this.is_simplify_report_closure_enabled); this.setupForm(); }); @@ -510,14 +280,14 @@ export class ExportSettingsComponent implements OnInit, OnDestroy { private setupForm(): void { this.exportSettingsForm = this.formBuilder.group({ expenseState: [this.exportSettings.expense_group_settings?.expense_state], - reimbursableExpense: [this.exportSettings.workspace_general_settings?.reimbursable_expenses_object ? true : false, this.exportSelectionValidator()], + reimbursableExpense: [this.exportSettings.workspace_general_settings?.reimbursable_expenses_object ? true : false], reimbursableExportType: [this.exportSettings.workspace_general_settings?.reimbursable_expenses_object], - reimbursableExportGroup: [this.getExportGroup(this.exportSettings.expense_group_settings?.reimbursable_expense_group_fields)], + reimbursableExportGroup: [this.exportSettingService.getExportGroup(this.exportSettings.expense_group_settings?.reimbursable_expense_group_fields)], reimbursableExportDate: [this.exportSettings.expense_group_settings?.reimbursable_export_date_type], cccExpenseState: [this.exportSettings.expense_group_settings?.ccc_expense_state], - creditCardExpense: [this.exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object ? true : false, this.exportSelectionValidator()], + creditCardExpense: [this.exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object ? true : false], creditCardExportType: [this.exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object], - creditCardExportGroup: [this.getExportGroup(this.exportSettings.expense_group_settings?.corporate_credit_card_expense_group_fields)], + creditCardExportGroup: [this.exportSettingService.getExportGroup(this.exportSettings.expense_group_settings?.corporate_credit_card_expense_group_fields)], creditCardExportDate: [this.exportSettings.expense_group_settings?.ccc_export_date_type], bankAccount: [this.exportSettings.general_mappings?.bank_account?.id ? this.exportSettings.general_mappings.bank_account : null], defaultCCCAccount: [this.exportSettings.general_mappings?.default_ccc_account?.id ? this.exportSettings.general_mappings.default_ccc_account : null], diff --git a/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts b/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts index 4f9a8fe9..87b0e46b 100644 --- a/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts +++ b/src/app/shared/components/configuration/export-settings/export-settings.fixture.ts @@ -1,7 +1,7 @@ import { ExportSettingFormOption, ExportSettingGet } from "src/app/core/models/configuration/export-setting.model"; import { GroupedDestinationAttribute } from "src/app/core/models/db/destination-attribute.model"; import { WorkspaceGeneralSetting } from "src/app/core/models/db/workspace-general-setting.model"; -import { AutoMapEmployee, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, CCCExpenseState, ExportDateType, ReimbursableExpensesObject } from "src/app/core/models/enum/enum.model"; +import { AutoMapEmployee, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, CCCExpenseState, ExportDateType, ReimbursableExpensesObject, ExpenseGroupingFieldOption } from "src/app/core/models/enum/enum.model"; export const export_settings: ExportSettingFormOption[] = [ { @@ -184,7 +184,7 @@ export const exportResponse: ExportSettingGet = { expense_group_settings: { expense_state: ExpenseState.PAID, ccc_expense_state: CCCExpenseState.PAID, - reimbursable_expense_group_fields: ['sample'], + reimbursable_expense_group_fields: [ExpenseGroupingFieldOption.EXPENSE_ID], reimbursable_export_date_type: ExportDateType.APPROVED_AT, corporate_credit_card_expense_group_fields: ['sipper'], ccc_export_date_type: ExportDateType.SPENT_AT @@ -225,3 +225,114 @@ export const errorResponse = { company_name: 'QBO' } }; + +export const mockReimbursableExpenseGroupingFieldOptions = [ + { + label: 'Report', + value: ExpenseGroupingFieldOption.CLAIM_NUMBER + }, + { + label: 'Payment', + value: ExpenseGroupingFieldOption.SETTLEMENT_ID + }, + { + label: 'Expense', + value: ExpenseGroupingFieldOption.EXPENSE_ID + } +]; + +export const mockReimbursableExpenseGroupingDateOptions = [ + + { + label: 'Current Date', + value: ExportDateType.CURRENT_DATE + }, + { + label: 'Verification Date', + value: ExportDateType.VERIFIED_AT + }, + { + label: 'Spend Date', + value: ExportDateType.SPENT_AT + }, + { + label: 'Approval Date', + value: ExportDateType.APPROVED_AT + }, + { + label: 'Last Spend Date', + value: ExportDateType.LAST_SPENT_AT + } +]; + +export const mockCreditCardExportType = [ + { + label: 'Bill', + value: CorporateCreditCardExpensesObject.BILL + }, + { + label: 'Credit Card Purchase', + value: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE + }, + { + label: 'Journal Entry', + value: CorporateCreditCardExpensesObject.JOURNAL_ENTRY + }, + { + label: 'Debit Card Expense', + value: CorporateCreditCardExpensesObject.DEBIT_CARD_EXPENSE + } +]; + +export const mockReimbursableExportTypeOptions = { + EMPLOYEE: [ + { + label: 'Check', + value: ReimbursableExpensesObject.CHECK + }, + { + label: 'Expense', + value: ReimbursableExpensesObject.EXPENSE + }, + { + label: 'Journal Entry', + value: ReimbursableExpensesObject.JOURNAL_ENTRY + } + ], + VENDOR: [ + { + label: 'Bill', + value: ReimbursableExpensesObject.BILL + }, + { + label: 'Expense', + value: ReimbursableExpensesObject.EXPENSE + }, + { + label: 'Journal Entry', + value: ReimbursableExpensesObject.JOURNAL_ENTRY + } + ] +}; + +export const mockCCCExpenseStateOptions = [ + { + label: 'Payment Processing', + value: CCCExpenseState.PAYMENT_PROCESSING + }, + { + label: 'Paid', + value: CCCExpenseState.PAID + } +]; + +export const mockReimbursableExpenseStateOptions = [ + { + label: 'Processing', + value: ExpenseState.PAYMENT_PROCESSING + }, + { + label: 'Closed', + value: ExpenseState.PAID + } +]; diff --git a/src/app/shared/components/core/select/select.component.html b/src/app/shared/components/core/select/select.component.html index 1a052075..46761f87 100644 --- a/src/app/shared/components/core/select/select.component.html +++ b/src/app/shared/components/core/select/select.component.html @@ -27,7 +27,8 @@ + [listName]="mandatoryErrorListName" [customErrorMessage]="customErrorMessage"> +

Click Date: Fri, 18 Aug 2023 13:48:12 +0530 Subject: [PATCH 43/47] conflicts fix --- .../models/configuration/export-setting.model.ts | 6 +----- .../configuration/export-setting.service.spec.ts | 16 +++------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/app/core/models/configuration/export-setting.model.ts b/src/app/core/models/configuration/export-setting.model.ts index 5d10902a..371d4898 100644 --- a/src/app/core/models/configuration/export-setting.model.ts +++ b/src/app/core/models/configuration/export-setting.model.ts @@ -1,9 +1,5 @@ import { UntypedFormGroup } from "@angular/forms"; -<<<<<<< HEAD -import { CorporateCreditCardExpensesObject, ExpenseGroupingFieldOption, ExpenseState, CCCExpenseState, ExportDateType, ReimbursableExpensesObject, AutoMapEmployee, EmployeeFieldMapping } from "../enum/enum.model"; -======= -import { CorporateCreditCardExpensesObject, ExpenseGroupingFieldOption, ExpenseState, CCCExpenseState, ExportDateType, ReimbursableExpensesObject, FyleField, NameInJournalEntry } from "../enum/enum.model"; ->>>>>>> 170b61efb196c94831dbcd371e7bd393dcdaa6a9 +import { CorporateCreditCardExpensesObject, ExpenseGroupingFieldOption, ExpenseState, CCCExpenseState, ExportDateType, ReimbursableExpensesObject, NameInJournalEntry } from "../enum/enum.model"; import { ExpenseGroupSettingGet, ExpenseGroupSettingPost } from "../db/expense-group-setting.model"; import { DefaultDestinationAttribute, GeneralMapping } from "../db/general-mapping.model"; import { SelectFormOption } from "../misc/select-form-option.model"; diff --git a/src/app/core/services/configuration/export-setting.service.spec.ts b/src/app/core/services/configuration/export-setting.service.spec.ts index 71f0cece..55619156 100644 --- a/src/app/core/services/configuration/export-setting.service.spec.ts +++ b/src/app/core/services/configuration/export-setting.service.spec.ts @@ -1,11 +1,7 @@ import { getTestBed, TestBed } from '@angular/core/testing'; import { ExportSettingService } from './export-setting.service'; import { ExportSettingGet, ExportSettingPost } from '../../models/configuration/export-setting.model'; -<<<<<<< HEAD -import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCreditCardExpensesObject, ExportDateType, ExpenseGroupingFieldOption } from '../../models/enum/enum.model'; -======= -import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCreditCardExpensesObject, ExportDateType, NameInJournalEntry } from '../../models/enum/enum.model'; ->>>>>>> 170b61efb196c94831dbcd371e7bd393dcdaa6a9 +import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCreditCardExpensesObject, ExportDateType, ExpenseGroupingFieldOption, NameInJournalEntry } from '../../models/enum/enum.model'; import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; import { environment } from 'src/environments/environment'; import { AbstractControl, FormBuilder } from '@angular/forms'; @@ -49,11 +45,8 @@ describe('ExportSettingService', () => { workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL, -<<<<<<< HEAD - is_simplify_report_closure_enabled: true -======= + is_simplify_report_closure_enabled: true, name_in_journal_entry: NameInJournalEntry.EMPLOYEE ->>>>>>> 170b61efb196c94831dbcd371e7bd393dcdaa6a9 }, general_mappings: { bank_account: { id: '1', name: 'Fyle' }, @@ -112,11 +105,8 @@ describe('ExportSettingService', () => { workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL, -<<<<<<< HEAD - is_simplify_report_closure_enabled: true -======= + is_simplify_report_closure_enabled: true, name_in_journal_entry: NameInJournalEntry.MERCHANT ->>>>>>> 170b61efb196c94831dbcd371e7bd393dcdaa6a9 }, general_mappings: { bank_account: { id: '1', name: 'Fyle' }, From b2a6b11c9688eb0198384c2990e69d859a8b5fd9 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Fri, 18 Aug 2023 16:17:44 +0530 Subject: [PATCH 44/47] merged master --- .../configuration/clone-setting.model.spec.ts | 7 ++-- .../configuration/clone-setting.model.ts | 6 ++-- .../clone-settings.component.html | 33 +++++++++---------- .../clone-settings.component.ts | 10 +++++- .../clone-settings/clone-settings.fixture.ts | 6 ++-- 5 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/app/core/models/configuration/clone-setting.model.spec.ts b/src/app/core/models/configuration/clone-setting.model.spec.ts index edb53ba0..0274b050 100644 --- a/src/app/core/models/configuration/clone-setting.model.spec.ts +++ b/src/app/core/models/configuration/clone-setting.model.spec.ts @@ -1,6 +1,6 @@ import { TestBed } from '@angular/core/testing'; import { UntypedFormControl, UntypedFormGroup} from '@angular/forms'; -import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, MappingDestinationField, MappingSourceField, ReimbursableExpensesObject } from '../enum/enum.model'; +import { AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, MappingDestinationField, MappingSourceField, NameInJournalEntry, ReimbursableExpensesObject } from '../enum/enum.model'; import { CloneSettingModel, CloneSettingPost } from './clone-setting.model'; import { ImportSettingModel } from './import-setting.model'; import { MappingSetting } from '../db/mapping-setting.model'; @@ -108,7 +108,8 @@ describe('CloneSettingModel', () => { }, workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, - corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL + corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.BILL, + name_in_journal_entry: NameInJournalEntry.EMPLOYEE }, general_mappings: { bank_account: {id: '1', name: 'Fyle'}, @@ -119,7 +120,7 @@ describe('CloneSettingModel', () => { default_debit_card_account: {id: '1', name: 'Fyle'} } }, - advanced_settings: { + advanced_configurations: { workspace_general_settings: { sync_fyle_to_qbo_payments: false, sync_qbo_to_fyle_payments: false, diff --git a/src/app/core/models/configuration/clone-setting.model.ts b/src/app/core/models/configuration/clone-setting.model.ts index 2fd9b470..5055b62f 100644 --- a/src/app/core/models/configuration/clone-setting.model.ts +++ b/src/app/core/models/configuration/clone-setting.model.ts @@ -9,14 +9,14 @@ export type CloneSetting = { workspace_id: number, export_settings: ExportSettingGet, import_settings: ImportSettingGet, - advanced_settings: AdvancedSettingGet, + advanced_configurations: AdvancedSettingGet, employee_mappings: EmployeeSettingGet } export type CloneSettingPost = { export_settings: ExportSettingPost, import_settings: ImportSettingPost, - advanced_settings: AdvancedSettingPost, + advanced_configurations: AdvancedSettingPost, employee_mappings: EmployeeSettingPost } @@ -36,7 +36,7 @@ export class CloneSettingModel { const cloneSettingPayload: CloneSettingPost = { export_settings: exportSettingPayload, import_settings: importSettingPayload, - advanced_settings: advancedSettingPayload, + advanced_configurations: advancedSettingPayload, employee_mappings: employeeMappingPayload }; diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 82994569..73ec5a79 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -15,7 +15,8 @@

Employee Mappings

- In this section, you can configure how map fyle employees to QuickBooks Online Vendor / Employee + In this section, you can configure how map fyle employees to QuickBooks Online Vendor / + Employee
@@ -34,7 +35,7 @@
@@ -184,7 +185,8 @@
In this section, you c
@@ -213,8 +215,7 @@
In this section, you c

Corporate Card Expense

-
@@ -257,8 +258,8 @@
In this section, you c
+ [placeholder]="'Select the export date'" [formControllerName]="'creditCardExportType'" + [phase]="ProgressPhase.ONBOARDING"> @@ -295,7 +296,8 @@
In this section, you c @@ -374,7 +376,8 @@
In this section, you c -
+
In this section, you c
-
- -
+ +
In this section, you c
-
diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts index b11d3cc5..eb4bca32 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.ts @@ -83,6 +83,8 @@ export class CloneSettingsComponent implements OnInit { SimpleSearchType = SimpleSearchType; taxCodes: DestinationAttribute[]; + + autoCreateMerchantsAsVendors: boolean; chartOfAccountTypesList: string[] = [ 'Expense', 'Other Expense', 'Fixed Asset', 'Cost of Goods Sold', 'Current Liability', 'Equity', @@ -162,6 +164,11 @@ export class CloneSettingsComponent implements OnInit { } } + showImportVendors(): boolean { + return !this.autoCreateMerchantsAsVendors; + } + + showExpenseAccountField(): boolean { return this.cloneSettingsForm.controls.reimbursableExportType.value === ReimbursableExpensesObject.EXPENSE; } @@ -303,6 +310,7 @@ export class CloneSettingsComponent implements OnInit { this.exportSettingService.createReimbursableExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); this.exportSettingService.createCreditCardExpenseWatcher(this.cloneSettingsForm, this.cloneSettings.export_settings); + this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); // Export select fields this.createReimbursableExportTypeWatcher(); @@ -317,7 +325,6 @@ export class CloneSettingsComponent implements OnInit { this.setCreditCardExpenseGroupingDateOptions(this.cloneSettingsForm.controls.creditCardExportGroup.value); this.setupExpenseFieldWatcher(); - this.exportSettingService.setGeneralMappingsValidator(this.cloneSettingsForm); } createChartOfAccountField(type: string): UntypedFormGroup { @@ -479,6 +486,7 @@ export class CloneSettingsComponent implements OnInit { this.employeeFieldMapping = this.cloneSettings.employee_mappings.workspace_general_settings.employee_field_mapping; this.mappingSettings = responses[2].results; + this.autoCreateMerchantsAsVendors = responses[0].advanced_configurations.workspace_general_settings.auto_create_merchants_as_vendors; this.bankAccounts = responses[1].BANK_ACCOUNT; this.cccAccounts = responses[1].CREDIT_CARD_ACCOUNT; this.accountsPayables = responses[1].ACCOUNTS_PAYABLE; diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts b/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts index 98a87f82..f22471dc 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts +++ b/src/app/integration/onboarding/clone-settings/clone-settings.fixture.ts @@ -1,6 +1,6 @@ import { CloneSetting, CloneSettingExist, CloneSettingPost } from "src/app/core/models/configuration/clone-setting.model"; import { GroupedDestinationAttribute } from "src/app/core/models/db/destination-attribute.model"; -import {AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, MappingDestinationField, MappingSourceField, ReimbursableExpensesObject } from "src/app/core/models/enum/enum.model"; +import {AutoMapEmployee, CCCExpenseState, CorporateCreditCardExpensesObject, EmployeeFieldMapping, ExpenseState, ExportDateType, MappingDestinationField, MappingSourceField, NameInJournalEntry, ReimbursableExpensesObject } from "src/app/core/models/enum/enum.model"; export const mockCloneSettingExist: CloneSettingExist = { is_available: true, @@ -20,6 +20,7 @@ export const mockCloneSettingsGet: CloneSetting = { }, workspace_general_settings: { reimbursable_expenses_object: ReimbursableExpensesObject.BILL, + name_in_journal_entry: NameInJournalEntry.EMPLOYEE, corporate_credit_card_expenses_object: null, is_simplify_report_closure_enabled: false }, @@ -92,12 +93,13 @@ export const mockCloneSettingsGet: CloneSetting = { workspace: 1, reimbursable_expenses_object: null, corporate_credit_card_expenses_object: CorporateCreditCardExpensesObject.CREDIT_CARD_PURCHASE, + name_in_journal_entry: NameInJournalEntry.EMPLOYEE, auto_map_employees: AutoMapEmployee.EMAIL, is_simplify_report_closure_enabled: true }, workspace_id: 1 }, - advanced_settings: { + advanced_configurations: { workspace_general_settings: { sync_fyle_to_qbo_payments: true, sync_qbo_to_fyle_payments: false, From 00ad64d36c78469ee99b473e41f84df2b0bd25fb Mon Sep 17 00:00:00 2001 From: Nilesh Pant <58652823+NileshPant1999@users.noreply.github.com> Date: Wed, 23 Aug 2023 12:19:41 +0530 Subject: [PATCH 45/47] clone settings Advance Settings (#298) --- src/app/app.module.ts | 2 +- src/app/core/core.module.ts | 5 +- .../email-multi-select.component.html | 57 ++++ .../email-multi-select.component.scss | 111 ++++++++ .../email-multi-select.component.spec.ts | 61 +++++ .../email-multi-select.component.ts | 53 ++++ .../advanced-setting.service.spec.ts | 16 +- .../configuration/advanced-setting.service.ts | 62 ++++- .../export-setting.service.spec.ts | 9 +- .../import-setting.service.spec.ts | 67 ++++- .../configuration/import-setting.service.ts | 4 +- src/app/integration/integration.module.ts | 1 - .../clone-settings.component.html | 256 +++++++++++++++++- .../clone-settings.component.scss | 33 +++ .../clone-settings.component.spec.ts | 84 +++++- .../clone-settings.component.ts | 133 ++++++++- .../onboarding/onboarding.module.ts | 4 +- .../advanced-settings.component.spec.ts | 3 +- .../advanced-settings.fixture.ts | 19 +- .../configuration-toggle-field.component.scss | 24 -- .../employee-settings.component.ts | 2 +- .../import-settings.fixture.ts | 7 + .../core/select/select.component.spec.ts | 16 +- .../onboarding-stepper.component.spec.ts | 5 + src/app/shared/shared.module.ts | 7 +- src/styles.scss | 32 +-- 26 files changed, 980 insertions(+), 93 deletions(-) create mode 100644 src/app/core/email-multi-select/email-multi-select.component.html create mode 100644 src/app/core/email-multi-select/email-multi-select.component.scss create mode 100644 src/app/core/email-multi-select/email-multi-select.component.spec.ts create mode 100644 src/app/core/email-multi-select/email-multi-select.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 02f2334d..7949b807 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -26,7 +26,7 @@ import { GlobalErrorHandler } from './app.errorhandling'; FormsModule, ReactiveFormsModule, MatSnackBarModule, - MatDialogModule + MatDialogModule, ], providers: [ { diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 17d1d58d..b2ef55d1 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -1,10 +1,13 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; +import { EmailMultiSelectComponent } from './email-multi-select/email-multi-select.component'; @NgModule({ - declarations: [], + declarations: [ + EmailMultiSelectComponent + ], imports: [ CommonModule, MatDialogModule diff --git a/src/app/core/email-multi-select/email-multi-select.component.html b/src/app/core/email-multi-select/email-multi-select.component.html new file mode 100644 index 00000000..5c827ccb --- /dev/null +++ b/src/app/core/email-multi-select/email-multi-select.component.html @@ -0,0 +1,57 @@ +
+ + + + +
+ +
+ +
+
+
+ +
+
+
+ + +
+ + +
+ +
+
+ +
+
+
+ +
diff --git a/src/app/core/email-multi-select/email-multi-select.component.scss b/src/app/core/email-multi-select/email-multi-select.component.scss new file mode 100644 index 00000000..e8ec6cb2 --- /dev/null +++ b/src/app/core/email-multi-select/email-multi-select.component.scss @@ -0,0 +1,111 @@ +.email-multi-select { + &--email-number { + margin-top: 5px; + } + + &--delele-all-icon { + margin-right: 5px; + color: #5a5d72; + } + + &--delele-all-icon-clone-settings { + margin-right: 25px; + color: #5a5d72; + } + + &--delele-all-icon img { + height: 10px; + width: 10px; + } + + &--delele-all-icon-clone-settings img { + height: 10px; + width: 10px; + } + + &--selected-email { + background-color: #ffffff; + border: 1px solid #dfdfe2; + border-radius: 12px; + padding: 10px; + height: 15px; + font-size: 12px; + margin-top: 2px; + } + + &--vertical { + border-left: 1px solid #dfdfe2; + height: 20px; + margin-left: 10px; + } + + &--display-email { + display: block; + max-width: 160px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + &--bottom-name { + font-size: 12px; + line-height: 15px; + color: #A9ACBC; + } + + &--head-name { + font-size: 14px; + line-height: 18px; + color: #414562; + flex: none; + order: 1; + flex-grow: 0; + } + + &--no-result { + padding: 8px 16px; + margin: 10px; + } +} + +.configuration { + &--field-section { + padding: 0px 32px; + } +} + +p { + margin: 0; +} + +.mat-icon-close { + color: #a9acbc; + padding-left: 5px; + padding-top: 5px; +} + +.mat-icon-close img { + height: 10px; + width: 10px; +} + +.mat-primary .mat-option.mat-selected:not(.mat-option-disabled) { + color: #e91e63; +} + +.multiline-mat-option.mat-option { + white-space: normal; + line-height: normal; + height: auto !important; + font-size: none !important; +} + +.mat-option { + padding-top: 8px; + padding-bottom: 8px; + margin: 10px; +} + +.example-additional-selection { + margin-left: 10px; +} diff --git a/src/app/core/email-multi-select/email-multi-select.component.spec.ts b/src/app/core/email-multi-select/email-multi-select.component.spec.ts new file mode 100644 index 00000000..b012823c --- /dev/null +++ b/src/app/core/email-multi-select/email-multi-select.component.spec.ts @@ -0,0 +1,61 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EmailMultiSelectComponent } from './email-multi-select.component'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { Router } from '@angular/router'; +import { SearchPipe } from 'src/app/shared/pipes/search.pipe'; +import { FormBuilder } from '@angular/forms'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; + +describe('EmailMultiSelectComponent', () => { + let component: EmailMultiSelectComponent; + let fixture: ComponentFixture; + const routerSpy = { navigate: jasmine.createSpy('navigate'), url: '/path' }; + let router: Router; + let formBuilder: FormBuilder; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatDialogModule, NoopAnimationsModule], + declarations: [ EmailMultiSelectComponent, SearchPipe ], + providers: [ + FormBuilder, + { provide: Router, useValue: routerSpy } + ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(EmailMultiSelectComponent); + component = fixture.componentInstance; + formBuilder = TestBed.inject(FormBuilder); + const form = formBuilder.group({ + searchOption: [], + emails: [['fyle@fyle.in', 'integrations@fyle.in']], + employeeMapping: [['EMPLOYEE']] + }); + component.form = form; + const adminEmails: any[] = [{name: 'fyle', email: 'fyle@fyle.in'}, {name: 'dhaara', email: 'fyle1@fyle.in'}]; + component.options = adminEmails; + component.formControllerName = 'employeeMapping'; + component.isFieldMandatory = true; + component.placeholder = 'Select representation'; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('delete function check', () => { + const event = new Event("click", undefined); + expect(component.delete(event, 'fyle@fyle.in')).toBeUndefined(); + fixture.detectChanges(); + expect(component.form.controls.emails.value).toEqual(['integrations@fyle.in']); + expect(component.delete(event, 'fyle@fyle.in', true)).toBeUndefined(); + fixture.detectChanges(); + expect(component.form.controls.emails.value).toBeNull(); + }); +}); diff --git a/src/app/core/email-multi-select/email-multi-select.component.ts b/src/app/core/email-multi-select/email-multi-select.component.ts new file mode 100644 index 00000000..a3a685ea --- /dev/null +++ b/src/app/core/email-multi-select/email-multi-select.component.ts @@ -0,0 +1,53 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { AdvancedSettingFormOption } from 'src/app/core/models/configuration/advanced-setting.model'; +import { ExportSettingFormOption } from 'src/app/core/models/configuration/export-setting.model'; +import { SimpleSearchPage, SimpleSearchType } from 'src/app/core/models/enum/enum.model'; +import { HelperService } from 'src/app/core/services/core/helper.service'; + +@Component({ + selector: 'app-email-multi-select', + templateUrl: './email-multi-select.component.html', + styleUrls: ['./email-multi-select.component.scss'] +}) +export class EmailMultiSelectComponent implements OnInit { + + @Input() form: FormGroup; + + @Input() options: ExportSettingFormOption[] | AdvancedSettingFormOption[] | any[]; + + @Input() placeholder: string; + + @Input() formControllerName: string; + + @Input() isFieldMandatory: boolean; + + @Input() mandatoryErrorListName: string; + + @Input() customErrorMessage: string; + + @Input() isCloneSettings: boolean; + + SimpleSearchPage = SimpleSearchPage; + + SimpleSearchType = SimpleSearchType; + + constructor( + public helperService: HelperService + ) { } + + delete(event: Event, email: string, deleteAll: boolean = false) { + event.preventDefault(); + event.stopPropagation(); + if (deleteAll) { + this.form.controls.emails.patchValue(null); + } else { + const emails = this.form.value.emails.filter((value: string) => value !== email); + this.form.controls.emails.patchValue(emails); + } + } + + ngOnInit(): void { + } + +} diff --git a/src/app/core/services/configuration/advanced-setting.service.spec.ts b/src/app/core/services/configuration/advanced-setting.service.spec.ts index 7d418906..970beb96 100644 --- a/src/app/core/services/configuration/advanced-setting.service.spec.ts +++ b/src/app/core/services/configuration/advanced-setting.service.spec.ts @@ -6,6 +6,9 @@ import { environment } from 'src/environments/environment'; import { WorkspaceScheduleEmailOptions } from '../../models/db/workspace-schedule.model'; import { ExpenseFilterResponse, SkipExport } from '../../models/misc/skip-export.model'; import { JoinOption, Operator } from '../../models/enum/enum.model'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; +import { FormBuilder } from '@angular/forms'; +import { paymentSyncOptions } from 'src/app/shared/components/configuration/advanced-settings/advanced-settings.fixture'; describe('AdvancedSettingService', () => { let service: AdvancedSettingService; @@ -13,13 +16,15 @@ describe('AdvancedSettingService', () => { let httpMock: HttpTestingController; const API_BASE_URL = environment.api_url; const workspace_id = environment.tests.workspaceId; + let formbuilder: FormBuilder; beforeEach(() => { TestBed.configureTestingModule({ - imports: [HttpClientTestingModule], + imports: [HttpClientTestingModule, MatDialogModule], providers: [AdvancedSettingService] }); injector = getTestBed(); + formbuilder = TestBed.inject(FormBuilder); service = injector.inject(AdvancedSettingService); httpMock = injector.inject(HttpTestingController); }); @@ -200,4 +205,13 @@ describe('AdvancedSettingService', () => { }); req.flush(response); }); + + it('getPaymentSyncOptions function check', () => { + const value = service.getPaymentSyncOptions(); + expect(value).toEqual(paymentSyncOptions); + }); + + it('getFrequencyIntervals function check', () => { + service.getFrequencyIntervals(); + }); }); diff --git a/src/app/core/services/configuration/advanced-setting.service.ts b/src/app/core/services/configuration/advanced-setting.service.ts index fe0d58cb..17f3c112 100644 --- a/src/app/core/services/configuration/advanced-setting.service.ts +++ b/src/app/core/services/configuration/advanced-setting.service.ts @@ -1,12 +1,16 @@ import { HttpParams } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, Output, EventEmitter } from '@angular/core'; import { Observable, Subject } from 'rxjs'; import { Cacheable, CacheBuster } from 'ts-cacheable'; -import { AdvancedSettingGet, AdvancedSettingPost, AdvancedSettingWorkspaceSchedulePost } from '../../models/configuration/advanced-setting.model'; +import { AdvancedSettingFormOption, AdvancedSettingGet, AdvancedSettingPost, AdvancedSettingWorkspaceSchedulePost } from '../../models/configuration/advanced-setting.model'; import { WorkspaceSchedule, WorkspaceScheduleEmailOptions } from '../../models/db/workspace-schedule.model'; import { ExpenseFilterResponse, SkipExport } from '../../models/misc/skip-export.model'; import { ApiService } from '../core/api.service'; import { WorkspaceService } from '../workspace/workspace.service'; +import { PaymentSyncDirection } from '../../models/enum/enum.model'; +import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog'; +import { FormGroup } from '@angular/forms'; +import { AddEmailDialogComponent } from 'src/app/shared/components/configuration/advanced-settings/add-email-dialog/add-email-dialog.component'; const advancedSettingsCache$ = new Subject(); const skipExportCache = new Subject(); @@ -16,9 +20,12 @@ const skipExportCache = new Subject(); }) export class AdvancedSettingService { + @Output() patchAdminEmailsEmitter: EventEmitter = new EventEmitter(); + constructor( private apiService: ApiService, - private workspaceService: WorkspaceService + private workspaceService: WorkspaceService, + private dialog: MatDialog ) { } @Cacheable({ @@ -59,4 +66,53 @@ export class AdvancedSettingService { getWorkspaceAdmins(): Observable<[WorkspaceScheduleEmailOptions]> { return this.apiService.get(`/workspaces/${this.workspaceService.getWorkspaceId()}/admins/`, {}); } + + getPaymentSyncOptions(): AdvancedSettingFormOption[] { + return [ + { + label: 'None', + value: null + }, + { + label: 'Export Fyle ACH Payments to Quickbooks Online', + value: PaymentSyncDirection.FYLE_TO_QBO + }, + { + label: 'Import Quickbooks Payments into Fyle', + value: PaymentSyncDirection.QBO_TO_FYLE + } + ]; + } + + getFrequencyIntervals(): AdvancedSettingFormOption[] { + return [...Array(24).keys()].map(day => { + return { + label: (day + 1) === 1 ? (day + 1) + ' Hour' : (day + 1) + ' Hours', + value: day + 1 + }; + }); + } + + openAddemailDialog(advancedSettingsForm: FormGroup, adminEmails: WorkspaceScheduleEmailOptions[]): void { + const dialogRef = this.dialog.open(AddEmailDialogComponent, { + width: '467px', + data: { + workspaceId: this.workspaceService.getWorkspaceId(), + hours: advancedSettingsForm.value.exportScheduleFrequency, + schedulEnabled: advancedSettingsForm.value.exportSchedule, + selectedEmails: advancedSettingsForm.value.emails + } + }); + + dialogRef.afterClosed().subscribe((result) => { + if (result) { + advancedSettingsForm.controls.exportScheduleFrequency.patchValue(result.hours); + advancedSettingsForm.controls.emails.patchValue(result.emails_selected); + advancedSettingsForm.controls.addedEmail.patchValue(result.email_added); + + const additionalEmails = adminEmails.concat(result.email_added); + this.patchAdminEmailsEmitter.emit(additionalEmails); + } + }); + } } diff --git a/src/app/core/services/configuration/export-setting.service.spec.ts b/src/app/core/services/configuration/export-setting.service.spec.ts index 00552325..5571a2ae 100644 --- a/src/app/core/services/configuration/export-setting.service.spec.ts +++ b/src/app/core/services/configuration/export-setting.service.spec.ts @@ -5,7 +5,7 @@ import { ExpenseState, CCCExpenseState, ReimbursableExpensesObject, CorporateCre import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; import { environment } from 'src/environments/environment'; import { AbstractControl, FormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; -import { exportResponse } from 'src/app/shared/components/configuration/export-settings/export-settings.fixture'; +import { exportResponse, mockCCCExpenseStateOptions, mockReimbursableExpenseGroupingFieldOptions, mockReimbursableExportTypeOptions } from 'src/app/shared/components/configuration/export-settings/export-settings.fixture'; describe('ExportSettingService', () => { let service: ExportSettingService; @@ -223,5 +223,12 @@ describe('ExportSettingService', () => { it('function check', () => { expect((service as any).getExportGroup([ExpenseGroupingFieldOption.EXPENSE_ID])).toEqual('expense_id'); expect((service as any).getExportGroup(null)).toEqual(''); + + expect((service as any).getReimbursableExpenseGroupingFieldOptions()); + expect((service as any).getReimbursableExportTypeOptions()); + expect((service as any).getcreditCardExportTypes()); + expect((service as any).getReimbursableExpenseGroupingDateOptions()); + expect((service as any).getReimbursableExpenseStateOptions()); + expect((service as any).getCCCExpenseStateOptions()); }); }); diff --git a/src/app/core/services/configuration/import-setting.service.spec.ts b/src/app/core/services/configuration/import-setting.service.spec.ts index 1f7da020..45d50dfe 100644 --- a/src/app/core/services/configuration/import-setting.service.spec.ts +++ b/src/app/core/services/configuration/import-setting.service.spec.ts @@ -4,7 +4,10 @@ import { ImportSettingPost, ImportSettingModel } from '../../models/configuratio import { MappingSourceField, MappingDestinationField } from '../../models/enum/enum.model'; import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; import { environment } from 'src/environments/environment'; -import { MatLegacyDialogModule } from '@angular/material/legacy-dialog'; +import { MatLegacyDialog as MatDialog, MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; + +import { FormBuilder } from '@angular/forms'; +import { of } from 'rxjs'; describe('ImportSettingService', () => { let service: ImportSettingService; @@ -12,17 +15,77 @@ describe('ImportSettingService', () => { let httpMock: HttpTestingController; const API_BASE_URL = environment.api_url; const workspace_id = environment.tests.workspaceId; + let formbuilder: FormBuilder; + let dialogSpy: jasmine.Spy; + const dialogRefSpyObj = jasmine.createSpyObj({ afterClosed: of({}), close: null }); + dialogRefSpyObj.componentInstance = { body: '' }; beforeEach(() => { TestBed.configureTestingModule({ - imports: [HttpClientTestingModule, MatLegacyDialogModule], + imports: [HttpClientTestingModule, MatDialogModule], providers: [ImportSettingService] }); + dialogSpy = spyOn(TestBed.get(MatDialog), 'open').and.returnValue(dialogRefSpyObj); injector = getTestBed(); + formbuilder = TestBed.inject(FormBuilder); service = injector.inject(ImportSettingService); httpMock = injector.inject(HttpTestingController); + + }); + + it('getQboExpenseFields function check', () => { + const qboAttributes = ['CUSTOMER']; + const mappingSettings = [ + { + "source_field": "COST_CENTER", + "destination_field": "CUSTOMER", + "import_to_fyle": true, + "is_custom": false, + "source_placeholder": null + } + ]; + const fyleFields = ['COST_CENTER', 'PROJECT']; + expect((service as any).getQboExpenseFields(qboAttributes, mappingSettings, true, fyleFields)); + }); + + it('getExpenseFieldsFormArray function check', () => { + const mappingSettings = [ + { + "source_field": "COST_CENTER", + "destination_field": "CUSTOMER", + "import_to_fyle": true, + "is_custom": false, + "source_placeholder": null + } + ]; + expect((service as any).getExpenseFieldsFormArray(mappingSettings, false)); }); + it('getPatchExpenseFieldValues function check', () => { + const mappingSettings = + { + "source_field": "COST_CENTER", + "destination_field": "CUSTOMER", + "import_to_fyle": true, + "disable_import_to_fyle": true, + "source_placeholder": '', + "addSourceField": false + }; + expect((service as any).getPatchExpenseFieldValues("CUSTOMER", "COST_CENTER")).toEqual(mappingSettings); + }); + + it('importToggleWatcher function check', () => { + const form = formbuilder.group({ + source_field: [MappingSourceField.PROJECT], + destination_field: [MappingDestinationField.CUSTOMER], + disable_import_to_fyle: [false], + import_to_fyle: [false, (service as any).importToggleWatcher()], + source_placeholder: [''] + }); + + form.controls.import_to_fyle.patchValue(true); + expect((service as any).importToggleWatcher()); + }); it('should be created', () => { expect(service).toBeTruthy(); diff --git a/src/app/core/services/configuration/import-setting.service.ts b/src/app/core/services/configuration/import-setting.service.ts index 67aff13c..c4cb7766 100644 --- a/src/app/core/services/configuration/import-setting.service.ts +++ b/src/app/core/services/configuration/import-setting.service.ts @@ -70,8 +70,8 @@ export class ImportSettingService { }; } - getExpenseFieldsFormArray(xeroExpenseFields: ExpenseFieldsFormOption[], isWatcherRequired: boolean): FormGroup[] { - return xeroExpenseFields.map((field) => { + getExpenseFieldsFormArray(qboExpenseField: ExpenseFieldsFormOption[], isWatcherRequired: boolean): FormGroup[] { + return qboExpenseField.map((field) => { return this.formBuilder.group({ source_field: [field.source_field, Validators.required], destination_field: [field.destination_field.toUpperCase()], diff --git a/src/app/integration/integration.module.ts b/src/app/integration/integration.module.ts index d760d555..9127d339 100644 --- a/src/app/integration/integration.module.ts +++ b/src/app/integration/integration.module.ts @@ -5,7 +5,6 @@ import { IntegrationRoutingModule } from './integration-routing.module'; import { SharedModule } from '../shared/shared.module'; - @NgModule({ declarations: [ IntegrationComponent diff --git a/src/app/integration/onboarding/clone-settings/clone-settings.component.html b/src/app/integration/onboarding/clone-settings/clone-settings.component.html index 73ec5a79..34caf9f1 100644 --- a/src/app/integration/onboarding/clone-settings/clone-settings.component.html +++ b/src/app/integration/onboarding/clone-settings/clone-settings.component.html @@ -147,20 +147,18 @@
In this section, you c
-
- - -
-
- +
+ + +
In this section, you c
-
@@ -609,6 +607,246 @@
In this section, you c
+ +
+
+
+ +
+
+

Advanced Settings

+
+ This section contains settings to automate and customize your expense exports +
+
+
+ +
+
+
+
+ +

Schedule automatic export

+ +
+ +
+ +
+
+
+ +
+
+
+

+ Set the frequency of export + +

+
+ +
+ +
+
+
+ +
+
+
+ +
+ +
+ +
+ or + + Add new email address +
+
+
+
+ +
+
+
+ +

Post entries in the next open accounting + period

+ +
+ +
+ +
+
+
+ +
+
+
+ +

Auto Create Vendor

+ +
+ +
+ +
+
+
+ +
+
+
+ +

Auto - Sync payment between Fyle and QuickBooks online +

+ +
+ +
+ +
+
+
+ +
+
+
+

+ To which Payment account should the payment entries be posted? + +

+
+ +
+ +
+
+
+ +
+
+
+ +

Auto-Create Merchants as Vendor

+ +
+ +
+ +
+
+
+ +
+
+
+ +

Create a single itemized offset credit entry for Journal

+ +
+ +
+ + +
+
+
+ +
+
+
+ +

Set description field in QuickBooks Online

+ +
+ +
+ + +
+ + {{ option | titlecase | snakeCaseToSpaceCase }} + +
+
+
+
+
+
+
+
+ Preview in QuickBooks Online +
+
+
+ {{ memoPreviewText }} +
+
+
+
+
+
+