Skip to content

Commit

Permalink
Merge pull request #268 from theopensystemslab/oz/update-maintenance-…
Browse files Browse the repository at this point in the history
…levels

feat: update maintenance levels
  • Loading branch information
zz-hh-aa authored Jan 10, 2025
2 parents 3c01a0d + 7ff6db2 commit 1fbc30f
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 23 deletions.
4 changes: 2 additions & 2 deletions app/api/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe("POST API Route", () => {
houseAge: 3,
houseBedrooms: 2,
houseType: "D",
maintenancePercentage: 0.02,
maintenancePercentage: 0.019,
};

const householdData = {
Expand Down Expand Up @@ -96,7 +96,7 @@ describe("POST API Route", () => {
houseAge: 3,
houseBedrooms: 2,
houseType: "D",
maintenancePercentage: 0.02,
maintenancePercentage: 0.019,
};

const errorMessage = "Service error";
Expand Down
24 changes: 12 additions & 12 deletions app/components/ui/CalculatorInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { Household } from "@/app/models/Household";
import Dashboard from "./Dashboard";
import { formSchema, FormFrontend } from "@/app/schemas/formSchema";
import { useSearchParams } from "next/navigation";
import { DEFAULT_INTEREST_RATE, DEFAULT_MORTGAGE_TERM, DEFAULT_INITIAL_DEPOSIT } from "../../models/constants"
import { DEFAULT_INTEREST_RATE, DEFAULT_MORTGAGE_TERM, DEFAULT_INITIAL_DEPOSIT, MAINTENANCE_LEVELS } from "../../models/constants"
import { z } from "zod";
import { maintenancePercentageSchema } from "@/app/schemas/calculationSchema";

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { ClipLoader } from "react-spinners";
Expand Down Expand Up @@ -49,11 +51,9 @@ const CalculatorInput = () => {
urlHouseType === "S"
? urlHouseType
: "D", // Default value for house type
maintenancePercentage: [0.015, 0.02, 0.0375].includes(
Number(urlMaintenancePercentage)
)
? (Number(urlMaintenancePercentage) as 0.015 | 0.02 | 0.0375) // Type assertion
: 0.015,
maintenancePercentage: (MAINTENANCE_LEVELS as readonly number[]).includes(Number(urlMaintenancePercentage))
? Number(urlMaintenancePercentage) as z.infer<typeof maintenancePercentageSchema>
: MAINTENANCE_LEVELS[0],
housePostcode: urlPostcode || "",
// Apply defaults if provided
// Type-safe to account for exactOptionalPropertyTypes propert in tsconfig.json
Expand Down Expand Up @@ -280,41 +280,41 @@ const CalculatorInput = () => {
>
<div className="flex items-center space-x-2">
<RadioGroupItem
value="0.015"
value={MAINTENANCE_LEVELS[0].toString()}
id="radio-option-low"
className="radio-button-style"
/>
<Label
htmlFor="radio-option-low"
className="radio-label-style"
>
Low (1.5%)
Low ({MAINTENANCE_LEVELS[0] * 100}%)
</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem
value="0.02"
value={MAINTENANCE_LEVELS[1].toString()}
id="radio-option-medium"
className="radio-button-style"
/>
<Label
htmlFor="radio-option-medium"
className="radio-label-style"
>
Medium (2%)
Medium ({MAINTENANCE_LEVELS[1] * 100}%)
</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem
value="0.0375"
value={MAINTENANCE_LEVELS[2].toString()}
id="radio-option-high"
className="radio-button-style"
/>
<Label
htmlFor="radio-option-high"
className="radio-label-style"
>
High (3.75%)
High ({MAINTENANCE_LEVELS[2] * 100}%)
</Label>
</div>
</RadioGroup>
Expand Down
4 changes: 2 additions & 2 deletions app/models/ForecastParameters.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MAINTENANCE_LEVELS } from "./constants";
import { createForecastParameters, DEFAULT_FORECAST_PARAMETERS } from "./ForecastParameters";

it("can create default forecast parameters", () => {
Expand All @@ -19,9 +20,8 @@ it("correctly sets maintenance percentage while keeping defaults", () => {
});

it("handles different maintenance percentage values", () => {
const testCases = [0.015, 0.02, 0.0375];

testCases.forEach(maintenance => {
MAINTENANCE_LEVELS.forEach(maintenance => {
const params = createForecastParameters(maintenance);
expect(params.maintenancePercentage).toBe(maintenance);
});
Expand Down
2 changes: 1 addition & 1 deletion app/models/ForecastParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface ForecastParameters {
* all values except years are percentages represented in decimal form
*/
export const DEFAULT_FORECAST_PARAMETERS: ForecastParameters = {
maintenancePercentage: 0.02,
maintenancePercentage: 0.019,
incomeGrowthPerYear: 0.04,
constructionPriceGrowthPerYear: 0.025,
rentGrowthPerYear: 0.03,
Expand Down
2 changes: 1 addition & 1 deletion app/models/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const NATIONAL_AVERAGES: NationalAverage = {
* Maintenance levels are percentages (represented as decimals),
* figures from our own model
*/
export const MAINTENANCE_LEVELS = [0.015, 0.02, 0.0375] as const;
export const MAINTENANCE_LEVELS = [0.015, 0.019, 0.025] as const;

/** Type for storing component values and depreciation*/
export type componentBreakdownType = {
Expand Down
6 changes: 3 additions & 3 deletions app/schemas/calculationSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
parse as parsePostcode,
isValid as isValidPostcode,
} from "postcode";
import { HOUSE_TYPES } from "../models/Property";
import { HOUSE_TYPES, MaintenancePercentage } from "../models/Property";
import { MAINTENANCE_LEVELS } from "../models/constants";

// Type not exported by postcode lib directly
Expand All @@ -12,8 +12,8 @@ export type ValidPostcode = Extract<ReturnType<typeof parsePostcode>, { valid: t
const HouseTypeEnum = z.enum(HOUSE_TYPES);

export const maintenancePercentageSchema = z.number().refine(
(value): value is typeof MAINTENANCE_LEVELS[number] =>
MAINTENANCE_LEVELS.includes(value as typeof MAINTENANCE_LEVELS[number]),
(value): value is MaintenancePercentage =>
(MAINTENANCE_LEVELS as readonly number[]).includes(value),
{
message: `Maintenance percentage must be one of: ${MAINTENANCE_LEVELS.join(', ')}`
}
Expand Down
6 changes: 4 additions & 2 deletions app/services/calculationService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { socialRentEarningsService } from "./socialRentEarningsService";
import { rentService } from "./rentService";
import { parse } from "postcode";
import { ValidPostcode } from "../schemas/calculationSchema";
import { z } from "zod";
import { maintenancePercentageSchema } from "../schemas/calculationSchema";

jest.mock("./itlService");
jest.mock("./gdhiService");
Expand Down Expand Up @@ -48,7 +50,7 @@ describe("getHouseholdData", () => {
houseAge: number;
houseBedrooms: number;
houseSize: number;
maintenancePercentage: 0.015 | 0.02 | 0.0375;
maintenancePercentage: z.infer<typeof maintenancePercentageSchema>;
}

const mockInput: MockInputType = {
Expand All @@ -57,7 +59,7 @@ describe("getHouseholdData", () => {
houseAge: 20,
houseBedrooms: 3,
houseSize: 100,
maintenancePercentage: 0.02
maintenancePercentage: 0.019
};

beforeEach(() => {
Expand Down

0 comments on commit 1fbc30f

Please sign in to comment.