add gross income and net tax to income page

This commit is contained in:
Anantha Kumaran 2022-05-28 11:42:12 +05:30
parent 38cf10dee8
commit d2fc5f93eb
5 changed files with 89 additions and 4 deletions

View File

@ -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
}

View File

@ -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)
}

View File

@ -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[]) {

View File

@ -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);

View File

@ -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">