Skip to content

Commit

Permalink
feat: Added the merchant name as Suggestion in expense detail card fo…
Browse files Browse the repository at this point in the history
…r CC expenses (#3369)

* feat: Added the merchant name in expense detials card for CC expenses

* added the merchant feature in view expense page

* minor updates

* test: Added unit tests for the cc merchant info (#3372)
  • Loading branch information
devendrafyle authored Dec 19, 2024
1 parent 5dcc9f9 commit c3edb99
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 4 deletions.
16 changes: 16 additions & 0 deletions src/app/fyle/add-edit-expense/add-edit-expense-6.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import { ccTransactionData, ccTransactionData1 } from 'src/app/core/mock-data/cc
import { ccTransactionResponseData } from 'src/app/core/mock-data/corporate-card-transaction-response.data';
import { cloneDeep } from 'lodash';
import { ExpenseTransactionStatus } from 'src/app/core/enums/platform/v1/expense-transaction-status.enum';
import { CCExpenseMerchantInfoPopoverComponent } from 'src/app/shared/components/cc-expense-merchant-info-popover/cc-expense-merchant-info-popover.component';

export function TestCases6(getTestBed) {
describe('AddEditExpensePage-6', () => {
Expand Down Expand Up @@ -1223,5 +1224,20 @@ export function TestCases6(getTestBed) {
});
expect(popoverSpy.present).toHaveBeenCalledTimes(1);
}));

it('openCCExpenseMerchantInfoModal(): should open the transaction status info modal', fakeAsync(() => {
const popoverSpy = jasmine.createSpyObj('HTMLIonPopoverElement', ['present']);
popoverController.create.and.resolveTo(popoverSpy);

component.openCCExpenseMerchantInfoModal();

tick();

expect(popoverController.create).toHaveBeenCalledOnceWith({
component: CCExpenseMerchantInfoPopoverComponent,
cssClass: 'fy-dialog-popover',
});
expect(popoverSpy.present).toHaveBeenCalledTimes(1);
}));
});
}
15 changes: 15 additions & 0 deletions src/app/fyle/add-edit-expense/add-edit-expense.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,21 @@
</ion-row>
</ng-container>

<ng-container>
<div class="add-edit-expense--card-container__merchant_block">
<div class="add-edit-expense--card-container__merchant_label">Merchant:</div>
<div class="add-edit-expense--card-container__merchant_value">
<span> {{ selectedCCCTransaction?.vendor || 'Unavailable' }} </span>
<ion-icon
(click)="openCCExpenseMerchantInfoModal()"
src="../../../assets/svg/info-circle-outline.svg"
class="add-edit-expense--card-container__merchant_info_icon"
data-testid="merchant-info-icon"
></ion-icon>
</div>
</div>
</ng-container>

<ng-container *ngIf="isRTFEnabled$ | async">
<ng-container *ngIf="platformExpense$ | async as expense">
<div
Expand Down
31 changes: 29 additions & 2 deletions src/app/fyle/add-edit-expense/add-edit-expense.page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,35 @@
margin: 12px 0;
border-radius: 8px;

&__merchant_block {
display: flex;
gap: 6px;
border-top: 1px solid $grey;
padding-top: 12px;
margin-top: 12px;
align-items: center;
}

&__merchant_label {
color: $black-light;
font-size: 12px;
}

&__merchant_value {
display: flex;
align-items: center;
gap: 2px;
color: $blue-black;
font-weight: 500;
font-size: 12px;
}

&__merchant_info_icon {
color: $blue-black;
width: 16px;
height: 16px;
}

&__label {
color: $black-light;
font-size: 12px;
Expand All @@ -699,8 +728,6 @@
}

