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

fix: Use new ResolveDuplicates when approver is resolving duplicates #48522

Merged
merged 25 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
36b7e06
fix: Use new ResolveDuplicates when approver is resolving duplicates
nkdengineer Sep 4, 2024
2d1d4ca
add new api params
nkdengineer Sep 4, 2024
6325f73
Merge branch 'main' into fix/48416
nkdengineer Sep 9, 2024
8086b11
complete parameter for API
nkdengineer Sep 9, 2024
06bdd10
Merge branch 'main' into fix/48416
nkdengineer Sep 11, 2024
107be8e
fix the order issue
nkdengineer Sep 11, 2024
c5023dc
fix lint
nkdengineer Sep 11, 2024
e881a3b
Merge branch 'main' into fix/48416
nkdengineer Sep 11, 2024
b549c50
merge main
nkdengineer Sep 12, 2024
96d0da4
create a util to get iou action
nkdengineer Sep 12, 2024
754932d
rename variable
nkdengineer Sep 12, 2024
b7a27c3
fix lint
nkdengineer Sep 12, 2024
b331032
use getIOUActionForTransactions
nkdengineer Sep 12, 2024
85cc2e9
merge main
nkdengineer Sep 12, 2024
5fcf063
remove unuse variable
nkdengineer Sep 12, 2024
f56ffab
Update src/libs/API/parameters/ResolveDuplicatesParams.ts
nkdengineer Sep 12, 2024
c076bdc
Merge branch 'main' into fix/48416
nkdengineer Sep 13, 2024
aee9154
fix lint
nkdengineer Sep 13, 2024
0ba5ac8
Merge branch 'main' into fix/48416
nkdengineer Sep 17, 2024
c776014
update param
nkdengineer Sep 17, 2024
46c75e1
Merge branch 'main' into fix/48416
nkdengineer Sep 19, 2024
e32ed93
Merge branch 'main' into fix/48416
nkdengineer Sep 24, 2024
98287b6
fix native bug
nkdengineer Sep 24, 2024
23e2313
Update src/libs/actions/IOU.ts
nkdengineer Sep 25, 2024
b3cce2d
Merge branch 'main' into fix/48416
nkdengineer Sep 25, 2024
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
17 changes: 17 additions & 0 deletions src/libs/API/parameters/TransactionResolveParams.ts
Copy link
Member

Choose a reason for hiding this comment

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

Rename this file too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as below.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
type TransactionResolveParams = {
transactionID: string;
transactionIDList: string[];
pecanoro marked this conversation as resolved.
Show resolved Hide resolved
created: string;
merchant: string;
amount: number;
currency: string;
category: string;
comment: string;
billable: boolean;
reimbursable: boolean;
tag: string;
optimisticReportActionID: string;
reportActionIDList: string[];
pecanoro marked this conversation as resolved.
Show resolved Hide resolved
};

export default TransactionResolveParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export type {default as SendInvoiceParams} from './SendInvoiceParams';
export type {default as PayInvoiceParams} from './PayInvoiceParams';
export type {default as MarkAsCashParams} from './MarkAsCashParams';
export type {default as TransactionMergeParams} from './TransactionMergeParams';
export type {default as TransactionResolveParams} from './TransactionResolveParams';
export type {default as UpdateSubscriptionTypeParams} from './UpdateSubscriptionTypeParams';
export type {default as SignUpUserParams} from './SignUpUserParams';
export type {default as UpdateSubscriptionAutoRenewParams} from './UpdateSubscriptionAutoRenewParams';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ const WRITE_COMMANDS = {
PAY_INVOICE: 'PayInvoice',
MARK_AS_CASH: 'MarkAsCash',
TRANSACTION_MERGE: 'Transaction_Merge',
TRANSACTION_RESOLVE: 'ResolveDuplicates',
nkdengineer marked this conversation as resolved.
Show resolved Hide resolved
UPDATE_SUBSCRIPTION_TYPE: 'UpdateSubscriptionType',
SIGN_UP_USER: 'SignUpUser',
UPDATE_SUBSCRIPTION_AUTO_RENEW: 'UpdateSubscriptionAutoRenew',
Expand Down Expand Up @@ -658,6 +659,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.PAY_INVOICE]: Parameters.PayInvoiceParams;
[WRITE_COMMANDS.MARK_AS_CASH]: Parameters.MarkAsCashParams;
[WRITE_COMMANDS.TRANSACTION_MERGE]: Parameters.TransactionMergeParams;
[WRITE_COMMANDS.TRANSACTION_RESOLVE]: Parameters.TransactionResolveParams;
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_TYPE]: Parameters.UpdateSubscriptionTypeParams;
[WRITE_COMMANDS.SIGN_UP_USER]: Parameters.SignUpUserParams;
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_AUTO_RENEW]: Parameters.UpdateSubscriptionAutoRenewParams;
Expand Down
144 changes: 144 additions & 0 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import type {
SubmitReportParams,
TrackExpenseParams,
TransactionMergeParams,
TransactionResolveParams,
UnapproveExpenseReportParams,
UpdateMoneyRequestParams,
} from '@libs/API/parameters';
Expand Down Expand Up @@ -8110,6 +8111,148 @@ function mergeDuplicates(params: TransactionMergeParams) {
API.write(WRITE_COMMANDS.TRANSACTION_MERGE, params, {optimisticData, failureData});
}

