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

Move bank sync payee name normalisation from actual to actual-server #353

Merged
merged 18 commits into from
Jul 9, 2024

Conversation

matt-fidd
Copy link
Contributor

@matt-fidd matt-fidd commented May 6, 2024

This PR fixes #348 and takes the approach discussed to add a new payeeName field to the transaction returned to actual.

It is designed to fix any inconsistencies in data returned from GoCardless with regards to the variety of payee fields that are used, and should result in the "best chance" of a human readable and non-transaction specific payee if it is available.

I have tested these with the bank that I originally spotted the issue with (Santander) and payee names are now correctly created in actual. Banks that I can test with that already worked as expected have not regressed and payees are still reflected correctly.

I can not test the custom bank handlers but all I have done to them is make sure they now return a payeeName as this will be required by actual to normalise the transactions on the client side.

I've also had to copy the title util that actual used to format the payee names.

Complimentary PR in Actual is: actualbudget/actual#2721

@matt-fidd matt-fidd changed the title Move bank sync payee name normalisation from actual to actual-server [WIP] Move bank sync payee name normalisation from actual to actual-server May 6, 2024
@matt-fidd matt-fidd force-pushed the payee-name branch 2 times, most recently from 27966c5 to 819f7ce Compare May 6, 2024 23:30
@matt-fidd matt-fidd changed the title [WIP] Move bank sync payee name normalisation from actual to actual-server Move bank sync payee name normalisation from actual to actual-server May 6, 2024
@psybers
Copy link
Contributor

psybers commented May 25, 2024

As mentioned in actualbudget/actual#2721 maybe the field can be named payee instead of payeeName? That way it should work with SimpleFIN too.

@psybers
Copy link
Contributor

psybers commented May 25, 2024

And I do wonder, does this function need called on the SimpleFIN side too?

@matt-fidd
Copy link
Contributor Author

matt-fidd commented May 25, 2024

Now that I'm thinking about this again, I'm not sure this is the best approach for gocardless. Previously each custom handler had this payee standardisation done regardless, but this change puts the onus on the contributer to make sure the field is included in the handler.

Maybe I could move the formatPayeeName call into gocardless-service to retain the behaviour from before and run on all transactions by default?

getTransactions: async ({ institutionId, accountId, startDate, endDate }) => {

Any thoughts?

@matt-fidd
Copy link
Contributor Author

Now that I'm thinking about this again, I'm not sure this is the best approach for gocardless. Previously each custom handler had this payee standardisation done regardless, but this change puts the onus on the contributer to make sure the field is included in the handler.

Maybe I could move the formatPayeeName call into gocardless-service to retain the behaviour from before and run on all transactions by default?

getTransactions: async ({ institutionId, accountId, startDate, endDate }) => {

Any thoughts?

Actually I reckon the above is the better way to go, it retains the behaviour from before and simplifies bank handlers. Will refactor now.

Comment on lines +23 to +29
name =
name ||
trans.debtorName ||
trans.creditorName ||
trans.remittanceInformationUnstructured ||
(trans.remittanceInformationUnstructuredArray || []).join(', ') ||
trans.additionalInformation;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the if/else above sets name to something (possibly), you can avoid the assignment here and simplify it quite a bit in that case it found a name already.

Suggested change
name =
name ||
trans.debtorName ||
trans.creditorName ||
trans.remittanceInformationUnstructured ||
(trans.remittanceInformationUnstructuredArray || []).join(', ') ||
trans.additionalInformation;
if (!name) {
name =
trans.remittanceInformationUnstructured ||
(trans.remittanceInformationUnstructuredArray || []).join(', ') ||
trans.additionalInformation;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This changes the logic, the key functional part of this change is to allow creditorName to be used even if GoCardless /should/ be using debtorName instead and vice versa.

Happy to put the whole assignment into an if and drop the first name || line if that aligns more closely with the style in this project?

Copy link
Contributor

Choose a reason for hiding this comment

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

That is curious logic! I guess if that is what needs to happen for GoCardless, the existing code is probably fine. I am not sure if there is a style preference between using an if to avoid name = name or leave it as is.

src/util/payee-name.js Outdated Show resolved Hide resolved
Comment on lines 215 to 227
transactions.transactions.booked = transactions.transactions.booked.map(
(t) => ({
...t,
payeeName: formatPayeeName(t),
}),
);

transactions.transactions.pending = transactions.transactions.pending.map(
(t) => ({
...t,
payeeName: formatPayeeName(t),
}),
);
Copy link
Member

Choose a reason for hiding this comment

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

💬 suggestion: ‏instead of doing this uniformly for ALL banks the same way - I think we should allow the bank-providers to do their own payee normalisation (if they wish to).

So my suggestion here is to move this payee name normalisation inside here.

Other than that - LGTM!

Copy link
Contributor Author

@matt-fidd matt-fidd Jul 8, 2024

Choose a reason for hiding this comment

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

That was my initial approach but I turned away from it because this way replicates the behaviour prior to this change.
If needed creditorName/debtorName can be altered in the bank handler to change the payee name, but I think that the default behaviour to fall back on other fields and append the IBAN when present is best retained.

Let me know what you reckon, happy to change if you disagree.

Copy link
Member

Choose a reason for hiding this comment

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

We can still keep the same behavior as before. But just have the normalization logic in a different location (the generic bank handler + the overrides).

IMO that would be more future proof solution since it would allow to change this logic on a per-bank basis.

@matt-fidd matt-fidd requested a review from MatissJanis July 8, 2024 22:50
Comment on lines -26 to -27
console.log(transaction);

Copy link
Member

Choose a reason for hiding this comment

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

👏 praise: ‏thanks!

@MatissJanis
Copy link
Member

Before merging this in: @psybers do you have any other feedback here? Or good to go on your end too?

@psybers
Copy link
Contributor

psybers commented Jul 9, 2024

@MatissJanis I think for now this is fine. I am a bit worried about having payeeName: formatPayee(transaction) all over the place, and specifically that it might get missed on new bank overrides. But we can probably find a cleaner way to handle that and refactor it down the road.

@MatissJanis MatissJanis merged commit 3661c15 into actualbudget:master Jul 9, 2024
6 checks passed
@matt-fidd matt-fidd deleted the payee-name branch July 9, 2024 22:33
duplaja added a commit to duplaja/actual-server that referenced this pull request Jul 13, 2024
Remove formatPayeeName function, since SimpleFIN transaction objects aren't compatible. ( trans.payee is the preferred method).
MMichotte pushed a commit to MMichotte/actual-server that referenced this pull request Sep 9, 2024
MMichotte pushed a commit to MMichotte/actual-server that referenced this pull request Sep 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: GoCardless inconsistent use of creditorName and debtorName fields
3 participants