show unit and unit price in ledger page

since the unit price is reverse calculated from the purchase amount,
export high precision number from ledger to avoid mismatch
This commit is contained in:
Anantha Kumaran 2022-08-07 20:04:56 +05:30
parent a63386ea77
commit 44152d530d
4 changed files with 56 additions and 31 deletions

View File

@ -4,11 +4,12 @@ import (
"bytes"
"encoding/csv"
log "github.com/sirupsen/logrus"
"os/exec"
"strconv"
"time"
log "github.com/sirupsen/logrus"
"github.com/ananthakumaran/paisa/internal/model/posting"
)
@ -20,7 +21,7 @@ func Parse(journalPath string) ([]*posting.Posting, error) {
log.Fatal(err)
}
command := exec.Command("ledger", "-f", journalPath, "csv", "--csv-format", "%(quoted(date)),%(quoted(payee)),%(quoted(display_account)),%(quoted(commodity(scrub(display_amount)))),%(quoted(quantity(scrub(display_amount)))),%(quoted(to_int(scrub(market(amount,date)))))\n")
command := exec.Command("ledger", "-f", journalPath, "csv", "--csv-format", "%(quoted(date)),%(quoted(payee)),%(quoted(display_account)),%(quoted(commodity(scrub(display_amount)))),%(quoted(quantity(scrub(display_amount)))),%(quoted(to_int(scrub(market(amount,date) * 100000))))\n")
var output, error bytes.Buffer
command.Stdout = &output
command.Stderr = &error
@ -51,6 +52,7 @@ func Parse(journalPath string) ([]*posting.Posting, error) {
if err != nil {
return nil, err
}
amount = amount / 100000
posting := posting.Posting{Date: date, Payee: record[1], Account: record[2], Commodity: record[3], Quantity: quantity, Amount: amount}
postings = append(postings, &posting)

View File

@ -47,25 +47,34 @@ function renderTransactions(postings: Posting[]) {
let market = "",
change = "",
changePercentage = "",
changeClass = "";
changeClass = "",
price = "",
units = "";
if (p.commodity !== "INR") {
market = formatCurrency(p.market_amount);
const changeAmount = p.market_amount - p.amount;
if (changeAmount > 0) {
changeClass = "has-text-success";
} else if (changeAmount < 0) {
changeClass = "has-text-danger";
units = formatFloat(p.quantity, 4);
price = formatCurrency(Math.abs(p.amount / p.quantity), 4);
const days = dayjs().diff(p.timestamp, "days");
if (p.quantity > 0 && days > 0) {
market = formatCurrency(p.market_amount);
const changeAmount = p.market_amount - p.amount;
if (changeAmount > 0) {
changeClass = "has-text-success";
} else if (changeAmount < 0) {
changeClass = "has-text-danger";
}
const perYear = 365 / days;
changePercentage = formatFloat(
(changeAmount / p.amount) * 100 * perYear
);
change = formatCurrency(changeAmount);
}
const perYear = 365 / dayjs().diff(p.timestamp, "days");
changePercentage = formatFloat(
(changeAmount / p.amount) * 100 * perYear
);
change = formatCurrency(changeAmount);
}
return `
<td>${p.timestamp.format("DD MMM YYYY")}</td>
<td>${p.account}</td>
<td class='has-text-right'>${purchase}</td>
<td class='has-text-right'>${units}</td>
<td class='has-text-right'>${price}</td>
<td class='has-text-right'>${market}</td>
<td class='${changeClass} has-text-right'>${change}</td>
<td class='${changeClass} has-text-right'>${changePercentage}</td>

View File

@ -9,7 +9,7 @@ export interface Posting {
payee: string;
account: string;
commodity: string;
quanity: number;
quantity: number;
amount: number;
market_amount: number;
@ -98,12 +98,15 @@ export async function ajax(route: string) {
const obscure = false;
export function formatCurrency(value: number) {
export function formatCurrency(value: number, precision = 0) {
if (obscure) {
return "00";
}
return Math.round(value).toLocaleString("hi");
return value.toLocaleString("hi", {
minimumFractionDigits: precision,
maximumFractionDigits: precision
});
}
export function formatCurrencyCrude(value: number) {

View File

@ -246,22 +246,31 @@
</section>
<section class="section tab-ledger">
<div class="container is-fluid">
<nav class="level">
<div class="level-left">
<div class="level-item">
<p class="subtitle is-5">
Postings
</p>
</div>
<div class="level-item">
<div class="field">
<p class="control">
<input class="d3-posting-filter input" style="width: 440px" type="text" placeholder="filter account">
</p>
<div class="columns">
<div class="column is-6">
<nav class="level">
<div class="level-left">
<div class="level-item">
<p class="subtitle is-5">
Postings
</p>
</div>
<div class="level-item">
<div class="field">
<p class="control">
<input class="d3-posting-filter input" style="width: 440px" type="text" placeholder="filter account">
</p>
</div>
</div>
</div>
</div>
</nav>
</div>
</nav>
<div class="column is-6">
<p class="subtitle is-5">
Holdings
</p>
</div>
</div>
<div class="columns">
<div class="column is-6">
<table class="table is-narrow is-fullwidth">
@ -270,6 +279,8 @@
<th>Date</th>
<th>Account</th>
<th class='has-text-right'>Amount</th>
<th class='has-text-right'>Units</th>
<th class='has-text-right'>Unit Price</th>
<th class='has-text-right'>Market Value</th>
<th class='has-text-right'>Change</th>
<th class='has-text-right'>CAGR</th>