function resolveDuplicates(params: TransactionMergeParams) {
nkdengineer marked this conversation as resolved.
Show resolved Hide resolved
const originalSelectedTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${params.transactionID}`];

const optimisticTransactionData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${params.transactionID}`,
value: {
...originalSelectedTransaction,
billable: params.billable,
comment: {
comment: params.comment,
},
category: params.category,
created: params.created,
currency: params.currency,
modifiedMerchant: params.merchant,
reimbursable: params.reimbursable,
tag: params.tag,
},
};

const failureTransactionData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${params.transactionID}`,
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
value: originalSelectedTransaction as OnyxTypes.Transaction,
};

const optimisticTransactionViolations: OnyxUpdate[] = [...params.transactionIDList, params.transactionID].map((id) => {
const violations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`] ?? [];
const newViolation = {name: CONST.VIOLATIONS.HOLD, type: CONST.VIOLATION_TYPES.VIOLATION};
const updatedViolations = id === params.transactionID ? violations : [...violations, newViolation];
return {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`,
value: updatedViolations.filter((violation) => violation.name !== CONST.VIOLATIONS.DUPLICATED_TRANSACTION),
};
});

const failureTransactionViolations: OnyxUpdate[] = [...params.transactionIDList, params.transactionID].map((id) => {
const violations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`] ?? [];
return {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`,
value: violations,
};
});

const iouActionList = Object.values(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${params.reportID}`] ?? {})?.filter(
(reportAction): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => {
if (!ReportActionsUtils.isMoneyRequestAction(reportAction)) {
return false;
}
const message = ReportActionsUtils.getOriginalMessage(reportAction);
if (!message?.IOUTransactionID) {
return false;
}
return params.transactionIDList.includes(message.IOUTransactionID);
},
);
nkdengineer marked this conversation as resolved.
Show resolved Hide resolved

const reportIDList = iouActionList.map((action) => action?.childReportID);
const orderedTransactionIDList = iouActionList.map((action) => {
const message = ReportActionsUtils.getOriginalMessage(action);
return message?.IOUTransactionID ?? '';
});

const optimisticHoldActions: OnyxUpdate[] = [];
const failureHoldActions: OnyxUpdate[] = [];
const reportActionIDList: string[] = [];
reportIDList.forEach((transactionThreadReportID) => {
const createdReportAction = ReportUtils.buildOptimisticHoldReportAction();
reportActionIDList.push(createdReportAction.reportActionID);
optimisticHoldActions.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
value: {
[createdReportAction.reportActionID]: createdReportAction,
},
});
failureHoldActions.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
value: {
[createdReportAction.reportActionID]: {
errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericHoldExpenseFailureMessage'),
},
},
});
});

