Skip to content

Commit

Permalink
feat: Calculate VAT using useFeeBreakdown(), not via Calculate co…
Browse files Browse the repository at this point in the history
…mponent
  • Loading branch information
DafyddLlyr committed Dec 5, 2024
1 parent dbd4569 commit c926c05
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const BoldTableRow = styled(TableRow)(() => ({
},
}));

const VAT_RATE = 0.2;
export const VAT_RATE = 0.2;

const DESCRIPTION =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface FeeBreakdown {
export interface PassportFeeFields {
"application.fee.calculated": number;
"application.fee.payable": number;
"application.fee.payable.vat": number;
"application.fee.payable.includesVAT": boolean;
"application.fee.reduction.alternative": boolean;
"application.fee.reduction.parishCouncil": boolean;
"application.fee.reduction.sports": boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": 1000,
"application.fee.payable": 800,
"application.fee.payable.vat": 160,
"application.fee.payable.includesVAT": ["true"],
"some.other.fields": ["abc", "xyz"],
};

Expand All @@ -33,7 +33,7 @@ describe("useFeeBreakdown() hook", () => {
applicationFee: 1000,
total: 800,
reduction: 200,
vat: 160,
vat: 166.67,
},
exemptions: [],
reductions: [],
Expand All @@ -44,7 +44,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": [1000],
"application.fee.payable": [800],
"application.fee.payable.vat": [160],
"application.fee.payable.includesVAT": ["true"],
"some.other.fields": ["abc", "xyz"],
};

Expand All @@ -57,7 +57,7 @@ describe("useFeeBreakdown() hook", () => {
applicationFee: 1000,
total: 800,
reduction: 200,
vat: 160,
vat: 166.67,
},
exemptions: [],
reductions: [],
Expand All @@ -68,7 +68,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": 1000,
"application.fee.payable": 800,
"application.fee.payable.vat": 160,
"application.fee.payable.includesVAT": ["true"],
"application.fee.reduction.alternative": ["true"],
"application.fee.reduction.parishCouncil": ["true"],
"some.other.fields": ["abc", "xyz"],
Expand All @@ -88,7 +88,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": 1000,
"application.fee.payable": 800,
"application.fee.payable.vat": 160,
"application.fee.payable.includesVAT": ["true"],
"application.fee.reduction.alternative": ["false"],
"application.fee.reduction.parishCouncil": ["false"],
"some.other.fields": ["abc", "xyz"],
Expand All @@ -105,7 +105,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": 1000,
"application.fee.payable": 800,
"application.fee.payable.vat": 160,
"application.fee.payable.includesVAT": ["true"],
"application.fee.reduction.alternative": ["true"],
"application.fee.reduction.parishCouncil": ["false"],
"application.fee.reduction.someReason": ["true"],
Expand All @@ -128,7 +128,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": 1000,
"application.fee.payable": 800,
"application.fee.payable.vat": 160,
"application.fee.payable.includesVAT": ["true"],
"application.fee.exemption.disability": ["true"],
"application.fee.exemption.resubmission": ["true"],
"some.other.fields": ["abc", "xyz"],
Expand All @@ -148,7 +148,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": 1000,
"application.fee.payable": 800,
"application.fee.payable.vat": 160,
"application.fee.payable.includesVAT": ["true"],
"application.fee.exemption.disability": ["false"],
"application.fee.exemption.resubmission": ["false"],
"some.other.fields": ["abc", "xyz"],
Expand All @@ -165,7 +165,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": 1000,
"application.fee.payable": 800,
"application.fee.payable.vat": 160,
"application.fee.payable.includesVAT": ["true"],
"application.fee.exemption.disability": ["false"],
"application.fee.exemption.resubmission": ["false"],
"application.fee.exemption.someReason": ["true"],
Expand All @@ -180,10 +180,10 @@ describe("useFeeBreakdown() hook", () => {

const result = useFeeBreakdown();

expect(result?.exemption).toEqual(
expect(result?.exemptions).toEqual(
expect.not.arrayContaining(["someReason"])
);
expect(result?.exemption).toEqual(
expect(result?.exemptions).toEqual(
expect.not.arrayContaining(["someOtherReason"])
);
});
Expand All @@ -205,7 +205,7 @@ describe("useFeeBreakdown() hook", () => {
it("returns undefined for partial data", () => {
const mockPassportData = {
"application.fee.calculated": [1000],
"application.fee.payable.vat": [160],
"application.fee.payable.includesVAT": ["true"],
"some.other.fields": ["abc", "xyz"],
};

Expand All @@ -220,7 +220,7 @@ describe("useFeeBreakdown() hook", () => {
const mockPassportData = {
"application.fee.calculated": "some string",
"application.fee.payable": [800, 700],
"application.fee.payable.vat": false,
"application.fee.payable.includesVAT": false,
"some.other.fields": ["abc", "xyz"],
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("calculateReduction() helper function", () => {
const input: PassportFeeFields = {
"application.fee.calculated": 100,
"application.fee.payable": 50,
"application.fee.payable.vat": 0,
"application.fee.payable.includesVAT": false,
"application.fee.reduction.alternative": false,
"application.fee.reduction.parishCouncil": false,
"application.fee.reduction.sports": false,
Expand All @@ -38,7 +38,7 @@ describe("calculateReduction() helper function", () => {
const input: PassportFeeFields = {
"application.fee.calculated": 0,
"application.fee.payable": 100,
"application.fee.payable.vat": 0,
"application.fee.payable.includesVAT": false,
"application.fee.reduction.alternative": false,
"application.fee.reduction.parishCouncil": false,
"application.fee.reduction.sports": false,
Expand All @@ -56,7 +56,7 @@ describe("toFeeBreakdown() helper function", () => {
const input: PassportFeeFields = {
"application.fee.calculated": 100,
"application.fee.payable": 50,
"application.fee.payable.vat": 10,
"application.fee.payable.includesVAT": true,
"application.fee.reduction.alternative": false,
"application.fee.reduction.parishCouncil": false,
"application.fee.reduction.sports": false,
Expand All @@ -68,14 +68,13 @@ describe("toFeeBreakdown() helper function", () => {

expect(amount.applicationFee).toEqual(input["application.fee.calculated"]);
expect(amount.total).toEqual(input["application.fee.payable"]);
expect(amount.vat).toEqual(input["application.fee.payable.vat"]);
expect(amount.reduction).toEqual(50);
});

it("sets applicationFee to payable amount if no calculated value is provided", () => {
const input: PassportFeeFields = {
"application.fee.calculated": 0,
"application.fee.payable.vat": 10,
"application.fee.payable.includesVAT": true,
"application.fee.payable": 50,
"application.fee.reduction.alternative": false,
"application.fee.reduction.parishCouncil": false,
Expand All @@ -88,4 +87,21 @@ describe("toFeeBreakdown() helper function", () => {

expect(amount.applicationFee).toEqual(input["application.fee.payable"]);
});

it("correctly calculates the VAT", () => {
const input: PassportFeeFields = {
"application.fee.calculated": 100,
"application.fee.payable": 50,
"application.fee.payable.includesVAT": true,
"application.fee.reduction.alternative": false,
"application.fee.reduction.parishCouncil": false,
"application.fee.reduction.sports": false,
"application.fee.exemption.disability": false,
"application.fee.exemption.resubmission": false,
};

const { amount } = toFeeBreakdown(input);

expect(amount.vat).toEqual(16.67);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from "zod";

import { VAT_RATE } from "./FeeBreakdown";
import { FeeBreakdown, PassportFeeFields } from "./types";

export const toNumber = (input: number | [number]) =>
Expand Down Expand Up @@ -29,6 +30,9 @@ const toBoolean = (val: ["true" | "false"]) => val[0] === "true";
return granularKeys;
};

export const calculateApplicationFee = (data: PassportFeeFields) =>
data["application.fee.calculated"] || data["application.fee.payable"]

/**
* A "reduction" is the sum of the difference between calculated and payable
*/
Expand All @@ -37,16 +41,24 @@ export const calculateReduction = (data: PassportFeeFields) =>
? data["application.fee.calculated"] - data["application.fee.payable"]
: 0;

export const calculateVAT = (data: PassportFeeFields) => {
if (!data["application.fee.payable.includesVAT"]) return 0;

const fee = calculateApplicationFee(data);
const vat = (fee * VAT_RATE) / (1 + VAT_RATE);
const roundedVAT = Number(vat.toFixed(2));

return roundedVAT;
};

/**
* Transform Passport data to a FeeBreakdown
*/
export const toFeeBreakdown = (data: PassportFeeFields): FeeBreakdown => ({
amount: {
applicationFee:
data["application.fee.calculated"] ||
data["application.fee.payable"],
applicationFee: calculateApplicationFee(data),
total: data["application.fee.payable"],
vat: data["application.fee.payable.vat"],
vat: calculateVAT(data),
reduction: calculateReduction(data),
},
reductions: getGranularKeys(data, "application.fee.reduction"),
Expand All @@ -70,7 +82,7 @@ export const createPassportSchema = () => {
.object({
"application.fee.calculated": feeSchema.optional().default(0),
"application.fee.payable": feeSchema,
"application.fee.payable.vat": feeSchema.optional().default(0),
"application.fee.payable.includesVAT": booleanSchema,
"application.fee.reduction.alternative": booleanSchema,
"application.fee.reduction.parishCouncil": booleanSchema,
"application.fee.reduction.sports": booleanSchema,
Expand Down

0 comments on commit c926c05

Please sign in to comment.