Skip to content

Commit

Permalink
Merge branch 'Fyle-8679027wa' of https://github.com/fylein/fyle-mobil…
Browse files Browse the repository at this point in the history
…e-app into Fyle-8679027wa
  • Loading branch information
arjunaj5 committed Nov 30, 2023
2 parents 59f6549 + d283e73 commit 9c9488c
Show file tree
Hide file tree
Showing 39 changed files with 5,812 additions and 181 deletions.
77 changes: 77 additions & 0 deletions src/app/core/guards/beta-page-feature-flag.guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { ActivatedRoute, Router } from '@angular/router';
import { OrgSettingsService } from '../services/org-settings.service';
import { BetaPageFeatureFlagGuard } from './beta-page-feature-flag.guard';
import { TestBed } from '@angular/core/testing';
import { Observable, of } from 'rxjs';
import { routerStateSnapshotData } from '../mock-data/router-state-snapshot.data';

describe('BetaPageFeatureFlagGuard', () => {
let guard: BetaPageFeatureFlagGuard;
let orgSettingsService: jasmine.SpyObj<OrgSettingsService>;
let router: jasmine.SpyObj<Router>;
let activatedRoute: jasmine.SpyObj<ActivatedRoute>;

beforeEach(() => {
const orgSettingsServiceSpy = jasmine.createSpyObj('OrgSettingsService', ['isBetaPageEnabledForPath']);
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);

TestBed.configureTestingModule({
providers: [
{
provide: OrgSettingsService,
useValue: orgSettingsServiceSpy,
},
{
provide: Router,
useValue: routerSpy,
},
{
provide: ActivatedRoute,
useValue: {
snapshot: {
routeConfig: {
path: 'my_view_report',
},
data: {
url: '/enterprise/my_view_report',
root: null,
},
},
},
},
],
});
guard = TestBed.inject(BetaPageFeatureFlagGuard);
orgSettingsService = TestBed.inject(OrgSettingsService) as jasmine.SpyObj<OrgSettingsService>;
activatedRoute = TestBed.inject(ActivatedRoute) as jasmine.SpyObj<ActivatedRoute>;
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
});

it('should be created', () => {
expect(guard).toBeTruthy();
});

describe('canActivate(): ', () => {
it('Should navigate to the beta page if the feature flag is enabled', (done) => {
orgSettingsService.isBetaPageEnabledForPath.and.returnValue(of(true));
const canActivate = guard.canActivate(activatedRoute.snapshot, routerStateSnapshotData) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(orgSettingsService.isBetaPageEnabledForPath).toHaveBeenCalledTimes(1);
expect(res).toBeFalse();
expect(router.navigate).toHaveBeenCalledWith(['/', 'enterprise', 'my_view_report_beta', {}]);
done();
});
});

it('Should navigate to the correct page if the feature flag is disabled', (done) => {
orgSettingsService.isBetaPageEnabledForPath.and.returnValue(of(false));
const canActivate = guard.canActivate(activatedRoute.snapshot, routerStateSnapshotData) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(orgSettingsService.isBetaPageEnabledForPath).toHaveBeenCalledTimes(1);
expect(res).toBeTrue();
expect(router.navigate).not.toHaveBeenCalled();
done();
});
});
});
});
32 changes: 32 additions & 0 deletions src/app/core/guards/beta-page-feature-flag.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable, map, of } from 'rxjs';
import { OrgSettingsService } from '../services/org-settings.service';

@Injectable({
providedIn: 'root',
})
export class BetaPageFeatureFlagGuard implements CanActivate {
constructor(private orgSettingsService: OrgSettingsService, private router: Router) {}

canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const currentPath = route.routeConfig && route.routeConfig.path;

if (currentPath) {
return this.orgSettingsService.isBetaPageEnabledForPath(currentPath).pipe(
map((isBetaPageEnabled) => {
if (isBetaPageEnabled) {
this.router.navigate(['/', 'enterprise', `${currentPath}_beta`, { ...route.params }]);
return false;
}
return true;
})
);
} else {
return of(true);
}
}
}
5 changes: 5 additions & 0 deletions src/app/core/mock-data/platform/v1/expense.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ export const mileageExpenseWithoutDistance: Expense = {
category: mileageCategory,
};

export const perDiemExpense: Expense = {
...expenseData,
category: perDiemCategory,
};

export const perDiemExpenseWithSingleNumDays: Expense = {
...expenseData,
category: perDiemCategory,
Expand Down
2 changes: 2 additions & 0 deletions src/app/core/models/org-settings.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ export interface OrgSettingsResponse {
enable_advances?: boolean;
enable_org_creation?: boolean;
enable_auto_report?: boolean;
mobile_app_view_report_beta_enabled?: boolean;

mileage_details?: MileageDetails;
policy_settings?: PolicySettings;
Expand Down Expand Up @@ -551,4 +552,5 @@ export interface OrgSettings {
mastercard_enrollment_settings?: CommonOrgSettings;
company_expenses_beta_settings?: CommonOrgSettings;
simplified_report_closure_settings?: CommonOrgSettings;
mobile_app_view_report_beta_enabled?: boolean;
}
2 changes: 1 addition & 1 deletion src/app/core/services/deep-link.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export class DeepLinkService {

getExpenseRoute(etxn: UnflattenedTransaction): string[] {
const category = etxn.tx.org_category?.toLowerCase();
const canEditTxn = ['DRAFT', 'DRAFT_INQUIRY', 'COMPLETE', 'APPROVER_PENDING'].includes(etxn.tx.state);
const canEditTxn = ['DRAFT', 'COMPLETE', 'APPROVER_PENDING'].includes(etxn.tx.state);

let route: string[] = [];
if (canEditTxn) {
Expand Down
14 changes: 13 additions & 1 deletion src/app/core/services/org-settings.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export class OrgSettingsService {
cacheBusterObserver: orgSettingsCacheBuster$,
})
get(): Observable<OrgSettings> {
return this.apiService.get('/org/settings').pipe(map((incoming) => this.processIncoming(incoming)));
return this.apiService
.get('/org/settings')
.pipe(map((incoming: OrgSettingsResponse) => this.processIncoming(incoming)));
}

@CacheBuster({
Expand All @@ -36,6 +38,15 @@ export class OrgSettingsService {
return this.apiService.post('/org/settings', data);
}

isBetaPageEnabledForPath(currentPath: string): Observable<boolean> {
const pathSettingsFlagMap = {
my_view_report: 'mobile_app_view_report_beta_enabled',
view_team_report: 'mobile_app_view_report_beta_enabled',
};
const featureFlag = pathSettingsFlagMap[currentPath];
return this.get().pipe(map((orgSettings: OrgSettings) => orgSettings[featureFlag]));
}

getIncomingAccountingObject(incomingAccountExport: AccountingExportSettings): IncomingAccountObject {
const accounting: IncomingAccountObject = {
enabled: false,
Expand Down Expand Up @@ -393,6 +404,7 @@ export class OrgSettingsService {
allowed: incoming?.simplified_report_closure_settings?.allowed,
enabled: incoming?.simplified_report_closure_settings?.enabled,
},
mobile_app_view_report_beta_enabled: incoming.mobile_app_view_report_beta_enabled,
};

Object.keys(orgSettings).forEach((settingsType) => {
Expand Down
23 changes: 13 additions & 10 deletions src/app/core/services/platform/v1/shared/expenses.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,14 @@ describe('ExpensesService', () => {
key: 'ccc',
},
];
const expensePaymentMode = { name: 'Reimbursable', key: 'reimbursable' };
const expensePaymentMode: { name: string; key: 'reimbursable' | 'nonReimbursable' | 'advance' | 'ccc' } = {
name: 'Reimbursable',
key: 'reimbursable',
};
// @ts-ignore
expect(service.getPaymentModeForExpense(expenseData, paymentModeList)).toEqual(expensePaymentMode);
expect(service.isExpenseInPaymentMode).toHaveBeenCalledOnceWith(
!expenseData.is_reimbursable,
expenseData.is_reimbursable,
expenseData.source_account.type,
expensePaymentMode.key
);
Expand Down Expand Up @@ -268,38 +271,38 @@ describe('ExpensesService', () => {

describe('isExpenseInPaymentMode():', () => {
it('should return isExpenseInPaymentMode with reimbursable payment mode', () => {
const expenseSkipReimbursement = false;
const isExpenseReimbursable = true;
const expensePaymentMode = 'reimbursable';
const expenseSourceAccountType = AccountType.PERSONAL_CASH_ACCOUNT;
expect(
service.isExpenseInPaymentMode(expenseSkipReimbursement, expenseSourceAccountType, expensePaymentMode)
service.isExpenseInPaymentMode(isExpenseReimbursable, expenseSourceAccountType, expensePaymentMode)
).toBeTrue();
});

it('should return isExpenseInPaymentMode with non-reimbursable payment mode', () => {
const expenseSkipReimbursement = true;
const isExpenseReimbursable = false;
const expensePaymentMode = 'nonReimbursable';
const expenseSourceAccountType = AccountType.PERSONAL_CASH_ACCOUNT;
expect(
service.isExpenseInPaymentMode(expenseSkipReimbursement, expenseSourceAccountType, expensePaymentMode)
service.isExpenseInPaymentMode(isExpenseReimbursable, expenseSourceAccountType, expensePaymentMode)
).toBeTrue();
});

it('should return isExpenseInPaymentMode with advance payment mode', () => {
const expenseSkipReimbursement = false;
const isExpenseReimbursable = true;
const expensePaymentMode = 'advance';
const expenseSourceAccountType = AccountType.PERSONAL_ADVANCE_ACCOUNT;
expect(
service.isExpenseInPaymentMode(expenseSkipReimbursement, expenseSourceAccountType, expensePaymentMode)
service.isExpenseInPaymentMode(isExpenseReimbursable, expenseSourceAccountType, expensePaymentMode)
).toBeTrue();
});

it('should return isExpenseInPaymentMode with advance payment mode', () => {
const expenseSkipReimbursement = false;
const isExpenseReimbursable = true;
const expensePaymentMode = 'ccc';
const expenseSourceAccountType = AccountType.PERSONAL_CORPORATE_CREDIT_CARD_ACCOUNT;
expect(
service.isExpenseInPaymentMode(expenseSkipReimbursement, expenseSourceAccountType, expensePaymentMode)
service.isExpenseInPaymentMode(isExpenseReimbursable, expenseSourceAccountType, expensePaymentMode)
).toBeTrue();
});
});
Expand Down
7 changes: 3 additions & 4 deletions src/app/core/services/report.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -948,12 +948,12 @@ describe('ReportService', () => {
const params = 'draft';

const expectedRes = {
state: ['DRAFT', 'DRAFT_INQUIRY'],
state: ['DRAFT'],
};

const result = reportService.getUserReportParams(params);
expect(result).toEqual(expectedRes);
expect(expectedRes.state.length).toEqual(2);
expect(expectedRes.state.length).toEqual(1);
});

it('generate parameters as per state | pending', () => {
Expand Down Expand Up @@ -1022,7 +1022,6 @@ describe('ReportService', () => {
const expectedRes = {
state: [
'DRAFT',
'DRAFT_INQUIRY',
'COMPLETE',
'APPROVED',
'APPROVER_PENDING',
Expand All @@ -1036,7 +1035,7 @@ describe('ReportService', () => {

const result = reportService.getUserReportParams(params);
expect(result).toEqual(expectedRes);
expect(expectedRes.state.length).toEqual(10);
expect(expectedRes.state.length).toEqual(9);
});
});

Expand Down
20 changes: 18 additions & 2 deletions src/app/core/services/report.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { SpenderPlatformV1ApiService } from './spender-platform-v1-api.service';
import { StorageService } from './storage.service';
import { TransactionService } from './transaction.service';
import { UserEventService } from './user-event.service';
import { Expense } from '../models/expense.model';

const reportsCacheBuster$ = new Subject<void>();

Expand Down Expand Up @@ -292,7 +293,7 @@ export class ReportService {
getUserReportParams(state: keyof ReportStateMap): Record<'state', string[]> {
const stateMap: ReportStateMap = {
draft: {
state: ['DRAFT', 'DRAFT_INQUIRY'],
state: ['DRAFT'],
},
pending: {
state: ['APPROVER_PENDING'],
Expand All @@ -315,7 +316,6 @@ export class ReportService {
all: {
state: [
'DRAFT',
'DRAFT_INQUIRY',
'COMPLETE',
'APPROVED',
'APPROVER_PENDING',
Expand Down Expand Up @@ -624,6 +624,22 @@ export class ReportService {
);
}

getReportETxnc(rptId: string, orgUserId: string): Observable<Expense[]> {
const data: {
params: {
approver_id?: string;
};
} = {
params: {},
};

if (orgUserId) {
data.params.approver_id = orgUserId;
}

return this.apiService.get('/erpts/' + rptId + '/etxns', data);
}

approverUpdateReportPurpose(erpt: ExtendedReport): Observable<PlatformReport> {
const params: { data: Pick<PlatformReport, 'id' | 'source' | 'purpose'> } = {
data: {
Expand Down
Loading

0 comments on commit 9c9488c

Please sign in to comment.