const transactionReportID = Object.values(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${params.reportID}`] ?? {})?.find(
nkdengineer marked this conversation as resolved.
Show resolved Hide resolved
(reportAction): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => {
if (!ReportActionsUtils.isMoneyRequestAction(reportAction)) {
return false;
}
const message = ReportActionsUtils.getOriginalMessage(reportAction);
if (!message?.IOUTransactionID) {
return false;
}
return params.transactionID === message.IOUTransactionID;
},
)?.childReportID;

const optimisticReportAction = ReportUtils.buildOptimisticDismissedViolationReportAction({
reason: 'manual',
violationName: CONST.VIOLATIONS.DUPLICATED_TRANSACTION,
});

const optimisticReportActionData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionReportID}`,
value: {
[optimisticReportAction.reportActionID]: optimisticReportAction,
},
};

const failureReportActionData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionReportID}`,
value: {
[optimisticReportAction.reportActionID]: null,
},
};

const optimisticData: OnyxUpdate[] = [];
const failureData: OnyxUpdate[] = [];

optimisticData.push(optimisticTransactionData, ...optimisticTransactionViolations, ...optimisticHoldActions, optimisticReportActionData);
failureData.push(failureTransactionData, ...failureTransactionViolations, ...failureHoldActions, failureReportActionData);
const {reportID, transactionIDList, receiptID, ...otherParams} = params;

const parameters: TransactionResolveParams = {
...otherParams,
reportActionIDList,
transactionIDList: orderedTransactionIDList,
optimisticReportActionID: optimisticReportAction.reportActionID,
};

API.write(WRITE_COMMANDS.TRANSACTION_RESOLVE, parameters, {optimisticData, failureData});
}

export {
adjustRemainingSplitShares,
approveMoneyRequest,
Expand Down Expand Up @@ -8180,5 +8323,6 @@ export {
updateMoneyRequestTaxAmount,
updateMoneyRequestTaxRate,
mergeDuplicates,
resolveDuplicates,
};
export type {GPSPoint as GpsPoint, IOURequestType};
21 changes: 20 additions & 1 deletion src/pages/TransactionDuplicate/Confirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import {ShowContextMenuContext} from '@components/ShowContextMenuContext';
import Text from '@components/Text';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
Expand All @@ -33,6 +34,8 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
function Confirmation() {
const styles = useThemeStyles();
const {translate} = useLocalize();
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
const route = useRoute<RouteProp<TransactionDuplicateNavigatorParamList, typeof SCREENS.TRANSACTION_DUPLICATE.REVIEW>>();
const [reviewDuplicates, reviewDuplicatesResult] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES);
const transaction = useMemo(() => TransactionUtils.buildNewTransactionAfterReviewingDuplicates(reviewDuplicates), [reviewDuplicates]);
Expand All @@ -42,12 +45,22 @@ function Confirmation() {
(action) => ReportActionsUtils.isMoneyRequestAction(action) && ReportActionsUtils.getOriginalMessage(action)?.IOUTransactionID === reviewDuplicates?.transactionID,
);

const isActionOwner = report?.ownerAccountID === currentUserPersonalDetails?.accountID;
pecanoro marked this conversation as resolved.
Show resolved Hide resolved
const isApprover = ReportUtils.isMoneyRequestReport(report) && report?.managerID !== null && currentUserPersonalDetails?.accountID === report?.managerID;
const isAdmin = ReportUtils.isPolicyAdmin(report?.policyID ?? '-1', allPolicies);

const transactionsMergeParams = useMemo(() => TransactionUtils.buildTransactionsMergeParams(reviewDuplicates, transaction), [reviewDuplicates, transaction]);

const mergeDuplicates = useCallback(() => {
IOU.mergeDuplicates(transactionsMergeParams);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportAction?.childReportID ?? '-1'));
}, [reportAction?.childReportID, transactionsMergeParams]);

const resolveDuplicates = useCallback(() => {
IOU.resolveDuplicates(transactionsMergeParams);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportAction?.childReportID ?? '-1'));
}, [transactionsMergeParams, reportAction?.childReportID]);

const contextValue = useMemo(
() => ({
transactionThreadReport: report,
Expand Down Expand Up @@ -109,7 +122,13 @@ function Confirmation() {
<Button
text={translate('common.confirm')}
success
onPress={mergeDuplicates}
onPress={() => {
if ((isAdmin || isApprover) && !isActionOwner) {
pecanoro marked this conversation as resolved.
Show resolved Hide resolved
resolveDuplicates();
return;
}
mergeDuplicates();
}}
large
/>
</FixedFooter>
Expand Down
Loading