Adding TDS Calculation in ViewExpense.

This commit is contained in:
Kartik Sharma 2025-11-17 10:31:41 +05:30
parent a21bec943d
commit b568188a3e
3 changed files with 112 additions and 77 deletions

View File

@ -10,6 +10,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { defaultActionValues, ExpenseActionScheam } from "./ExpenseSchema"; import { defaultActionValues, ExpenseActionScheam } from "./ExpenseSchema";
import { useExpenseContext } from "../../pages/Expense/ExpensePage"; import { useExpenseContext } from "../../pages/Expense/ExpensePage";
import { import {
calculateTDSPercentage,
formatCurrency, formatCurrency,
formatFigure, formatFigure,
getColorNameFromHex, getColorNameFromHex,
@ -54,12 +55,22 @@ const ViewExpense = ({ ExpenseId }) => {
setValue, setValue,
reset, reset,
control, control,
watch,
formState: { errors }, formState: { errors },
} = useForm({ } = useForm({
resolver: zodResolver(ActionSchema), resolver: zodResolver(ActionSchema),
defaultValues: defaultActionValues, 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( const userPermissions = useSelector(
(state) => state?.globalVariables?.loginUser?.featurePermissions || [] (state) => state?.globalVariables?.loginUser?.featurePermissions || []
); );
@ -132,8 +143,7 @@ const ViewExpense = ({ ExpenseId }) => {
<span>{data?.expenseUId}</span> <span>{data?.expenseUId}</span>
</div>{" "} </div>{" "}
<span <span
className={`badge bg-label-${ className={`badge bg-label-${getColorNameFromHex(data?.status?.color) || "secondary"
getColorNameFromHex(data?.status?.color) || "secondary"
}`} }`}
t t
> >
@ -307,8 +317,7 @@ const ViewExpense = ({ ExpenseId }) => {
lastName={data.createdBy?.lastName} lastName={data.createdBy?.lastName}
/> />
<span className="text-muted"> <span className="text-muted">
{`${data.createdBy?.firstName ?? ""} ${ {`${data.createdBy?.firstName ?? ""} ${data.createdBy?.lastName ?? ""
data.createdBy?.lastName ?? ""
}`.trim() || "N/A"} }`.trim() || "N/A"}
</span> </span>
</div> </div>
@ -355,8 +364,7 @@ const ViewExpense = ({ ExpenseId }) => {
lastName={data.paidBy?.lastName} lastName={data.paidBy?.lastName}
/> />
<span className="text-muted"> <span className="text-muted">
{`${data.paidBy?.firstName ?? ""} ${ {`${data.paidBy?.firstName ?? ""} ${data.paidBy?.lastName ?? ""
data.paidBy?.lastName ?? ""
}`.trim() || "N/A"} }`.trim() || "N/A"}
</span> </span>
</div> </div>
@ -493,19 +501,7 @@ const ViewExpense = ({ ExpenseId }) => {
projectId={null} projectId={null}
/> />
</div> </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"> <div className="col-12 col-md-6 text-start">
<Label className="form-label" required> <Label className="form-label" required>
Base Amount Base Amount
@ -536,7 +532,32 @@ const ViewExpense = ({ ExpenseId }) => {
</small> </small>
)} )}
</div> </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>
<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"> <div className="col-12 mb-3 text-start mt-1">
{((nextStatusWithPermission.length > 0 && {((nextStatusWithPermission.length > 0 &&

View File

@ -24,7 +24,7 @@ import { useNavigate } from "react-router-dom";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequestPage"; import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequestPage";
import { localToUtc } from "../../utils/appUtils"; import { calculateTDSPercentage, localToUtc } from "../../utils/appUtils";
import { usePaymentMode } from "../../hooks/masterHook/useMaster"; import { usePaymentMode } from "../../hooks/masterHook/useMaster";
import Filelist from "../Expenses/Filelist"; import Filelist from "../Expenses/Filelist";
@ -69,15 +69,10 @@ const ActionPaymentRequest = ({ requestId }) => {
const taxAmount = watch("taxAmount") || 0; const taxAmount = watch("taxAmount") || 0;
const tdsPercentage = watch("tdsPercentage") || 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( const userPermissions = useSelector(
(state) => state?.globalVariables?.loginUser?.featurePermissions || [] (state) => state?.globalVariables?.loginUser?.featurePermissions || []
@ -428,6 +423,7 @@ const ActionPaymentRequest = ({ requestId }) => {
<span className="badge bg-label-secondary">{netPayable.toFixed(2)}</span> <span className="badge bg-label-secondary">{netPayable.toFixed(2)}</span>
</div> </div>
</div> </div>
</div> </div>
)} )}

View File

@ -228,3 +228,21 @@ export function daysLeft(startDate, dueDate) {
return { days, color }; 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,
};
}