Adding TDS Calculation in ViewExpense.
This commit is contained in:
parent
a21bec943d
commit
b568188a3e
@ -10,6 +10,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { defaultActionValues, ExpenseActionScheam } from "./ExpenseSchema";
|
||||
import { useExpenseContext } from "../../pages/Expense/ExpensePage";
|
||||
import {
|
||||
calculateTDSPercentage,
|
||||
formatCurrency,
|
||||
formatFigure,
|
||||
getColorNameFromHex,
|
||||
@ -54,12 +55,22 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
setValue,
|
||||
reset,
|
||||
control,
|
||||
watch,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: zodResolver(ActionSchema),
|
||||
defaultValues: defaultActionValues,
|
||||
});
|
||||
|
||||
const baseAmount = Number(watch("baseAmount")) || 0;
|
||||
const taxAmount = Number(watch("taxAmount")) || 0;
|
||||
const tdsPercentage = Number(watch("tdsPercentage")) || 0;
|
||||
|
||||
|
||||
const { grossAmount, tdsAmount, netPayable } = useMemo(() => {
|
||||
return calculateTDSPercentage(baseAmount, taxAmount, tdsPercentage);
|
||||
}, [baseAmount, taxAmount, tdsPercentage]);
|
||||
|
||||
const userPermissions = useSelector(
|
||||
(state) => state?.globalVariables?.loginUser?.featurePermissions || []
|
||||
);
|
||||
@ -132,9 +143,8 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
<span>{data?.expenseUId}</span>
|
||||
</div>{" "}
|
||||
<span
|
||||
className={`badge bg-label-${
|
||||
getColorNameFromHex(data?.status?.color) || "secondary"
|
||||
}`}
|
||||
className={`badge bg-label-${getColorNameFromHex(data?.status?.color) || "secondary"
|
||||
}`}
|
||||
t
|
||||
>
|
||||
{data?.status?.name}
|
||||
@ -142,7 +152,7 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
</div>
|
||||
|
||||
{/* Row 1 */}
|
||||
<div className="row text-start">
|
||||
<div className="row text-start">
|
||||
<div className="col-md-6 mb-3">
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||
@ -264,28 +274,28 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
</div> */}
|
||||
|
||||
{/* Row 5 */}
|
||||
|
||||
|
||||
<div className="row text-start">
|
||||
|
||||
<div className="row text-start">
|
||||
<div className="col-md-6 mb-3">
|
||||
|
||||
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||
style={{ minWidth: "130px" }}
|
||||
>
|
||||
Created At :
|
||||
</label>
|
||||
|
||||
|
||||
</div>
|
||||
<div className="col-md-6 mb-3">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div className="col-md-6 mb-3">
|
||||
|
||||
<small className="text-muted">
|
||||
{formatUTCToLocalTime(data?.createdAt, true)}
|
||||
</small>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Created & Paid By */}
|
||||
{data.createdBy && (
|
||||
@ -307,9 +317,8 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
lastName={data.createdBy?.lastName}
|
||||
/>
|
||||
<span className="text-muted">
|
||||
{`${data.createdBy?.firstName ?? ""} ${
|
||||
data.createdBy?.lastName ?? ""
|
||||
}`.trim() || "N/A"}
|
||||
{`${data.createdBy?.firstName ?? ""} ${data.createdBy?.lastName ?? ""
|
||||
}`.trim() || "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -337,31 +346,30 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
</span>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="row text-start">
|
||||
<div className="col-md-6 text-start mb-3">
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold"
|
||||
style={{ minWidth: "130px" }}
|
||||
>
|
||||
Paid By :
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-md-6 text-start mb-3">
|
||||
<div className="d-flex align-items-center">
|
||||
<Avatar
|
||||
size="xs"
|
||||
classAvatar="m-0 me-1"
|
||||
firstName={data.paidBy?.firstName}
|
||||
lastName={data.paidBy?.lastName}
|
||||
/>
|
||||
<span className="text-muted">
|
||||
{`${data.paidBy?.firstName ?? ""} ${
|
||||
data.paidBy?.lastName ?? ""
|
||||
<div className="row text-start">
|
||||
<div className="col-md-6 text-start mb-3">
|
||||
<label
|
||||
className="form-label me-2 mb-0 fw-semibold"
|
||||
style={{ minWidth: "130px" }}
|
||||
>
|
||||
Paid By :
|
||||
</label>
|
||||
</div>
|
||||
<div className="col-md-6 text-start mb-3">
|
||||
<div className="d-flex align-items-center">
|
||||
<Avatar
|
||||
size="xs"
|
||||
classAvatar="m-0 me-1"
|
||||
firstName={data.paidBy?.firstName}
|
||||
lastName={data.paidBy?.lastName}
|
||||
/>
|
||||
<span className="text-muted">
|
||||
{`${data.paidBy?.firstName ?? ""} ${data.paidBy?.lastName ?? ""
|
||||
}`.trim() || "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div className="col-12 text-start mb-2">
|
||||
@ -493,19 +501,7 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
projectId={null}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<Label className="form-label">TDS Percentage</Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("tdsPercentage")}
|
||||
/>
|
||||
{errors.tdsPercentage && (
|
||||
<small className="danger-text">
|
||||
{errors.tdsPercentage.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<Label className="form-label" required>
|
||||
Base Amount
|
||||
@ -536,28 +532,53 @@ const ViewExpense = ({ ExpenseId }) => {
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 col-md-6 text-start">
|
||||
<Label className="form-label">TDS Percentage</Label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
{...register("tdsPercentage")}
|
||||
/>
|
||||
{errors.tdsPercentage && (
|
||||
<small className="danger-text">
|
||||
{errors.tdsPercentage.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-12 d-flex align-items-center gap-4 mb-2 mt-1">
|
||||
<div>
|
||||
<span className="fw-semibold">TDS Amount: </span>
|
||||
<span className="badge bg-label-secondary">{tdsAmount.toFixed(2)}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="fw-semibold">Net Payable: </span>
|
||||
<span className="badge bg-label-secondary">{netPayable.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)}
|
||||
<div className="col-12 mb-3 text-start mt-1">
|
||||
{((nextStatusWithPermission.length > 0 &&
|
||||
!IsRejectedExpense) ||
|
||||
(IsRejectedExpense && isCreatedBy)) && (
|
||||
<>
|
||||
<Label className="form-label me-2 mb-0" required>
|
||||
Comment
|
||||
</Label>
|
||||
<textarea
|
||||
className="form-control form-control-sm"
|
||||
{...register("comment")}
|
||||
rows="2"
|
||||
/>
|
||||
{errors.comment && (
|
||||
<small className="danger-text">
|
||||
{errors.comment.message}
|
||||
</small>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<>
|
||||
<Label className="form-label me-2 mb-0" required>
|
||||
Comment
|
||||
</Label>
|
||||
<textarea
|
||||
className="form-control form-control-sm"
|
||||
{...register("comment")}
|
||||
rows="2"
|
||||
/>
|
||||
{errors.comment && (
|
||||
<small className="danger-text">
|
||||
{errors.comment.message}
|
||||
</small>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{nextStatusWithPermission?.length > 0 &&
|
||||
(!IsRejectedExpense || isCreatedBy) && (
|
||||
|
||||
@ -24,7 +24,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useSelector } from "react-redux";
|
||||
import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequestPage";
|
||||
import { localToUtc } from "../../utils/appUtils";
|
||||
import { calculateTDSPercentage, localToUtc } from "../../utils/appUtils";
|
||||
import { usePaymentMode } from "../../hooks/masterHook/useMaster";
|
||||
import Filelist from "../Expenses/Filelist";
|
||||
|
||||
@ -69,15 +69,10 @@ const ActionPaymentRequest = ({ requestId }) => {
|
||||
const taxAmount = watch("taxAmount") || 0;
|
||||
const tdsPercentage = watch("tdsPercentage") || 0;
|
||||
|
||||
const grossAmount = baseAmount + taxAmount;
|
||||
|
||||
const tdsAmount = useMemo(() => (baseAmount * tdsPercentage) / 100, [
|
||||
baseAmount,
|
||||
tdsPercentage,
|
||||
]);
|
||||
|
||||
const netPayable = useMemo(() => grossAmount - tdsAmount, [grossAmount, tdsAmount]);
|
||||
|
||||
const { grossAmount, tdsAmount, netPayable } = useMemo(() => {
|
||||
return calculateTDSPercentage(baseAmount, taxAmount, tdsPercentage);
|
||||
}, [baseAmount, taxAmount, tdsPercentage]);
|
||||
|
||||
const userPermissions = useSelector(
|
||||
(state) => state?.globalVariables?.loginUser?.featurePermissions || []
|
||||
@ -428,6 +423,7 @@ const ActionPaymentRequest = ({ requestId }) => {
|
||||
<span className="badge bg-label-secondary">{netPayable.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
)}
|
||||
|
||||
@ -228,3 +228,21 @@ export function daysLeft(startDate, dueDate) {
|
||||
|
||||
return { days, color };
|
||||
}
|
||||
|
||||
export function calculateTDSPercentage(baseAmount = 0, taxAmount = 0, tdsPercentage = 0) {
|
||||
baseAmount = Number(baseAmount) || 0;
|
||||
taxAmount = Number(taxAmount) || 0;
|
||||
tdsPercentage = Number(tdsPercentage) || 0;
|
||||
|
||||
const grossAmount = baseAmount + taxAmount;
|
||||
const tdsAmount = (baseAmount * tdsPercentage) / 100;
|
||||
const netPayable = grossAmount - tdsAmount;
|
||||
|
||||
return {
|
||||
grossAmount,
|
||||
tdsAmount,
|
||||
netPayable,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user