added acion api t update status
This commit is contained in:
parent
edafc204b8
commit
d02b14272f
@ -7,11 +7,11 @@ const ExpenseStatusLogs = ({ data }) => {
|
|||||||
const [visibleCount, setVisibleCount] = useState(4);
|
const [visibleCount, setVisibleCount] = useState(4);
|
||||||
|
|
||||||
const sortedLogs = useMemo(() => {
|
const sortedLogs = useMemo(() => {
|
||||||
if (!data?.expenseLogs) return [];
|
if (!data?.updateLogs) return [];
|
||||||
return [...data.expenseLogs].sort(
|
return [...data.updateLogs].sort(
|
||||||
(a, b) => new Date(b.updateAt) - new Date(a.updateAt)
|
(a, b) => new Date(b.updateAt) - new Date(a.updateAt)
|
||||||
);
|
);
|
||||||
}, [data?.expenseLogs]);
|
}, [data?.updateLogs]);
|
||||||
|
|
||||||
const logsToShow = sortedLogs.slice(0, visibleCount);
|
const logsToShow = sortedLogs.slice(0, visibleCount);
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,6 @@ const PaymentRequestFilterPanel = ({ onApply, handleGroupBy }) => {
|
|||||||
const [selectedGroup, setSelectedGroup] = useState(groupByList[6]);
|
const [selectedGroup, setSelectedGroup] = useState(groupByList[6]);
|
||||||
const [resetKey, setResetKey] = useState(0);
|
const [resetKey, setResetKey] = useState(0);
|
||||||
|
|
||||||
console.log("Kartik",data)
|
|
||||||
|
|
||||||
const methods = useForm({
|
const methods = useForm({
|
||||||
resolver: zodResolver(SearchPaymentRequestSchema),
|
resolver: zodResolver(SearchPaymentRequestSchema),
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
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 {
|
import {
|
||||||
formatCurrency,
|
formatCurrency,
|
||||||
getColorNameFromHex,
|
getColorNameFromHex,
|
||||||
@ -12,12 +12,16 @@ import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequ
|
|||||||
import { ExpenseTableSkeleton } from "../Expenses/ExpenseSkeleton";
|
import { ExpenseTableSkeleton } from "../Expenses/ExpenseSkeleton";
|
||||||
import ConfirmModal from "../common/ConfirmModal";
|
import ConfirmModal from "../common/ConfirmModal";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
const PaymentRequestList = ({filters, groupBy = "submittedBy", search }) => {
|
const PaymentRequestList = ({filters, groupBy = "submittedBy", search }) => {
|
||||||
const { setManageRequest } = usePaymentRequestContext();
|
const { setManageRequest,setVieRequest } = usePaymentRequestContext();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
const [deletingId, setDeletingId] = useState(null);
|
const [deletingId, setDeletingId] = useState(null);
|
||||||
|
const SelfId = useSelector(
|
||||||
|
(store) => store?.globalVariables?.loginUser?.employeeInfo?.id
|
||||||
|
);
|
||||||
const groupByField = (items, field) => {
|
const groupByField = (items, field) => {
|
||||||
return items.reduce((acc, item) => {
|
return items.reduce((acc, item) => {
|
||||||
let key;
|
let key;
|
||||||
@ -180,14 +184,14 @@ const PaymentRequestList = ({filters, groupBy = "submittedBy", search }) => {
|
|||||||
|
|
||||||
const canEditExpense = (paymentRequest) => {
|
const canEditExpense = (paymentRequest) => {
|
||||||
return (
|
return (
|
||||||
(paymentRequest?.status?.id === EXPENSE_DRAFT ||
|
(paymentRequest?.expenseStatus?.id === EXPENSE_DRAFT ||
|
||||||
EXPENSE_REJECTEDBY.includes(paymentRequest?.status?.id)) &&
|
EXPENSE_REJECTEDBY.includes(paymentRequest?.expenseStatus?.id)) &&
|
||||||
paymentRequest?.createdBy?.id === SelfId
|
paymentRequest?.createdBy?.id === SelfId
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const canDetetExpense = (expense) => {
|
const canDetetExpense = (request) => {
|
||||||
return (
|
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 }) => {
|
|||||||
<i
|
<i
|
||||||
className="bx bx-show text-primary cursor-pointer"
|
className="bx bx-show text-primary cursor-pointer"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setViewExpense({
|
setVieRequest({
|
||||||
expenseId: paymentRequest.id,
|
requestId: paymentRequest.id,
|
||||||
view: true,
|
view: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
></i>
|
></i>
|
||||||
|
{canDetetExpense(paymentRequest) &&
|
||||||
|
canEditExpense(paymentRequest) && (
|
||||||
<div className="dropdown z-2">
|
<div className="dropdown z-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -319,7 +324,7 @@ const PaymentRequestList = ({filters, groupBy = "submittedBy", search }) => {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -85,4 +85,63 @@ export const defaultPaymentRequestFilter = {
|
|||||||
payees: [],
|
payees: [],
|
||||||
startDate: null,
|
startDate: null,
|
||||||
endDate: 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,
|
||||||
};
|
};
|
||||||
@ -1,12 +1,24 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { useActionOnExpense, usePaymentRequestDetail } from "../../hooks/useExpense";
|
import {
|
||||||
import { getColorNameFromHex, getIconByFileType, localToUtc } from "../../utils/appUtils";
|
useActionOnExpense,
|
||||||
|
useActionOnPaymentRequest,
|
||||||
|
usePaymentRequestDetail,
|
||||||
|
} from "../../hooks/useExpense";
|
||||||
|
import {
|
||||||
|
formatCurrency,
|
||||||
|
getColorNameFromHex,
|
||||||
|
getIconByFileType,
|
||||||
|
localToUtc,
|
||||||
|
} from "../../utils/appUtils";
|
||||||
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../common/Avatar";
|
||||||
import DatePicker from "../common/DatePicker";
|
import DatePicker from "../common/DatePicker";
|
||||||
import EmployeeSearchInput from "../common/EmployeeSearchInput";
|
import EmployeeSearchInput from "../common/EmployeeSearchInput";
|
||||||
import Error from "../common/Error";
|
import Error from "../common/Error";
|
||||||
import { defaultActionValues, ExpenseActionScheam } from "../Expenses/ExpenseSchema";
|
import {
|
||||||
|
defaultActionValues,
|
||||||
|
ExpenseActionScheam,
|
||||||
|
} from "../Expenses/ExpenseSchema";
|
||||||
import { ExpenseDetailsSkeleton } from "../Expenses/ExpenseSkeleton";
|
import { ExpenseDetailsSkeleton } from "../Expenses/ExpenseSkeleton";
|
||||||
import ExpenseStatusLogs from "../Expenses/ExpenseStatusLogs";
|
import ExpenseStatusLogs from "../Expenses/ExpenseStatusLogs";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
@ -14,16 +26,25 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
|||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { usePaymentRequestContext } from "../../pages/PaymentRequest/PaymentRequestPage";
|
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 ViewPaymentRequest = ({ requestId }) => {
|
||||||
const { data, isLoading, isError, error, isFetching } = usePaymentRequestDetail(RequestId);
|
const { data, isLoading, isError, error, isFetching } =
|
||||||
|
usePaymentRequestDetail(requestId);
|
||||||
const [IsPaymentProcess, setIsPaymentProcess] = useState(false);
|
const [IsPaymentProcess, setIsPaymentProcess] = useState(false);
|
||||||
const [clickedStatusId, setClickedStatusId] = useState(null);
|
const [clickedStatusId, setClickedStatusId] = useState(null);
|
||||||
|
|
||||||
const IsReview = useHasUserPermission(REVIEW_EXPENSE);
|
const IsReview = useHasUserPermission(REVIEW_EXPENSE);
|
||||||
const [imageLoaded, setImageLoaded] = useState({});
|
const [imageLoaded, setImageLoaded] = useState({});
|
||||||
const { setDocumentView } = usePaymentRequestContext();
|
const { setDocumentView } = usePaymentRequestContext();
|
||||||
const ActionSchema = ExpenseActionScheam(IsPaymentProcess,data?.createdAt) ?? z.object({});
|
const ActionSchema =
|
||||||
|
ExpenseActionScheam(IsPaymentProcess, data?.createdAt) ?? z.object({});
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
@ -65,10 +86,10 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const isCreatedBy = useMemo(() => {
|
const isCreatedBy = useMemo(() => {
|
||||||
return data?.createdBy.id === CurrentUser?.id;
|
return data?.createdBy?.id === CurrentUser?.id;
|
||||||
}, [data, CurrentUser]);
|
}, [data, CurrentUser]);
|
||||||
|
|
||||||
const { mutate: MakeAction, isPending } = useActionOnExpense(() => {
|
const { mutate: MakeAction, isPending } = useActionOnPaymentRequest(() => {
|
||||||
setClickedStatusId(null);
|
setClickedStatusId(null);
|
||||||
reset();
|
reset();
|
||||||
});
|
});
|
||||||
@ -76,8 +97,8 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
const onSubmit = (formData) => {
|
const onSubmit = (formData) => {
|
||||||
const Payload = {
|
const Payload = {
|
||||||
...formData,
|
...formData,
|
||||||
reimburseDate:localToUtc(formData.reimburseDate),
|
paidAt: localToUtc(formData.reimburseDate),
|
||||||
expenseId: ExpenseId,
|
paymentRequestId: data.id,
|
||||||
comment: formData.comment,
|
comment: formData.comment,
|
||||||
};
|
};
|
||||||
MakeAction(Payload);
|
MakeAction(Payload);
|
||||||
@ -93,10 +114,12 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
<form className="container px-3" onSubmit={handleSubmit(onSubmit)}>
|
<form className="container px-3" onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="row mb-1">
|
<div className="row mb-1">
|
||||||
<div className="col-12 mb-1">
|
<div className="col-12 mb-1">
|
||||||
<h5 className="fw-semibold m-0">Expense Details</h5>
|
<h5 className="fw-semibold m-0">Request Details</h5>
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 text-start fw-semibold my-2">{data?.expenseUId}</div>
|
<div className="col-12 text-start fw-semibold my-2">
|
||||||
|
{data?.paymentRequestUID}
|
||||||
|
</div>
|
||||||
{/* Row 1 */}
|
{/* Row 1 */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<div className="d-flex">
|
<div className="d-flex">
|
||||||
@ -104,10 +127,23 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
style={{ minWidth: "130px" }}
|
style={{ minWidth: "130px" }}
|
||||||
>
|
>
|
||||||
Transaction Date :
|
Projct Name :
|
||||||
</label>
|
</label>
|
||||||
<div className="text-muted">
|
<div className="text-muted">
|
||||||
{formatUTCToLocalTime(data?.transactionDate)}
|
{data.project.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6 mb-3">
|
||||||
|
<div className="d-flex">
|
||||||
|
<label
|
||||||
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
|
style={{ minWidth: "130px" }}
|
||||||
|
>
|
||||||
|
Due Date :
|
||||||
|
</label>
|
||||||
|
<div className="text-muted">
|
||||||
|
{formatUTCToLocalTime(data?.dueDate)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -119,7 +155,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
>
|
>
|
||||||
Expense Type :
|
Expense Type :
|
||||||
</label>
|
</label>
|
||||||
<div className="text-muted">{data?.expensesType?.name}</div>
|
<div className="text-muted">{data?.expenseCategory?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -132,7 +168,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
>
|
>
|
||||||
Supplier :
|
Supplier :
|
||||||
</label>
|
</label>
|
||||||
<div className="text-muted">{data?.supplerName}</div>
|
<div className="text-muted">{data?.payee}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
@ -143,12 +179,14 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
>
|
>
|
||||||
Amount :
|
Amount :
|
||||||
</label>
|
</label>
|
||||||
<div className="text-muted">₹ {data.amount}</div>
|
<div className="text-muted">
|
||||||
|
{formatCurrency(data?.amount, data?.currency?.currencyCode)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Row 3 */}
|
{/* Row 3 */}
|
||||||
<div className="col-md-6 mb-3">
|
{/* <div className="col-md-6 mb-3">
|
||||||
<div className="d-flex">
|
<div className="d-flex">
|
||||||
<label
|
<label
|
||||||
className="form-label me-2 mb-0 fw-semibold text-start"
|
className="form-label me-2 mb-0 fw-semibold text-start"
|
||||||
@ -158,7 +196,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
</label>
|
</label>
|
||||||
<div className="text-muted">{data?.paymentMode?.name}</div>
|
<div className="text-muted">{data?.paymentMode?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
{data?.gstNumber && (
|
{data?.gstNumber && (
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<div className="d-flex">
|
<div className="d-flex">
|
||||||
@ -184,10 +222,10 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
className={`badge bg-label-${
|
className={`badge bg-label-${
|
||||||
getColorNameFromHex(data?.status?.color) || "secondary"
|
getColorNameFromHex(data?.expenseStatus?.color) || "secondary"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{data?.status?.name}
|
{data?.expenseStatus?.name}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -199,7 +237,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
>
|
>
|
||||||
Pre-Approved :
|
Pre-Approved :
|
||||||
</label>
|
</label>
|
||||||
<div className="text-muted">{data.preApproved ? "Yes" : "No"}</div>
|
<div className="text-muted">{data?.preApproved ? "Yes" : "No"}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -229,7 +267,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Row 6 */}
|
{/* Row 6 */}
|
||||||
{data.createdBy && (
|
{data?.createdBy && (
|
||||||
<div className="col-md-6 text-start">
|
<div className="col-md-6 text-start">
|
||||||
<div className="d-flex align-items-center">
|
<div className="d-flex align-items-center">
|
||||||
<label
|
<label
|
||||||
@ -242,44 +280,46 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
<Avatar
|
<Avatar
|
||||||
size="xs"
|
size="xs"
|
||||||
classAvatar="m-0"
|
classAvatar="m-0"
|
||||||
firstName={data.createdBy?.firstName}
|
firstName={data?.createdBy?.firstName}
|
||||||
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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="col-md-6 text-start">
|
{data?.paidBy && (
|
||||||
<div className="d-flex align-items-center">
|
<div className="col-md-6 text-start">
|
||||||
<label
|
<div className="d-flex align-items-center">
|
||||||
className="form-label me-2 mb-0 fw-semibold"
|
<label
|
||||||
style={{ minWidth: "130px" }}
|
className="form-label me-2 mb-0 fw-semibold"
|
||||||
>
|
style={{ minWidth: "130px" }}
|
||||||
Paid By :
|
>
|
||||||
</label>
|
Paid By :
|
||||||
<div className="d-flex align-items-center ">
|
</label>
|
||||||
<Avatar
|
<div className="d-flex align-items-center ">
|
||||||
size="xs"
|
<Avatar
|
||||||
classAvatar="m-0"
|
size="xs"
|
||||||
firstName={data.paidBy?.firstName}
|
classAvatar="m-0"
|
||||||
lastName={data.paidBy?.lastName}
|
firstName={data?.paidBy?.firstName}
|
||||||
/>
|
lastName={data?.paidBy?.lastName}
|
||||||
<span className="text-muted">
|
/>
|
||||||
{`${data.paidBy?.firstName ?? ""} ${
|
<span className="text-muted">
|
||||||
data.paidBy?.lastName ?? ""
|
{`${data?.paidBy?.firstName ?? ""} ${
|
||||||
}`.trim() || "N/A"}
|
data?.paidBy?.lastName ?? ""
|
||||||
</span>
|
}`.trim() || "N/A"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<div className="text-start my-1">
|
<div className="text-start my-1">
|
||||||
<label className="fw-semibold form-label">Description : </label>
|
<label className="fw-semibold form-label">Description : </label>
|
||||||
<div className="text-muted">{data?.description}</div>
|
<div className="text-muted">{data?.description}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -289,7 +329,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
|
|
||||||
<div className="d-flex flex-wrap gap-2">
|
<div className="d-flex flex-wrap gap-2">
|
||||||
{data?.documents?.map((doc) => {
|
{data?.documents?.map((doc) => {
|
||||||
const isImage = doc.contentType?.includes("image");
|
const isImage = doc?.contentType?.includes("image");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -324,35 +364,35 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data.expensesReimburse && (
|
{data?.paidTransactionId && (
|
||||||
<div className="row text-start mt-2">
|
<div className="row text-start mt-2">
|
||||||
<div className="col-md-6 mb-sm-0 mb-2">
|
<div className="col-md-6 mb-sm-0 mb-2">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">
|
<label className="form-label me-2 mb-0 fw-semibold">
|
||||||
Transaction ID :
|
Transaction ID :
|
||||||
</label>
|
</label>
|
||||||
{data.expensesReimburse.reimburseTransactionId || "N/A"}
|
{data?.paidTransactionId }
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6 ">
|
<div className="col-md-6 ">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">
|
<label className="form-label me-2 mb-0 fw-semibold">
|
||||||
Reimburse Date :
|
Transaction Date :
|
||||||
</label>
|
</label>
|
||||||
{formatUTCToLocalTime(data.expensesReimburse.reimburseDate)}
|
{formatUTCToLocalTime(data?.paidAt)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data.expensesReimburse && (
|
{data?.paidBy && (
|
||||||
<>
|
<>
|
||||||
<div className="col-md-6 d-flex align-items-center">
|
<div className="col-md-6 d-flex align-items-center">
|
||||||
<label className="form-label me-2 mb-0 fw-semibold">
|
<label className="form-label me-2 mb-0 fw-semibold">
|
||||||
Reimburse By :
|
Paid By :
|
||||||
</label>
|
</label>
|
||||||
<Avatar
|
<Avatar
|
||||||
size="xs"
|
size="xs"
|
||||||
classAvatar="m-0 me-1"
|
classAvatar="m-0 me-1"
|
||||||
firstName={data?.expensesReimburse?.reimburseBy?.firstName}
|
firstName={data?.paidBy?.firstName}
|
||||||
lastName={data?.expensesReimburse?.reimburseBy?.lastName}
|
lastName={data?.paidBy?.lastName}
|
||||||
/>
|
/>
|
||||||
<span className="text-muted">
|
<span className="text-muted">
|
||||||
{`${data?.expensesReimburse?.reimburseBy?.firstName} ${data?.expensesReimburse?.reimburseBy?.lastName}`.trim()}
|
{`${data?.paidBy?.firstName} ${data?.paidBy?.lastName}`.trim()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -361,7 +401,7 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
)}
|
)}
|
||||||
<hr className="divider my-1 border-2 divider-primary my-2" />
|
<hr className="divider my-1 border-2 divider-primary my-2" />
|
||||||
|
|
||||||
{Array.isArray(data?.nextStatus) && data.nextStatus.length > 0 && (
|
{Array.isArray(data?.nextStatus) && data?.nextStatus.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{IsPaymentProcess && nextStatusWithPermission?.length > 0 && (
|
{IsPaymentProcess && nextStatusWithPermission?.length > 0 && (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -370,34 +410,34 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control form-control-sm"
|
className="form-control form-control-sm"
|
||||||
{...register("reimburseTransactionId")}
|
{...register("paidTransactionId")}
|
||||||
/>
|
/>
|
||||||
{errors.reimburseTransactionId && (
|
{errors.paidTransactionId && (
|
||||||
<small className="danger-text">
|
<small className="danger-text">
|
||||||
{errors.reimburseTransactionId.message}
|
{errors.paidTransactionId.message}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-6 text-start">
|
<div className="col-12 col-md-6 text-start">
|
||||||
<label className="form-label">Transaction Date </label>
|
<label className="form-label">Transaction Date </label>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
name="reimburseDate"
|
name="paidAt"
|
||||||
control={control}
|
control={control}
|
||||||
minDate={data?.createdAt}
|
minDate={data?.createdAt}
|
||||||
maxDate={new Date()}
|
maxDate={new Date()}
|
||||||
/>
|
/>
|
||||||
{errors.reimburseDate && (
|
{errors.paidAt && (
|
||||||
<small className="danger-text">
|
<small className="danger-text">
|
||||||
{errors.reimburseDate.message}
|
{errors.paidAt.message}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-6 text-start">
|
<div className="col-12 col-md-6 text-start">
|
||||||
<label className="form-label">Reimburse By </label>
|
<label className="form-label">Paid By </label>
|
||||||
<EmployeeSearchInput
|
<EmployeeSearchInput
|
||||||
control={control}
|
control={control}
|
||||||
name="reimburseById"
|
name="paidById"
|
||||||
projectId={null}
|
projectId={null}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -406,7 +446,9 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
{((nextStatusWithPermission.length > 0 && !isRejectedRequest) ||
|
{((nextStatusWithPermission.length > 0 && !isRejectedRequest) ||
|
||||||
(isRejectedRequest && isCreatedBy)) && (
|
(isRejectedRequest && isCreatedBy)) && (
|
||||||
<>
|
<>
|
||||||
<Label className="form-label me-2 mb-0" required>Comment</Label>
|
<Label className="form-label me-2 mb-0" required>
|
||||||
|
Comment
|
||||||
|
</Label>
|
||||||
<textarea
|
<textarea
|
||||||
className="form-control form-control-sm"
|
className="form-control form-control-sm"
|
||||||
{...register("comment")}
|
{...register("comment")}
|
||||||
@ -423,12 +465,12 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
{nextStatusWithPermission?.length > 0 &&
|
{nextStatusWithPermission?.length > 0 &&
|
||||||
(!isRejectedRequest || isCreatedBy) && (
|
(!isRejectedRequest || isCreatedBy) && (
|
||||||
<div className="text-end flex-wrap gap-2 my-2 mt-3">
|
<div className="text-end flex-wrap gap-2 my-2 mt-3">
|
||||||
{nextStatusWithPermission.map((status, index) => (
|
{nextStatusWithPermission?.map((status, index) => (
|
||||||
<button
|
<button
|
||||||
key={status.id || index}
|
key={status.id || index}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setClickedStatusId(status.id);
|
setClickedStatusId(status.id);
|
||||||
setValue("statusId", status.id);
|
setValue("statusId", status.id);
|
||||||
handleSubmit(onSubmit)();
|
handleSubmit(onSubmit)();
|
||||||
}}
|
}}
|
||||||
@ -450,3 +492,4 @@ const ViewPaymentRequest = ({ RequestId }) => {
|
|||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
export default ViewPaymentRequest;
|
||||||
@ -273,7 +273,7 @@ export const usePaymentRequestList = (
|
|||||||
searchString = "",
|
searchString = "",
|
||||||
) => {
|
) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ["paymentRequest",pageSize,pageNumber,filter,isActive,searchString],
|
queryKey: ["paymentRequestList",pageSize,pageNumber,filter,isActive,searchString],
|
||||||
queryFn: async()=>{
|
queryFn: async()=>{
|
||||||
const resp = await ExpenseRepository.GetPaymentRequestList(pageSize,pageNumber,filter,isActive,searchString);
|
const resp = await ExpenseRepository.GetPaymentRequestList(pageSize,pageNumber,filter,isActive,searchString);
|
||||||
return resp.data;
|
return resp.data;
|
||||||
@ -285,6 +285,7 @@ export const usePaymentRequestDetail =(RequestId)=>{
|
|||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey:['paymentRequest',RequestId],
|
queryKey:['paymentRequest',RequestId],
|
||||||
queryFn:async()=>{
|
queryFn:async()=>{
|
||||||
|
RequestId
|
||||||
const resp = await ExpenseRepository.GetPaymentRequest(RequestId);
|
const resp = await ExpenseRepository.GetPaymentRequest(RequestId);
|
||||||
return resp.data;
|
return resp.data;
|
||||||
},
|
},
|
||||||
@ -301,7 +302,7 @@ export const useCreatePaymentRequest = (onSuccessCallBack) => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: (_, variables) => {
|
onSuccess: (_, variables) => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["PaymentRequest"] });
|
queryClient.invalidateQueries({ queryKey: ["paymentRequestList"] });
|
||||||
showToast("Payment Created Successfully", "success");
|
showToast("Payment Created Successfully", "success");
|
||||||
if (onSuccessCallBack) onSuccessCallBack();
|
if (onSuccessCallBack) onSuccessCallBack();
|
||||||
},
|
},
|
||||||
@ -322,7 +323,7 @@ export const useUpdatePaymentRequest = (onSuccessCallBack) => {
|
|||||||
},
|
},
|
||||||
onSuccess: (updatedExpense, variables) => {
|
onSuccess: (updatedExpense, variables) => {
|
||||||
queryClient.removeQueries({ queryKey: ["paymentRequest", variables.id] });
|
queryClient.removeQueries({ queryKey: ["paymentRequest", variables.id] });
|
||||||
queryClient.invalidateQueries({ queryKey: ["paymentRequest"] });
|
queryClient.invalidateQueries({ queryKey: ["paymentRequestList"] });
|
||||||
showToast("PaymentRequest updated Successfully", "success");
|
showToast("PaymentRequest updated Successfully", "success");
|
||||||
|
|
||||||
if (onSuccessCallBack) onSuccessCallBack();
|
if (onSuccessCallBack) onSuccessCallBack();
|
||||||
@ -332,6 +333,31 @@ export const useUpdatePaymentRequest = (onSuccessCallBack) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
export const useActionOnPaymentRequest = (onSuccessCallBack) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async (payload) => {
|
||||||
|
const response = await ExpenseRepository.ActionOnPaymentRequest(payload);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
onSuccess: (updatedExpense, variables) => {
|
||||||
|
showToast("Request processed successfully.", "success");
|
||||||
|
|
||||||
|
queryClient.invalidateQueries({queryKey:["paymentRequest",updatedExpense.id]})
|
||||||
|
queryClient.invalidateQueries({queryKey:["paymentRequestList"]})
|
||||||
|
|
||||||
|
if (onSuccessCallBack) onSuccessCallBack();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
showToast(
|
||||||
|
error.response.data.message ||
|
||||||
|
"Something went wrong.Please try again later.",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
export const usePaymentRequestFilter = () => {
|
export const usePaymentRequestFilter = () => {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { useFab } from "../../Context/FabContext";
|
|||||||
import PaymentRequestList from "../../components/PaymentRequest/PaymentRequestList";
|
import PaymentRequestList from "../../components/PaymentRequest/PaymentRequestList";
|
||||||
import PaymentRequestFilterPanel from "../../components/PaymentRequest/PaymentRequestFilterPanel";
|
import PaymentRequestFilterPanel from "../../components/PaymentRequest/PaymentRequestFilterPanel";
|
||||||
import { defaultPaymentRequestFilter,SearchPaymentRequestSchema } from "../../components/PaymentRequest/PaymentRequestSchema";
|
import { defaultPaymentRequestFilter,SearchPaymentRequestSchema } from "../../components/PaymentRequest/PaymentRequestSchema";
|
||||||
|
import ViewPaymentRequest from "../../components/PaymentRequest/ViewPaymentRequest";
|
||||||
|
|
||||||
export const PaymentRequestContext = createContext();
|
export const PaymentRequestContext = createContext();
|
||||||
export const usePaymentRequestContext = () => {
|
export const usePaymentRequestContext = () => {
|
||||||
@ -29,6 +30,7 @@ const PaymentRequestPage = () => {
|
|||||||
|
|
||||||
const contextValue = {
|
const contextValue = {
|
||||||
setManageRequest,
|
setManageRequest,
|
||||||
|
setVieRequest
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -120,9 +122,9 @@ const PaymentRequestPage = () => {
|
|||||||
isOpen
|
isOpen
|
||||||
size="lg"
|
size="lg"
|
||||||
modalType="top"
|
modalType="top"
|
||||||
closeModal={() => setViewExpense({ requestId: null, view: false })}
|
closeModal={() => setVieRequest({ requestId: null, view: false })}
|
||||||
>
|
>
|
||||||
<ViewRequest ExpenseId={ViewRequest.requestId} />
|
<ViewPaymentRequest requestId={ViewRequest?.requestId}/>
|
||||||
</GlobalModel>
|
</GlobalModel>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ const ExpenseRepository = {
|
|||||||
UpdatePaymentRequest: (id, data) => api.put(`/api/Expense/payment-request/edit/${id}`, data),
|
UpdatePaymentRequest: (id, data) => api.put(`/api/Expense/payment-request/edit/${id}`, data),
|
||||||
GetPaymentRequest: (id) => api.get(`/api/Expense/get/payment-request/details/${id}`),
|
GetPaymentRequest: (id) => api.get(`/api/Expense/get/payment-request/details/${id}`),
|
||||||
GetPaymentRequestFilter: () => api.get('/api/Expense/payment-request/filter'),
|
GetPaymentRequestFilter: () => api.get('/api/Expense/payment-request/filter'),
|
||||||
|
ActionOnPaymentRequest: (data) => api.post('/api/Expense/payment-request/action', data),
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user