Merge branch 'Purchase_Invoice_Management' of https://git.marcoaiot.com/admin/marco.pms.web into Finance_Export_Functionality
This commit is contained in:
commit
06ac8099ed
@ -205,7 +205,7 @@ const TaskReportList = () => {
|
|||||||
id="total_pending_task"
|
id="total_pending_task"
|
||||||
title="Total Pending Task"
|
title="Total Pending Task"
|
||||||
content={
|
content={
|
||||||
<div className="text-wrap" style={{ maxWidth: "200px" }}>
|
<div className="text-wrap" style={{ minWidth: "200px" }}>
|
||||||
This shows the total pending tasks for each activity on that date.
|
This shows the total pending tasks for each activity on that date.
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,7 +69,7 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
id="STATUS_CHANEG"
|
id="STATUS_CHANEG"
|
||||||
Mode="click"
|
Mode="click"
|
||||||
className=""
|
className=""
|
||||||
align="right"
|
align="left"
|
||||||
content={
|
content={
|
||||||
<ChangeStatus
|
<ChangeStatus
|
||||||
statusId={data?.status?.id}
|
statusId={data?.status?.id}
|
||||||
@ -149,7 +149,8 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
<HoverPopup
|
<HoverPopup
|
||||||
id="BRANCH_DETAILS"
|
id="BRANCH_DETAILS"
|
||||||
Mode="click"
|
Mode="click"
|
||||||
align="auto"
|
align="right"
|
||||||
|
minWidth="340px"
|
||||||
boundaryRef={drawerRef}
|
boundaryRef={drawerRef}
|
||||||
content={<BranchDetails branch={data?.projectBranch?.id} />}
|
content={<BranchDetails branch={data?.projectBranch?.id} />}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -6,10 +6,6 @@ import {
|
|||||||
togglePopup,
|
togglePopup,
|
||||||
} from "../../slices/localVariablesSlice";
|
} from "../../slices/localVariablesSlice";
|
||||||
|
|
||||||
/**
|
|
||||||
* align: "auto" | "left" | "right"
|
|
||||||
* boundaryRef: optional ref to the drawer/container element to use as boundary
|
|
||||||
*/
|
|
||||||
const HoverPopup = ({
|
const HoverPopup = ({
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
@ -17,7 +13,9 @@ const HoverPopup = ({
|
|||||||
children,
|
children,
|
||||||
className = "",
|
className = "",
|
||||||
Mode = "hover",
|
Mode = "hover",
|
||||||
align = "auto",
|
align = "auto", // <-- dynamic placement
|
||||||
|
minWidth = "250px",
|
||||||
|
maxWidth = "350px",
|
||||||
boundaryRef = null,
|
boundaryRef = null,
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -26,20 +24,15 @@ const HoverPopup = ({
|
|||||||
const triggerRef = useRef(null);
|
const triggerRef = useRef(null);
|
||||||
const popupRef = useRef(null);
|
const popupRef = useRef(null);
|
||||||
|
|
||||||
const handleMouseEnter = () => {
|
const handleMouseEnter = () => Mode === "hover" && dispatch(openPopup(id));
|
||||||
if (Mode === "hover") dispatch(openPopup(id));
|
const handleMouseLeave = () => Mode === "hover" && dispatch(closePopup(id));
|
||||||
};
|
|
||||||
const handleMouseLeave = () => {
|
|
||||||
if (Mode === "hover") dispatch(closePopup(id));
|
|
||||||
};
|
|
||||||
const handleClick = (e) => {
|
const handleClick = (e) => {
|
||||||
if (Mode === "click") {
|
if (Mode !== "click") return;
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
dispatch(togglePopup(id));
|
dispatch(togglePopup(id));
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Close on outside click when using click mode
|
// Close popup when clicking outside (click mode)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Mode !== "click" || !visible) return;
|
if (Mode !== "click" || !visible) return;
|
||||||
|
|
||||||
@ -56,40 +49,68 @@ const HoverPopup = ({
|
|||||||
|
|
||||||
document.addEventListener("click", handler);
|
document.addEventListener("click", handler);
|
||||||
return () => document.removeEventListener("click", handler);
|
return () => document.removeEventListener("click", handler);
|
||||||
}, [Mode, visible, dispatch, id]);
|
}, [visible, Mode, id, dispatch]);
|
||||||
|
|
||||||
|
// ---------- DYNAMIC POSITIONING LOGIC ----------
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!visible || !popupRef.current || !triggerRef.current) return;
|
if (!visible || !popupRef.current || !triggerRef.current) return;
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const popup = popupRef.current;
|
const popup = popupRef.current;
|
||||||
const boundaryEl = (boundaryRef && boundaryRef.current) || popup.parentElement;
|
const trigger = triggerRef.current;
|
||||||
if (!boundaryEl) return;
|
|
||||||
|
const boundaryEl =
|
||||||
|
(boundaryRef && boundaryRef.current) || popup.parentElement;
|
||||||
|
|
||||||
const boundaryRect = boundaryEl.getBoundingClientRect();
|
const boundaryRect = boundaryEl.getBoundingClientRect();
|
||||||
const triggerRect = triggerRef.current.getBoundingClientRect();
|
const triggerRect = trigger.getBoundingClientRect();
|
||||||
popup.style.left = "";
|
|
||||||
popup.style.right = "";
|
|
||||||
popup.style.transform = "";
|
|
||||||
popup.style.top = "";
|
|
||||||
|
|
||||||
const popupRect = popup.getBoundingClientRect();
|
const popupRect = popup.getBoundingClientRect();
|
||||||
const triggerCenterX = triggerRect.left + triggerRect.width / 2 - boundaryRect.left;
|
|
||||||
let left = triggerCenterX - popupRect.width / 2;
|
|
||||||
|
|
||||||
// Clamp to boundaries
|
let left;
|
||||||
left = Math.max(0, Math.min(left, boundaryRect.width - popupRect.width));
|
|
||||||
|
// AUTO ALIGN (smart)
|
||||||
|
if (align === "auto") {
|
||||||
|
const center =
|
||||||
|
triggerRect.left +
|
||||||
|
triggerRect.width / 2 -
|
||||||
|
boundaryRect.left -
|
||||||
|
popupRect.width / 2;
|
||||||
|
|
||||||
|
left = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(center, boundaryRect.width - popupRect.width)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LEFT ALIGN
|
||||||
|
else if (align === "left") {
|
||||||
|
left = triggerRect.left - boundaryRect.left;
|
||||||
|
if (left + popupRect.width > boundaryRect.width) {
|
||||||
|
left = boundaryRect.width - popupRect.width; // clamp right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RIGHT ALIGN
|
||||||
|
else if (align === "right") {
|
||||||
|
left =
|
||||||
|
triggerRect.left +
|
||||||
|
triggerRect.width -
|
||||||
|
boundaryRect.left -
|
||||||
|
popupRect.width;
|
||||||
|
|
||||||
|
if (left < 0) left = 0; // clamp left
|
||||||
|
}
|
||||||
|
|
||||||
popup.style.left = `${left}px`;
|
popup.style.left = `${left}px`;
|
||||||
|
popup.style.top = `100%`;
|
||||||
});
|
});
|
||||||
}, [visible, align, boundaryRef]);
|
}, [visible, align, boundaryRef]);
|
||||||
|
|
||||||
return (
|
// ------------------------------------------------
|
||||||
<div
|
|
||||||
className="d-inline-block position-relative" // <-- ADD THIS !!
|
|
||||||
style={{ overflow: "visible" }}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="d-inline-block position-relative" style={{ overflow: "visible" }}>
|
||||||
|
<div
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
@ -105,20 +126,18 @@ const HoverPopup = ({
|
|||||||
className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
|
className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
|
||||||
style={{
|
style={{
|
||||||
zIndex: 2000,
|
zIndex: 2000,
|
||||||
top: "100%",
|
minWidth,
|
||||||
minWidth: "200px",
|
maxWidth,
|
||||||
maxWidth: "300px",
|
|
||||||
wordWrap: "break-word",
|
wordWrap: "break-word",
|
||||||
}}
|
}}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
|
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
|
||||||
<div>{content}</div>
|
{content}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HoverPopup;
|
export default HoverPopup;
|
||||||
|
|||||||
@ -28,21 +28,21 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
|||||||
const stepsConfig = useMemo(
|
const stepsConfig = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
name: "Party Details",
|
name: "Vendor & Project Details",
|
||||||
icon: "bx bx-user bx-md",
|
icon: "bx bx-user bx-md",
|
||||||
subtitle: "Supplier & project information",
|
subtitle: "Vendor information and project association",
|
||||||
component: <PurchasePartyDetails purchase={data} />,
|
component: <PurchasePartyDetails purchase={data} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invoice & Transport",
|
name: "Invoice & Logistics",
|
||||||
icon: "bx bx-receipt bx-md",
|
icon: "bx bx-receipt bx-md",
|
||||||
subtitle: "Invoice, eWay bill & transport info",
|
subtitle: "Invoice, e-Way bill, and logistics information",
|
||||||
component: <PurchaseTransportDetails />,
|
component: <PurchaseTransportDetails />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Payment Details",
|
name: "Invoice & Tax Amount",
|
||||||
icon: "bx bx-credit-card bx-md",
|
icon: "bx bx-credit-card bx-md",
|
||||||
subtitle: "Amount, tax & due date",
|
subtitle: "Payment terms, tax breakdown, and due dates",
|
||||||
component: <PurchasePaymentDetails purchaseId={purchaseId} />,
|
component: <PurchasePaymentDetails purchaseId={purchaseId} />,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -127,8 +127,6 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
|||||||
|
|
||||||
const onSubmit = useCallback(
|
const onSubmit = useCallback(
|
||||||
(formData) => {
|
(formData) => {
|
||||||
if (activeTab !== 2) return;
|
|
||||||
|
|
||||||
if (purchaseId) {
|
if (purchaseId) {
|
||||||
const payload = generatePatchOps(formData);
|
const payload = generatePatchOps(formData);
|
||||||
updatePurchase({ purchaseId, payload });
|
updatePurchase({ purchaseId, payload });
|
||||||
@ -136,7 +134,7 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
|||||||
CreateInvoice(formData);
|
CreateInvoice(formData);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[activeTab, purchaseId, generatePatchOps, updatePurchase, CreateInvoice]
|
[purchaseId, generatePatchOps, updatePurchase, CreateInvoice]
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<div className="bs-stepper horizontically mt-2 b-secondry shadow-none border-0">
|
<div className="bs-stepper horizontically mt-2 b-secondry shadow-none border-0">
|
||||||
@ -184,18 +182,10 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
|||||||
{/* --- Form Content --- */}
|
{/* --- Form Content --- */}
|
||||||
<div className="bs-stepper-content py-2 px-3">
|
<div className="bs-stepper-content py-2 px-3">
|
||||||
<AppFormProvider {...purchaseOrder}>
|
<AppFormProvider {...purchaseOrder}>
|
||||||
<form
|
{activeTab !== 2 && (
|
||||||
onSubmitCapture={(e) => {
|
<div>
|
||||||
if (activeTab !== 2) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onSubmit={purchaseOrder.handleSubmit(onSubmit)}
|
|
||||||
>
|
|
||||||
{stepsConfig[activeTab].component}
|
{stepsConfig[activeTab].component}
|
||||||
|
|
||||||
{/* Buttons */}
|
|
||||||
<div className="d-flex justify-content-between mt-4">
|
<div className="d-flex justify-content-between mt-4">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -206,28 +196,39 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
|
|||||||
Previous
|
Previous
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div>
|
|
||||||
{activeTab < stepsConfig.length - 1 ? (
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
onClick={handleNext}
|
onClick={handleNext}
|
||||||
disabled={isPending || isUpdating}
|
|
||||||
>
|
>
|
||||||
Next
|
Next
|
||||||
</button>
|
</button>
|
||||||
) : (
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{activeTab === 2 && (
|
||||||
|
<form onSubmit={purchaseOrder.handleSubmit(onSubmit)}>
|
||||||
|
{stepsConfig[2].component}
|
||||||
|
|
||||||
|
<div className="d-flex justify-content-between mt-4">
|
||||||
<button
|
<button
|
||||||
type={activeTab == 2 ? "submit" : "button"}
|
type="button"
|
||||||
|
className="btn btn-sm btn-outline-secondary"
|
||||||
|
onClick={handlePrev}
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
disabled={isPending || isUpdating}
|
disabled={isPending || isUpdating}
|
||||||
>
|
>
|
||||||
{isPending || isUpdating ? "Please Wait" : "Submit"}
|
{isPending || isUpdating ? "Please Wait" : "Submit"}
|
||||||
</button>
|
</button>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
)}
|
||||||
</AppFormProvider>
|
</AppFormProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
102
src/components/purchase/PurchaseActions.jsx
Normal file
102
src/components/purchase/PurchaseActions.jsx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
export const getPurchaseActions = ({
|
||||||
|
item,
|
||||||
|
isActive,
|
||||||
|
canDelete,
|
||||||
|
canAddChallan,
|
||||||
|
setViewPurchase,
|
||||||
|
setManagePurchase,
|
||||||
|
setDeletingId,
|
||||||
|
setIsDeleteModalOpen,
|
||||||
|
setChallan,
|
||||||
|
setAddPayment,
|
||||||
|
}) => {
|
||||||
|
const actions = [];
|
||||||
|
|
||||||
|
// VIEW
|
||||||
|
actions.push({
|
||||||
|
key: "view",
|
||||||
|
label: "View",
|
||||||
|
icon: "bx bx-show",
|
||||||
|
show: true,
|
||||||
|
onClick: () =>
|
||||||
|
setViewPurchase({
|
||||||
|
isOpen: true,
|
||||||
|
purchaseId: item.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
// EDIT
|
||||||
|
actions.push({
|
||||||
|
key: "edit",
|
||||||
|
label: "Edit",
|
||||||
|
icon: "bx bx-edit",
|
||||||
|
show: true,
|
||||||
|
onClick: () =>
|
||||||
|
setManagePurchase({
|
||||||
|
isOpen: true,
|
||||||
|
purchaseId: item.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// DELETE
|
||||||
|
actions.push({
|
||||||
|
key: "delete",
|
||||||
|
label: "Delete",
|
||||||
|
icon: "bx bx-trash",
|
||||||
|
show: canDelete,
|
||||||
|
onClick: () => {
|
||||||
|
setDeletingId(item.id);
|
||||||
|
setIsDeleteModalOpen(true);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// ADD CHALLAN
|
||||||
|
actions.push({
|
||||||
|
key: "challan",
|
||||||
|
label: "Add Delivery Challan",
|
||||||
|
icon: "bx bx-file bx-plus",
|
||||||
|
show: canAddChallan,
|
||||||
|
onClick: () =>
|
||||||
|
setChallan({
|
||||||
|
isOpen: true,
|
||||||
|
purchaseId: item.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// ADD PAYMENT
|
||||||
|
actions.push({
|
||||||
|
key: "payment",
|
||||||
|
label: "Add Payment",
|
||||||
|
icon: "bx bx-wallet",
|
||||||
|
show: true,
|
||||||
|
onClick: () =>
|
||||||
|
setAddPayment({
|
||||||
|
isOpen: true,
|
||||||
|
purchaseId: item.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// RESTORE
|
||||||
|
actions.push({
|
||||||
|
key: "restore",
|
||||||
|
label: "Restore",
|
||||||
|
icon: "bx bx-undo",
|
||||||
|
show: true,
|
||||||
|
onClick: () => {
|
||||||
|
setDeletingId(item.id);
|
||||||
|
setIsDeleteModalOpen(true);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions.filter((a) => a.show);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DropdownItem = ({ icon, label, onClick }) => (
|
||||||
|
<li>
|
||||||
|
<a className="dropdown-item cursor-pointer" onClick={onClick}>
|
||||||
|
<i className={`${icon} me-2`}></i> {label}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
@ -1,21 +1,40 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { usePurchasesList } from "../../hooks/usePurchase";
|
import {
|
||||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
useDeletePurchaseInvoice,
|
||||||
|
usePurchasesList,
|
||||||
|
} from "../../hooks/usePurchase";
|
||||||
|
import {
|
||||||
|
ADD_DELIVERY_CHALLAN,
|
||||||
|
DELETEPURCHASE_INVOICE,
|
||||||
|
ITEMS_PER_PAGE,
|
||||||
|
} from "../../utils/constants";
|
||||||
import Pagination from "../common/Pagination";
|
import Pagination from "../common/Pagination";
|
||||||
import { PurchaseColumn } from "./Purchasetable";
|
import { PurchaseColumn } from "./Purchasetable";
|
||||||
import { SpinnerLoader } from "../common/Loader";
|
import { SpinnerLoader } from "../common/Loader";
|
||||||
import { useDebounce } from "../../utils/appUtils";
|
import { useDebounce } from "../../utils/appUtils";
|
||||||
import { usePurchaseContext } from "../../pages/purchase/PurchasePage";
|
import { usePurchaseContext } from "../../pages/purchase/PurchasePage";
|
||||||
|
import ConfirmModal from "../common/ConfirmModal";
|
||||||
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||||
|
import { DropdownItem, getPurchaseActions } from "./PurchaseActions";
|
||||||
|
|
||||||
const PurchaseList = ({ searchString }) => {
|
const PurchaseList = ({ searchString, isActive }) => {
|
||||||
const { setViewPurchase, setManagePurchase, setChallan } =
|
const { setViewPurchase, setManagePurchase, setChallan, setAddPayment } =
|
||||||
usePurchaseContext();
|
usePurchaseContext();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const { mutate: DeletePurchaseInvoice, isPending } =
|
||||||
|
useDeletePurchaseInvoice();
|
||||||
|
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
|
const [deletingId, setDeletingId] = useState(null);
|
||||||
|
|
||||||
|
const canAddChallan = useHasUserPermission(ADD_DELIVERY_CHALLAN);
|
||||||
|
const canDelete = useHasUserPermission(DELETEPURCHASE_INVOICE);
|
||||||
|
|
||||||
const debounceSearch = useDebounce(searchString, 300);
|
const debounceSearch = useDebounce(searchString, 300);
|
||||||
const { data, isLoading } = usePurchasesList(
|
const { data, isLoading } = usePurchasesList(
|
||||||
ITEMS_PER_PAGE,
|
ITEMS_PER_PAGE,
|
||||||
currentPage,
|
currentPage,
|
||||||
true,
|
// true,
|
||||||
|
!isActive,
|
||||||
{},
|
{},
|
||||||
debounceSearch
|
debounceSearch
|
||||||
);
|
);
|
||||||
@ -28,9 +47,38 @@ const PurchaseList = ({ searchString }) => {
|
|||||||
|
|
||||||
const visibleColumns = PurchaseColumn.filter((col) => !col.hidden);
|
const visibleColumns = PurchaseColumn.filter((col) => !col.hidden);
|
||||||
|
|
||||||
|
const handleDeleteRestore = (id) => {
|
||||||
|
DeletePurchaseInvoice(
|
||||||
|
{ id, isActive: isActive }, // delete if active, restore if deleted
|
||||||
|
{
|
||||||
|
onSettled: () => {
|
||||||
|
setDeletingId(null);
|
||||||
|
setIsDeleteModalOpen(false);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card mt-2 page-min-h px-sm-4">
|
<>
|
||||||
<div className="table-responsive px-2">
|
{IsDeleteModalOpen && (
|
||||||
|
<ConfirmModal
|
||||||
|
isOpen={IsDeleteModalOpen}
|
||||||
|
type={!isActive ? "delete" : "undo"}
|
||||||
|
header={!isActive ? "Delete Invoice" : "Restore Invoice"}
|
||||||
|
message={
|
||||||
|
!isActive
|
||||||
|
? "Are you sure you want to delete?"
|
||||||
|
: "Are you sure you want to restore?"
|
||||||
|
}
|
||||||
|
onSubmit={handleDeleteRestore}
|
||||||
|
onClose={() => setIsDeleteModalOpen(false)}
|
||||||
|
loading={isPending}
|
||||||
|
paramData={deletingId}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className="card mt-2 page-min-h table-responsive px-sm-4">
|
||||||
|
<div className="px-2">
|
||||||
<table className="datatables-users table border-top text-nowrap">
|
<table className="datatables-users table border-top text-nowrap">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -47,18 +95,24 @@ const PurchaseList = ({ searchString }) => {
|
|||||||
{/* LOADING */}
|
{/* LOADING */}
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={visibleColumns.length + 1} className="border-0">
|
<td
|
||||||
<div className="py-6 py-12">
|
colSpan={visibleColumns.length + 1}
|
||||||
|
className="border-0"
|
||||||
|
style={{ height: "300px", verticalAlign: "middle" }}
|
||||||
|
>
|
||||||
|
<div className="d-flex justify-content-center align-items-center w-100 h-100">
|
||||||
<SpinnerLoader />
|
<SpinnerLoader />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isLoading && data?.data?.length === 0 && (
|
{!isLoading && data?.data?.length === 0 && (
|
||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
colSpan={visibleColumns.length}
|
colSpan={visibleColumns.length + 1}
|
||||||
className="text-center py-4 border-0"
|
className="text-center border-0"
|
||||||
|
style={{ height: "400px", verticalAlign: "middle" }}
|
||||||
>
|
>
|
||||||
No Data Found
|
No Data Found
|
||||||
</td>
|
</td>
|
||||||
@ -73,7 +127,7 @@ const PurchaseList = ({ searchString }) => {
|
|||||||
{col.render ? col.render(item) : item[col.key] || "NA"}
|
{col.render ? col.render(item) : item[col.key] || "NA"}
|
||||||
</td>
|
</td>
|
||||||
))}
|
))}
|
||||||
<td >
|
<td>
|
||||||
<div className="dropdown z-2">
|
<div className="dropdown z-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -91,49 +145,25 @@ const PurchaseList = ({ searchString }) => {
|
|||||||
></i>
|
></i>
|
||||||
</button>
|
</button>
|
||||||
<ul className="dropdown-menu dropdown-menu-end">
|
<ul className="dropdown-menu dropdown-menu-end">
|
||||||
<li>
|
{getPurchaseActions({
|
||||||
<a
|
item,
|
||||||
className="dropdown-item cursor-pointer"
|
isActive,
|
||||||
onClick={() =>
|
canDelete,
|
||||||
setViewPurchase({
|
canAddChallan,
|
||||||
isOpen: true,
|
setViewPurchase,
|
||||||
purchaseId: item.id,
|
setManagePurchase,
|
||||||
})
|
setDeletingId,
|
||||||
}
|
setIsDeleteModalOpen,
|
||||||
>
|
setChallan,
|
||||||
<i className="bx bx-show me-2"></i>
|
setAddPayment,
|
||||||
<span className="align-left">view</span>
|
}).map((action) => (
|
||||||
</a>
|
<DropdownItem
|
||||||
</li>
|
key={action.key}
|
||||||
<li>
|
icon={action.icon}
|
||||||
<a
|
label={action.label}
|
||||||
className="dropdown-item cursor-pointer"
|
onClick={action.onClick}
|
||||||
onClick={() =>
|
/>
|
||||||
setManagePurchase({
|
))}
|
||||||
isOpen: true,
|
|
||||||
purchaseId: item.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i className="bx bx-edit me-2"></i>
|
|
||||||
<span className="align-left">Edit</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
className="dropdown-item cursor-pointer"
|
|
||||||
onClick={() =>
|
|
||||||
setChallan({
|
|
||||||
isOpen: true,
|
|
||||||
purchaseId: item.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i className="bx bx-file bx-plus me-2"></i>
|
|
||||||
|
|
||||||
<span className="align-left">Add Delivery Challan</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -151,6 +181,7 @@ const PurchaseList = ({ searchString }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -36,9 +36,7 @@ const PurchasePartyDetails = () => {
|
|||||||
<input
|
<input
|
||||||
id="title"
|
id="title"
|
||||||
type="text"
|
type="text"
|
||||||
className={`form-control form-control-xs ${
|
className={`form-control form-control-xs `}
|
||||||
errors?.title ? "is-invalid" : ""
|
|
||||||
}`}
|
|
||||||
{...register("title")}
|
{...register("title")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -73,15 +71,16 @@ const PurchasePartyDetails = () => {
|
|||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<SelectFieldSearch
|
<SelectFieldSearch
|
||||||
{...field}
|
|
||||||
label="Organization"
|
label="Organization"
|
||||||
placeholder="Select Organization"
|
placeholder="Select Organization"
|
||||||
required
|
required
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
valueKey="id"
|
valueKey="id"
|
||||||
labelKey="name"
|
labelKey="name"
|
||||||
useFetchHook={useGlobaleOrganizations}
|
useFetchHook={useGlobaleOrganizations}
|
||||||
hookParams={[ITEMS_PER_PAGE, 1]}
|
hookParams={[ITEMS_PER_PAGE, 1]}
|
||||||
error={errors?.organizationId?.message}
|
errors={errors?.organizationId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -109,7 +108,7 @@ const PurchasePartyDetails = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-md-6 my-0">
|
<div className="col-12 col-md-6 my-0">
|
||||||
<Label htmlFor="billingAddress">Billing Address</Label>
|
<Label required htmlFor="billingAddress">Billing Address</Label>
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
id="billingAddress"
|
id="billingAddress"
|
||||||
@ -124,7 +123,7 @@ const PurchasePartyDetails = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-md-6 my-0 mb-1">
|
<div className="col-12 col-md-6 my-0 mb-1">
|
||||||
<Label htmlFor="shippingAddress">Shipping Address</Label>
|
<Label required htmlFor="shippingAddress">Shipping Address</Label>
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
id="shippingAddress"
|
id="shippingAddress"
|
||||||
@ -140,7 +139,7 @@ const PurchasePartyDetails = () => {
|
|||||||
|
|
||||||
{/* Purchase Order Number */}
|
{/* Purchase Order Number */}
|
||||||
<div className="col-12 col-md-6 ">
|
<div className="col-12 col-md-6 ">
|
||||||
<Label htmlFor="purchaseOrderNumber" required>
|
<Label htmlFor="purchaseOrderNumber" >
|
||||||
Purchase Order Number
|
Purchase Order Number
|
||||||
</Label>
|
</Label>
|
||||||
|
|
||||||
@ -160,7 +159,7 @@ const PurchasePartyDetails = () => {
|
|||||||
|
|
||||||
{/* Purchase Order Date */}
|
{/* Purchase Order Date */}
|
||||||
<div className="col-12 col-md-6 mb-1">
|
<div className="col-12 col-md-6 mb-1">
|
||||||
<Label htmlFor="purchaseOrderDate" required>
|
<Label htmlFor="purchaseOrderDate" >
|
||||||
Purchase Order Date
|
Purchase Order Date
|
||||||
</Label>
|
</Label>
|
||||||
|
|
||||||
|
|||||||
298
src/components/purchase/PurchasePayment.jsx
Normal file
298
src/components/purchase/PurchasePayment.jsx
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
AppFormController,
|
||||||
|
AppFormProvider,
|
||||||
|
useAppForm,
|
||||||
|
} from "../../hooks/appHooks/useAppForm";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { AddPurchasePayment, defaultPurchasePayment } from "./PurchaseSchema";
|
||||||
|
import { usePaymentAjustmentHead } from "../../hooks/masterHook/useMaster";
|
||||||
|
import { formatFigure, localToUtc } from "../../utils/appUtils";
|
||||||
|
import Label from "../common/Label";
|
||||||
|
import DatePicker from "../common/DatePicker";
|
||||||
|
import {
|
||||||
|
useAddPurchasePayment,
|
||||||
|
usePurchase,
|
||||||
|
usePurchasePaymentHistory,
|
||||||
|
} from "../../hooks/usePurchase";
|
||||||
|
import SelectField from "../common/Forms/SelectField";
|
||||||
|
import { SpinnerLoader } from "../common/Loader";
|
||||||
|
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
||||||
|
import Avatar from "../common/Avatar";
|
||||||
|
|
||||||
|
const PurchasePayment = ({onClose, purchaseId }) => {
|
||||||
|
const {
|
||||||
|
data: Purchase,
|
||||||
|
isLoading: isPurchaseLoading,
|
||||||
|
error: purchaseError,
|
||||||
|
} = usePurchase(purchaseId);
|
||||||
|
const methods = useAppForm({
|
||||||
|
resolver: zodResolver(AddPurchasePayment),
|
||||||
|
defaultValues: defaultPurchasePayment,
|
||||||
|
});
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = methods;
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: paymentTypes,
|
||||||
|
isLoading: isPaymentTypeLoading,
|
||||||
|
isError: isPaymentTypeError,
|
||||||
|
error: paymentError,
|
||||||
|
} = usePaymentAjustmentHead(true);
|
||||||
|
|
||||||
|
const { mutate: AddPayment, isPending } = useAddPurchasePayment(() => {
|
||||||
|
handleClose();
|
||||||
|
});
|
||||||
|
const { data, isLoading, isError, error } =
|
||||||
|
usePurchasePaymentHistory(purchaseId);
|
||||||
|
const onSubmit = (formData) => {
|
||||||
|
const payload = {
|
||||||
|
...formData,
|
||||||
|
paymentReceivedDate: localToUtc(formData.paymentReceivedDate),
|
||||||
|
invoiceId: purchaseId,
|
||||||
|
};
|
||||||
|
AddPayment(payload);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = (formData) => {
|
||||||
|
reset(defaultPurchasePayment);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="contianer p-1">
|
||||||
|
<div className="text-center">
|
||||||
|
<p className="fs-5 text-semibod">Supplier / Vendor Transaction </p>
|
||||||
|
</div>
|
||||||
|
<div className="row g-3">
|
||||||
|
<div className="col-12 col-sm-6 px-2 p-sm-0">
|
||||||
|
<AppFormProvider {...methods}>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)} className="p-0 text-start">
|
||||||
|
<div className="row px-md-1 px-0">
|
||||||
|
<div className="col-12 col-md-6 mb-2">
|
||||||
|
<Label required>TransanctionId</Label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control form-control-md"
|
||||||
|
{...register("transactionId")}
|
||||||
|
/>
|
||||||
|
{errors.transactionId && (
|
||||||
|
<small className="danger-text">
|
||||||
|
{errors.transactionId.message}
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-md-6 mb-2">
|
||||||
|
<Label required>Transaction Date </Label>
|
||||||
|
<DatePicker
|
||||||
|
className="w-100"
|
||||||
|
size="md"
|
||||||
|
name="paymentReceivedDate"
|
||||||
|
control={control}
|
||||||
|
minDate={
|
||||||
|
Purchase?.createdAt
|
||||||
|
? new Date(
|
||||||
|
new Date(Purchase?.createdAt).setDate(
|
||||||
|
new Date(Purchase?.createdAt).getDate() + 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
maxDate={new Date()}
|
||||||
|
/>
|
||||||
|
{errors.paymentReceivedDate && (
|
||||||
|
<small className="danger-text">
|
||||||
|
{errors.paymentReceivedDate.message}
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-md-6 mb-2">
|
||||||
|
<AppFormController
|
||||||
|
name="paymentAdjustmentHeadId"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<SelectField
|
||||||
|
label="Payment Adjustment Head"
|
||||||
|
options={paymentTypes?.data ?? []}
|
||||||
|
placeholder="Choose a Status"
|
||||||
|
required
|
||||||
|
labelKeyKey="name"
|
||||||
|
valueKeyKey="id"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
isLoading={isPaymentTypeLoading}
|
||||||
|
className="m-0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.paymentAdjustmentHeadId && (
|
||||||
|
<small className="danger-text">
|
||||||
|
{errors.paymentAdjustmentHeadId.message}
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-md-6 mb-2">
|
||||||
|
<Label htmlFor="amount" className="form-label" required>
|
||||||
|
Amount
|
||||||
|
</Label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
id="amount"
|
||||||
|
className="form-control form-control-md"
|
||||||
|
min="1"
|
||||||
|
step="0.01"
|
||||||
|
inputMode="decimal"
|
||||||
|
{...register("amount", { valueAsNumber: true })}
|
||||||
|
/>
|
||||||
|
{errors.amount && (
|
||||||
|
<small className="danger-text">
|
||||||
|
{errors.amount.message}
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="col-12 mb-2">
|
||||||
|
<Label htmlFor="comment" className="form-label" required>
|
||||||
|
Comment
|
||||||
|
</Label>
|
||||||
|
<textarea
|
||||||
|
id="comment"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("comment")}
|
||||||
|
/>
|
||||||
|
{errors.comment && (
|
||||||
|
<small className="danger-text">
|
||||||
|
{errors.comment.message}
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="d-flex justify-content-end gap-3">
|
||||||
|
{" "}
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
className="btn btn-label-secondary btn-sm mt-3"
|
||||||
|
onClick={() => {
|
||||||
|
handleClose();
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
disabled={isPending}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-primary btn-sm mt-3"
|
||||||
|
disabled={isPending}
|
||||||
|
>
|
||||||
|
{isPending ? "Please Wait..." : "Submit"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</AppFormProvider>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-sm-6 px-2 p-sm-0">
|
||||||
|
<div className="d-flex flex-row gap-2 text-start">
|
||||||
|
<i className="bx bx-history"></i> <p>Purchase Payment Log</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<SpinnerLoader />
|
||||||
|
) : (
|
||||||
|
data?.length > 0 && (
|
||||||
|
<div
|
||||||
|
className="row text-start mx-2"
|
||||||
|
style={{ maxHeight: "70vh", overflowY: "auto" }}
|
||||||
|
>
|
||||||
|
{data
|
||||||
|
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
|
||||||
|
.map((payment, index) => (
|
||||||
|
<div className="col-12 mb-2" key={payment.id}>
|
||||||
|
<div className=" p-2 border-start border-warning">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12 col-md-6 d-flex justify-content-between align-items-center ">
|
||||||
|
<div>
|
||||||
|
<small className="fw-semibold me-1">
|
||||||
|
Transaction Date:
|
||||||
|
</small>{" "}
|
||||||
|
{formatUTCToLocalTime(
|
||||||
|
payment.paymentReceivedDate
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<span className="fs-semibold d-block d-md-none">
|
||||||
|
{formatFigure(payment.amount, {
|
||||||
|
type: "currency",
|
||||||
|
currency: "INR",
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-md-6 mb-0 d-flex align-items-center m-0">
|
||||||
|
<small className="fw-semibold me-2">
|
||||||
|
Updated By:
|
||||||
|
</small>{" "}
|
||||||
|
<Avatar
|
||||||
|
size="xs"
|
||||||
|
firstName={payment?.createdBy?.firstName}
|
||||||
|
lastName={payment?.createdBy?.lastName}
|
||||||
|
/>{" "}
|
||||||
|
{payment?.createdBy?.firstName}{" "}
|
||||||
|
{payment.createdBy?.lastName}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12 col-md-6">
|
||||||
|
<p className="mb-1">
|
||||||
|
<small className="fw-semibold">
|
||||||
|
Transaction ID:
|
||||||
|
</small>{" "}
|
||||||
|
{payment.transactionId}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="col-12 ">
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
|
<span>
|
||||||
|
{payment?.paymentAdjustmentHead?.name}
|
||||||
|
</span>
|
||||||
|
<span className="fs-semibold d-none d-md-block">
|
||||||
|
{formatFigure(payment.amount, {
|
||||||
|
type: "currency",
|
||||||
|
currency: "INR",
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-tiny m-0 mt-1">
|
||||||
|
{payment?.comment}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
{data?.length === 0 && (
|
||||||
|
<div className="d-flex justify-content-center algin-items-center text-center">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<i className='bx bx-box'></i>
|
||||||
|
<p className="text-secondary">You don't have any payment yet.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PurchasePayment;
|
||||||
@ -26,15 +26,16 @@ const PurchasePaymentDetails = ({ purchaseId = null }) => {
|
|||||||
|
|
||||||
const baseAmount = watch("baseAmount");
|
const baseAmount = watch("baseAmount");
|
||||||
const taxAmount = watch("taxAmount");
|
const taxAmount = watch("taxAmount");
|
||||||
|
const trCharge = watch("transportCharges");
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const base = parseFloat(baseAmount) || 0;
|
const base = parseFloat(baseAmount) || 0;
|
||||||
const tax = parseFloat(taxAmount) || 0;
|
const tax = parseFloat(taxAmount) || 0;
|
||||||
|
const transportCharges = parseFloat(trCharge) || 0;
|
||||||
|
|
||||||
if (base || tax) {
|
if (base || tax || transportCharges) {
|
||||||
setValue("totalAmount", (base + tax).toFixed(2));
|
setValue("totalAmount", (base + tax + transportCharges).toFixed(2));
|
||||||
}
|
}
|
||||||
}, [baseAmount, taxAmount, setValue]);
|
}, [baseAmount, taxAmount, trCharge, setValue]);
|
||||||
const invoiceAttachmentType = watch("invoiceAttachmentTypeId");
|
const invoiceAttachmentType = watch("invoiceAttachmentTypeId");
|
||||||
const files = watch("attachments");
|
const files = watch("attachments");
|
||||||
const toBase64 = (file) =>
|
const toBase64 = (file) =>
|
||||||
@ -108,9 +109,7 @@ const PurchasePaymentDetails = ({ purchaseId = null }) => {
|
|||||||
return (
|
return (
|
||||||
<div className="row g-1 text-start">
|
<div className="row g-1 text-start">
|
||||||
<div className="col-12 col-md-4">
|
<div className="col-12 col-md-4">
|
||||||
<Label htmlFor="baseAmount" required>
|
<Label htmlFor="baseAmount">Base Amount</Label>
|
||||||
Base Amount
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="baseAmount"
|
id="baseAmount"
|
||||||
@ -127,9 +126,7 @@ const PurchasePaymentDetails = ({ purchaseId = null }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-md-4">
|
<div className="col-12 col-md-4">
|
||||||
<Label htmlFor="taxAmount" required>
|
<Label htmlFor="taxAmount">Tax Amount</Label>
|
||||||
Tax Amount
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="taxAmount"
|
id="taxAmount"
|
||||||
@ -144,28 +141,7 @@ const PurchasePaymentDetails = ({ purchaseId = null }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-md-4">
|
<div className="col-12 col-md-4">
|
||||||
<Label htmlFor="totalAmount" required>
|
|
||||||
Total Amount
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<input
|
|
||||||
id="totalAmount"
|
|
||||||
type="number"
|
|
||||||
className="form-control form-control-xs"
|
|
||||||
{...register("totalAmount", { valueAsNumber: true })}
|
|
||||||
readOnly
|
|
||||||
/>
|
|
||||||
|
|
||||||
{errors?.totalAmount && (
|
|
||||||
<div className="small danger-text mt-1">
|
|
||||||
{errors.totalAmount.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-12 col-md-6">
|
|
||||||
<Label htmlFor="transportCharges">Transport Charges</Label>
|
<Label htmlFor="transportCharges">Transport Charges</Label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
@ -182,6 +158,23 @@ const PurchasePaymentDetails = ({ purchaseId = null }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 col-md-6">
|
||||||
|
<Label htmlFor="totalAmount">Total Amount</Label>
|
||||||
|
|
||||||
|
<input
|
||||||
|
id="totalAmount"
|
||||||
|
type="number"
|
||||||
|
className="form-control form-control-xs"
|
||||||
|
{...register("totalAmount", { valueAsNumber: true })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{errors?.totalAmount && (
|
||||||
|
<div className="small danger-text mt-1">
|
||||||
|
{errors.totalAmount.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-md-6">
|
<div className="col-12 col-md-6">
|
||||||
<Label htmlFor="paymentDueDate">Payment Due Date</Label>
|
<Label htmlFor="paymentDueDate">Payment Due Date</Label>
|
||||||
|
|
||||||
@ -200,9 +193,7 @@ const PurchasePaymentDetails = ({ purchaseId = null }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 mb-2">
|
<div className="col-12 mb-2">
|
||||||
<Label htmlFor="description" required>
|
<Label htmlFor="description">Description</Label>
|
||||||
Description
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
id="description"
|
id="description"
|
||||||
|
|||||||
@ -13,9 +13,7 @@ export const AttachmentSchema = z.object({
|
|||||||
invoiceAttachmentTypeId: z.string().nullable(),
|
invoiceAttachmentTypeId: z.string().nullable(),
|
||||||
fileName: z.string().min(1, { message: "Filename is required" }),
|
fileName: z.string().min(1, { message: "Filename is required" }),
|
||||||
base64Data: z.string().nullable(),
|
base64Data: z.string().nullable(),
|
||||||
contentType: z
|
contentType: z.string().refine((val) => ALLOWED_TYPES.includes(val), {
|
||||||
.string()
|
|
||||||
.refine((val) => ALLOWED_TYPES.includes(val), {
|
|
||||||
message: "Only PDF, PNG, JPG, or JPEG files are allowed",
|
message: "Only PDF, PNG, JPG, or JPEG files are allowed",
|
||||||
}),
|
}),
|
||||||
fileSize: z.number().max(MAX_FILE_SIZE, {
|
fileSize: z.number().max(MAX_FILE_SIZE, {
|
||||||
@ -23,10 +21,9 @@ export const AttachmentSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
description: z.string().optional().default(""),
|
description: z.string().optional().default(""),
|
||||||
isActive: z.boolean().default(true),
|
isActive: z.boolean().default(true),
|
||||||
documentId:z.string().nullable().default(null)
|
documentId: z.string().nullable().default(null),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export const PurchaseSchema = z.object({
|
export const PurchaseSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Title is required" }),
|
title: z.string().min(1, { message: "Title is required" }),
|
||||||
projectId: z.string().min(1, { message: "Project is required" }),
|
projectId: z.string().min(1, { message: "Project is required" }),
|
||||||
@ -51,20 +48,29 @@ export const PurchaseSchema = z.object({
|
|||||||
acknowledgmentDate: z.coerce.date().nullable(),
|
acknowledgmentDate: z.coerce.date().nullable(),
|
||||||
acknowledgmentNumber: z.string().nullable(),
|
acknowledgmentNumber: z.string().nullable(),
|
||||||
|
|
||||||
baseAmount: z.number().min(1, { message: "Base amount is required" }),
|
baseAmount: z
|
||||||
taxAmount: z.number().min(1, { message: "Tax amount is required" }),
|
.number()
|
||||||
totalAmount: z.number().min(1, { message: "Total amount is required" }),
|
.or(z.nan()) // allow NaN
|
||||||
|
.transform((val) => (Number.isNaN(val) ? null : val)),
|
||||||
|
|
||||||
|
taxAmount: z
|
||||||
|
.number()
|
||||||
|
.or(z.nan()) // allow NaN
|
||||||
|
.transform((val) => (Number.isNaN(val) ? null : val)),
|
||||||
|
totalAmount: z
|
||||||
|
.number()
|
||||||
|
.or(z.nan()) // allow NaN
|
||||||
|
.transform((val) => (Number.isNaN(val) ? null : val)),
|
||||||
paymentDueDate: z.coerce.date().nullable(),
|
paymentDueDate: z.coerce.date().nullable(),
|
||||||
transportCharges: z.number().nullable(),
|
transportCharges: z
|
||||||
description: z.string().min(1, { message: "Description is required" }),
|
.number()
|
||||||
invoiceAttachmentTypeId:z.string().nullable(),
|
.or(z.nan()) // allow NaN
|
||||||
attachments: z
|
.transform((val) => (Number.isNaN(val) ? null : val)),
|
||||||
.array(AttachmentSchema)
|
description: z.string(),
|
||||||
|
invoiceAttachmentTypeId: z.string().nullable(),
|
||||||
|
attachments: z.array(AttachmentSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export const defaultPurchaseValue = {
|
export const defaultPurchaseValue = {
|
||||||
title: "",
|
title: "",
|
||||||
projectId: "",
|
projectId: "",
|
||||||
@ -92,9 +98,9 @@ export const defaultPurchaseValue = {
|
|||||||
taxAmount: 0,
|
taxAmount: 0,
|
||||||
totalAmount: 0,
|
totalAmount: 0,
|
||||||
paymentDueDate: null,
|
paymentDueDate: null,
|
||||||
transportCharges: null,
|
transportCharges: 0,
|
||||||
description: "",
|
description: "",
|
||||||
invoiceAttachmentTypeId:null,
|
invoiceAttachmentTypeId: null,
|
||||||
attachments: [],
|
attachments: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -130,7 +136,7 @@ export const getStepFields = (stepIndex) => {
|
|||||||
"paymentDueDate",
|
"paymentDueDate",
|
||||||
"invoiceAttachmentTypeId",
|
"invoiceAttachmentTypeId",
|
||||||
"description",
|
"description",
|
||||||
"attachments"
|
"attachments",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -172,12 +178,11 @@ export const DeliveryChallanSchema = z.object({
|
|||||||
invoiceAttachmentTypeId: z.string().nullable(),
|
invoiceAttachmentTypeId: z.string().nullable(),
|
||||||
deliveryChallanDate: z.string().min(1, { message: "Deliver date required" }),
|
deliveryChallanDate: z.string().min(1, { message: "Deliver date required" }),
|
||||||
description: z.string().min(1, { message: "Description required" }),
|
description: z.string().min(1, { message: "Description required" }),
|
||||||
attachment: z.any().refine(
|
attachment: z
|
||||||
(val) => val && typeof val === "object" && !!val.base64Data,
|
.any()
|
||||||
{
|
.refine((val) => val && typeof val === "object" && !!val.base64Data, {
|
||||||
message: "Please upload document",
|
message: "Please upload document",
|
||||||
}
|
}),
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const DeliveryChallanDefaultValue = {
|
export const DeliveryChallanDefaultValue = {
|
||||||
@ -187,3 +192,20 @@ export const DeliveryChallanDefaultValue = {
|
|||||||
attachment: null,
|
attachment: null,
|
||||||
invoiceAttachmentTypeId: null,
|
invoiceAttachmentTypeId: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const AddPurchasePayment = z.object({
|
||||||
|
paymentReceivedDate: z.string().min(1, { message: "Date is required" }),
|
||||||
|
transactionId: z.string().min(1, "Transaction ID is required"),
|
||||||
|
amount: z.number().min(1, "Amount must be greater than zero"),
|
||||||
|
comment: z.string().min(1, { message: "Comment required" }),
|
||||||
|
paymentAdjustmentHeadId: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: "Payment Type required" }),
|
||||||
|
});
|
||||||
|
export const defaultPurchasePayment = {
|
||||||
|
paymentReceivedDate: null,
|
||||||
|
transactionId: "",
|
||||||
|
amount: 0,
|
||||||
|
comment: "",
|
||||||
|
paymentAdjustmentHeadId: "",
|
||||||
|
};
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const PurchaseTransportDetails = () => {
|
|||||||
<div className="row g-3 text-start">
|
<div className="row g-3 text-start">
|
||||||
{/* Invoice Number */}
|
{/* Invoice Number */}
|
||||||
<div className="col-12 col-md-6">
|
<div className="col-12 col-md-6">
|
||||||
<Label htmlFor="invoiceNumber" required>
|
<Label htmlFor="invoiceNumber" >
|
||||||
Invoice Number
|
Invoice Number
|
||||||
</Label>
|
</Label>
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,17 @@ export const usePurchase = (id) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const usePurchasePaymentHistory = (id) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["purchase_payment_history", id],
|
||||||
|
queryFn: async () => {
|
||||||
|
const resp = await PurchaseRepository.GetPaymentHistory(id);
|
||||||
|
return resp.data;
|
||||||
|
},
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useCreatePurchaseInvoice = (onSuccessCallback) => {
|
export const useCreatePurchaseInvoice = (onSuccessCallback) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
@ -120,3 +131,51 @@ export const useAddDeliverChallan = (onSuccessCallback) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
export const useAddPurchasePayment =(onSuccessCallback)=>{
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async (payload) =>
|
||||||
|
PurchaseRepository.AddPayment(payload),
|
||||||
|
onSuccess: (data, variables) => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["purchase_payment_history"] });
|
||||||
|
showToast("Payment added successfully", "success");
|
||||||
|
if (onSuccessCallback) onSuccessCallback();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to Add payment",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const useDeletePurchaseInvoice = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({ id, isActive }) =>
|
||||||
|
await PurchaseRepository.deletePurchase(id, isActive),
|
||||||
|
|
||||||
|
onSuccess: (_, variable) => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["purchase_list"] });
|
||||||
|
showToast(
|
||||||
|
`Purchase Invoice ${variable.isActive ? "restored" : "deleted"} successfully`,
|
||||||
|
"success"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
onError: (error) => {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to delete branch",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@ -6,6 +6,9 @@ import ManagePurchase from "../../components/purchase/ManagePurchase";
|
|||||||
import PurchaseList from "../../components/purchase/PurchaseList";
|
import PurchaseList from "../../components/purchase/PurchaseList";
|
||||||
import ViewPurchase from "../../components/purchase/ViewPurchase";
|
import ViewPurchase from "../../components/purchase/ViewPurchase";
|
||||||
import DeliveryChallane from "../../components/purchase/DeliveryChallane";
|
import DeliveryChallane from "../../components/purchase/DeliveryChallane";
|
||||||
|
import PurchasePayment from "../../components/purchase/PurchasePayment";
|
||||||
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||||
|
import { MANAGEPURCHASE_INVOICE } from "../../utils/constants";
|
||||||
|
|
||||||
export const PurchaseContext = createContext();
|
export const PurchaseContext = createContext();
|
||||||
export const usePurchaseContext = () => {
|
export const usePurchaseContext = () => {
|
||||||
@ -19,6 +22,8 @@ export const usePurchaseContext = () => {
|
|||||||
};
|
};
|
||||||
const PurchasePage = () => {
|
const PurchasePage = () => {
|
||||||
const [searchText, setSearchText] = useState("");
|
const [searchText, setSearchText] = useState("");
|
||||||
|
const [showDelete, setShowDelete] = useState(false);
|
||||||
|
const [showInactive, setShowInactive] = useState(false);
|
||||||
const [addChallan, setChallan] = useState({
|
const [addChallan, setChallan] = useState({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
purchaseId: null,
|
purchaseId: null,
|
||||||
@ -27,15 +32,22 @@ const PurchasePage = () => {
|
|||||||
isOpen: false,
|
isOpen: false,
|
||||||
purchaseId: null,
|
purchaseId: null,
|
||||||
});
|
});
|
||||||
|
const [addPayment, setAddPayment] = useState({
|
||||||
|
isOpen: false,
|
||||||
|
purchaseId: null,
|
||||||
|
});
|
||||||
const [viewPurchaseState, setViewPurchase] = useState({
|
const [viewPurchaseState, setViewPurchase] = useState({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
purchaseId: null,
|
purchaseId: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const canCreatePurchase = useHasUserPermission(MANAGEPURCHASE_INVOICE);
|
||||||
|
|
||||||
const contextValue = {
|
const contextValue = {
|
||||||
setViewPurchase,
|
setViewPurchase,
|
||||||
setManagePurchase,
|
setManagePurchase,
|
||||||
setChallan,
|
setChallan,
|
||||||
|
setAddPayment,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<PurchaseContext.Provider value={contextValue}>
|
<PurchaseContext.Provider value={contextValue}>
|
||||||
@ -61,8 +73,24 @@ const PurchasePage = () => {
|
|||||||
aria-controls="DataTables_Table_0"
|
aria-controls="DataTables_Table_0"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
<div className="form-check form-switch d-inline-flex align-items-center ms-3">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="form-check-input"
|
||||||
|
id="inactiveEmployeesCheckbox"
|
||||||
|
checked={showInactive}
|
||||||
|
onChange={() => setShowInactive(!showInactive)}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor="inactiveEmployeesCheckbox"
|
||||||
|
className="ms-2 text-xs"
|
||||||
|
>
|
||||||
|
{!showInactive ? "Show Deleted" : "Hide Deleted"}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<di className="col-sm-6 text-end">
|
</div>
|
||||||
|
<div className="col-sm-6 text-end">
|
||||||
|
{canCreatePurchase && (
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@ -74,11 +102,12 @@ const PurchasePage = () => {
|
|||||||
>
|
>
|
||||||
<i className="bx bx-plus-circle me-2"></i>Add
|
<i className="bx bx-plus-circle me-2"></i>Add
|
||||||
</button>
|
</button>
|
||||||
</di>
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<PurchaseList searchString={searchText} />
|
<PurchaseList searchString={searchText} isActive={showInactive} />
|
||||||
{managePurchase.isOpen && (
|
{managePurchase.isOpen && (
|
||||||
<GlobalModel
|
<GlobalModel
|
||||||
isOpen={managePurchase.isOpen}
|
isOpen={managePurchase.isOpen}
|
||||||
@ -115,7 +144,8 @@ const PurchasePage = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{addChallan.isOpen && (
|
{addChallan.isOpen && (
|
||||||
<GlobalModel size="xl"
|
<GlobalModel
|
||||||
|
size="xl"
|
||||||
isOpen={addChallan.isOpen}
|
isOpen={addChallan.isOpen}
|
||||||
closeModal={() => setChallan({ isOpen: false, purchaseId: null })}
|
closeModal={() => setChallan({ isOpen: false, purchaseId: null })}
|
||||||
>
|
>
|
||||||
@ -125,6 +155,21 @@ const PurchasePage = () => {
|
|||||||
/>
|
/>
|
||||||
</GlobalModel>
|
</GlobalModel>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{addPayment.isOpen && (
|
||||||
|
<GlobalModel
|
||||||
|
size="xl"
|
||||||
|
isOpen={addPayment.isOpen}
|
||||||
|
closeModal={() =>
|
||||||
|
setAddPayment({ isOpen: false, purchaseId: null })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<PurchasePayment
|
||||||
|
onClose={() => setAddPayment({ isOpen: false, purchaseId: null })}
|
||||||
|
purchaseId={addPayment.purchaseId}
|
||||||
|
/>
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</PurchaseContext.Provider>
|
</PurchaseContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,6 +14,12 @@ export const PurchaseRepository = {
|
|||||||
api.get(`/api/PurchaseInvoice/delivery-challan/list/${purchaseInvoiceId}`),
|
api.get(`/api/PurchaseInvoice/delivery-challan/list/${purchaseInvoiceId}`),
|
||||||
addDelievryChallan: (data) =>
|
addDelievryChallan: (data) =>
|
||||||
api.post(`/api/PurchaseInvoice/delivery-challan/create`, data),
|
api.post(`/api/PurchaseInvoice/delivery-challan/create`, data),
|
||||||
|
|
||||||
|
AddPayment: (data) => api.post(`/api/PurchaseInvoice/add/payment`, data),
|
||||||
|
GetPaymentHistory: (purchaseInvoiceId) =>
|
||||||
|
api.get(`/api/PurchaseInvoice/payment-history/list/${purchaseInvoiceId}`),
|
||||||
|
deletePurchase: (id, isActive = false) =>
|
||||||
|
api.delete(`/api/PurchaseInvoice/delete/${id}?isActive=${isActive}`),
|
||||||
};
|
};
|
||||||
|
|
||||||
// const filterPayload = JSON.stringify({
|
// const filterPayload = JSON.stringify({
|
||||||
|
|||||||
@ -2,7 +2,6 @@ export const BASE_URL = process.env.VITE_BASE_URL;
|
|||||||
|
|
||||||
// export const BASE_URL = "https://api.marcoaiot.com";
|
// export const BASE_URL = "https://api.marcoaiot.com";
|
||||||
|
|
||||||
|
|
||||||
export const THRESH_HOLD = 48; // hours
|
export const THRESH_HOLD = 48; // hours
|
||||||
export const DURATION_TIME = 10; // minutes
|
export const DURATION_TIME = 10; // minutes
|
||||||
export const ITEMS_PER_PAGE = 20;
|
export const ITEMS_PER_PAGE = 20;
|
||||||
@ -66,8 +65,6 @@ export const PROCESS_EXPENSE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11";
|
|||||||
|
|
||||||
export const EXPENSE_MANAGE = "bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3";
|
export const EXPENSE_MANAGE = "bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------Collection----------------------------
|
// --------------------------------Collection----------------------------
|
||||||
|
|
||||||
export const ADMIN_COLLECTION = "dbf17591-09fe-4c93-9e1a-12db8f5cc5de";
|
export const ADMIN_COLLECTION = "dbf17591-09fe-4c93-9e1a-12db8f5cc5de";
|
||||||
@ -76,6 +73,13 @@ export const CREATE_COLLECTION = "b93141fd-dbd3-4051-8f57-bf25d18e3555";
|
|||||||
export const EDIT_COLLECTION = "455187b4-fef1-41f9-b3d0-025d0b6302c3";
|
export const EDIT_COLLECTION = "455187b4-fef1-41f9-b3d0-025d0b6302c3";
|
||||||
export const ADDPAYMENT_COLLECTION = "061d9ccd-85b4-4cb0-be06-2f9f32cebb72";
|
export const ADDPAYMENT_COLLECTION = "061d9ccd-85b4-4cb0-be06-2f9f32cebb72";
|
||||||
|
|
||||||
|
// --------------------Purchase Invoice--------------------------------
|
||||||
|
export const VIEWSELF_PURCHASEINVOICE = "91e09825-512a-465e-82ad-fa355b305585";
|
||||||
|
export const VIEWALL_PURCHASEINVOICE = "d6ae78d3-a941-4cc4-8d0a-d40479be4211";
|
||||||
|
export const MANAGEPURCHASE_INVOICE = "68ff925d-8ebf-4034-a137-8d3317c56ca1";
|
||||||
|
export const DELETEPURCHASE_INVOICE = "a4b77638-bf31-42bb-afd4-d5bbd15ccadc";
|
||||||
|
export const ADD_DELIVERY_CHALLAN = "a4b77638-bf31-42bb-afd4-d5bbd15ccadc";
|
||||||
|
|
||||||
// ----------------------------Tenant-------------------------
|
// ----------------------------Tenant-------------------------
|
||||||
export const SUPPER_TENANT = "d032cb1a-3f30-462c-bef0-7ace73a71c0b";
|
export const SUPPER_TENANT = "d032cb1a-3f30-462c-bef0-7ace73a71c0b";
|
||||||
export const MANAGE_TENANTS = "00e20637-ce8d-4417-bec4-9b31b5e65092";
|
export const MANAGE_TENANTS = "00e20637-ce8d-4417-bec4-9b31b5e65092";
|
||||||
@ -98,7 +102,7 @@ export const EXPENSE_REJECTEDBY = [
|
|||||||
];
|
];
|
||||||
export const EXPENSE_DRAFT = "297e0d8f-f668-41b5-bfea-e03b354251c8";
|
export const EXPENSE_DRAFT = "297e0d8f-f668-41b5-bfea-e03b354251c8";
|
||||||
export const EXPENSE_MANAGEMENT = "a4e25142-449b-4334-a6e5-22f70e4732d7";
|
export const EXPENSE_MANAGEMENT = "a4e25142-449b-4334-a6e5-22f70e4732d7";
|
||||||
export const EXPENSE_CREATE = "b8586f67-dc19-49c3-b4af-224149efe1d3"
|
export const EXPENSE_CREATE = "b8586f67-dc19-49c3-b4af-224149efe1d3";
|
||||||
export const INR_CURRENCY_CODE = "78e96e4a-7ce0-4164-ae3a-c833ad45ec2c";
|
export const INR_CURRENCY_CODE = "78e96e4a-7ce0-4164-ae3a-c833ad45ec2c";
|
||||||
export const EXPENSE_PROCESSED = "61578360-3a49-4c34-8604-7b35a3787b95";
|
export const EXPENSE_PROCESSED = "61578360-3a49-4c34-8604-7b35a3787b95";
|
||||||
export const TENANT_STATUS = [
|
export const TENANT_STATUS = [
|
||||||
@ -165,7 +169,7 @@ export const EXPENSE_STATUS = {
|
|||||||
approve_pending: "4068007f-c92f-4f37-a907-bc15fe57d4d8",
|
approve_pending: "4068007f-c92f-4f37-a907-bc15fe57d4d8",
|
||||||
payment_processed: "61578360-3a49-4c34-8604-7b35a3787b95",
|
payment_processed: "61578360-3a49-4c34-8604-7b35a3787b95",
|
||||||
payment_done: "b8586f67-dc19-49c3-b4af-224149efe1d3",
|
payment_done: "b8586f67-dc19-49c3-b4af-224149efe1d3",
|
||||||
}
|
};
|
||||||
|
|
||||||
export const UUID_REGEX =
|
export const UUID_REGEX =
|
||||||
/^\/employee\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
/^\/employee\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
||||||
@ -184,7 +188,7 @@ export const FREQUENCY_FOR_RECURRING = {
|
|||||||
2: "Half-Yearly",
|
2: "Half-Yearly",
|
||||||
3: "Yearly",
|
3: "Yearly",
|
||||||
4: "Daily",
|
4: "Daily",
|
||||||
5: "Weekly"
|
5: "Weekly",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PAYEE_RECURRING_EXPENSE = [
|
export const PAYEE_RECURRING_EXPENSE = [
|
||||||
@ -206,9 +210,8 @@ export const PAYEE_RECURRING_EXPENSE = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
//#region Service Project and Jobs
|
//#region Service Project and Jobs
|
||||||
export const STATUS_JOB_CLOSED = "3ddeefb5-ae3c-4e10-a922-35e0a452bb69"
|
export const STATUS_JOB_CLOSED = "3ddeefb5-ae3c-4e10-a922-35e0a452bb69";
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user