Skip to content

Commit ef1024b

Browse files
committed
Fix negative transaction total after moving IOU report to a workspace
When an IOU report is converted to an expense report, the optimistic transaction data negated amount and modifiedAmount to match the expense-report sign convention but left convertedAmount and convertedTaxAmount untouched. Because getConvertedAmount flips the sign for expense reports, the per-row TOTAL column rendered the still-positive convertedAmount as a negative value. Negate convertedAmount and convertedTaxAmount in the optimistic data in both convertIOUReportToExpenseReport and createWorkspaceFromIOUPayment, using a conditional spread so absent values are not overwritten. Rollback data is built from the unmodified transaction, so failure restores the original values.
1 parent ed3aefa commit ef1024b

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

src/libs/actions/Policy/Policy.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4475,6 +4475,8 @@ function createWorkspaceFromIOUPayment(
44754475
...transaction,
44764476
amount: -transaction.amount,
44774477
modifiedAmount: hasValidModifiedAmount(transaction) ? -Number(transaction.modifiedAmount) : '',
4478+
...(transaction.convertedAmount != null && {convertedAmount: -transaction.convertedAmount}),
4479+
...(transaction.convertedTaxAmount != null && {convertedTaxAmount: -transaction.convertedTaxAmount}),
44784480
};
44794481

44804482
transactionFailureData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = transaction;

src/libs/actions/Report/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6793,6 +6793,8 @@ function convertIOUReportToExpenseReport(iouReport: Report, policy: Policy, poli
67936793
...transaction,
67946794
amount: -transaction.amount,
67956795
modifiedAmount: hasValidModifiedAmount(transaction) ? -Number(transaction.modifiedAmount) : '',
6796+
...(transaction.convertedAmount != null && {convertedAmount: -transaction.convertedAmount}),
6797+
...(transaction.convertedTaxAmount != null && {convertedTaxAmount: -transaction.convertedTaxAmount}),
67966798
};
67976799

67986800
transactionFailureData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = transaction;

tests/actions/ReportTest.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3935,6 +3935,64 @@ describe('actions/Report', () => {
39353935
const reportValue = reportUpdate?.value as Partial<OnyxTypes.Report> | undefined;
39363936
expect(reportValue?.reportName).toBe(CONST.REPORT.DEFAULT_EXPENSE_REPORT_NAME);
39373937
});
3938+
3939+
it('should negate convertedAmount and convertedTaxAmount on the optimistic transactions so the table total stays positive', () => {
3940+
// Given a policy and an IOU report with a transaction that has positive converted amounts (IOU sign convention)
3941+
const policyID = '302';
3942+
const policyWithEmptyFieldList: OnyxTypes.Policy = {
3943+
...createRandomPolicy(Number(policyID)),
3944+
id: policyID,
3945+
type: CONST.POLICY.TYPE.TEAM,
3946+
fieldList: {},
3947+
name: 'Test Policy',
3948+
};
3949+
3950+
const iouReport: OnyxTypes.Report = {
3951+
...createRandomReport(3, undefined),
3952+
reportID: 'iouReport302',
3953+
type: CONST.REPORT.TYPE.IOU,
3954+
ownerAccountID: 3,
3955+
reportName: 'Original IOU Report Name',
3956+
total: 5000,
3957+
};
3958+
3959+
const transaction: OnyxTypes.Transaction = {
3960+
...createRandomTransaction(302),
3961+
transactionID: 'transaction302',
3962+
reportID: iouReport.reportID,
3963+
amount: 5000,
3964+
modifiedAmount: '',
3965+
convertedAmount: 6000,
3966+
convertedTaxAmount: 600,
3967+
};
3968+
3969+
Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, policyWithEmptyFieldList);
3970+
3971+
// When converting the IOU report to an expense report
3972+
const result = Report.convertIOUReportToExpenseReport(iouReport, policyWithEmptyFieldList, policyID, 'expenseChat302', [transaction]);
3973+
3974+
// Then the optimistic transaction stores amount, convertedAmount and convertedTaxAmount with the expense-report (negative) sign convention
3975+
const transactionUpdate = result.optimisticData.find((update) => update.key === ONYXKEYS.COLLECTION.TRANSACTION) as
3976+
| OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION>
3977+
| undefined;
3978+
const optimisticTransaction = (transactionUpdate?.value as Record<string, OnyxTypes.Transaction> | undefined)?.[
3979+
`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`
3980+
];
3981+
expect(optimisticTransaction?.amount).toBe(-5000);
3982+
expect(optimisticTransaction?.convertedAmount).toBe(-6000);
3983+
expect(optimisticTransaction?.convertedTaxAmount).toBe(-600);
3984+
3985+
// And the failure data restores the original positive values on rollback
3986+
const transactionFailure = result.failureData.find((update) => update.key === ONYXKEYS.COLLECTION.TRANSACTION) as
3987+
| OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION>
3988+
| undefined;
3989+
const rolledBackTransaction = (transactionFailure?.value as Record<string, OnyxTypes.Transaction> | undefined)?.[
3990+
`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`
3991+
];
3992+
expect(rolledBackTransaction?.amount).toBe(5000);
3993+
expect(rolledBackTransaction?.convertedAmount).toBe(6000);
3994+
expect(rolledBackTransaction?.convertedTaxAmount).toBe(600);
3995+
});
39383996
});
39393997
});
39403998

0 commit comments

Comments
 (0)