Skip to content

Commit

Permalink
feat: Kill compliances (Part 1) (#2651)
Browse files Browse the repository at this point in the history
* WIP

* More stuff

* Minor

* Minor

* Added tests

* Removed fdescribe

* Minor

* Minor

* Minor

* Minor

* Revert "Minor"

This reverts commit 74d6610.

* Minor

* Minor

* Minor

* feat: Kill compliances (Part 2) (#2654)

* Added dismiss changes

* Minor

* Tests

* Minor

* feat:kill compliances 3 (#2664)

* feat:kill compliances-3

* minor

* minor

* minor

---------

Co-authored-by: sowmya <[email protected]>

---------

Co-authored-by: SowmyaFyle <[email protected]>
Co-authored-by: sowmya <[email protected]>

* minor

* minor

* minor

---------

Co-authored-by: SowmyaFyle <[email protected]>
Co-authored-by: sowmya <[email protected]>
  • Loading branch information
3 people authored and sowmya committed Jan 10, 2024
1 parent 1172a24 commit 246be5f
Show file tree
Hide file tree
Showing 20 changed files with 602 additions and 115 deletions.
4 changes: 4 additions & 0 deletions src/app/core/mock-data/duplicate-sets.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ export const duplicateSetData3: DuplicateSet = {
fields: ['field1', 'field2'],
transaction_ids: ['txcSFe6efB6R', 'txDDLtRaflUW'],
};

export const duplicateSetData4: DuplicateSet = {
transaction_ids: ['tx5fBcPBAxLv'],
};
16 changes: 16 additions & 0 deletions src/app/core/mock-data/org-settings.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1373,3 +1373,19 @@ export const orgSettingsWoV2ExpensesPage: OrgSettings = {
...orgSettingsRes,
mobile_app_my_expenses_beta_enabled: false,
};

export const orgSettingsWithDuplicateDetectionV2: OrgSettings = {
...orgSettingsRes,
duplicate_detection_v2_settings: {
allowed: true,
enabled: true,
},
};

export const orgSettingsWoDuplicateDetectionV2: OrgSettings = {
...orgSettingsRes,
duplicate_detection_v2_settings: {
allowed: false,
enabled: false,
},
};
29 changes: 29 additions & 0 deletions src/app/core/mock-data/platform/v1/expense-duplicate-sets.data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ExpenseDuplicateSet } from 'src/app/core/models/platform/v1/expense-duplicate-sets.model';

export const expenseDuplicateSet: ExpenseDuplicateSet = {
expense_ids: ['tx5fBcPBAxLv', 'tx3nHShG60zq'],
};

export const expenseDuplicateSet2: ExpenseDuplicateSet = {
expense_ids: ['tx5fBcPBAxLv'],
};

export const expenseDuplicateSets: ExpenseDuplicateSet[] = [
{ expense_ids: ['tx3I0ccSGlhg', 'txvAmVCGZUZi'] },
{ expense_ids: ['tx3rq5G9gzgf', 'txS1cDov9iZn'] },
{ expense_ids: ['tx6KauIKfjdJ', 'txT0ZmCrVOiD'] },
{ expense_ids: ['tx6KauIKfjdJ', 'txws78AoalC9', 'txzjWIcqYxa9'] },
{ expense_ids: ['tx86H1wDT5aK', 'txQYb76PXaC8', 'txWTiNPneIW5'] },
{ expense_ids: ['tx96W9dASsje', 'txJVuyoiir2c', 'txqcNXONJpiR'] },
{
expense_ids: ['txeG0ozaWXAv', 'txi5sCnM706r', 'txJfGPgyDQTj', 'txQhnRluTgSl', 'txtJUQJBvTiv'],
},
{ expense_ids: ['txfQtm19a26X', 'txOoNP4AguMY'] },
{
expense_ids: ['txiqfeRdVP58', 'txKe7x7WoEfg', 'txvQepZO5jiw', 'txxSrpiC5Eaz'],
},
{ expense_ids: ['txivvQdKDGfZ', 'txvqhZ4SRBx9'] },
{ expense_ids: ['txjh5iDt7xXO', 'txkJsHIF6a9X'] },
{ expense_ids: ['txT0ZmCrVOiD', 'txws78AoalC9'] },
{ expense_ids: ['txT0ZmCrVOiD', 'txzjWIcqYxa9'] },
];
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 @@ -400,6 +400,7 @@ export interface OrgSettingsResponse {
budget_settings?: CommonOrgSettings;
custom_category_settings?: CommonOrgSettings;
duplicate_detection_settings?: CommonOrgSettings;
duplicate_detection_v2_settings?: CommonOrgSettings;
dynamic_form_settings?: CommonOrgSettings;
hrms_integration_settings?: CommonOrgSettings;
multi_org_settings?: CommonOrgSettings;
Expand Down Expand Up @@ -514,6 +515,7 @@ export interface OrgSettings {
settlements_excel_settings?: SettlementsExcelSettings;
gmail_addon_settings?: CommonOrgSettings;
duplicate_detection_settings?: CommonOrgSettings;
duplicate_detection_v2_settings?: CommonOrgSettings;
custom_category_settings?: CommonOrgSettings;
bulk_fyle_settings?: CommonOrgSettings;
auto_reminder_settings?: CommonOrgSettings;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface ExpenseDuplicateSetsResponse {
data: ExpenseDuplicateSet[];
}

export interface ExpenseDuplicateSet {
expense_ids: string[];
}
2 changes: 1 addition & 1 deletion src/app/core/models/v2/duplicate-sets.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface DuplicateSet {
fields: string[];
fields?: string[]; // in platform, fields aren't present -> so making it optional
transaction_ids: string[];
}
2 changes: 1 addition & 1 deletion src/app/core/services/handle-duplicates.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class HandleDuplicatesService {
});
}

dismissAll(duplicateSetTransactionIds: string[], transactionIds: string[]) {
dismissAll(duplicateSetTransactionIds: string[], transactionIds: string[]): Observable<void> {
return this.apiService.post('/transactions/duplicates/dismiss', {
duplicate_set_transaction_ids: duplicateSetTransactionIds,
transaction_ids: transactionIds,
Expand Down
5 changes: 5 additions & 0 deletions src/app/core/services/org-settings.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@ export class OrgSettingsService {
allowed: incoming.duplicate_detection_settings && incoming.duplicate_detection_settings.allowed,
enabled: incoming.duplicate_detection_settings && incoming.duplicate_detection_settings.enabled,
},
duplicate_detection_v2_settings: {
allowed: incoming.duplicate_detection_v2_settings && incoming.duplicate_detection_v2_settings.allowed,
enabled: incoming.duplicate_detection_v2_settings && incoming.duplicate_detection_v2_settings.enabled,
},
custom_category_settings: {
allowed: incoming.custom_category_settings && incoming.custom_category_settings.allowed,
enabled: incoming.custom_category_settings && incoming.custom_category_settings.enabled,
Expand Down Expand Up @@ -527,6 +531,7 @@ export class OrgSettingsService {
transaction_field_configurations: outgoing.transaction_field_configurations,
gmail_addon_settings: outgoing.gmail_addon_settings,
duplicate_detection_settings: outgoing.duplicate_detection_settings,
duplicate_detection_v2_settings: outgoing.duplicate_detection_v2_settings,
custom_category_settings: outgoing.custom_category_settings,
org_bulk_fyle_settings: outgoing.bulk_fyle_settings,
auto_reminder_settings: outgoing.auto_reminder_settings,
Expand Down
52 changes: 52 additions & 0 deletions src/app/core/services/platform/v1/spender/expenses.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PAGINATION_SIZE } from 'src/app/constants';
import { expensesResponse } from 'src/app/core/mock-data/platform/v1/expenses-response.data';
import { getExpensesQueryParams } from 'src/app/core/mock-data/platform/v1/expenses-query-params.data';
import { expensesCacheBuster$ } from '../../../transaction.service';
import { expenseDuplicateSets } from 'src/app/core/mock-data/platform/v1/expense-duplicate-sets.data';
import { completeStats } from 'src/app/core/mock-data/platform/v1/expenses-stats.data';
import { ExpensesService as SharedExpenseService } from '../shared/expenses.service';

Expand All @@ -18,6 +19,7 @@ describe('ExpensesService', () => {
beforeEach(() => {
const spenderServiceSpy = jasmine.createSpyObj('SpenderService', ['get', 'post']);
const sharedExpenseServiceSpy = jasmine.createSpyObj('SharedExpenseService', ['generateStatsQueryParams']);

TestBed.configureTestingModule({
providers: [
{ provide: SpenderService, useValue: spenderServiceSpy },
Expand Down Expand Up @@ -146,6 +148,33 @@ describe('ExpensesService', () => {
});
});

it('getDuplicateSets(): should return expense duplicate sets', (done) => {
spenderService.get.and.returnValue(of({ data: expenseDuplicateSets }));

service.getDuplicateSets().subscribe((response) => {
expect(response).toEqual(expenseDuplicateSets);

expect(spenderService.get).toHaveBeenCalledOnceWith('/expenses/duplicate_sets');
done();
});
});

it('getDuplicatesByExpense() : should get the duplicates by expense', (done) => {
const expenseId = 'txaiCW1efU0n';
spenderService.get.and.returnValue(of({ data: expenseDuplicateSets }));

service.getDuplicatesByExpense(expenseId).subscribe((response) => {
expect(response).toEqual(expenseDuplicateSets);

expect(spenderService.get).toHaveBeenCalledOnceWith('/expenses/duplicate_sets', {
params: {
expense_id: 'txaiCW1efU0n',
},
});
done();
});
});

it('getExpenseStats(): should get expense stats for unreported stats', (done) => {
spenderService.post.and.returnValue(of(completeStats));
sharedExpenseService.generateStatsQueryParams.and.returnValue(
Expand All @@ -168,4 +197,27 @@ describe('ExpensesService', () => {
done();
});
});

it('dismissDuplicates(): should dismiss duplicate expenses', (done) => {
spenderService.post.and.returnValue(of({}));

const duplicateExpenseIds = ['tx1234', 'tx2345'];
const targetExpenseIds = ['tx1234', 'tx2345'];

service.dismissDuplicates(duplicateExpenseIds, targetExpenseIds).subscribe(() => {
expect(spenderService.post).toHaveBeenCalledOnceWith('/expenses/dismiss_duplicates/bulk', {
data: [
{
id: 'tx1234',
duplicate_expense_ids: ['tx1234', 'tx2345'],
},
{
id: 'tx2345',
duplicate_expense_ids: ['tx1234', 'tx2345'],
},
],
});
done();
});
});
});
31 changes: 31 additions & 0 deletions src/app/core/services/platform/v1/spender/expenses.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { ExpensesQueryParams } from 'src/app/core/models/platform/v1/expenses-qu
import { PAGINATION_SIZE } from 'src/app/constants';
import { Cacheable } from 'ts-cacheable';
import { expensesCacheBuster$ } from '../../../transaction.service';
import {
ExpenseDuplicateSet,
ExpenseDuplicateSetsResponse,
} from 'src/app/core/models/platform/v1/expense-duplicate-sets.model';
import { ExpensesService as SharedExpenseService } from '../shared/expenses.service';

@Injectable({
Expand Down Expand Up @@ -82,6 +86,33 @@ export class ExpensesService {
.pipe(map((expenses) => expenses.data));
}

getDuplicateSets(): Observable<ExpenseDuplicateSet[]> {
return this.spenderService
.get<ExpenseDuplicateSetsResponse>('/expenses/duplicate_sets')
.pipe(map((response) => response.data));
}

getDuplicatesByExpense(expenseId: string): Observable<ExpenseDuplicateSet[]> {
return this.spenderService
.get<ExpenseDuplicateSetsResponse>('/expenses/duplicate_sets', {
params: {
expense_id: expenseId,
},
})
.pipe(map((response) => response.data));
}

dismissDuplicates(duplicateExpenseIds: string[], targetExpenseIds: string[]): Observable<void> {
const payload = targetExpenseIds.map((targetExpenseId) => ({
id: targetExpenseId,
duplicate_expense_ids: duplicateExpenseIds,
}));

return this.spenderService.post<void>('/expenses/dismiss_duplicates/bulk', {
data: payload,
});
}

getExpenseStats(
params: Record<string, string | string[] | boolean>
): Observable<{ data: { count: number; total_amount: number } }> {
Expand Down
35 changes: 34 additions & 1 deletion src/app/core/services/tasks.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ import {
unreportedExpenseTaskSample2,
} from '../mock-data/task.data';
import { mastercardRTFCard } from '../mock-data/platform-corporate-card.data';
import { OrgSettingsService } from './org-settings.service';
import { ExpensesService } from './platform/v1/spender/expenses.service';
import { orgSettingsWithDuplicateDetectionV2, orgSettingsWoDuplicateDetectionV2 } from '../mock-data/org-settings.data';
import { expenseDuplicateSets } from '../mock-data/platform/v1/expense-duplicate-sets.data';
import { completeStats, incompleteStats } from '../mock-data/platform/v1/expenses-stats.data';

describe('TasksService', () => {
Expand All @@ -54,6 +57,7 @@ describe('TasksService', () => {
let corporateCreditCardExpenseService: jasmine.SpyObj<CorporateCreditCardExpenseService>;
let currencyService: jasmine.SpyObj<CurrencyService>;
let humanizeCurrencyPipe: jasmine.SpyObj<HumanizeCurrencyPipe>;
let orgSettingsService: jasmine.SpyObj<OrgSettingsService>;
let expensesService: jasmine.SpyObj<ExpensesService>;

const mockTaskClearSubject = new Subject();
Expand All @@ -66,7 +70,7 @@ describe('TasksService', () => {
'getAllExtendedReports',
]);
const transactionServiceSpy = jasmine.createSpyObj('TransactionService', ['getTransactionStats']);
const expensesServiceSpy = jasmine.createSpyObj('ExpensesService', ['getExpenseStats']);
const expensesServiceSpy = jasmine.createSpyObj('ExpensesService', ['getExpenseStats', 'getDuplicateSets']);
const userEventServiceSpy = jasmine.createSpyObj('UserEventService', ['onTaskCacheClear']);
const authServiceSpy = jasmine.createSpyObj('AuthService', ['getEou']);
const handleDuplicatesServiceSpy = jasmine.createSpyObj('HandleDuplicatesService', ['getDuplicateSets']);
Expand All @@ -76,6 +80,7 @@ describe('TasksService', () => {
]);
const currencyServiceSpy = jasmine.createSpyObj('CurrencyService', ['getHomeCurrency']);
const humanizeCurrencyPipeSpy = jasmine.createSpyObj('HumanizeCurrencyPipe', ['transform']);
const orgSettingsServiceSpy = jasmine.createSpyObj('OrgSettingsService', ['get']);

TestBed.configureTestingModule({
providers: [
Expand Down Expand Up @@ -116,6 +121,10 @@ describe('TasksService', () => {
provide: CurrencyService,
useValue: currencyServiceSpy,
},
{
provide: OrgSettingsService,
useValue: orgSettingsServiceSpy,
},
{
provide: ExpensesService,
useValue: expensesServiceSpy,
Expand All @@ -135,6 +144,7 @@ describe('TasksService', () => {
) as jasmine.SpyObj<CorporateCreditCardExpenseService>;
currencyService = TestBed.inject(CurrencyService) as jasmine.SpyObj<CurrencyService>;
humanizeCurrencyPipe = TestBed.inject(HumanizeCurrencyPipe) as jasmine.SpyObj<HumanizeCurrencyPipe>;
orgSettingsService = TestBed.inject(OrgSettingsService) as jasmine.SpyObj<OrgSettingsService>;
expensesService = TestBed.inject(ExpensesService) as jasmine.SpyObj<ExpensesService>;
});

Expand Down Expand Up @@ -260,13 +270,24 @@ describe('TasksService', () => {
});

it('should be able to fetch potential duplicate tasks', (done) => {
setupData();
handleDuplicatesService.getDuplicateSets.and.returnValue(of(potentialDuplicatesApiResponse));
tasksService.getPotentialDuplicatesTasks().subscribe((potentialDuplicateTasks) => {
expect(potentialDuplicateTasks).toEqual([potentailDuplicateTaskSample]);
done();
});
});

it('should be able to fetch potential duplicate tasks when duplicate detection v2 is enabled', (done) => {
setupData();
orgSettingsService.get.and.returnValue(of(orgSettingsWithDuplicateDetectionV2));
expensesService.getDuplicateSets.and.returnValue(of(expenseDuplicateSets));
tasksService.getPotentialDuplicatesTasks().subscribe((potentialDuplicateTasks) => {
expect(potentialDuplicateTasks).toEqual([potentailDuplicateTaskSample]);
done();
});
});

it('should be able to fetch incomplete tasks', (done) => {
expensesService.getExpenseStats
.withArgs({
Expand Down Expand Up @@ -655,13 +676,24 @@ describe('TasksService', () => {
});

it('should be able to handle null reponse from potential duplicates get call', (done) => {
setupData();
handleDuplicatesService.getDuplicateSets.and.returnValue(of(null));
tasksService.getPotentialDuplicatesTasks().subscribe((tasks) => {
expect(tasks).toEqual([]);
done();
});
});

it('should be able to handle null response from duplicate detection v2 duplicates sets call', (done) => {
setupData();
orgSettingsService.get.and.returnValue(of(orgSettingsWithDuplicateDetectionV2));
expensesService.getDuplicateSets.and.returnValue(of(null));
tasksService.getPotentialDuplicatesTasks().subscribe((tasks) => {
expect(tasks).toEqual([]);
done();
});
});

function setupData() {
currencyService.getHomeCurrency.and.returnValue(of(homeCurrency));
advanceRequestService.getMyAdvanceRequestStats.and.returnValue(of(sentBackAdvancesResponse));
Expand Down Expand Up @@ -689,6 +721,7 @@ describe('TasksService', () => {
false
)
.and.returnValue(of(teamReportResponse));
orgSettingsService.get.and.returnValue(of(orgSettingsWoDuplicateDetectionV2));
handleDuplicatesService.getDuplicateSets.and.returnValue(of(potentialDuplicatesApiResponse));
expensesService.getExpenseStats
.withArgs({
Expand Down
Loading

0 comments on commit 246be5f

Please sign in to comment.