Closed pecanoro closed 2 weeks ago
@parasharrajat I am assigning you as the C+ in this issue since you reviewed the main ones.
Sure
Triggered auto assignment to @sonialiap (Bug
), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.
Job added to Upwork: https://www.upwork.com/jobs/~011781060ec2a6c428
Current assignee @parasharrajat is eligible for the External assigner, not assigning anyone new.
Add a new command for admin/approver when resolving the duplicate transaction from submitter
We're always calling mergeDuplicates
function without checking the current user is admin/approver or not
resolveDuplicates
that will call ResolveDuplicates
comman with the param as described here. It will be almost the same with mergeDuplicates
, the only difference with mergeDuplicates
is It won't delete the rest of the transactions in transactionIDList but it will HOLD them by adding the hold NVP to it and will add the corresponding HOLD actions to each of them.
transactionIDList
. Instead, we will add a hold action for these transaction thread reports in optimistic data and reset in failure data and also add hold
violation for these transactionIt will add a DISMISSEDVIOLATION action to the transactionIDToKeep
reason
in originalMessage
is duplicatedTransaction
for the transaction thread report of transactionIDToKeep
listIt will dismiss the violation by adding the corresponding transaction NVP for all transactions.
transactionIDToKeep
The proposal sounds good @nkdengineer sounds good to me.
:ribbon: :eyes: :ribbon: C+ reviewed
Current assignee @pecanoro is eligible for the choreEngineerContributorManagement assigner, not assigning anyone new.
Assigning @nkdengineer!
📣 @nkdengineer 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!
Offer link Upwork job Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑💻 Keep in mind: Code of Conduct | Contributing 📖
Will raise the PR tomorrow.
@pecanoro In the ResolveDuplicates
API, what is the structure of reportActionIDList
params?
In the ResolveDuplicates API, what is the structure of reportActionIDList params?
A comma-separated list of report actions
A comma-separated list of report actions
@pecanoro Can you give an example? Do we need to add reportID
in data?
@pecanoro Can you give an example?
Imagine we have 3 duplicates with transactionIDs 111, 222 and 333. We want to keep 111 and hold the other two. Then:
'transactionIDToKeep' => '111',
'transactionIDList' => '222,333',
Do we need to add reportID in data?
Nope, no reportID since they are not changing reports
@pecanoro I mean I need an example for reportActionIDList
param.
Ahh, the same, another comma-separated list, same as DismissViolations. The reportActionIDList contains the optimistic report actions for the HOLD actions. Then optimisticReportActionID should be for the dismissViolation action.
Got it, So the reportActionIDList
is the same order with the transactionIDList
right (example the first reportActionID is the hold action of the first transaction in transactionIDList
)?
actually for the normal hold reason flow it will have two report actions, one is the hold message, one is the reason. Should we do the same in this case or we will add only the first action or add both actions?
Got it, So the reportActionIDList is the same order with the transactionIDList right (example the first reportActionID is the hold action of the first transaction in transactionIDList)?
Yes!
actually for the normal hold reason flow it will have two report actions, one is the hold message, one is the reason. Should we do the same in this case or we will add only the first action or add both actions?
No need to add a reason for this one, it will only show that is was held.
@nkdengineer when can we expect the PR raised? ty!
Will open this today
amazing, ty!
@pecanoro When I call ResolveDuplicates
, BE returns the error like this video. Here is the parameter that I called this API. Am I missing something?
{
"amount": -200,
"currency": "VND",
"created": "2024-09-09",
"transactionIDList": [
"4002616464040896678"
],
"billable": false,
"reimbursable": true,
"category": "",
"tag": "",
"merchant": "ssd",
"comment": "",
"transactionIDToKeep": "5332969134080823220",
"reportActionIDList": [
"637476526581947356"
],
"optimisticReportActionID": "3766068727586466325"
}
https://github.com/user-attachments/assets/d9ca09c3-9441-41c9-9465-145f28816be9
Oh, it's a BE problem, I j just checked the logs. Let me create a PR to fix it
The PR is merged, we are waiting for a deploy and then you will be able to use the endpoint in staging again. I renamed transactionIDToKeep for just transactionID
@nkdengineer PR is deployed to prod now!
@parasharrajat The PR is here.
it will HOLD them by adding the hold NVP to it
What do you mean by NVP @pecanoro?
@pecanoro While testing I found another BE bug, the dismiss violation action isn't stored from BE side.
What do you mean by NVP @pecanoro?
Ah sorry, when the transaction is put on HOLD, we add a value to the transaction namevaluepairs in the comment.
@pecanoro While testing I found another BE bug, the dismiss violation action isn't stored from BE side.
Are you sure? It is added for the transaction we want to keep, not for the others.
Yes, I tested and after reset cache this action is removed since BE doesn't return this action. Also the resolve duplicate API doesn't return dismiss violation action data.
Let me double-check manually, but it's pretty odd since I even wrote automated tests for this and they are passing
@nkdengineer Can you paste here what the BE is returning for you?
{
"accountID": 18311825,
"accounts": {
"18311825": {
"lastUpdateID": 1775760902,
"previousUpdateID": 1775614249,
"updateIDs": [
1775760897,
1775760898,
1775760899,
1775760900,
1775760901,
1775760902
]
}
},
"authToken": "ED538D6882FC6B872FD1E38C8B75EC3ED4799DAF2809D40258D5A38DF3F448972D57954AF21C6EF04D9DBA533734CD6FC5B8908331F9904CF87AF73E8B286E9DDC523F8C2153DB499A0D6E433B2BD2E21CB71155B10A7F6D64826D4ACD1CA0443ECF354E9006107CD6DAC056448043E0FBDE3C32367A157108E87CBB53EDBFFD03E891BCEB5DA77E8EBEF24B5AF0D7E9FD9A757BDA391A6568E463678C8EF1BF1E55E96771BEEE6228EF37F1B8FF3BE280B9E5C6B2235E5FAD8E30F652EAA244C06EFE2E8B18BFB3CB8DA94286CC32C74D0B5F03C003CD78D2BB8A9D02A9478C89F64E9674B229779DDC5DEA5EED7B3DF5A513373D224C022CE70012AEAEA03F4BF4CF18ED5EBE8DF44F7A53F64C623731EF5689A91E9FB3E061CDF663B373ED10CECB4758B6D759E25715BB2EF0BE6C729E7A3928CF1F89005D8434D3BD4556A86E95D218CB4353E3B6E6A20E66F7775725A89AEB459453192F36B84EA2742A",
"email": "nkdengineer+s102@outlook.com",
"fetchableOnyxUpdates": [
"1775760897",
"1775760898",
"1775760899",
"1775760900",
"1775760901",
"1775760902"
],
"onyxUpdates": {
"1775760897": [
{
"key": "transactions_398480206897163307",
"onyxMethod": "merge",
"value": {
"comment": {
"dismissedViolations": {
"duplicatedTransaction": {
"nkdengineer+s102@outlook.com": 1726161878570510
}
}
}
}
}
],
"1775760898": [
{
"key": "transactions_1367302367436179941",
"onyxMethod": "merge",
"value": {
"comment": {
"comment": "",
"dismissedViolations": {
"duplicatedTransaction": {
"nkdengineer+s102@outlook.com": 1726161878570610
}
}
}
}
}
],
"1775760899": [
{
"key": "report_1113086820473870",
"onyxMethod": "merge",
"value": {
"participants": {
"18301280": {
"hidden": true,
"notificationPreference": "hidden"
},
"18308128": {
"hidden": true,
"notificationPreference": "hidden"
},
"18311825": {
"hidden": true,
"notificationPreference": "hidden"
}
}
}
}
],
"1775760900": [
{
"key": "report_1113086820473870",
"onyxMethod": "merge",
"value": {
"chatType": "",
"description": "",
"lastActorAccountID": 18311825,
"lastMessageText": "held this expense with the comment: ",
"lastVisibleActionCreated": "2024-09-12 17:24:38.571",
"managerID": null,
"ownerAccountID": 0,
"parentReportActionID": "2951370456346266262",
"parentReportID": "8755324512976856",
"policyID": "2D62A4DBCE91AD7E",
"reportID": "1113086820473870",
"reportName": "Chat Report",
"state": "OPEN",
"stateNum": 0,
"statusNum": 0,
"type": "chat",
"visibility": null
}
},
{
"key": "reportActions_1113086820473870",
"onyxMethod": "merge",
"value": {
"2272851721205218606": {
"actionName": "HOLD",
"actorAccountID": 18311825,
"avatar": "https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/default-avatar_18.png",
"created": "2024-09-12 17:24:38.571",
"lastModified": "2024-09-12 17:24:38.571",
"message": [
{
"html": "",
"text": "",
"type": "COMMENT",
"whisperedTo": []
}
],
"originalMessage": {
"accountID": 18311825,
"date": "2024-09-12 17:24:38",
"isDuplicate": "true",
"lastModified": "2024-09-12 17:24:38.571",
"message": ""
},
"person": [
{
"style": "strong",
"text": "nkd102",
"type": "TEXT"
}
],
"reportActionID": "2272851721205218606",
"shouldShow": true
}
}
}
],
"1775760901": [
{
"key": "personalDetailsList",
"onyxMethod": "merge",
"value": {
"18311825": {
"accountID": 18311825,
"avatar": "https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/default-avatar_18.png",
"displayName": "nkd102",
"firstName": "nkd102",
"lastName": "",
"login": "nkdengineer+s102@outlook.com",
"phoneNumber": "",
"pronouns": "",
"status": null,
"timezone": {
"automatic": true,
"selected": "Asia/Ho_Chi_Minh"
},
"validated": true
}
}
}
],
"1775760902": [
{
"key": "transactions_1367302367436179941",
"onyxMethod": "merge",
"value": {
"comment": {
"hold": "2272851721205218606"
}
}
}
]
},
"httpCode": 200,
"jsonCode": 200,
"authResponseMessage": "200 OK",
"requestID": "8c21979b5e5e1fbc-HKG",
"onyxData": [
{
"key": "transactions_398480206897163307",
"onyxMethod": "merge",
"value": {
"comment": {
"dismissedViolations": {
"duplicatedTransaction": {
"nkdengineer+s102@outlook.com": 1726161878570510
}
}
}
}
},
{
"key": "transactions_1367302367436179941",
"onyxMethod": "merge",
"value": {
"comment": {
"comment": "",
"dismissedViolations": {
"duplicatedTransaction": {
"nkdengineer+s102@outlook.com": 1726161878570610
}
}
}
}
},
{
"key": "report_1113086820473870",
"onyxMethod": "merge",
"value": {
"participants": {
"18301280": {
"hidden": true,
"notificationPreference": "hidden"
},
"18308128": {
"hidden": true,
"notificationPreference": "hidden"
},
"18311825": {
"hidden": true,
"notificationPreference": "hidden"
}
}
}
},
{
"key": "report_1113086820473870",
"onyxMethod": "merge",
"value": {
"chatType": "",
"description": "",
"lastActorAccountID": 18311825,
"lastMessageText": "held this expense with the comment: ",
"lastVisibleActionCreated": "2024-09-12 17:24:38.571",
"managerID": null,
"ownerAccountID": 0,
"parentReportActionID": "2951370456346266262",
"parentReportID": "8755324512976856",
"policyID": "2D62A4DBCE91AD7E",
"reportID": "1113086820473870",
"reportName": "Chat Report",
"state": "OPEN",
"stateNum": 0,
"statusNum": 0,
"type": "chat",
"visibility": null
}
},
{
"key": "reportActions_1113086820473870",
"onyxMethod": "merge",
"value": {
"2272851721205218606": {
"actionName": "HOLD",
"actorAccountID": 18311825,
"avatar": "https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/default-avatar_18.png",
"created": "2024-09-12 17:24:38.571",
"lastModified": "2024-09-12 17:24:38.571",
"message": [
{
"html": "",
"text": "",
"type": "COMMENT",
"whisperedTo": []
}
],
"originalMessage": {
"accountID": 18311825,
"date": "2024-09-12 17:24:38",
"isDuplicate": "true",
"lastModified": "2024-09-12 17:24:38.571",
"message": ""
},
"person": [
{
"style": "strong",
"text": "nkd102",
"type": "TEXT"
}
],
"reportActionID": "2272851721205218606",
"shouldShow": true
}
}
},
{
"key": "personalDetailsList",
"onyxMethod": "merge",
"value": {
"18311825": {
"accountID": 18311825,
"avatar": "https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/default-avatar_18.png",
"displayName": "nkd102",
"firstName": "nkd102",
"lastName": "",
"login": "nkdengineer+s102@outlook.com",
"phoneNumber": "",
"pronouns": "",
"status": null,
"timezone": {
"automatic": true,
"selected": "Asia/Ho_Chi_Minh"
},
"validated": true
}
}
},
{
"key": "transactions_1367302367436179941",
"onyxMethod": "merge",
"value": {
"comment": {
"hold": "2272851721205218606"
}
}
}
],
"previousUpdateID": 1775614249,
"lastUpdateID": 1775760902
}
@pecanoro The response here.
The payload here.
There is something off, also because both hold actions are returned for the same report
Ah nvm, forget my previous comment, you were resolving duplicates with only two transactions. I am going to check the database
Ah I found the problem, another parameter name that got cleared because of sanitization. I am going to rename it to something better either way. I will create a PR in the back-end
@nkdengineer BE fix is on staging, you can test it in the PR now! New parameter is called dismissedViolationReportActionID
instead of optimisticReportActionID
@pecanoro Does this change affect keep All
functionality as well? Do we need to change that too?
@parasharrajat No, it should not change it
Got it. Thanks.
Note for future: I noticed that when admin resolves a duplicate, the transaction is no more duplicate for admin but same transaction still shown duplicate for the original user who requested. I confirmed that this is expected https://github.com/Expensify/App/pull/48522#issuecomment-2364201769
@parasharrajat The original PR was reverted so I created a new one here to fix another bug https://github.com/Expensify/App/issues/49900
Reviewing
label has been removed, please complete the "BugZero Checklist".
The solution for this issue has been :rocket: deployed to production :rocket: in version 9.0.45-4 and is now subject to a 7-day regression period :calendar:. Here is the list of pull requests that resolve this issue:
If no regressions arise, payment will be issued on 2024-10-14. :confetti_ball:
For reference, here are some details about the assignees on this issue:
BugZero Checklist: The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:
Part of the Duplicate Detection project
Main issue: https://github.com/Expensify/Expensify/issues/411008 Project: Dupe detection
Feature Description
Right now, we always call MergeTransactions when resolving duplicates and click
Confirm
at the last page of resolving duplicates. However, we need to call a new command calledResolveDuplicates
when an approver or admin (basically anyone but the submitter) is the person resolving the duplicates. The behaviour (so we can create the proper optimistic actions) should be as follows:This command will update the transaction to match the fields we chose during the flow. It should already be doing this.
Main issue: https://github.com/Expensify/Expensify/issues/411008
Upwork Automation - Do Not Edit
Issue Owner
Current Issue Owner: @Issue Owner
Current Issue Owner: @parasharrajat