aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/classes/item.js17
-rw-r--r--src/components/pickers/item-picker.js10
-rw-r--r--src/components/tables/invoice-item-table.js116
-rw-r--r--src/components/tables/scss/table.scss8
-rw-r--r--src/views/invoice/new.js13
5 files changed, 113 insertions, 51 deletions
diff --git a/src/classes/item.js b/src/classes/item.js
index 0486262..639a63f 100644
--- a/src/classes/item.js
+++ b/src/classes/item.js
@@ -64,3 +64,20 @@ export const editItem = (item, ok, fail) => {
.then(res => ok())
.catch(err => fail())
}
+
+export const getDiscountValue = (item) => item.DiscountPercentage > 0
+ ? ((item.UnitPrice * item.Quantity)/100) * item.DiscountPercentage : 0.00;
+
+export const getGSTValue = (item) => item.GSTPercentage > 0
+ ? (((item.UnitPrice * item.Quantity) - getDiscountValue(item))/100) * item.GSTPercentage : 0.00;
+
+export const getAmount = (item) =>
+ (item.UnitPrice * item.Quantity) - getDiscountValue(item) + 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});
diff --git a/src/components/pickers/item-picker.js b/src/components/pickers/item-picker.js
index 339319f..d756427 100644
--- a/src/components/pickers/item-picker.js
+++ b/src/components/pickers/item-picker.js
@@ -37,10 +37,10 @@ const ItemPicker = ({invoiceItems, addInvoiceItem}) => {
}
const handleInput = e => {
- const { name, value } = e.target;
+ const { name, value, type } = e.target;
setItem(prevItem => ({
...prevItem,
- [name]: value
+ [name]: type === "number" ? parseFloat(value) : value
}));
}
@@ -65,7 +65,7 @@ const ItemPicker = ({invoiceItems, addInvoiceItem}) => {
<option key="placeholder" value={""} disabled>Select an Item</option>
{items.map(i =>
<option key={i.Id} value={i.Id} disabled={invoiceItems.some(j => j.Id === i.Id)}>
- {i.Name}{i.Brand.Id === null ? "" : " - " + i.Brand.Name}
+ {i.Name}{i.Brand.Id === undefined ? "" : " - " + i.Brand.Name}
</option>
)}
</select>
@@ -76,8 +76,8 @@ const ItemPicker = ({invoiceItems, addInvoiceItem}) => {
type="number"
value={item.Quantity}
name="Quantity"
- min={item.MinQuantity}
- max={item.MaxQuantity}
+ min={item.MinQuantity > 0 ? item.MinQuantity : 1}
+ max={item.MaxQuantity > 0 ? item.MaxQuantity : null}
onChange={handleInput} />
</label>
<label className={"narrow"}>
diff --git a/src/components/tables/invoice-item-table.js b/src/components/tables/invoice-item-table.js
index 6b0a1a5..12ee52e 100644
--- a/src/components/tables/invoice-item-table.js
+++ b/src/components/tables/invoice-item-table.js
@@ -16,11 +16,11 @@
*/
import './scss/table.scss';
-import { deleteItem } from './../../classes/item';
+import { deleteItem, getDiscountValue, getGSTValue, getAmount } from './../../classes/item';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPencil, faTrashCan } from '@fortawesome/free-solid-svg-icons'
-const ItemTable = ({items, setItems}) => {
+const ItemTable = ({items, setItems, isInterstate, sum}) => {
const handleEdit = (i) => {
alert("coming soon; please delete and add item again");
}
@@ -29,15 +29,7 @@ const ItemTable = ({items, setItems}) => {
setItems(items.filter(i => i.Id !== item.Id));
}
- /* TODO: all the math should be done here
- * i.e CGST, IGST, total price (i.e price x quantity)
- * discount/gst value (i.e number instead of percentage)
- *
- * the total cost and the like may be handled by
- * parent component since they are needed
- * by other things (probably)
- *
- * all the values will be calculated on runtime.
+ /* all the values will be calculated on runtime.
* the database will only store the unit price
* and gst/discount *percentages* and everything else
* will be calculated on runtime. i.e the
@@ -45,40 +37,80 @@ const ItemTable = ({items, setItems}) => {
* those same values shown to the user while creating the invoice
*/
return (
- <table>
- <thead>
- <tr>
- <th>S. No</th>
- <th>Name</th>
- <th>Description</th>
- <th>Brand Name</th>
- <th>UOM</th>
- <th>HSN</th>
- <th>Unit Price</th>
- <th>GST %</th>
- {/* TODO: CGST, IGST, etc */}
- <th></th>
- </tr>
- </thead>
- <tbody>
- {items && items.map((i, id=id+1) => (
- <tr key={id}>
- <td>{id+1}</td>
- <td className={i.Name === "" ? "empty" : ""}>{i.Name}</td>
- <td className={i.Description === "" ? "empty" : ""}>{i.Description}</td>
- <td className={i.Brand.Name === "" ? "empty" : ""}>{i.Brand.Name}</td>
- <td className={i.UnitOfMeasure === "" ? "empty" : ""}>{i.UnitOfMeasure}</td>
- <td className={i.HSN === "" ? "empty" : ""}>{i.HSN}</td>
- <td className={i.UnitPrice === 0.0 ? "empty" : ""}>{i.UnitPrice}</td>
- <td className={i.GSTPercentage === 0.0 ? "empty" : ""}>{i.GSTPercentage}</td>
+ <>
+ <table>
+ <thead>
+ <tr>
+ <th>S. No</th>
+ <th>Name</th>
+ <th>Description</th>
+ <th>Brand Name</th>
+ <th>Quantity</th>
+ <th>UOM</th>
+ <th>Unit Price</th>
+ <th>Discount (%)</th>
+ {isInterstate
+ ? <th>IGST (%)</th>
+ : <>
+ <th>SGST (%)</th>
+ <th>CGST (%)</th>
+ </>
+ }
+ <th>HSN</th>
+ <th>Amount</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {items && items.map((i, id) => (
+ <tr key={id}>
+ <td>{id+1}</td>
+ <td className={i.Name === "" ? "empty" : ""}>{i.Name}</td>
+ <td className={i.Description === "" ? "empty" : ""}>{i.Description}</td>
+ <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>
+ {isInterstate
+ ? <td className={i.GSTPercentage > 0 ? "" : "empty"}>{getGSTValue(i)} ({i.GSTPercentage}%)</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>
+ </>
+ }
+ <td className={i.HSN === "" ? "empty" : ""}>{i.HSN}</td>
+ <td>{getAmount(i)}</td>
+ <td className={"buttons"}>
+ <FontAwesomeIcon icon={faPencil} onClick={() => handleEdit(i)}/>
+ <FontAwesomeIcon icon={faTrashCan} onClick={() => handleDelete(i)}/>
+ </td>
+ </tr>
+ ))}
+ <tr className={"total"}>
+ <td>Total</td>
+ <td className={"empty"}></td>
+ <td className={"empty"}></td>
+ <td className={"empty"}></td>
+ <td className={sum.Quantity > 0 ? "" : "empty"}>{sum.Quantity}</td>
+ <td className={"empty"}></td>
+ <td className={sum.UnitPrice > 0 ? "" : "empty"}>{sum.UnitPrice}</td>
+ <td className={sum.Discount > 0 ? "" : "empty"}>{sum.Discount}</td>
+ {isInterstate
+ ? <td className={sum.GST > 0 ? "" : "empty"}>{sum.GST}</td>
+ : <>
+ <td className={sum.GST > 0 ? "" : "empty"}>{sum.GST / 2}</td>
+ <td className={sum.GST > 0 ? "" : "empty"}>{sum.GST / 2}</td>
+ </>
+ }
+ <td className={"empty"}></td>
+ <td className={sum.Amount > 0 ? "" : "empty"}>{sum.Amount}</td>
<td className={"buttons"}>
- <FontAwesomeIcon icon={faPencil} onClick={() => handleEdit(i)}/>
- <FontAwesomeIcon icon={faTrashCan} onClick={() => handleDelete(i)}/>
</td>
</tr>
- ))}
- </tbody>
- </table>
+ </tbody>
+ </table>
+ </>
);
}
diff --git a/src/components/tables/scss/table.scss b/src/components/tables/scss/table.scss
index 13e247a..0bb5a48 100644
--- a/src/components/tables/scss/table.scss
+++ b/src/components/tables/scss/table.scss
@@ -53,3 +53,11 @@ table {
white-space: pre-line;
}
}
+
+table .total {
+ font-size: 1.2em;
+ color: $primaryAccentColor;
+ td:not(.empty) {
+ border-color: $secondaryAccentColor;
+ }
+}
diff --git a/src/views/invoice/new.js b/src/views/invoice/new.js
index 70bc545..1d162ad 100644
--- a/src/views/invoice/new.js
+++ b/src/views/invoice/new.js
@@ -20,6 +20,7 @@ import ItemPicker from '../../components/pickers/item-picker';
import ItemTable from '../../components/tables/invoice-item-table';
import { InvoiceClient } from '../../classes/client';
+import { calcSum } from '../../classes/item';
import { useState, useEffect } from 'react';
@@ -27,10 +28,12 @@ const NewInvoicePage = () => {
const [client, setClient] = useState(new InvoiceClient());
const [shippingAddressId, setShippingAddressId] = useState(-1);
const [items, setItems] = useState([]);
+ const [isInterstate, setIsInterstate] = useState(false);
+ const [sum, setSum] = useState({});
- useEffect(() => {
- setShippingAddressId(-1);
- }, [client]);
+ useEffect(() => setShippingAddressId(-1), [client]);
+
+ useEffect(() => setSum(calcSum(items)), [items]);
return (
<>
@@ -44,7 +47,9 @@ const NewInvoicePage = () => {
addInvoiceItem={(item) => setItems(prev => [...prev, item])} />
<ItemTable
items={items}
- setItems={setItems} />
+ setItems={setItems}
+ isInterstate={isInterstate}
+ sum={sum} />
</>
);
}