Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct per diem time calculation for same-day expenses #56295

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/libs/PerDiemRequestUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {addDays, differenceInDays, differenceInMinutes, format, startOfDay} from 'date-fns';
import {addDays, differenceInDays, differenceInMinutes, format, isSameDay, startOfDay} from 'date-fns';
import lodashSortBy from 'lodash/sortBy';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
Expand Down Expand Up @@ -258,6 +258,16 @@ function getTimeDifferenceIntervals(transaction: OnyxEntry<Transaction>) {
const customUnitRateDate = transaction?.comment?.customUnit?.attributes?.dates ?? {start: '', end: ''};
const startDate = new Date(customUnitRateDate.start);
const endDate = new Date(customUnitRateDate.end);

if (isSameDay(startDate, endDate)) {
const hourDiff = differenceInMinutes(endDate, startDate) / 60;
return {
firstDay: hourDiff,
tripDays: 0,
lastDay: undefined,
};
}

const firstDayDiff = differenceInMinutes(startOfDay(addDays(startDate, 1)), startDate);
const tripDaysDiff = differenceInDays(startOfDay(endDate), startOfDay(addDays(startDate, 1)));
const lastDayDiff = differenceInMinutes(endDate, startOfDay(endDate));
Expand Down
82 changes: 82 additions & 0 deletions tests/unit/getTimeDifferenceIntervalsTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {addDays, differenceInDays, differenceInMinutes, startOfDay} from 'date-fns';
import type {OnyxEntry} from 'react-native-onyx';
import {getTimeDifferenceIntervals} from '@libs/PerDiemRequestUtils';
import type Transaction from '@src/types/onyx/Transaction';

describe('getTimeDifferenceIntervals', () => {
const createMockTransaction = (startDate: string, endDate: string): OnyxEntry<Transaction> =>
({
comment: {
customUnit: {
attributes: {
dates: {
start: startDate,
end: endDate,
},
},
},
},
} as OnyxEntry<Transaction>);

it('calculates hours for same-day transactions', () => {
// Given a transaction that starts and ends on the same day
const startDate = '2024-03-20T09:00:00Z';
const endDate = '2024-03-20T17:00:00Z';
const transaction = createMockTransaction(startDate, endDate);

const result = getTimeDifferenceIntervals(transaction);

// When we calculate the time difference intervals
const expectedHours = differenceInMinutes(new Date(endDate), new Date(startDate)) / 60;

// Then we should get the correct number of hours for a single day, there should be no trip days and no last day
expect(result).toEqual({
firstDay: expectedHours,
tripDays: 0,
lastDay: undefined,
});
});

it('calculates hours spanning two days', () => {
// Given a transaction that spans across two days
const startDate = '2024-03-20T14:00:00Z';
const endDate = '2024-03-21T16:00:00Z';
const transaction = createMockTransaction(startDate, endDate);

const result = getTimeDifferenceIntervals(transaction);

// When we calculate the time difference intervals
const startDateTime = new Date(startDate);
const firstDayDiff = differenceInMinutes(startOfDay(addDays(startDateTime, 1)), startDateTime);
const lastDayDiff = differenceInMinutes(new Date(endDate), startOfDay(new Date(endDate)));

// Then we should get the correct split of hours, there should be no trip days
expect(result).toEqual({
firstDay: firstDayDiff / 60,
tripDays: 0,
lastDay: lastDayDiff / 60,
});
});

it('calculates hours for multi-day trips', () => {
// Given a transaction that spans multiple days
const startDate = '2024-03-20T16:00:00Z';
const endDate = '2024-03-23T14:00:00Z';
const transaction = createMockTransaction(startDate, endDate);

const result = getTimeDifferenceIntervals(transaction);

// When we calculate the time difference intervals
const startDateTime = new Date(startDate);
const firstDayDiff = differenceInMinutes(startOfDay(addDays(startDateTime, 1)), startDateTime);
const tripDaysDiff = differenceInDays(startOfDay(new Date(endDate)), startOfDay(addDays(startDateTime, 1)));
const lastDayDiff = differenceInMinutes(new Date(endDate), startOfDay(new Date(endDate)));

// Then we should get the correct hours split, there should be trip days and last day
expect(result).toEqual({
firstDay: firstDayDiff / 60,
tripDays: tripDaysDiff,
lastDay: lastDayDiff / 60,
});
});
});