diff options
| author | Joe Carstairs <me@joeac.net> | 2024-12-12 08:26:53 +0000 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2024-12-12 08:26:53 +0000 |
| commit | 8a30bcbdf9264d235bf93da3df8e170cfde53d02 (patch) | |
| tree | 5f9b6fe956c72b89a89cc936ab86ec1bffc271f5 /gui/src/types | |
| parent | 51711fb42a44b452cdf1b4fd6a716d0251f23dda (diff) | |
Removes web GUI
Diffstat (limited to 'gui/src/types')
| -rw-r--r-- | gui/src/types/BalanceToBudgetRatio.spec.ts | 307 | ||||
| -rw-r--r-- | gui/src/types/account.ts | 33 | ||||
| -rw-r--r-- | gui/src/types/balanceMap.ts | 17 | ||||
| -rw-r--r-- | gui/src/types/balanceToBudgetRatio.ts | 83 | ||||
| -rw-r--r-- | gui/src/types/budget.ts | 12 | ||||
| -rw-r--r-- | gui/src/types/budgetMap.ts | 16 | ||||
| -rw-r--r-- | gui/src/types/budgetUpdate.ts | 31 | ||||
| -rw-r--r-- | gui/src/types/category.ts | 48 | ||||
| -rw-r--r-- | gui/src/types/currency/currency.ts | 6 | ||||
| -rw-r--r-- | gui/src/types/currency/gbp.ts | 54 | ||||
| -rw-r--r-- | gui/src/types/group.ts | 8 |
11 files changed, 0 insertions, 615 deletions
diff --git a/gui/src/types/BalanceToBudgetRatio.spec.ts b/gui/src/types/BalanceToBudgetRatio.spec.ts deleted file mode 100644 index 3a956ea..0000000 --- a/gui/src/types/BalanceToBudgetRatio.spec.ts +++ /dev/null @@ -1,307 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { BalanceToBudgetRatio } from "./balanceToBudgetRatio"; -import { Gbp } from "./currency/gbp"; - -describe("balanceToBudgetRatio", () => { - it("new() returns null when budget is null", () => { - const result = BalanceToBudgetRatio.new(new Gbp(1, 0, 1), null); - expect(result).toBeNull(); - }); - - it("toString() rounds to 2 decimal places", () => { - const mockCurrencyPi = { valueOf: () => Math.PI }; - const mockCurrencyUnit = { valueOf: () => 1 }; - const sut = BalanceToBudgetRatio.new(mockCurrencyPi, { - quantity: mockCurrencyUnit, - period: 42, - }); - - const result = sut?.toString(); - - expect(result).toBe("3.14"); - }); - - it("new() sets normalisedRatio to 1 when balance and budget are equal and positive", () => { - const twoFifty = new Gbp(2, 50, 1); - const result = BalanceToBudgetRatio.new(twoFifty, { - quantity: twoFifty, - period: 42, - }); - expect(result?.normalisedRatio).toBeCloseTo(1.0); - }); - - it("new() sets normalisedRatio to 2 when balance is twice budget", () => { - const twoFifty = new Gbp(2, 50, 1); - const oneTwentyFive = new Gbp(1, 25, 1); - const result = BalanceToBudgetRatio.new(twoFifty, { - quantity: oneTwentyFive, - period: 42, - }); - expect(result?.normalisedRatio).toBeCloseTo(2.0); - }); - - it("new() sets normalisedRatio to -2 when a negative balance is -1 * twice budget", () => { - const minusTwoFifty = new Gbp(2, 50, -1); - const oneTwentyFive = new Gbp(1, 25, 1); - const result = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: oneTwentyFive, - period: 42, - }); - expect(result?.normalisedRatio).toBeCloseTo(-2.0); - }); - - it("new() sets normalisedRatio to -0.5 when balance is -1 * half a negative budget", () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const minusTwoFifty = new Gbp(2, 50, -1); - const result = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: minusTwoFifty, - period: 42, - }); - expect(result?.normalisedRatio).toBeCloseTo(-0.5); - }); - - it("new() sets normalisedRatio to 1 when balance and budget are equal and negative", () => { - const minusTwoFifty = new Gbp(2, 50, -1); - const result = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: minusTwoFifty, - period: 42, - }); - expect(result?.normalisedRatio).toBeCloseTo(1.0); - }); - - it('new() sets recommended action to "arrears" when ratio is less than 0', () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const minusTwoFifty = new Gbp(2, 50, -1); - - const result = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: minusTwoFifty, - period: 42, - }); - - expect(result?.recommendedAction).toBe("arrears"); - }); - - it('new() sets recommended action to "save" when ratio is between 0 and 1', () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const twoFifty = new Gbp(2, 50, 1); - - const result = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: twoFifty, - period: 42, - }); - - expect(result?.recommendedAction).toBe("save"); - }); - - it('new() sets recommended action to "spend" when ratio is larger than 1', () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const twoFifty = new Gbp(2, 50, 1); - - const result = BalanceToBudgetRatio.new(twoFifty, { - quantity: oneTwentyFive, - period: 42, - }); - - expect(result?.recommendedAction).toBe("spend"); - }); - - it("normalises to a factor of 2 when all ratios are positive", () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const twoFifty = new Gbp(2, 50, 1); - const twoOverOne = BalanceToBudgetRatio.new(twoFifty, { - quantity: oneTwentyFive, - period: 42, - }); - const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { - quantity: twoFifty, - period: 42, - }); - const oneOverOne = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: oneTwentyFive, - period: 42, - }); - const oneOverTwo = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: twoFifty, - period: 42, - }); - - const normaliser = BalanceToBudgetRatio.makeNormaliser( - twoOverOne, - twoOverTwo, - oneOverOne, - oneOverTwo, - ); - - expect(normaliser(twoOverOne).normalisedRatio).toBeCloseTo(1.0); - expect(normaliser(twoOverTwo).normalisedRatio).toBeCloseTo(0.5); - expect(normaliser(oneOverOne).normalisedRatio).toBeCloseTo(0.5); - expect(normaliser(oneOverTwo).normalisedRatio).toBeCloseTo(0.25); - }); - - it("normalises to a factor of 2 when all ratios are negative", () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const twoFifty = new Gbp(2, 50, 1); - const minusOneTwentyFive = new Gbp(1, 25, -1); - const minusTwoFifty = new Gbp(2, 50, -1); - const minusTwoOverOne = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: oneTwentyFive, - period: 42, - }); - const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: twoFifty, - period: 42, - }); - const minusOneOverOne = BalanceToBudgetRatio.new(minusOneTwentyFive, { - quantity: oneTwentyFive, - period: 42, - }); - const minusOneOverTwo = BalanceToBudgetRatio.new(minusOneTwentyFive, { - quantity: twoFifty, - period: 42, - }); - - const normaliser = BalanceToBudgetRatio.makeNormaliser( - minusTwoOverOne, - minusTwoOverTwo, - minusOneOverOne, - minusOneOverTwo, - ); - - expect(normaliser(minusTwoOverOne).normalisedRatio).toBeCloseTo(-1.0); - expect(normaliser(minusTwoOverTwo).normalisedRatio).toBeCloseTo(-0.5); - expect(normaliser(minusOneOverOne).normalisedRatio).toBeCloseTo(-0.5); - expect(normaliser(minusOneOverTwo).normalisedRatio).toBeCloseTo(-0.25); - }); - - it("normalises to a factor of 2 when ratios are a mix of positive and negative", () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const twoFifty = new Gbp(2, 50, 1); - const minusOneTwentyFive = new Gbp(1, 25, -1); - const minusTwoFifty = new Gbp(2, 50, -1); - const twoOverOne = BalanceToBudgetRatio.new(twoFifty, { - quantity: oneTwentyFive, - period: 42, - }); - const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { - quantity: twoFifty, - period: 42, - }); - const oneOverOne = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: oneTwentyFive, - period: 42, - }); - const oneOverTwo = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: twoFifty, - period: 42, - }); - const minusTwoOverOne = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: oneTwentyFive, - period: 42, - }); - const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: twoFifty, - period: 42, - }); - const minusOneOverOne = BalanceToBudgetRatio.new(minusOneTwentyFive, { - quantity: oneTwentyFive, - period: 42, - }); - const minusOneOverTwo = BalanceToBudgetRatio.new(minusOneTwentyFive, { - quantity: twoFifty, - period: 42, - }); - - const normaliser = BalanceToBudgetRatio.makeNormaliser( - twoOverOne, - twoOverTwo, - oneOverOne, - oneOverTwo, - minusTwoOverOne, - minusTwoOverTwo, - minusOneOverOne, - minusOneOverTwo, - ); - - expect(normaliser(twoOverOne).normalisedRatio).toBeCloseTo(1.0); - expect(normaliser(twoOverTwo).normalisedRatio).toBeCloseTo(0.5); - expect(normaliser(oneOverOne).normalisedRatio).toBeCloseTo(0.5); - expect(normaliser(oneOverTwo).normalisedRatio).toBeCloseTo(0.25); - expect(normaliser(minusTwoOverOne).normalisedRatio).toBeCloseTo(-1.0); - expect(normaliser(minusTwoOverTwo).normalisedRatio).toBeCloseTo(-0.5); - expect(normaliser(minusOneOverOne).normalisedRatio).toBeCloseTo(-0.5); - expect(normaliser(minusOneOverTwo).normalisedRatio).toBeCloseTo(-0.25); - }); - - it("sorts large positive ratios before small positive ratios", () => { - const oneTwentyFive = new Gbp(1, 25, 1); - const twoFifty = new Gbp(2, 50, 1); - const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { - quantity: twoFifty, - period: 42, - }); - const oneOverTwo = BalanceToBudgetRatio.new(oneTwentyFive, { - quantity: twoFifty, - period: 42, - }); - - const resultLeftways = BalanceToBudgetRatio.compare(twoOverTwo, oneOverTwo); - const resultRightways = BalanceToBudgetRatio.compare( - oneOverTwo, - twoOverTwo, - ); - - expect(resultLeftways).toBeCloseTo(-resultRightways); - expect(resultLeftways).toBeLessThan(0); - }); - - it("sorts small negative ratios before large negative ratios", () => { - const twoFifty = new Gbp(2, 50, 1); - const minusOneTwentyFive = new Gbp(1, 25, -1); - const minusTwoFifty = new Gbp(2, 50, -1); - const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: twoFifty, - period: 42, - }); - const minusOneOverTwo = BalanceToBudgetRatio.new(minusOneTwentyFive, { - quantity: twoFifty, - period: 42, - }); - - const resultLeftways = BalanceToBudgetRatio.compare( - minusOneOverTwo, - minusTwoOverTwo, - ); - const resultRightways = BalanceToBudgetRatio.compare( - minusTwoOverTwo, - minusOneOverTwo, - ); - - expect(resultLeftways).toBeCloseTo(-resultRightways); - expect(resultLeftways).toBeLessThan(0); - }); - - it("sorts positive ratios before negative ratios", () => { - const twoFifty = new Gbp(2, 50, 1); - const minusTwoFifty = new Gbp(2, 50, -1); - const twoOverTwo = BalanceToBudgetRatio.new(twoFifty, { - quantity: twoFifty, - period: 42, - }); - const minusTwoOverTwo = BalanceToBudgetRatio.new(minusTwoFifty, { - quantity: twoFifty, - period: 42, - }); - - const resultLeftways = BalanceToBudgetRatio.compare( - twoOverTwo, - minusTwoOverTwo, - ); - const resultRightways = BalanceToBudgetRatio.compare( - minusTwoOverTwo, - twoOverTwo, - ); - - expect(resultLeftways).toBeCloseTo(-resultRightways); - expect(resultLeftways).toBeLessThan(0); - }); -}); diff --git a/gui/src/types/account.ts b/gui/src/types/account.ts deleted file mode 100644 index a463304..0000000 --- a/gui/src/types/account.ts +++ /dev/null @@ -1,33 +0,0 @@ -import moment, { Moment } from "moment"; -import Currency from "./currency/currency"; -import Gbp from "./currency/gbp"; - -function newAccountFromDto(dto: unknown): Account { - const dtoDangerous = dto as AccountDto; - return { - id: dtoDangerous.id, - name: dtoDangerous.name, - openingBalance: new Gbp( - Math.floor(Math.abs(dtoDangerous.opening_balance) / 100), - Math.abs(dtoDangerous.opening_balance) % 100, - dtoDangerous.opening_balance < 0 ? -1 : 1, - ), - openingDate: moment(dtoDangerous.opening_date), - }; -} - -interface AccountDto { - readonly id: number; - readonly name: string; - readonly opening_balance: number; - readonly opening_date: string; -} - -interface Account { - readonly id: number; - readonly name: string; - readonly openingBalance: Currency; - readonly openingDate: Moment; -} - -export { type Account, newAccountFromDto }; diff --git a/gui/src/types/balanceMap.ts b/gui/src/types/balanceMap.ts deleted file mode 100644 index 760843f..0000000 --- a/gui/src/types/balanceMap.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Category } from "./category"; -import Currency from "./currency/currency"; -import { newGbpFromDto } from "./currency/gbp"; - -type BalanceMap<T extends { id: any }> = { - [id in T["id"]]: Currency; -}; - -function newCategoryBalanceMapFromDto(dto: unknown): BalanceMap<Category> { - return Object.fromEntries( - (dto as { category_id: Category["id"]; balance: number }[]).map( - ({ category_id, balance }) => [category_id, newGbpFromDto(balance)], - ), - ); -} - -export { type BalanceMap, newCategoryBalanceMapFromDto }; diff --git a/gui/src/types/balanceToBudgetRatio.ts b/gui/src/types/balanceToBudgetRatio.ts deleted file mode 100644 index 2f8000c..0000000 --- a/gui/src/types/balanceToBudgetRatio.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Budget } from "./budget"; -import Currency from "./currency/currency"; - -class BalanceToBudgetRatio { - toString(): string { - return this._ratio?.toFixed(2) ?? ""; - } - - public readonly recommendedAction: "arrears" | "save" | "spend" | null; - public readonly normalisedRatio: number | null; - - private constructor( - private readonly _ratio: number | null, - private readonly _normalisationFactor: number, - ) { - if (this._ratio === null) { - this.normalisedRatio = null; - this.recommendedAction = null; - return; - } - - this.normalisedRatio = this._ratio * this._normalisationFactor; - - if (this._ratio < 0) { - this.recommendedAction = "arrears"; - } else if (this._ratio >= 1) { - this.recommendedAction = "spend"; - } else { - this.recommendedAction = "save"; - } - } - - static new(balance: Currency, budget: Budget | null) { - if (budget === null || budget.quantity === 0 || budget.quantity === -0) { - return null; - } - - return new BalanceToBudgetRatio( - balance.valueOf() / budget.quantity.valueOf(), - 1, - ); - } - - static makeNormaliser( - ...balanceToBudgetRatios: (BalanceToBudgetRatio | null)[] - ): (r: BalanceToBudgetRatio | null) => BalanceToBudgetRatio { - const validRatios = balanceToBudgetRatios.filter( - (r) => - r && - r._ratio && - !isNaN(r._ratio) && - Infinity > r._ratio && - -Infinity < r._ratio, - ); - - const maxAbsRatio = Math.max( - ...validRatios.map((r) => Math.abs(r?._ratio ?? 0)), - ); - - const normalisationFactor = 1 / maxAbsRatio; - return (r) => - new BalanceToBudgetRatio(r?._ratio ?? null, normalisationFactor); - } - - static compare( - lhs: BalanceToBudgetRatio | null, - rhs: BalanceToBudgetRatio | null, - ): number { - if (lhs === null || lhs._ratio === null) { - if (rhs === null || rhs._ratio === null) { - return 0; - } - return 1; - } - if (rhs === null || rhs._ratio === null) { - return -1; - } - - return rhs._ratio - lhs._ratio; - } -} - -export { BalanceToBudgetRatio }; diff --git a/gui/src/types/budget.ts b/gui/src/types/budget.ts deleted file mode 100644 index 5a19a1b..0000000 --- a/gui/src/types/budget.ts +++ /dev/null @@ -1,12 +0,0 @@ -import Currency from "./currency/currency"; - -interface Budget { - quantity: Currency; - period: number; -} - -function newBudgetFromDto(dto: unknown) { - return dto as Budget; -} - -export { type Budget, newBudgetFromDto }; diff --git a/gui/src/types/budgetMap.ts b/gui/src/types/budgetMap.ts deleted file mode 100644 index 5fa09f2..0000000 --- a/gui/src/types/budgetMap.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Budget, newBudgetFromDto } from "./budget"; -import { Category } from "./category"; - -type BudgetMap<T extends { id: any }> = { - [id in T["id"]]: Budget | null; -}; - -function newCategoryBudgetMapFromDto(dto: unknown): BudgetMap<Category> { - return Object.fromEntries( - (dto as { category_id: number; budget: unknown }[]).map( - ({ category_id, budget }) => [category_id, newBudgetFromDto(budget)], - ), - ); -} - -export { type BudgetMap, newCategoryBudgetMapFromDto as newBudgetMapFromDto }; diff --git a/gui/src/types/budgetUpdate.ts b/gui/src/types/budgetUpdate.ts deleted file mode 100644 index 0696f8a..0000000 --- a/gui/src/types/budgetUpdate.ts +++ /dev/null @@ -1,31 +0,0 @@ -import moment, { Moment } from "moment"; -import Currency from "./currency/currency"; - -interface BudgetUpdate { - id: number; - categoryId: number; - date: Moment; - newQuantity: Currency; - newPeriod: number; -} - -interface BudgetUpdateDto { - id: number; - category_id: number; - date: string; - new_budget: number; - new_period: number; -} - -function newBudgetUpdateFromDto(dto: unknown): BudgetUpdate { - const typedDto = dto as BudgetUpdateDto; - return { - id: typedDto.id, - categoryId: typedDto.category_id, - date: moment(typedDto.date), - newQuantity: typedDto.new_budget, - newPeriod: typedDto.new_period, - }; -} - -export { type BudgetUpdate, type BudgetUpdateDto, newBudgetUpdateFromDto }; diff --git a/gui/src/types/category.ts b/gui/src/types/category.ts deleted file mode 100644 index 9c2a651..0000000 --- a/gui/src/types/category.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { BalanceMap } from "./balanceMap"; -import { BalanceToBudgetRatio } from "./balanceToBudgetRatio"; -import { Budget } from "./budget"; -import { BudgetMap } from "./budgetMap"; -import Currency from "./currency/currency"; - -interface Category { - id: number; - name: string; - groupName: string; - currentBalance: Currency; - currentBudget: Budget | null; - balanceToBudgetRatio: BalanceToBudgetRatio | null; -} - -interface CategoryDto { - id: number; - name: string; - group: string; -} - -function newCategoryFromDto( - balances: BalanceMap<Category> | null, - budgets: BudgetMap<Category> | null, -): (dto: unknown) => Category | null { - if (balances === null || budgets === null) { - return () => null; - } - - return function (dto: unknown): Category { - const dtoDangerous = dto as CategoryDto; - const currentBalance = balances[dtoDangerous.id]; - const currentBudget = budgets[dtoDangerous.id]; - return { - id: dtoDangerous.id, - name: dtoDangerous.name, - groupName: dtoDangerous.group, - currentBalance, - currentBudget, - balanceToBudgetRatio: BalanceToBudgetRatio.new( - currentBalance, - currentBudget, - ), - }; - }; -} - -export { type Category, newCategoryFromDto }; diff --git a/gui/src/types/currency/currency.ts b/gui/src/types/currency/currency.ts deleted file mode 100644 index 7c15324..0000000 --- a/gui/src/types/currency/currency.ts +++ /dev/null @@ -1,6 +0,0 @@ -interface Currency { - valueOf(): number; - toString(): string; -} - -export default Currency; diff --git a/gui/src/types/currency/gbp.ts b/gui/src/types/currency/gbp.ts deleted file mode 100644 index b88aae3..0000000 --- a/gui/src/types/currency/gbp.ts +++ /dev/null @@ -1,54 +0,0 @@ -import Currency from "./currency"; - -class Gbp implements Currency { - private readonly sign: 1 | -1; - private readonly pounds: number; - private readonly pence: number; - - constructor(pounds: number, pence: number, sign?: 1 | -1) { - sign = sign ?? 1; - - if (Math.round(pounds) !== pounds) { - throw new Error( - `Cannot construct GBP with non-whole number of pounds: ${pounds}`, - ); - } - if (Math.round(pence) !== pence) { - throw new Error( - `Cannot construct GBP with non-whole number of pence: ${pence}`, - ); - } - if (pounds < 0) { - throw new Error( - `Cannot construct GBP with negative number of pounds: ${pounds}`, - ); - } - if (pence < 0) { - throw new Error( - `Cannot construct GBP with negative number of pounds: ${pounds}`, - ); - } - - this.sign = sign; - this.pounds = pounds; - this.pence = pence; - } - - valueOf(): number { - return this.sign * (this.pounds * 100 + this.pence); - } - - toString(): string { - return `£${this.pounds}·${this.pence < 10 ? `0${this.pence}` : this.pence}`; - } -} - -function newGbpFromDto(dto: unknown): Gbp { - const signedPence = dto as number; - const pounds = Math.floor(Math.abs(signedPence) / 100); - const pence = Math.abs(signedPence) % 100; - const sign = signedPence < 0 ? -1 : 1; - return new Gbp(pounds, pence, sign); -} - -export { Gbp, newGbpFromDto }; diff --git a/gui/src/types/group.ts b/gui/src/types/group.ts deleted file mode 100644 index 4a04019..0000000 --- a/gui/src/types/group.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Category } from "./category"; - -interface Group { - name: string; - categories: Category[]; -} - -export { type Group }; |
