diff options
author | Vidhu Kant Sharma <vidhukant@vidhukant.xyz> | 2022-10-16 12:46:41 +0530 |
---|---|---|
committer | Vidhu Kant Sharma <vidhukant@vidhukant.xyz> | 2022-10-16 12:46:41 +0530 |
commit | 5f8407ae4c60922057e2f88f65178773786bddb4 (patch) | |
tree | 0016085e04520cd8f831374b2c7cc6342e1c92a2 | |
parent | 097a393b2bf170d69ba1cef16c5e70f204e2fe65 (diff) |
calculating currency/other floating point values with currency.js
-rw-r--r-- | src/classes/item.js | 31 | ||||
-rw-r--r-- | src/components/tables/invoice-item-table.js | 30 | ||||
-rw-r--r-- | src/components/tables/invoice-summary.js | 42 | ||||
-rw-r--r-- | src/views/invoice/new.js | 10 |
4 files changed, 65 insertions, 48 deletions
diff --git a/src/classes/item.js b/src/classes/item.js index 639a63f..e9e692b 100644 --- a/src/classes/item.js +++ b/src/classes/item.js @@ -16,7 +16,16 @@ */ import axios from "axios"; -import { Brand } from "./brand" +import c from "currency.js"; +import { Brand } from "./brand"; + +// TODO: load from config or something +export const currency = value => c(value, { + decimal: '.', + seperator: ',', + precision: 2, + symbol: '₹', +}); export class Item { constructor() { @@ -62,22 +71,22 @@ export const getAllItems = (ok, fail) => { export const editItem = (item, ok, fail) => { axios.put(`/item/${item.Id}`, item) .then(res => ok()) - .catch(err => fail()) + .catch(err => fail()); } export const getDiscountValue = (item) => item.DiscountPercentage > 0 - ? ((item.UnitPrice * item.Quantity)/100) * item.DiscountPercentage : 0.00; + ? currency(item.UnitPrice).multiply(item.Quantity).divide(100) : currency(0.00) export const getGSTValue = (item) => item.GSTPercentage > 0 - ? (((item.UnitPrice * item.Quantity) - getDiscountValue(item))/100) * item.GSTPercentage : 0.00; + ? currency(item.UnitPrice).multiply(item.Quantity).subtract(getDiscountValue).divide(100).multiply(item.GSTPercentage) : currency(0.00) export const getAmount = (item) => - (item.UnitPrice * item.Quantity) - getDiscountValue(item) + getGSTValue(item) + currency(item.UnitPrice).multiply(item.Quantity).add(getDiscountValue(item)).add(getGSTValue(item)) export const calcSum = (items) => items.reduce((prev, current, id, arr) => ({ - GST: prev.GST + getGSTValue(current), - Discount: prev.Discount + getDiscountValue(current), - UnitPrice: prev.UnitPrice + current.UnitPrice, - Amount: prev.Amount + getAmount(current), - Quantity: prev.Quantity + current.Quantity -}), {GST: 0, Discount: 0, UnitPrice: 0, Amount: 0, Quantity: 0}); + GST: prev.GST.add(getGSTValue(current)), + Discount: prev.Discount.add(getDiscountValue(current)), + UnitPrice: prev.UnitPrice.add(currency(current.UnitPrice).multiply(current.Quantity)), + Amount: prev.Amount.add(getAmount(current)), + Quantity: prev.Quantity.add(current.Quantity) // stored as a currency because it can be float +}), {GST: currency(0), Discount: currency(0), UnitPrice: currency(0), Amount: currency(0), Quantity: currency(0)}); diff --git a/src/components/tables/invoice-item-table.js b/src/components/tables/invoice-item-table.js index fb91af3..d008ebc 100644 --- a/src/components/tables/invoice-item-table.js +++ b/src/components/tables/invoice-item-table.js @@ -16,7 +16,7 @@ */ import './scss/table.scss'; -import { getDiscountValue, getGSTValue, getAmount } from './../../classes/item'; +import { getDiscountValue, getGSTValue, getAmount, currency } from './../../classes/item'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faPencil, faTrashCan } from '@fortawesome/free-solid-svg-icons' @@ -70,17 +70,18 @@ const ItemTable = ({items, setItems, isInterstate, sum}) => { <td className={i.Brand.Name === "" ? "empty" : ""}>{i.Brand.Name}</td> <td>{i.Quantity}</td> <td className={i.UnitOfMeasure === "" ? "empty" : ""}>{i.UnitOfMeasure}</td> - <td className={i.UnitPrice > 0 ? "" : "empty"}>{i.UnitPrice}</td> - <td className={i.DiscountPercentage > 0 ? "" : "empty"}>{getDiscountValue(i)} ({i.DiscountPercentage}%)</td> + <td className={i.UnitPrice > 0 ? "" : "empty"}>{currency(i.UnitPrice).format()}</td> + <td className={i.DiscountPercentage > 0 ? "" : "empty"}>{getDiscountValue(i).format()} ({i.DiscountPercentage}%)</td> {isInterstate - ? <td className={i.GSTPercentage > 0 ? "" : "empty"}>{getGSTValue(i)} ({i.GSTPercentage}%)</td> + ? <td className={i.GSTPercentage > 0 ? "" : "empty"}>{getGSTValue(i).format()}</td> : <> - <td className={i.GSTPercentage > 0 ? "" : "empty"}>{getGSTValue(i) / 2} ({i.GSTPercentage / 2}%)</td> - <td className={i.GSTPercentage > 0 ? "" : "empty"}>{getGSTValue(i) / 2} ({i.GSTPercentage / 2}%)</td> + {getGSTValue(i).distribute(2).map((j, id) => + <td key={`g-${id}`} className={i.GSTPercentage > 0 ? "" : "empty"}>{j.format()} ({currency(i.GSTPercentage).divide(2).value}%)</td> + )} </> } <td className={i.HSN === "" ? "empty" : ""}>{i.HSN}</td> - <td>{getAmount(i)}</td> + <td>{getAmount(i).format()}</td> <td className={"buttons"}> <FontAwesomeIcon icon={faPencil} onClick={() => handleEdit(i)}/> <FontAwesomeIcon icon={faTrashCan} onClick={() => handleDelete(i)}/> @@ -92,19 +93,20 @@ const ItemTable = ({items, setItems, isInterstate, sum}) => { <td className={"empty"}></td> <td className={"empty"}></td> <td className={"empty"}></td> - <td className={sum.Quantity > 0 ? "" : "empty"}>{sum.Quantity}</td> + <td className={sum.Quantity.value > 0 ? "" : "empty"}>{sum.Quantity.value}</td> <td className={"empty"}></td> - <td className={sum.UnitPrice > 0 ? "" : "empty"}>{sum.UnitPrice}</td> - <td className={sum.Discount > 0 ? "" : "empty"}>{sum.Discount}</td> + <td className={sum.UnitPrice.value > 0 ? "" : "empty"}>{sum.UnitPrice.format()}</td> + <td className={sum.Discount.value > 0 ? "" : "empty"}>{sum.Discount.format()}</td> {isInterstate - ? <td className={sum.GST > 0 ? "" : "empty"}>{sum.GST || 0}</td> + ? <td className={sum.GST.value > 0 ? "" : "empty"}>{sum.GST.format()}</td> : <> - <td className={sum.GST > 0 ? "" : "empty"}>{sum.GST / 2 || 0}</td> - <td className={sum.GST > 0 ? "" : "empty"}>{sum.GST / 2 || 0}</td> + {sum.GST.distribute(2).map((i, id) => + <td key={`g-${id}`} className={i.value > 0 ? "" : "empty"}>{i.format()}</td> + )} </> } <td className={"empty"}></td> - <td className={sum.Amount > 0 ? "" : "empty"}>{sum.Amount}</td> + <td className={sum.Amount.value > 0 ? "" : "empty"}>{sum.Amount.format()}</td> <td className={"buttons"}> </td> </tr> diff --git a/src/components/tables/invoice-summary.js b/src/components/tables/invoice-summary.js index 5899105..7018d50 100644 --- a/src/components/tables/invoice-summary.js +++ b/src/components/tables/invoice-summary.js @@ -15,47 +15,47 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import './scss/table.scss'; +import { currency } from '../../classes/item'; const InvoiceSummary = ({sum}) => { - const totalRoundedOff = Math.round(sum.Amount); - const roundedOffDiff = sum.Amount - totalRoundedOff; - - const formatter = new Intl.NumberFormat("en-US", { - maximumSignificantDigits: 2, - }) + const totalRoundedOff = currency(sum.Amount !== undefined ? Math.round(sum.Amount.value) : 0.00); + const roundedOffDiff = sum.Amount !== undefined ? sum.Amount.subtract(totalRoundedOff) : currency(0.00); return ( <> <h1>Summary:</h1> <table> <tbody> - <tr> - <td>Base Total</td> - <td>{formatter.format(sum.UnitPrice)}</td> - </tr> - {sum.Discount > 0 && + {sum.UnitPrice !== undefined && + <tr> + <td>Base Total</td> + <td>{sum.UnitPrice.format()}</td> + </tr> + } + {sum.Discount !== undefined && sum.Discount.value > 0 && <tr> <td>Total After Discount</td> - <td>{formatter.format(sum.UnitPrice - sum.Discount)} (-{formatter.format(sum.Discount)})</td> + <td>{sum.UnitPrice.subtract(sum.Discount).format()} (-{sum.Discount.format()})</td> </tr> } - {sum.GST > 0 && + {sum.GST !== undefined && sum.GST.value > 0 && <tr> <td>Total After Tax</td> - <td>{formatter.format(sum.UnitPrice - (sum.Discount > 0 ? sum.Discount : 0) + sum.GST)} (+{formatter.format(sum.GST)})</td> + <td>{sum.UnitPrice.subtract(sum.Discount.value > 0 ? sum.Discount : currency(0)).add(sum.GST).format()} (+{sum.GST.format()})</td> </tr> } - {(isNaN(roundedOffDiff) || roundedOffDiff !== 0) && + {roundedOffDiff.intValue !== 0 && <tr> <td>Rounded Off</td> - <td>{`${roundedOffDiff > 0 ? `(-) ${formatter.format(roundedOffDiff)}` : `(+) ${formatter.format(roundedOffDiff * -1)}`}`}</td> + <td>{`${roundedOffDiff.value > 0 ? `(-) ${roundedOffDiff.format()}` : `(+) ${roundedOffDiff.multiply(-1).format()}`}`}</td> + </tr> + } + {sum.Amount !== undefined && + <tr> + <td>Grand Total</td> + <td>{sum.Amount.subtract(roundedOffDiff).format()}</td> </tr> } - <tr> - <td>Grand Total</td> - <td>{formatter.format(sum.Amount - (isNaN(roundedOffDiff) ? 0 : roundedOffDiff))}</td> - </tr> </tbody> </table> </> diff --git a/src/views/invoice/new.js b/src/views/invoice/new.js index 429808f..be180cf 100644 --- a/src/views/invoice/new.js +++ b/src/views/invoice/new.js @@ -21,7 +21,7 @@ import ItemTable from '../../components/tables/invoice-item-table'; import InvoiceSummary from '../../components/tables/invoice-summary'; import { InvoiceClient } from '../../classes/client'; -import { calcSum } from '../../classes/item'; +import { calcSum, currency } from '../../classes/item'; import { useState, useEffect } from 'react'; @@ -31,7 +31,13 @@ const NewInvoicePage = () => { const [items, setItems] = useState([]); //const [isInterstate, setIsInterstate] = useState(false); const isInterstate = false; // temporary - const [sum, setSum] = useState({}); + const [sum, setSum] = useState({ + GST: currency(0), + Discount: currency(0), + UnitPrice: currency(0), + Amount: currency(0), + Quantity: currency(0) + }); useEffect(() => setShippingAddressId(-1), [client]); |