178 lines
5.3 KiB
JavaScript
178 lines
5.3 KiB
JavaScript
import { z } from "zod";
|
|
import { localToUtc } from "../../utils/appUtils";
|
|
|
|
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
|
|
const ALLOWED_TYPES = [
|
|
"application/pdf",
|
|
"image/png",
|
|
"image/jpg",
|
|
"image/jpeg",
|
|
];
|
|
|
|
export const ExpenseSchema = (expenseTypes) => {
|
|
return z
|
|
.object({
|
|
projectId: z.string().min(1, { message: "Project is required" }),
|
|
expensesTypeId: z
|
|
.string()
|
|
.min(1, { message: "Expense type is required" }),
|
|
paymentModeId: z.string().min(1, { message: "Payment mode is required" }),
|
|
paidById: z.string().min(1, { message: "Employee name is required" }),
|
|
transactionDate: z.string().min(1, { message: "Date is required" }),
|
|
transactionId: z.string().optional(),
|
|
description: z.string().min(1, { message: "Description is required" }),
|
|
location: z.string().min(1, { message: "Location is required" }),
|
|
supplerName: z.string().min(1, { message: "Supplier name is required" }),
|
|
gstNumber: z.string().optional(),
|
|
amount: z.coerce
|
|
.number({
|
|
invalid_type_error: "Amount is required and must be a number",
|
|
})
|
|
.min(1, "Amount must be Enter")
|
|
.refine((val) => /^\d+(\.\d{1,2})?$/.test(val.toString()), {
|
|
message: "Amount must have at most 2 decimal places",
|
|
}),
|
|
noOfPersons: z.coerce.number().optional(),
|
|
billAttachments: z
|
|
.array(
|
|
z.object({
|
|
fileName: z.string().min(1, { message: "Filename is required" }),
|
|
base64Data: z.string().nullable(),
|
|
contentType: z
|
|
.string()
|
|
.refine((val) => ALLOWED_TYPES.includes(val), {
|
|
message: "Only PDF, PNG, JPG, or JPEG files are allowed",
|
|
}),
|
|
documentId: z.string().optional(),
|
|
fileSize: z.number().max(MAX_FILE_SIZE, {
|
|
message: "File size must be less than or equal to 5MB",
|
|
}),
|
|
description: z.string().optional(),
|
|
isActive: z.boolean().default(true),
|
|
})
|
|
)
|
|
.nonempty({ message: "At least one file attachment is required" }),
|
|
})
|
|
.refine(
|
|
(data) => {
|
|
return (
|
|
!data.projectId || (data.paidById && data.paidById.trim() !== "")
|
|
);
|
|
},
|
|
{
|
|
message: "Please select who paid (employee)",
|
|
path: ["paidById"],
|
|
}
|
|
)
|
|
.superRefine((data, ctx) => {
|
|
const expenseType = expenseTypes.find(
|
|
(et) => et.id === data.expensesTypeId
|
|
);
|
|
if (
|
|
expenseType?.noOfPersonsRequired &&
|
|
(!data.noOfPersons || data.noOfPersons < 1)
|
|
) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "No. of Persons is required and must be at least 1",
|
|
path: ["noOfPersons"],
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
export const defaultExpense = {
|
|
projectId: "",
|
|
expensesTypeId: "",
|
|
paymentModeId: "",
|
|
paidById: "",
|
|
transactionDate: "",
|
|
transactionId: "",
|
|
description: "",
|
|
location: "",
|
|
supplerName: "",
|
|
amount: "",
|
|
noOfPersons: "",
|
|
gstNumber: "",
|
|
billAttachments: [],
|
|
};
|
|
|
|
export const ExpenseActionScheam = (
|
|
isReimbursement = false,
|
|
transactionDate
|
|
) => {
|
|
return z
|
|
.object({
|
|
comment: z.string().min(1, { message: "Please leave comment" }),
|
|
statusId: z.string().min(1, { message: "Please select a status" }),
|
|
reimburseTransactionId: z.string().nullable().optional(),
|
|
reimburseDate: z.string().nullable().optional(),
|
|
reimburseById: z.string().nullable().optional(),
|
|
})
|
|
.superRefine((data, ctx) => {
|
|
if (isReimbursement) {
|
|
if (!data.reimburseTransactionId?.trim()) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["reimburseTransactionId"],
|
|
message: "Reimburse Transaction ID is required",
|
|
});
|
|
}
|
|
if (!data.reimburseDate) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["reimburseDate"],
|
|
message: "Reimburse 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.reimburseById) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["reimburseById"],
|
|
message: "Reimburse By is required",
|
|
});
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
export const defaultActionValues = {
|
|
comment: "",
|
|
statusId: "",
|
|
|
|
reimburseTransactionId: null,
|
|
reimburseDate: null,
|
|
reimburseById: null,
|
|
};
|
|
|
|
export const SearchSchema = z.object({
|
|
projectIds: z.array(z.string()).optional(),
|
|
statusIds: z.array(z.string()).optional(),
|
|
createdByIds: z.array(z.string()).optional(),
|
|
paidById: z.array(z.string()).optional(),
|
|
ExpenseTypeIds: z.array(z.string()).optional(),
|
|
startDate: z.string().optional(),
|
|
endDate: z.string().optional(),
|
|
isTransactionDate: z.boolean().default(true),
|
|
});
|
|
|
|
export const defaultFilter = {
|
|
projectIds: [],
|
|
statusIds: [],
|
|
createdByIds: [],
|
|
paidById: [],
|
|
ExpenseTypeIds: [],
|
|
isTransactionDate: true,
|
|
startDate: null,
|
|
endDate: null,
|
|
};
|