Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b5a31a4
Implemented BE part of Per Diem Request
shubham1206agra Jan 2, 2025
28f18ee
Fix default values
shubham1206agra Jan 2, 2025
ab084f2
Fix optimistic bug
shubham1206agra Jan 2, 2025
7bd8de9
Fix navigation bug
shubham1206agra Jan 2, 2025
868c4d2
Fix parameters
shubham1206agra Jan 3, 2025
35c0bd7
Fix weird tab navigator behavior
shubham1206agra Jan 5, 2025
57f1e3a
Renaming component
shubham1206agra Jan 7, 2025
e3cde6d
Merge branch 'Expensify:main' into per-diem-6
shubham1206agra Jan 7, 2025
c3688b4
Fixed subrate page
shubham1206agra Jan 7, 2025
ed00cdc
Fixed empty time case
shubham1206agra Jan 7, 2025
6c34373
Fixed weird destination options when options are less than the threshold
shubham1206agra Jan 7, 2025
394a07e
Fixed offline behavior in destination page
shubham1206agra Jan 7, 2025
b89b6b5
Fixed subrate form
shubham1206agra Jan 7, 2025
6aa760e
Fix qty translation
shubham1206agra Jan 8, 2025
afb3c15
Fix time badge translation
shubham1206agra Jan 8, 2025
eb98559
Merge branch 'Expensify:main' into per-diem-6
shubham1206agra Jan 9, 2025
6b69c5c
Fix eReceipts
shubham1206agra Jan 10, 2025
e723cf7
Merge branch 'Expensify:main' into per-diem-6
shubham1206agra Jan 10, 2025
06a6ea1
Fix eReceipts part 2
shubham1206agra Jan 10, 2025
a51ff73
Fix translations
shubham1206agra Jan 10, 2025
393ba99
Merge branch 'Expensify:main' into per-diem-6
shubham1206agra Jan 11, 2025
1c0d561
Fix variable names
shubham1206agra Jan 12, 2025
3e366f4
Minor fix
shubham1206agra Jan 12, 2025
312b9ff
Merge branch 'Expensify:main' into per-diem-6
shubham1206agra Jan 12, 2025
348c201
Fixed default category not setting up properly
shubham1206agra Jan 12, 2025
c07a2bf
Disable blur validation in subrate step
shubham1206agra Jan 12, 2025
35e70a3
Fix lint
shubham1206agra Jan 13, 2025
4bae644
Fix conflicts
shubham1206agra Jan 14, 2025
9616b52
Fix lint part 1
shubham1206agra Jan 14, 2025
784da8e
Fix lint part 2
shubham1206agra Jan 14, 2025
850c339
Fix lint part 3
shubham1206agra Jan 14, 2025
2ae74b1
Merge main
shubham1206agra Jan 16, 2025
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
2 changes: 2 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2303,6 +2303,8 @@ const CONST = {

IOU: {
MAX_RECENT_REPORTS_TO_SHOW: 5,
// This will guranatee that the quantity input will not exceed 9,007,199,254,740,991 (Number.MAX_SAFE_INTEGER).
QUANTITY_MAX_LENGTH: 12,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @shubham1206agra, coming from this issue, just wanna confirm if for PerDiem expenses, we allow quantity up to 12 max-length?

// This is the transactionID used when going through the create expense flow so that it mimics a real transaction (like the edit flow)
OPTIMISTIC_TRANSACTION_ID: '1',
// Note: These payment types are used when building IOU reportAction message values in the server and should
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ function MoneyRequestPreviewContent({
const hasWarningTypeViolations = TransactionUtils.hasWarningTypeViolation(transaction?.transactionID, transactionViolations, true);
const hasFieldErrors = TransactionUtils.hasMissingSmartscanFields(transaction);
const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction);
const isPerDiemRequest = TransactionUtils.isPerDiemRequest(transaction);
const isFetchingWaypointsFromServer = TransactionUtils.isFetchingWaypointsFromServer(transaction);
const isCardTransaction = TransactionUtils.isCardTransaction(transaction);
const isSettled = ReportUtils.isSettled(iouReport?.reportID);
Expand Down Expand Up @@ -197,6 +198,8 @@ function MoneyRequestPreviewContent({

if (isDistanceRequest) {
message = translate('common.distance');
} else if (isPerDiemRequest) {
message = translate('common.perDiem');
} else if (isScanning) {
message = translate('common.receipt');
} else if (isBillSplit) {
Expand Down
5 changes: 3 additions & 2 deletions src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
} = useMemo<Partial<TransactionDetails>>(() => ReportUtils.getTransactionDetails(transaction) ?? {}, [transaction]);
const isEmptyMerchant = transactionMerchant === '' || transactionMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT;
const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction);
const isPerDiemRequest = TransactionUtils.isPerDiemRequest(transaction);
const formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : '';
const formattedPerAttendeeAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount / (transactionAttendees?.length ?? 1), transactionCurrency) : '';
const formattedOriginalAmount = transactionOriginalAmount && transactionOriginalCurrency && CurrencyUtils.convertToDisplayString(transactionOriginalAmount, transactionOriginalCurrency);
Expand Down Expand Up @@ -243,15 +244,15 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
amountDescription += ` ${CONST.DOT_SEPARATOR} ${translate('iou.canceled')}`;
}
} else {
if (!isDistanceRequest) {
if (!isDistanceRequest && !isPerDiemRequest) {
amountDescription += ` ${CONST.DOT_SEPARATOR} ${translate('iou.cash')}`;
}
if (isApproved) {
amountDescription += ` ${CONST.DOT_SEPARATOR} ${translate('iou.approved')}`;
} else if (isCancelled) {
amountDescription += ` ${CONST.DOT_SEPARATOR} ${translate('iou.canceled')}`;
} else if (isSettled) {
amountDescription += ` ${translate('iou.settledExpensify')}`;
amountDescription += ` ${CONST.DOT_SEPARATOR} ${translate('iou.settledExpensify')}`;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/TimeModalPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function TimeModalPicker({value, errorText, label, onInputChange = () => {}}: Ti
<TimePicker
defaultValue={value}
onSubmit={updateInput}
shouldValidate={false}
shouldValidateFutureTime={false}
/>
</View>
</ScreenWrapper>
Expand Down
13 changes: 11 additions & 2 deletions src/components/TimePicker/TimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type TimePickerProps = {
/** Whether the time value should be validated */
shouldValidate?: boolean;

/** Whether the time value should be validated for future time only */
shouldValidateFutureTime?: boolean;

/** Whether the picker shows hours, minutes, seconds and milliseconds */
showFullFormat?: boolean;
};
Expand Down Expand Up @@ -118,7 +121,10 @@ function clearSelectedValue(
setSelection({start: newCursorPosition, end: newCursorPosition});
}

function TimePicker({defaultValue = '', onSubmit, onInputChange = () => {}, shouldValidate = true, showFullFormat = false}: TimePickerProps, ref: ForwardedRef<TimePickerRef>) {
function TimePicker(
{defaultValue = '', onSubmit, onInputChange = () => {}, shouldValidate = true, shouldValidateFutureTime = true, showFullFormat = false}: TimePickerProps,
ref: ForwardedRef<TimePickerRef>,
) {
const {numberFormat, translate} = useLocalize();
const {isExtraSmallScreenHeight} = useResponsiveLayout();
const styles = useThemeStyles();
Expand Down Expand Up @@ -166,12 +172,15 @@ function TimePicker({defaultValue = '', onSubmit, onInputChange = () => {}, shou
setErrorMessage(translate('common.error.invalidTimeRange'));
return false;
}
if (!shouldValidateFutureTime) {
return true;
}
const isValid = DateUtils.isTimeAtLeastOneMinuteInFuture({timeString, dateTimeString: defaultValue});
setError(!isValid);
setErrorMessage(translate('common.error.invalidTimeShouldBeFuture'));
return isValid;
},
[shouldValidate, hours, minutes, amPmValue, defaultValue, translate],
[shouldValidate, hours, minutes, amPmValue, shouldValidateFutureTime, defaultValue, translate],
);

const resetHours = () => {
Expand Down
24 changes: 24 additions & 0 deletions src/libs/API/parameters/CreatePerDiemRequestParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
type CreatePerDiemRequestParams = {
policyID: string;
created: string;
customUnitID: string;
customUnitRateID: string;
subRates: string;
currency: string;
startDateTime: string;
endDateTime: string;
category?: string;
description: string;
tag?: string;
iouReportID: string;
chatReportID: string;
transactionID: string;
reportActionID: string;
createdChatReportActionID: string;
createdIOUReportActionID: string;
reportPreviewReportActionID: string;
transactionThreadReportID: string;
createdReportActionIDForThread: string;
};

export default CreatePerDiemRequestParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,4 @@ export type {default as ExportPerDiemCSVParams} from './ExportPerDiemCSVParams';
export type {default as UpdateWorkspaceCustomUnitParams} from './UpdateWorkspaceCustomUnitParams';
export type {default as DismissProductTrainingParams} from './DismissProductTraining';
export type {default as OpenWorkspacePlanPageParams} from './OpenWorkspacePlanPage';
export type {default as CreatePerDiemRequestParams} from './CreatePerDiemRequestParams';
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ const WRITE_COMMANDS = {
UPDATE_BILLING_CARD_CURRENCY: 'UpdateBillingCardCurrency',
UNHOLD_MONEY_REQUEST: 'UnHoldRequest',
REQUEST_MONEY: 'RequestMoney',
CREATE_PER_DIEM_REQUEST: 'CreatePerDiemRequest',
SPLIT_BILL: 'SplitBill',
SPLIT_BILL_AND_OPEN_REPORT: 'SplitBillAndOpenReport',
DELETE_MONEY_REQUEST: 'DeleteMoneyRequest',
Expand Down Expand Up @@ -626,6 +627,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.UNHOLD_MONEY_REQUEST]: Parameters.UnHoldMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.REQUEST_MONEY]: Parameters.RequestMoneyParams;
[WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST]: Parameters.CreatePerDiemRequestParams;
[WRITE_COMMANDS.SPLIT_BILL]: Parameters.SplitBillParams;
[WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT]: Parameters.SplitBillParams;
[WRITE_COMMANDS.DELETE_MONEY_REQUEST]: Parameters.DeleteMoneyRequestParams;
Expand Down
5 changes: 5 additions & 0 deletions src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,10 @@ function isValidDateString(dateString: string) {
return !Number.isNaN(date.getTime());
}

function getFormattedDateRangeForPerDiem(date1: Date, date2: Date): string {
return `${format(date1, 'MMM d, yyyy')} - ${format(date2, 'MMM d, yyyy')}`;
}

const DateUtils = {
isDate,
formatToDayOfWeek,
Expand Down Expand Up @@ -959,6 +963,7 @@ const DateUtils = {
isValidDateString,
getFormattedDurationBetweenDates,
getFormattedDuration,
getFormattedDateRangeForPerDiem,
};

export default DateUtils;
2 changes: 1 addition & 1 deletion src/libs/Navigation/OnyxTabNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function OnyxTabNavigator({
const index = state.index;
const routeNames = state.routeNames;
const newSelectedTab = routeNames.at(index);
if (selectedTab === newSelectedTab || (selectedTab && !routeNames.includes(selectedTab))) {
if (selectedTab === newSelectedTab) {
Comment thread
shubham1206agra marked this conversation as resolved.
return;
}
Tab.setSelectedTab(id, newSelectedTab as SelectedTabRequest);
Expand Down
8 changes: 8 additions & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3327,12 +3327,20 @@ function canEditFieldOfMoneyRequest(reportAction: OnyxInputOrEntry<ReportAction>
return isAdmin || isManager;
}

if (
(fieldToEdit === CONST.EDIT_REQUEST_FIELD.AMOUNT || fieldToEdit === CONST.EDIT_REQUEST_FIELD.CURRENCY || fieldToEdit === CONST.EDIT_REQUEST_FIELD.MERCHANT) &&
TransactionUtils.isPerDiemRequest(transaction)
) {
return false;
}

if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.RECEIPT) {
const isRequestor = currentUserAccountID === reportAction?.actorAccountID;
return (
!isInvoiceReport(moneyRequestReport) &&
!TransactionUtils.isReceiptBeingScanned(transaction) &&
!TransactionUtils.isDistanceRequest(transaction) &&
!TransactionUtils.isPerDiemRequest(transaction) &&
(isAdmin || isManager || isRequestor)
);
}
Expand Down
12 changes: 11 additions & 1 deletion src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {OnyxInputOrEntry, Policy, RecentWaypoint, Report, ReviewDuplicates, TaxRate, TaxRates, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
import type {Attendee} from '@src/types/onyx/IOU';
import type {SearchPolicy, SearchReport} from '@src/types/onyx/SearchResults';
import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction';
import type {Comment, Receipt, TransactionChanges, TransactionCustomUnit, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction';
import type DeepValueOf from '@src/types/utils/DeepValueOf';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import getDistanceInMeters from './getDistanceInMeters';
Expand All @@ -51,6 +51,7 @@ type TransactionParams = {
reimbursable?: boolean;
source?: string;
filename?: string;
customUnit?: TransactionCustomUnit;
};

type BuildOptimisticTransactionParams = {
Expand Down Expand Up @@ -194,6 +195,7 @@ function buildOptimisticTransaction(params: BuildOptimisticTransactionParams): T
reimbursable = true,
source = '',
filename = '',
customUnit,
} = transactionParams;
// transactionIDs are random, positive, 64-bit numeric strings.
// Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID)
Expand All @@ -213,6 +215,12 @@ function buildOptimisticTransaction(params: BuildOptimisticTransactionParams): T
lodashSet(commentJSON, 'customUnit.distanceUnit', DistanceRequestUtils.getUpdatedDistanceUnit({transaction: existingTransaction, policy}));
}

const isPerDiemTransaction = !!pendingFields?.subRates;
if (isPerDiemTransaction) {
// Set the custom unit, which comes from the policy per diem rate data
lodashSet(commentJSON, 'customUnit', customUnit);
}

return {
...(!isEmptyObject(pendingFields) ? {pendingFields} : {}),
transactionID,
Expand Down Expand Up @@ -265,6 +273,7 @@ function isMerchantMissing(transaction: OnyxEntry<Transaction>) {
function shouldShowAttendees(iouType: IOUType, policy: OnyxEntry<Policy>): boolean {
return false;
// To be renabled once feature is complete: https://github.com/Expensify/App/issues/44725
// Keep this disabled for per diem expense
// return iouType === CONST.IOU.TYPE.SUBMIT && !!policy?.id && (policy?.type === CONST.POLICY.TYPE.CORPORATE || policy?.type === CONST.POLICY.TYPE.TEAM);
}

Expand Down Expand Up @@ -1424,6 +1433,7 @@ export {
getAllSortedTransactions,
getFormattedPostedDate,
getCategoryTaxCodeAndAmount,
isPerDiemRequest,
};

export type {TransactionChanges};
Loading