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

feat(fee-breakdown): Parse and display reductions and exemptions #4022

Closed
wants to merge 16 commits into from

Conversation

DafyddLlyr
Copy link
Contributor

@DafyddLlyr DafyddLlyr commented Nov 29, 2024

What does this PR do?

  • Parses Passport for reductions and exemptions
  • Displays these as a list to the user
  • Does not try to match or generate a value for either of these

image

@DafyddLlyr DafyddLlyr changed the base branch from main to dp/simple-fee-breakdown November 29, 2024 17:37
Copy link

github-actions bot commented Nov 29, 2024

Pizza

Deployed 175095d to https://4022.planx.pizza.

Useful links:

Comment on lines +13 to +19
amount: {
"application.fee.calculated": number;
"application.fee.payable": number;
"application.fee.payable.vat": number;
},
reductions?: Record<string, boolean>
exemptions?: Record<string, boolean>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The change to this structure was pretty much required in order for this to be parsed by Zod.

Initially I spend a fair bit of time trying to get a "raw" passport in here, but as the type of they keys was a list of known strings, and a list of unknown strings (i.e. just string) it wasn't possible to parse in a meaningful way.

Here's an invalid / not meaningful TS interface that shows this -

interface PassportFeeFields {
  // Known keys
  "application.fee.calculated": number;
  "application.fee.payable": number;
  "application.fee.payable.vat": number;
  // Unknown keys
  [key: string]: string[];
}
image

As a result, I've added the preProcessPassport() function to map a raw passport to this data shape.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another valid and really nice approach here I haven't dug into (but could be worth trying) would be to use template literal types.

I think this is a super interesting approach, but I suspect it will add more complexity not less. I'm also not sure how Zod would handle this, and I still have questions around if application.fee should be hardcoded or dynamic. One to explore another time I think!

interface PassportFeeFields {
  "application.fee.calculated": number;
  "application.fee.payable": number;
  "application.fee.payable.vat": number;
  [key: `application.fee.reductions.${string}`]: string[];
  [key: `application.fee.exemptions.${string}`]: string[];
}

Comment on lines +89 to +91
amount: amountsSchema,
reductions: reductionsSchema,
exemptions: exemptionsSchema,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Breaking these down into their own schemas solved the known / unknown keys issue described here - https://github.com/theopensystemslab/planx-new/pull/4022/files#r1865505036

I was hitting some issues using z.intersection() or z.and() to combine these into a flat schema.

@DafyddLlyr DafyddLlyr requested a review from a team December 2, 2024 09:29
@DafyddLlyr DafyddLlyr marked this pull request as ready for review December 2, 2024 09:29
);
};

// TODO: This won't show as if a fee is 0, we hide the whole Pay component from the user
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll pick this up as a follow up PR 👍

data.amount["application.fee.calculated"] ||
data.amount["application.fee.payable"],
total: data.amount["application.fee.payable"],
vat: data.amount["application.fee.payable.vat"],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll also pick up calculating this ourselves (and toggling the display in-component) as a follow on PR as discussed on the call this morning 👍

reductions.map((reduction) => (
<TableRow>
<TableCell colSpan={2}>
<Box sx={{ pl: 2, color: "grey" }}>{reduction}</Box>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll pick up displaying a meaningful value here, alongside associated validation, as another PR.

A meaningful value could be .description from the schema, or a .reason from the passport.

@DafyddLlyr DafyddLlyr marked this pull request as draft December 4, 2024 15:20
@DafyddLlyr
Copy link
Contributor Author

Converted back to draft, following the design call I'll make this a discrete list of passport variables that we care about as opposed to a more generic solution.

@DafyddLlyr
Copy link
Contributor Author

Closed in favour of #4040 as many of the core comments here no longer apply. I'll carry over relevant comments and list of todos/next PRs.

@DafyddLlyr DafyddLlyr force-pushed the dp/simple-fee-breakdown branch from d4ffe09 to dbd4569 Compare December 5, 2024 08:36
@DafyddLlyr DafyddLlyr closed this Dec 5, 2024
@DafyddLlyr DafyddLlyr deleted the dp/exemptions-reductions branch December 5, 2024 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant