add gross income and net tax to income page
This commit is contained in:
parent
38cf10dee8
commit
d2fc5f93eb
|
@ -15,13 +15,25 @@ type Income struct {
|
|||
Postings []posting.Posting `json:"postings"`
|
||||
}
|
||||
|
||||
type Tax struct {
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
Postings []posting.Posting `json:"postings"`
|
||||
}
|
||||
|
||||
func GetIncome(db *gorm.DB) gin.H {
|
||||
var postings []posting.Posting
|
||||
result := db.Where("account like ?", "Income:%").Order("date ASC").Find(&postings)
|
||||
var incomePostings []posting.Posting
|
||||
result := db.Where("account like ?", "Income:%").Order("date ASC").Find(&incomePostings)
|
||||
if result.Error != nil {
|
||||
log.Fatal(result.Error)
|
||||
}
|
||||
return gin.H{"income_timeline": computeIncomeTimeline(postings)}
|
||||
|
||||
var taxPostings []posting.Posting
|
||||
result = db.Where("account = ?", "Tax").Order("date ASC").Find(&taxPostings)
|
||||
if result.Error != nil {
|
||||
log.Fatal(result.Error)
|
||||
}
|
||||
return gin.H{"income_timeline": computeIncomeTimeline(incomePostings), "tax_timeline": computeTaxTimeline(taxPostings)}
|
||||
}
|
||||
|
||||
func computeIncomeTimeline(postings []posting.Posting) []Income {
|
||||
|
@ -45,3 +57,26 @@ func computeIncomeTimeline(postings []posting.Posting) []Income {
|
|||
}
|
||||
return incomes
|
||||
}
|
||||
|
||||
func computeTaxTimeline(postings []posting.Posting) []Tax {
|
||||
var taxes []Tax = make([]Tax, 0)
|
||||
|
||||
if len(postings) == 0 {
|
||||
return taxes
|
||||
}
|
||||
|
||||
var p posting.Posting
|
||||
end := time.Now()
|
||||
for start := utils.BeginningOfFinancialYear(postings[0].Date); start.Before(end); start = start.AddDate(1, 0, 0) {
|
||||
yearEnd := utils.EndOfFinancialYear(start)
|
||||
var currentMonthPostings []posting.Posting = make([]posting.Posting, 0)
|
||||
for len(postings) > 0 && (postings[0].Date.Before(yearEnd) || postings[0].Date.Equal(start)) {
|
||||
p, postings = postings[0], postings[1:]
|
||||
currentMonthPostings = append(currentMonthPostings, p)
|
||||
}
|
||||
|
||||
taxes = append(taxes, Tax{StartDate: start, EndDate: yearEnd, Postings: currentMonthPostings})
|
||||
|
||||
}
|
||||
return taxes
|
||||
}
|
||||
|
|
|
@ -15,6 +15,19 @@ func BTreeDescendFirstLessOrEqual[I btree.Item](tree *btree.BTree, item I) I {
|
|||
return hit
|
||||
}
|
||||
|
||||
func BeginningOfFinancialYear(date time.Time) time.Time {
|
||||
beginningOfMonth := BeginningOfMonth(date)
|
||||
if beginningOfMonth.Month() < time.April {
|
||||
return beginningOfMonth.AddDate(-1, int(time.April-beginningOfMonth.Month()), 0)
|
||||
} else {
|
||||
return beginningOfMonth.AddDate(0, -int(beginningOfMonth.Month()-time.April), 0)
|
||||
}
|
||||
}
|
||||
|
||||
func EndOfFinancialYear(date time.Time) time.Time {
|
||||
return EndOfMonth(BeginningOfFinancialYear(date).AddDate(0, 11, 0))
|
||||
}
|
||||
|
||||
func BeginningOfMonth(date time.Time) time.Time {
|
||||
return date.AddDate(0, 0, -date.Day()+1)
|
||||
}
|
||||
|
|
|
@ -9,14 +9,26 @@ import {
|
|||
Income,
|
||||
Posting,
|
||||
restName,
|
||||
setHtml,
|
||||
skipTicks,
|
||||
tooltip
|
||||
} from "./utils";
|
||||
|
||||
export default async function () {
|
||||
const { income_timeline: incomes } = await ajax("/api/income");
|
||||
const { income_timeline: incomes, tax_timeline: taxes } = await ajax(
|
||||
"/api/income"
|
||||
);
|
||||
_.each(incomes, (i) => (i.timestamp = dayjs(i.date)));
|
||||
renderMonthlyInvestmentTimeline(incomes);
|
||||
|
||||
const grossIncome = _.sumBy(incomes, (i) =>
|
||||
_.sumBy(i.postings, (p) => -p.amount)
|
||||
);
|
||||
|
||||
const netTax = _.sumBy(taxes, (t) => _.sumBy(t.postings, (p) => p.amount));
|
||||
|
||||
setHtml("gross-income", formatCurrency(grossIncome));
|
||||
setHtml("net-tax", formatCurrency(netTax));
|
||||
}
|
||||
|
||||
function renderMonthlyInvestmentTimeline(incomes: Income[]) {
|
||||
|
|
|
@ -55,6 +55,12 @@ export interface Income {
|
|||
timestamp: dayjs.Dayjs;
|
||||
}
|
||||
|
||||
export interface Tax {
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
postings: Posting[];
|
||||
}
|
||||
|
||||
export function ajax(
|
||||
route: "/api/investment"
|
||||
): Promise<{ postings: Posting[] }>;
|
||||
|
@ -74,6 +80,7 @@ export function ajax(route: "/api/allocation"): Promise<{
|
|||
}>;
|
||||
export function ajax(route: "/api/income"): Promise<{
|
||||
income_timeline: Income[];
|
||||
tax_timeline: Tax[];
|
||||
}>;
|
||||
export async function ajax(route: string) {
|
||||
const response = await fetch(route);
|
||||
|
|
|
@ -129,6 +129,24 @@
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section tab-income">
|
||||
<div class="container">
|
||||
<nav class="level">
|
||||
<div class="level-item has-text-centered">
|
||||
<div>
|
||||
<p class="heading">Gross Income</p>
|
||||
<p class="d3-gross-income title"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-item has-text-centered">
|
||||
<div>
|
||||
<p class="heading">Net Tax</p>
|
||||
<p class="d3-net-tax title"></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section tab-income">
|
||||
<div class="container is-fluid">
|
||||
<div class="columns">
|
||||
|
|
Loading…
Reference in New Issue