From d02b14272fec5fbd35c5f87d694f40674dc984ee Mon Sep 17 00:00:00 2001 From: "pramod.mahajan" Date: Mon, 3 Nov 2025 20:25:41 +0530 Subject: [PATCH] added acion api t update status --- src/components/Expenses/ExpenseStatusLogs.jsx | 6 +- .../PaymentRequestFilterPanel.jsx | 1 - .../PaymentRequest/PaymentRequestList.jsx | 25 ++- .../PaymentRequest/PaymentRequestSchema.js | 59 ++++++ ...mentRequest.jsx => ViewPaymentRequest.jsx} | 193 +++++++++++------- src/hooks/useExpense.js | 32 ++- .../PaymentRequest/PaymentRequestPage.jsx | 6 +- src/repositories/ExpsenseRepository.jsx | 2 +- 8 files changed, 229 insertions(+), 95 deletions(-) rename src/components/PaymentRequest/{VewPaymentRequest.jsx => ViewPaymentRequest.jsx} (73%) diff --git a/src/components/Expenses/ExpenseStatusLogs.jsx b/src/components/Expenses/ExpenseStatusLogs.jsx index 575508db..d04796fc 100644 --- a/src/components/Expenses/ExpenseStatusLogs.jsx +++ b/src/components/Expenses/ExpenseStatusLogs.jsx @@ -7,11 +7,11 @@ const ExpenseStatusLogs = ({ data }) => { const [visibleCount, setVisibleCount] = useState(4); const sortedLogs = useMemo(() => { - if (!data?.expenseLogs) return []; - return [...data.expenseLogs].sort( + if (!data?.updateLogs) return []; + return [...data.updateLogs].sort( (a, b) => new Date(b.updateAt) - new Date(a.updateAt) ); - }, [data?.expenseLogs]); + }, [data?.updateLogs]); const logsToShow = sortedLogs.slice(0, visibleCount); diff --git a/src/components/PaymentRequest/PaymentRequestFilterPanel.jsx b/src/components/PaymentRequest/PaymentRequestFilterPanel.jsx index 84375874..5aaa894e 100644 --- a/src/components/PaymentRequest/PaymentRequestFilterPanel.jsx +++ b/src/components/PaymentRequest/PaymentRequestFilterPanel.jsx @@ -38,7 +38,6 @@ const PaymentRequestFilterPanel = ({ onApply, handleGroupBy }) => { const [selectedGroup, setSelectedGroup] = useState(groupByList[6]); const [resetKey, setResetKey] = useState(0); -console.log("Kartik",data) const methods = useForm({ resolver: zodResolver(SearchPaymentRequestSchema), diff --git a/src/components/PaymentRequest/PaymentRequestList.jsx b/src/components/PaymentRequest/PaymentRequestList.jsx index 0f3a8d66..3c823f92 100644 --- a/src/components/PaymentRequest/PaymentRequestList.jsx +++ b/src/components/PaymentRequest/PaymentRequestList.jsx @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { EXPENSE_DRAFT, ITEMS_PER_PAGE } from "../../utils/constants"; +import { EXPENSE_DRAFT, EXPENSE_REJECTEDBY, ITEMS_PER_PAGE } from "../../utils/constants"; import { formatCurrency, getColorNameFromHex, @@ -12,12 +12,16 @@ import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequ import { ExpenseTableSkeleton } from "../Expenses/ExpenseSkeleton"; import ConfirmModal from "../common/ConfirmModal"; import { useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; const PaymentRequestList = ({filters, groupBy = "submittedBy", search }) => { - const { setManageRequest } = usePaymentRequestContext(); + const { setManageRequest,setVieRequest } = usePaymentRequestContext(); const navigate = useNavigate(); const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [deletingId, setDeletingId] = useState(null); + const SelfId = useSelector( + (store) => store?.globalVariables?.loginUser?.employeeInfo?.id + ); const groupByField = (items, field) => { return items.reduce((acc, item) => { let key; @@ -180,14 +184,14 @@ const PaymentRequestList = ({filters, groupBy = "submittedBy", search }) => { const canEditExpense = (paymentRequest) => { return ( - (paymentRequest?.status?.id === EXPENSE_DRAFT || - EXPENSE_REJECTEDBY.includes(paymentRequest?.status?.id)) && + (paymentRequest?.expenseStatus?.id === EXPENSE_DRAFT || + EXPENSE_REJECTEDBY.includes(paymentRequest?.expenseStatus?.id)) && paymentRequest?.createdBy?.id === SelfId ); }; - const canDetetExpense = (expense) => { + const canDetetExpense = (request) => { return ( - expense?.status?.id === EXPENSE_DRAFT && expense?.createdBy?.id === SelfId + request?.expenseStatus?.id === EXPENSE_DRAFT && request?.createdBy?.id === SelfId ); }; @@ -269,13 +273,14 @@ const PaymentRequestList = ({filters, groupBy = "submittedBy", search }) => { - setViewExpense({ - expenseId: paymentRequest.id, + setVieRequest({ + requestId: paymentRequest.id, view: true, }) } > - + {canDetetExpense(paymentRequest) && + canEditExpense(paymentRequest) && (
+ )} diff --git a/src/components/PaymentRequest/PaymentRequestSchema.js b/src/components/PaymentRequest/PaymentRequestSchema.js index 96497562..927baa3b 100644 --- a/src/components/PaymentRequest/PaymentRequestSchema.js +++ b/src/components/PaymentRequest/PaymentRequestSchema.js @@ -85,4 +85,63 @@ export const defaultPaymentRequestFilter = { payees: [], startDate: null, endDate: null, +}; + + +export const PaymentRequestActionScheam = ( + isTransaction = false, + transactionDate +) => { + return z + .object({ + comment: z.string().min(1, { message: "Please leave comment" }), + statusId: z.string().min(1, { message: "Please select a status" }), + paymentRequestId: z.string().nullable().optional(), + paidAt: z.string().nullable().optional(), + paidById: z.string().nullable().optional(), + + }) + .superRefine((data, ctx) => { + if (isTransaction) { + if (!data.paymentRequestId?.trim()) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["reimburseTransactionId"], + message: "Reimburse Transaction ID is required", + }); + } + if (!data.paidAt) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["paidAt"], + message: "Transacion Date is required", + }); + } + // let reimburse_Date = localToUtc(data.reimburseDate); + // if (transactionDate > reimburse_Date) { + // ctx.addIssue({ + // code: z.ZodIssueCode.custom, + // path: ["reimburseDate"], + // message: + // "Reimburse Date must be greater than or equal to Expense created Date", + // }); + // } + if (!data.paidById) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["paidById"], + message: "Paid By is required", + }); + } + } + }); +}; + +export const defaultActionValues = { + comment: "", + statusId: "", + + paidTransactionId: null, + paidAt: null, + paidById: null, }; \ No newline at end of file diff --git a/src/components/PaymentRequest/VewPaymentRequest.jsx b/src/components/PaymentRequest/ViewPaymentRequest.jsx similarity index 73% rename from src/components/PaymentRequest/VewPaymentRequest.jsx rename to src/components/PaymentRequest/ViewPaymentRequest.jsx index 52d8f7cc..d8d70a32 100644 --- a/src/components/PaymentRequest/VewPaymentRequest.jsx +++ b/src/components/PaymentRequest/ViewPaymentRequest.jsx @@ -1,12 +1,24 @@ -import { useMemo } from "react"; -import { useActionOnExpense, usePaymentRequestDetail } from "../../hooks/useExpense"; -import { getColorNameFromHex, getIconByFileType, localToUtc } from "../../utils/appUtils"; +import { useMemo, useState } from "react"; +import { + useActionOnExpense, + useActionOnPaymentRequest, + usePaymentRequestDetail, +} from "../../hooks/useExpense"; +import { + formatCurrency, + getColorNameFromHex, + getIconByFileType, + localToUtc, +} from "../../utils/appUtils"; import { formatUTCToLocalTime } from "../../utils/dateUtils"; import Avatar from "../common/Avatar"; import DatePicker from "../common/DatePicker"; import EmployeeSearchInput from "../common/EmployeeSearchInput"; import Error from "../common/Error"; -import { defaultActionValues, ExpenseActionScheam } from "../Expenses/ExpenseSchema"; +import { + defaultActionValues, + ExpenseActionScheam, +} from "../Expenses/ExpenseSchema"; import { ExpenseDetailsSkeleton } from "../Expenses/ExpenseSkeleton"; import ExpenseStatusLogs from "../Expenses/ExpenseStatusLogs"; import { useSelector } from "react-redux"; @@ -14,16 +26,25 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { useNavigate } from "react-router-dom"; import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequestPage"; +import { useHasUserPermission } from "../../hooks/useHasUserPermission"; +import { + EXPENSE_REJECTEDBY, + PROCESS_EXPENSE, + REVIEW_EXPENSE, +} from "../../utils/constants"; +import Label from "../common/Label"; -const ViewPaymentRequest = ({ RequestId }) => { - const { data, isLoading, isError, error, isFetching } = usePaymentRequestDetail(RequestId); +const ViewPaymentRequest = ({ requestId }) => { + const { data, isLoading, isError, error, isFetching } = + usePaymentRequestDetail(requestId); const [IsPaymentProcess, setIsPaymentProcess] = useState(false); const [clickedStatusId, setClickedStatusId] = useState(null); const IsReview = useHasUserPermission(REVIEW_EXPENSE); const [imageLoaded, setImageLoaded] = useState({}); const { setDocumentView } = usePaymentRequestContext(); - const ActionSchema = ExpenseActionScheam(IsPaymentProcess,data?.createdAt) ?? z.object({}); + const ActionSchema = + ExpenseActionScheam(IsPaymentProcess, data?.createdAt) ?? z.object({}); const navigate = useNavigate(); const { register, @@ -65,10 +86,10 @@ const ViewPaymentRequest = ({ RequestId }) => { }, [data]); const isCreatedBy = useMemo(() => { - return data?.createdBy.id === CurrentUser?.id; + return data?.createdBy?.id === CurrentUser?.id; }, [data, CurrentUser]); - const { mutate: MakeAction, isPending } = useActionOnExpense(() => { + const { mutate: MakeAction, isPending } = useActionOnPaymentRequest(() => { setClickedStatusId(null); reset(); }); @@ -76,8 +97,8 @@ const ViewPaymentRequest = ({ RequestId }) => { const onSubmit = (formData) => { const Payload = { ...formData, - reimburseDate:localToUtc(formData.reimburseDate), - expenseId: ExpenseId, + paidAt: localToUtc(formData.reimburseDate), + paymentRequestId: data.id, comment: formData.comment, }; MakeAction(Payload); @@ -93,10 +114,12 @@ const ViewPaymentRequest = ({ RequestId }) => {
-
Expense Details
+
Request Details

-
{data?.expenseUId}
+
+ {data?.paymentRequestUID} +
{/* Row 1 */}
@@ -104,10 +127,23 @@ const ViewPaymentRequest = ({ RequestId }) => { className="form-label me-2 mb-0 fw-semibold text-start" style={{ minWidth: "130px" }} > - Transaction Date : + Projct Name :
- {formatUTCToLocalTime(data?.transactionDate)} + {data.project.name} +
+
+
+
+
+ +
+ {formatUTCToLocalTime(data?.dueDate)}
@@ -119,7 +155,7 @@ const ViewPaymentRequest = ({ RequestId }) => { > Expense Type : -
{data?.expensesType?.name}
+
{data?.expenseCategory?.name}
@@ -132,7 +168,7 @@ const ViewPaymentRequest = ({ RequestId }) => { > Supplier : -
{data?.supplerName}
+
{data?.payee}
@@ -143,12 +179,14 @@ const ViewPaymentRequest = ({ RequestId }) => { > Amount : -
₹ {data.amount}
+
+ {formatCurrency(data?.amount, data?.currency?.currencyCode)} +
{/* Row 3 */} -
+ {/*
{data?.paymentMode?.name}
-
+
*/} {data?.gstNumber && (
@@ -184,10 +222,10 @@ const ViewPaymentRequest = ({ RequestId }) => { - {data?.status?.name} + {data?.expenseStatus?.name}
@@ -199,7 +237,7 @@ const ViewPaymentRequest = ({ RequestId }) => { > Pre-Approved : -
{data.preApproved ? "Yes" : "No"}
+
{data?.preApproved ? "Yes" : "No"}
@@ -229,7 +267,7 @@ const ViewPaymentRequest = ({ RequestId }) => { {/* Row 6 */} - {data.createdBy && ( + {data?.createdBy && (
)} -
-
- -
- - - {`${data.paidBy?.firstName ?? ""} ${ - data.paidBy?.lastName ?? "" - }`.trim() || "N/A"} - + {data?.paidBy && ( +
+
+ +
+ + + {`${data?.paidBy?.firstName ?? ""} ${ + data?.paidBy?.lastName ?? "" + }`.trim() || "N/A"} + +
-
- -
- + )} + +
+
{data?.description}
@@ -289,7 +329,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
{data?.documents?.map((doc) => { - const isImage = doc.contentType?.includes("image"); + const isImage = doc?.contentType?.includes("image"); return (
{
- {data.expensesReimburse && ( + {data?.paidTransactionId && (
- {data.expensesReimburse.reimburseTransactionId || "N/A"} + {data?.paidTransactionId }
- {formatUTCToLocalTime(data.expensesReimburse.reimburseDate)} + {formatUTCToLocalTime(data?.paidAt)}
- {data.expensesReimburse && ( + {data?.paidBy && ( <>
- {`${data?.expensesReimburse?.reimburseBy?.firstName} ${data?.expensesReimburse?.reimburseBy?.lastName}`.trim()} + {`${data?.paidBy?.firstName} ${data?.paidBy?.lastName}`.trim()}
@@ -361,7 +401,7 @@ const ViewPaymentRequest = ({ RequestId }) => { )}
- {Array.isArray(data?.nextStatus) && data.nextStatus.length > 0 && ( + {Array.isArray(data?.nextStatus) && data?.nextStatus.length > 0 && ( <> {IsPaymentProcess && nextStatusWithPermission?.length > 0 && (
@@ -370,34 +410,34 @@ const ViewPaymentRequest = ({ RequestId }) => { - {errors.reimburseTransactionId && ( + {errors.paidTransactionId && ( - {errors.reimburseTransactionId.message} + {errors.paidTransactionId.message} )}
- {errors.reimburseDate && ( + {errors.paidAt && ( - {errors.reimburseDate.message} + {errors.paidAt.message} )}
- +
@@ -406,7 +446,9 @@ const ViewPaymentRequest = ({ RequestId }) => { {((nextStatusWithPermission.length > 0 && !isRejectedRequest) || (isRejectedRequest && isCreatedBy)) && ( <> - +