rename Checking to Assets:Checking

This commit is contained in:
Anantha Kumaran 2022-08-21 16:29:09 +05:30
parent 3ca646004f
commit 97b407b345
10 changed files with 66 additions and 73 deletions

View File

@ -103,8 +103,8 @@ func emitSalary(file *os.File, start time.Time) {
%s Salary
Income:Salary:%s
Assets:Debt:EPF %s INR
Tax %s INR
Checking %s INR
Expenses:Tax %s INR
Assets:Checking %s INR
`, start.Format("2006/01/02"), company, formatFloat(salary*0.12), formatFloat(salary*0.20), formatFloat(salary*0.68)))
if err != nil {
log.Fatal(err)
@ -134,7 +134,7 @@ func emitEquityMutualFund(file *os.File, start time.Time, pricesTree map[string]
_, err := file.WriteString(fmt.Sprintf(`
%s Mutual Fund Nifty
Assets:Equity:NIFTY %s NIFTY @ %s INR
Checking
Assets:Checking
`, start.Format("2006/01/02"), formatFloat(10000/pc.Value*multiplier), formatFloat(pc.Value)))
if err != nil {
log.Fatal(err)
@ -144,7 +144,7 @@ func emitEquityMutualFund(file *os.File, start time.Time, pricesTree map[string]
_, err = file.WriteString(fmt.Sprintf(`
%s Mutual Fund Nifty Next 50
Assets:Equity:NIFTY_JR %s NIFTY_JR @ %s INR
Checking
Assets:Checking
`, start.Format("2006/01/02"), formatFloat(10000/pc.Value*multiplier), formatFloat(pc.Value)))
if err != nil {
log.Fatal(err)
@ -161,7 +161,7 @@ func emitDebtMutualFund(file *os.File, start time.Time, pricesTree map[string]*b
_, err := file.WriteString(fmt.Sprintf(`
%s Mutual Fund Birla Corporate Fund
Assets:Debt:ABCBF %s ABCBF @ %s INR
Checking
Assets:Checking
`, start.Format("2006/01/02"), formatFloat(10000/pc.Value*multiplier), formatFloat(pc.Value)))
if err != nil {
log.Fatal(err)

View File

@ -9,15 +9,15 @@ tracked as a commodity. Few example transactions can be found below.
Assets:Equity:NPS:SBI:E 15.9378 NPS_SBI_E @ 23.5289 INR
;// account name units commodity purchase price
;// name per unit
Checking
Assets:Checking
2019/02/21 NPS
Assets:Equity:NPS:SBI:E 1557.2175 NPS_SBI_E @ 23.8406 INR
Checking
Assets:Checking
2020/06/25 Gold
Assets:Gold 40 GOLD @ 4650 INR
Checking
Assets:Checking
```
**paisa** comes with inbuilt support for fetching the latest price of

View File

@ -14,13 +14,13 @@ content
```go
2022/01/01 Salary
Income:Salary:Acme -100,000 INR
Checking 100,000 INR
Assets:Checking 100,000 INR
```
**ledger** follows the double-entry accounting system. In simple terms, it
tracks the movement of money from debit account to credit
account. Here `Income:Salary:Acme` is the debit account and
`Checking` is the credit account. The date at which the
`Assets:Checking` is the credit account. The date at which the
transaction took place and a description of the transaction is written
in the first line followed by the list of credit or debit
entry. Account [naming conventions](./accounts.md) are explained later. The `:` in the account name
@ -31,23 +31,23 @@ accounts must be zero.
```go
2022/01/01 Salary
Income:Salary:Acme -100,000 INR
Checking 100,000 INR
Assets:Checking 100,000 INR
2022/02/01 Salary
Income:Salary:Acme -100,000 INR
Checking 100,000 INR
Assets:Checking 100,000 INR
2022/03/01 Salary
Income:Salary:Acme -100,000 INR
Checking 100,000 INR
Assets:Checking 100,000 INR
```
let's add few more entries. The total balance in your savings account
could be found by
```go
ledger -f personal.ledger balance Checking
300,000 INR Checking
ledger -f personal.ledger balance Assets:Checking
300,000 INR Assets:Checking
```
Let's say your company deducts 12,000 INR and contributes it to EPF,
@ -56,25 +56,25 @@ we could represent it as follows
```go
2022/01/01 Salary
Income:Salary:Acme -100,000 INR
Checking 88,000 INR
Assets:Checking 88,000 INR
Assets:Debt:EPF 12,000 INR
2022/02/01 Salary
Income:Salary:Acme -100,000 INR
Checking 88,000 INR
Assets:Checking 88,000 INR
Assets:Debt:EPF 12,000 INR
2022/03/01 Salary
Income:Salary:Acme -100,000 INR
Checking 88,000 INR
Assets:Checking 88,000 INR
Assets:Debt:EPF 12,000 INR
```
```shell
ledger -f personal.ledger balance Assets Checking
ledger -f personal.ledger balance Assets
36,000 INR Assets:Debt:EPF
264,000 INR Checking
264,000 INR Assets:Checking
--------------------
300,000 INR
```
@ -88,17 +88,17 @@ month.
```go
2018/01/01 Investment
Checking -20,000 INR
Assets:Checking -20,000 INR
Assets:Equity:NIFTY 148.0865 NIFTY @ 67.5281 INR
Assets:Equity:NIFTY_JR 358.6659 NIFTY_JR @ 27.8811 INR
2018/02/01 Investment
Checking -20,000 INR
Assets:Checking -20,000 INR
Assets:Equity:NIFTY 140.2870 NIFTY @ 71.2824 INR
Assets:Equity:NIFTY_JR 363.2242 NIFTY_JR @ 27.5312 INR
2018/03/01 Investment
Checking -20,000 INR
Assets:Checking -20,000 INR
Assets:Equity:NIFTY 147.5908 NIFTY @ 67.7549 INR
Assets:Equity:NIFTY_JR 378.4323 NIFTY_JR @ 26.4248 INR
```

View File

@ -18,7 +18,7 @@ type Gain struct {
func GetGain(db *gorm.DB) gin.H {
var postings []posting.Posting
result := db.Where("account like ?", "Assets:%").Order("date ASC").Find(&postings)
result := db.Where("account like ? and account != ?", "Assets:%", "Assets:Checking").Order("date ASC").Find(&postings)
if result.Error != nil {
log.Fatal(result.Error)
}

View File

@ -28,7 +28,7 @@ func GetInvestment(db *gorm.DB) gin.H {
var assets []posting.Posting
var incomes []posting.Posting
var expenses []posting.Posting
result := db.Where("account like ? order by date asc", "Assets:%").Find(&assets)
result := db.Where("account like ? and account != ? order by date asc", "Assets:%", "Assets:Checking").Find(&assets)
if result.Error != nil {
log.Fatal(result.Error)
}

View File

@ -30,7 +30,9 @@ func GetLedger(db *gorm.DB) gin.H {
}
postings = service.PopulateMarketPrice(db, postings)
breakdowns := computeBreakdown(db, lo.Filter(postings, func(p posting.Posting, _ int) bool { return strings.HasPrefix(p.Account, "Assets:") }))
breakdowns := computeBreakdown(db, lo.Filter(postings, func(p posting.Posting, _ int) bool {
return strings.HasPrefix(p.Account, "Assets:")
}))
return gin.H{"postings": postings, "breakdowns": breakdowns}
}
@ -51,14 +53,14 @@ func computeBreakdown(db *gorm.DB, postings []posting.Posting) map[string]Breakd
for group, leaf := range accounts {
ps := lo.Filter(postings, func(p posting.Posting, _ int) bool { return strings.HasPrefix(p.Account, group) })
investmentAmount := lo.Reduce(ps, func(acc float64, p posting.Posting, _ int) float64 {
if p.Amount < 0 || service.IsInterest(db, p) {
if p.Account == "Assets:Checking" || p.Amount < 0 || service.IsInterest(db, p) {
return acc
} else {
return acc + p.Amount
}
}, 0.0)
withdrawalAmount := lo.Reduce(ps, func(acc float64, p posting.Posting, _ int) float64 {
if p.Amount > 0 || service.IsInterest(db, p) {
if p.Account == "Assets:Checking" || p.Amount > 0 || service.IsInterest(db, p) {
return acc
} else {
return acc + -p.Amount

View File

@ -9,6 +9,7 @@ import (
)
func XIRR(db *gorm.DB, ps []posting.Posting) float64 {
ps = lo.Filter(ps, func(p posting.Posting, _ int) bool { return p.Account != "Assets:Checking" })
today := time.Now()
marketAmount := lo.Reduce(ps, func(acc float64, p posting.Posting, _ int) float64 { return acc + p.MarketAmount }, 0.0)
payments := lo.Reverse(lo.Map(ps, func(p posting.Posting, _ int) xirr.Payment {

View File

@ -114,14 +114,24 @@ function renderBreakdowns(breakdowns: Breakdown[]) {
<td style='max-width: 200px; overflow: hidden;'>${indent}${lastName(
b.group
)}</td>
<td class='has-text-right'>${formatCurrency(b.investment_amount)}</td>
<td class='has-text-right'>${formatCurrency(b.withdrawal_amount)}</td>
<td class='has-text-right'>${
b.investment_amount != 0 ? formatCurrency(b.investment_amount) : ""
}</td>
<td class='has-text-right'>${
b.withdrawal_amount != 0 ? formatCurrency(b.withdrawal_amount) : ""
}</td>
<td class='has-text-right'>${
b.balance_units > 0 ? formatFloat(b.balance_units, 4) : ""
}</td>
<td class='has-text-right'>${formatCurrency(b.market_amount)}</td>
<td class='${changeClass} has-text-right'>${formatCurrency(gain)}</td>
<td class='${changeClass} has-text-right'>${formatFloat(b.xirr)}</td>
<td class='has-text-right'>${
b.market_amount != 0 ? formatCurrency(b.market_amount) : ""
}</td>
<td class='${changeClass} has-text-right'>${
b.investment_amount != 0 && gain != 0 ? formatCurrency(gain) : ""
}</td>
<td class='${changeClass} has-text-right'>${
b.xirr > 0.0001 ? formatFloat(b.xirr) : ""
}</td>
`;
});
}

View File

@ -24,8 +24,10 @@ export default async function () {
current.withdrawal_amount
)
);
setHtml("investment", formatCurrency(current.investment_amount));
setHtml("withdrawal", formatCurrency(current.withdrawal_amount));
setHtml(
"investment",
formatCurrency(current.investment_amount - current.withdrawal_amount)
);
setHtml("gains", formatCurrency(current.gain_amount));
setHtml("xirr", formatFloat(xirr));
@ -48,22 +50,20 @@ function renderOverview(points: Overview[], element: Element) {
const colors = ["#b2df8a", "#fb9a99"];
const areaScale = d3.scaleOrdinal().domain(areaKeys).range(colors);
const lineKeys = ["networth", "investment", "withdrawal"];
const lineKeys = ["networth", "investment"];
const lineScale = d3
.scaleOrdinal<string>()
.domain(lineKeys)
.range(["#1f77b4", "#17becf", "#ff7f0e"]);
const positions = _.flatMap(points, (p) => [
p.gain_amount + p.investment_amount - p.withdrawal_amount,
p.investment_amount - p.withdrawal_amount
]);
positions.push(0);
const x = d3.scaleTime().range([0, width]).domain([start, end]),
y = d3
.scaleLinear()
.range([height, 0])
.domain([
0,
d3.max<Overview, number>(
points,
(d) => d.gain_amount + d.investment_amount
)
]),
y = d3.scaleLinear().range([height, 0]).domain(d3.extent(positions)),
z = d3.scaleOrdinal<string>(colors).domain(areaKeys);
const area = (y0, y1) =>
@ -103,7 +103,7 @@ function renderOverview(points: Overview[], element: Element) {
.attr(
"d",
area(height, (d) => {
return y(d.gain_amount + d.investment_amount);
return y(d.gain_amount + d.investment_amount - d.withdrawal_amount);
})
);
@ -115,7 +115,7 @@ function renderOverview(points: Overview[], element: Element) {
.attr(
"d",
area(0, (d) => {
return y(d.gain_amount + d.investment_amount);
return y(d.gain_amount + d.investment_amount - d.withdrawal_amount);
})
);
@ -130,7 +130,7 @@ function renderOverview(points: Overview[], element: Element) {
.attr(
"d",
area(0, (d) => {
return y(d.investment_amount);
return y(d.investment_amount - d.withdrawal_amount);
})
);
@ -145,7 +145,7 @@ function renderOverview(points: Overview[], element: Element) {
.attr(
"d",
area(height, (d) => {
return y(d.investment_amount);
return y(d.investment_amount - d.withdrawal_amount);
})
);
@ -159,21 +159,7 @@ function renderOverview(points: Overview[], element: Element) {
.line<Overview>()
.curve(d3.curveBasis)
.x((d) => x(d.timestamp))
.y((d) => y(d.investment_amount))
);
layer
.append("path")
.style("stroke", lineScale("withdrawal"))
.style("fill", "none")
.attr(
"d",
d3
.line<Overview>()
.curve(d3.curveBasis)
.defined((d) => d.withdrawal_amount > 0)
.x((d) => x(d.timestamp))
.y((d) => y(d.withdrawal_amount))
.y((d) => y(d.investment_amount - d.withdrawal_amount))
);
layer
@ -192,7 +178,7 @@ function renderOverview(points: Overview[], element: Element) {
svg
.append("g")
.attr("class", "legendOrdinal")
.attr("transform", "translate(365,3)");
.attr("transform", "translate(265,3)");
const legendOrdinal = legend
.legendColor()

View File

@ -42,16 +42,10 @@
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Investment</p>
<p class="heading">Net Investment</p>
<p class="d3-investment title"></p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Withdrawal</p>
<p class="d3-withdrawal title"></p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Gain</p>