&__transaction-status {
border-top: 1px solid $grey;
padding-top: 12px;
margin-top: 12px;
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/app/fyle/add-edit-expense/add-edit-expense.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ import { SpenderFileService } from 'src/app/core/services/platform/v1/spender/fi
import { ExpenseTransactionStatus } from 'src/app/core/enums/platform/v1/expense-transaction-status.enum';
import { RefinerService } from 'src/app/core/services/refiner.service';
import { CostCentersService } from 'src/app/core/services/cost-centers.service';
import { CCExpenseMerchantInfoPopoverComponent } from 'src/app/shared/components/cc-expense-merchant-info-popover/cc-expense-merchant-info-popover.component';

// eslint-disable-next-line
type FormValue = {
Expand Down Expand Up @@ -5241,6 +5242,15 @@ export class AddEditExpensePage implements OnInit {
await popover.present();
}

async openCCExpenseMerchantInfoModal(): Promise<void> {
const popover = await this.popoverController.create({
component: CCExpenseMerchantInfoPopoverComponent,
cssClass: 'fy-dialog-popover',
});

await popover.present();
}

private filterVendor(vendor: string): string | null {
if (!vendor || this.vendorOptions?.length === 0) {
return vendor;
Expand Down
15 changes: 15 additions & 0 deletions src/app/fyle/view-expense/view-expense.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@
</div>
</div>

<ng-container *ngIf="isCCCTransaction">
<div class="view-expense--card-container__merchant_block">
<div class="view-expense--card-container__merchant_label">Merchant:</div>
<div class="view-expense--card-container__merchant_value">
<span> {{ selectedCCCTransaction?.vendor || 'Unavailable' }} </span>
<ion-icon
(click)="openCCExpenseMerchantInfoModal()"
src="../../../assets/svg/info-circle-outline.svg"
class="view-expense--card-container__merchant_info_icon"
data-testid="merchant-info-icon"
></ion-icon>
</div>
</div>
</ng-container>

<ng-container *ngIf="isCCCTransaction && isRTFEnabled">
<div
*ngIf="expense.matched_corporate_card_transactions[0]?.status as transactionStatus"
Expand Down
29 changes: 29 additions & 0 deletions src/app/fyle/view-expense/view-expense.page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,35 @@
width: 100%;
}

&__merchant_block {
display: flex;
gap: 6px;
border-top: 1px solid $grey;
padding-top: 12px;
margin-top: 12px;
align-items: center;
}

&__merchant_label {
color: $black-light;
font-size: 12px;
}

&__merchant_value {
display: flex;
align-items: center;
gap: 2px;
color: $blue-black;
font-weight: 500;
font-size: 12px;
}

&__merchant_info_icon {
color: $blue-black;
width: 16px;
height: 16px;
}

&__amount-section {
display: flex;
justify-content: flex-end;
Expand Down
16 changes: 16 additions & 0 deletions src/app/fyle/view-expense/view-expense.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
paidReportData,
} from 'src/app/core/mock-data/platform-report.data';
import { ExpenseTransactionStatus } from 'src/app/core/enums/platform/v1/expense-transaction-status.enum';
import { CCExpenseMerchantInfoPopoverComponent } from 'src/app/shared/components/cc-expense-merchant-info-popover/cc-expense-merchant-info-popover.component';

describe('ViewExpensePage', () => {
let component: ViewExpensePage;
Expand Down Expand Up @@ -1076,4 +1077,19 @@ describe('ViewExpensePage', () => {
});
expect(popoverSpy.present).toHaveBeenCalledTimes(1);
}));

it('openCCExpenseMerchantInfoModal(): should open the transaction status info modal', fakeAsync(() => {
const popoverSpy = jasmine.createSpyObj('HTMLIonPopoverElement', ['present']);
popoverController.create.and.resolveTo(popoverSpy);

component.openCCExpenseMerchantInfoModal();

tick();

expect(popoverController.create).toHaveBeenCalledOnceWith({
component: CCExpenseMerchantInfoPopoverComponent,
cssClass: 'fy-dialog-popover',
});
expect(popoverSpy.present).toHaveBeenCalledTimes(1);
}));
});
10 changes: 10 additions & 0 deletions src/app/fyle/view-expense/view-expense.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { ApproverFileService } from 'src/app/core/services/platform/v1/approver/
import { PlatformFileGenerateUrlsResponse } from 'src/app/core/models/platform/platform-file-generate-urls-response.model';
import { ApproverReportsService } from 'src/app/core/services/platform/v1/approver/reports.service';
import { ExpenseTransactionStatus } from 'src/app/core/enums/platform/v1/expense-transaction-status.enum';
import { CCExpenseMerchantInfoPopoverComponent } from 'src/app/shared/components/cc-expense-merchant-info-popover/cc-expense-merchant-info-popover.component';

