Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public sealed record AccountInterestDto(
InterestPayout Payout,
decimal YearToDate,
decimal YearToDateEstimated,
decimal EstimatedInBalance);
decimal EstimatedInBalance,
DateOnly? AccruingSince = null);

public sealed record CreateAccountRequest(
string Name,
Expand Down Expand Up @@ -285,11 +286,17 @@ public static async Task<Dictionary<Guid, AccountInterestDto>> InterestSummaries
Amount = account.Currency == Currency.Base ? s.Base : s.Original,
})
.ToList();
// This year's figure only covers the days the app knows the account and its rate: say from when.
var firstRate = rates.Where(r => r.AccountId == account.Id).MinBy(r => r.EffectiveFrom)?.EffectiveFrom;
DateOnly? since = firstRate is { } f
? new[] { yearStart, account.OpeningBalanceOn, f }.Max()
: null;
result[account.Id] = new AccountInterestDto(current?.AnnualRatePercent, current?.WithholdingPercent,
current?.EffectiveFrom, account.InterestPayout,
mine.Where(s => s.ThisYear).Sum(s => s.Amount),
mine.Where(s => s.ThisYear && s.Estimated).Sum(s => s.Amount),
mine.Where(s => s.Estimated).Sum(s => s.Amount));
mine.Where(s => s.Estimated).Sum(s => s.Amount),
since);
}

return result;
Expand Down
29 changes: 25 additions & 4 deletions web/public/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"assistant": "Assistant",
"more": "More",
"main": "Main navigation",
"general": "General"
"general": "General",
"loans": "Loans"
},
"common": {
"save": "Save",
Expand Down Expand Up @@ -404,7 +405,13 @@
"countsTowards": "Deposits count towards",
"countsTowardsHint": "Money you deposit here counts in that bucket’s monthly allocation, without recording it by hand.",
"noBucket": "No bucket",
"countsTowardsSaved": "Saved. The monthly allocation now includes this broker’s deposits."
"countsTowardsSaved": "Saved. The monthly allocation now includes this broker’s deposits.",
"group": {
"money": "Everyday money",
"savings": "Savings",
"investments": "Investments",
"debts": "Debts"
}
},
"categories": {
"new": "New category",
Expand Down Expand Up @@ -1022,7 +1029,12 @@
},
"history": "Rate history",
"withheld": "{{pct}} withheld",
"removeLatest": "Remove latest rate"
"removeLatest": "Remove latest rate",
"perDay": "≈ {{gross}}/day gross ({{net}} net)",
"perDayHint": "Balance × TANB / 365, before the {{withholding}} % withholding tax.",
"thisYearNet": "{{amount}} net this year",
"since": "(since {{date}})",
"thisYearHint": "Interest after withholding tax, from the days the app knows this account and its rate. Record interest the bank paid earlier as income in the Interest category to include it."
},
"crypto": {
"addButton": "Add crypto",
Expand Down Expand Up @@ -1245,6 +1257,15 @@
"skip": "Skip",
"dashboardTitle": "Loans",
"owed": "Owed",
"endsOn": "ends {{date}}"
"endsOn": "ends {{date}}",
"listSubtitle": "Mortgages, car and personal loans: what you owe and when each ends.",
"new": "New loan",
"monthly": "Instalments per month",
"interestLeftAll": "Interest still to pay",
"emptyTitle": "No loans",
"emptyText": "Add a mortgage, car or personal loan to see what you owe, the instalment, when it ends and what early repayments would save.",
"namePlaceholder": "Mortgage, Car loan…",
"newHint": "Next you enter the amount, rate and term.",
"next": "Continue"
}
}
29 changes: 25 additions & 4 deletions web/public/i18n/pt-PT.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"assistant": "Assistente",
"more": "Mais",
"main": "Navegação principal",
"general": "Geral"
"general": "Geral",
"loans": "Empréstimos"
},
"common": {
"save": "Guardar",
Expand Down Expand Up @@ -404,7 +405,13 @@
"countsTowards": "Os depósitos contam para",
"countsTowardsHint": "O dinheiro que depositas aqui conta na alocação mensal desse balde, sem o registares à mão.",
"noBucket": "Nenhum balde",
"countsTowardsSaved": "Guardado. A alocação mensal passa a incluir os depósitos desta corretora."
"countsTowardsSaved": "Guardado. A alocação mensal passa a incluir os depósitos desta corretora.",
"group": {
"money": "Dinheiro do dia a dia",
"savings": "Poupança",
"investments": "Investimentos",
"debts": "Dívidas"
}
},
"categories": {
"new": "Nova categoria",
Expand Down Expand Up @@ -1022,7 +1029,12 @@
},
"history": "Histórico de taxas",
"withheld": "{{pct}} retidos",
"removeLatest": "Remover a taxa mais recente"
"removeLatest": "Remover a taxa mais recente",
"perDay": "≈ {{gross}}/dia brutos ({{net}} líquidos)",
"perDayHint": "Saldo × TANB / 365, antes da retenção de {{withholding}} %.",
"thisYearNet": "{{amount}} líquidos este ano",
"since": "(desde {{date}})",
"thisYearHint": "Juros depois da retenção na fonte, nos dias em que a app conhece esta conta e a taxa. Para incluir juros que o banco pagou antes, regista-os como receita na categoria Juros."
},
"crypto": {
"addButton": "Adicionar cripto",
Expand Down Expand Up @@ -1245,6 +1257,15 @@
"skip": "Saltar",
"dashboardTitle": "Empréstimos",
"owed": "Em dívida",
"endsOn": "termina {{date}}"
"endsOn": "termina {{date}}",
"listSubtitle": "Crédito habitação, automóvel e pessoal: quanto deves e quando acaba cada um.",
"new": "Novo empréstimo",
"monthly": "Prestações por mês",
"interestLeftAll": "Juros por pagar",
"emptyTitle": "Sem empréstimos",
"emptyText": "Adiciona um crédito habitação, automóvel ou pessoal para veres quanto deves, a prestação, quando acaba e quanto pouparias a amortizar.",
"namePlaceholder": "Crédito habitação, Carro…",
"newHint": "A seguir indicas o montante, a taxa e o prazo.",
"next": "Continuar"
}
}
4 changes: 4 additions & 0 deletions web/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ export const routes: Routes = [
loadComponent: () =>
import('./features/connections/connections').then((m) => m.ConnectionsComponent),
},
{
path: 'loans',
loadComponent: () => import('./features/loans/loans').then((m) => m.LoansComponent),
},
{
path: 'loans/:accountId',
loadComponent: () => import('./features/loans/loan').then((m) => m.LoanComponent),
Expand Down
2 changes: 2 additions & 0 deletions web/src/app/core/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ export interface AccountInterest {
yearToDateEstimated: number;
/** Part of the balance that is still an estimate. */
estimatedInBalance: number;
/** This year's interest counts from this day (the account or its rate is newer than 1 January). */
accruingSince?: string | null;
}

export interface InterestRate {
Expand Down
Loading
Loading