@Component({
selector: 'app-view-expense',
Expand Down Expand Up @@ -515,4 +516,13 @@ export class ViewExpensePage {

await popover.present();
}

async openCCExpenseMerchantInfoModal(): Promise<void> {
const popover = await this.popoverController.create({
component: CCExpenseMerchantInfoPopoverComponent,
cssClass: 'fy-dialog-popover',
});

await popover.present();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<ion-header mode="md" class="header">
<ion-toolbar mode="md" class="fy-modal-toolbar">
<ion-buttons slot="start">
<ion-button
(click)="closePopover()"
class="cc-expense-merchant-info-popover__toolbar-close-btn"
data-testid="close-btn"
>
<mat-icon class="fy-icon-close" svgIcon="cross"></mat-icon>
</ion-button>
</ion-buttons>
<ion-title class="text-center cc-expense-merchant-info-popover__toolbar-title" data-testid="title"
>Merchant</ion-title
>
</ion-toolbar>
</ion-header>

<ion-content class="cc-expense-merchant-info-popover__content">
<div class="cc-expense-merchant-info-popover__body" data-testid="content">
<ng-container>This merchant name comes from the transaction.</ng-container>
</div>
</ion-content>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@import '../../../../theme/colors.scss';

.header {
border-radius: 10px;
}

.cc-expense-merchant-info-popover {
position: relative;

&__toolbar-title {
color: $black;
font-size: 18px;
line-height: normal;
font-weight: 500;
}

&__toolbar-close-btn {
position: absolute;
}

&__body {
font-size: 14px;
color: $black;
padding: 20px 16px;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule, PopoverController } from '@ionic/angular';

import { CCExpenseMerchantInfoPopoverComponent } from './cc-expense-merchant-info-popover.component';
import { getElementBySelector } from 'src/app/core/dom-helpers';

describe('CCExpenseMerchantInfoComponent', () => {
let component: CCExpenseMerchantInfoPopoverComponent;
let popoverController: jasmine.SpyObj<PopoverController>;
let fixture: ComponentFixture<CCExpenseMerchantInfoPopoverComponent>;

beforeEach(waitForAsync(() => {
const popoverControllerSpy = jasmine.createSpyObj('PopoverController', ['dismiss']);

TestBed.configureTestingModule({
declarations: [CCExpenseMerchantInfoPopoverComponent],
imports: [IonicModule.forRoot()],
providers: [
{
provide: PopoverController,
useValue: popoverControllerSpy,
},
],
}).compileComponents();

fixture = TestBed.createComponent(CCExpenseMerchantInfoPopoverComponent);
popoverController = TestBed.inject(PopoverController) as jasmine.SpyObj<PopoverController>;
component = fixture.componentInstance;
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});

it('should close the popover when clicked on close button', () => {
const closeBtn = getElementBySelector(fixture, '[data-testid="close-btn"') as HTMLButtonElement;
closeBtn.click();

fixture.detectChanges();

expect(popoverController.dismiss).toHaveBeenCalled();
});

describe('template', () => {
it('should display the correct title', () => {
fixture.detectChanges();
const title = getElementBySelector(fixture, '[data-testid="title"');
expect(title.textContent).toEqual('Merchant');
});

it('should display the correct content', () => {
fixture.detectChanges();
const content = getElementBySelector(fixture, '[data-testid="content"');
expect(content.textContent).toEqual('This merchant name comes from the transaction.');
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component } from '@angular/core';
import { PopoverController } from '@ionic/angular';

@Component({
selector: 'app-cc-expense-merchant-info',
templateUrl: './cc-expense-merchant-info-popover.component.html',
styleUrls: ['./cc-expense-merchant-info-popover.component.scss'],
})
export class CCExpenseMerchantInfoPopoverComponent {
constructor(private popoverController: PopoverController) {}

closePopover(): void {
this.popoverController.dismiss();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
posted: transactionStatus === TransactionStatus.POSTED
}"
></div>

Transaction Status:
<div class="transaction-status__status-label">Transaction Status:</div>
<div (click)="statusClick.emit(transactionStatus)" class="transaction-status__status-value-container">
<span class="transaction-status__status-value" data-testid="status-value">{{ transactionStatus | titlecase }}</span>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,19 @@
align-items: center;
}

&__status-label {
color: $black-light;
font-size: 12px;
margin-bottom: 2px;
}

&__status-value {
color: $blue-black;
font-weight: 500;
margin-left: 6px;
margin-right: 2px;
line-height: 1.4;
font-size: 12px;
}

&__info-icon {
Expand Down
Loading

0 comments on commit c3edb99

Please sign in to comment.