const express = require('express'); const Joi = require('joi'); const { getData, getServices, getResources, getPortals, getAllProjects, getAllProjectTasks, getAllProjectTaskLists, getAllProjectIssues, getAllProjectPhases, getSalesOrders, getPurchaseOrders, getInvoices, getDepartments, getLeaveRequests, getAttendance, getOrganizations, getCustomers, getVendors, getItems, getEstimates, getBills, getExpenses, getBankAccounts, getBankTransactions, getReports, getBooksSalesOrders, getBooksPurchaseOrders, getContacts, getBooksContacts, getBooksInvoices, getEmployeeForms, getEmployeeById, getAttendanceEntries, getShiftConfiguration, getLeaveData, getGoalsData, getPerformanceData, getUserReport, getLeaveTrackerReport, getHolidays } = require('../controllers/integrationController'); const auth = require('../middlewares/auth'); const ZohoHandler = require('../../integrations/zoho/handler'); const router = express.Router(); function validate(schema, source = 'query') { return (req, res, next) => { const data = source === 'body' ? req.body : req.query; const { error, value } = schema.validate(data, { abortEarly: false, stripUnknown: true }); if (error) { return res.status(400).json({ status: 'error', message: 'Validation failed', errorCode: 'VALIDATION_ERROR', details: error.details, timestamp: new Date().toISOString() }); } if (source === 'body') { req.body = value; } else { req.query = value; } next(); }; } // Get data from any provider/service/resource const dataSchema = Joi.object({ provider: Joi.string().valid('zoho', 'hubspot', 'quickbooks', 'bamboohr').required(), service: Joi.string().required(), resource: Joi.string().required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/data', auth, validate(dataSchema), getData); // Get available services const servicesSchema = Joi.object({ provider: Joi.string().valid('zoho', 'hubspot', 'quickbooks', 'bamboohr').required() }); router.get('/services', auth, validate(servicesSchema), getServices); // Get available resources const resourcesSchema = Joi.object({ provider: Joi.string().valid('zoho', 'hubspot', 'quickbooks', 'bamboohr').required(), service: Joi.string().required() }); router.get('/resources', auth, validate(resourcesSchema), getResources); // Get Zoho portals const portalsSchema = Joi.object({ provider: Joi.string().valid('zoho').required() }); // Zoho Projects specific routes with clear service identification router.get('/zoho/projects/portals', auth, validate(portalsSchema), getPortals); // Get all Zoho projects (across all portals) const allProjectsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/zoho/projects/all-projects', auth, validate(allProjectsSchema), getAllProjects); // Get all project tasks for a specific portal const allProjectTasksSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), portal_id: Joi.string().required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/zoho/projects/all-project-tasks', auth, validate(allProjectTasksSchema), getAllProjectTasks); // Get all project task lists for a specific portal const allProjectTaskListsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), portal_id: Joi.string().required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/zoho/projects/all-project-tasklists', auth, validate(allProjectTaskListsSchema), getAllProjectTaskLists); // Get all project issues for a specific portal const allProjectIssuesSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), portal_id: Joi.string().required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/zoho/projects/all-project-issues', auth, validate(allProjectIssuesSchema), getAllProjectIssues); // Get all project phases for a specific portal const allProjectPhasesSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), portal_id: Joi.string().required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/zoho/projects/all-project-phases', auth, validate(allProjectPhasesSchema), getAllProjectPhases); // Get Zoho Sales Orders const salesOrdersSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); // Zoho CRM specific routes with clear service identification router.get('/zoho/crm/sales-orders', auth, validate(salesOrdersSchema), getSalesOrders); // Get Zoho Purchase Orders const purchaseOrdersSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/zoho/crm/purchase-orders', auth, validate(purchaseOrdersSchema), getPurchaseOrders); // Get Zoho Invoices const invoicesSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); router.get('/zoho/crm/invoices', auth, validate(invoicesSchema), getInvoices); router.get('/zoho/crm/contacts', auth, validate(invoicesSchema), getContacts); // Zoho People specific routes const departmentsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const leaveRequestsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const attendanceSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); // Zoho People Forms API schemas const employeeFormsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const employeeByIdSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), recordId: Joi.string().required(), formLinkName: Joi.string().default('employee') }); const attendanceEntriesSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const shiftConfigurationSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const leaveDataSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), formLinkName: Joi.string().default('leave'), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const goalsDataSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), formLinkName: Joi.string().default('goals'), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const performanceDataSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), formLinkName: Joi.string().default('performance'), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); // Zoho People specific routes with clear service identification router.get('/zoho/people/departments', auth, validate(departmentsSchema), getDepartments); router.get('/zoho/people/leave-requests', auth, validate(leaveRequestsSchema), getLeaveRequests); router.get('/zoho/people/attendance', auth, validate(attendanceSchema), getAttendance); // Zoho People Forms API routes router.get('/zoho/people/employee-forms', auth, validate(employeeFormsSchema), getEmployeeForms); router.get('/zoho/people/employee/:recordId', auth, validate(employeeByIdSchema), getEmployeeById); router.get('/zoho/people/attendance-entries', auth, validate(attendanceEntriesSchema), getAttendanceEntries); router.get('/zoho/people/shift-configuration', auth, validate(shiftConfigurationSchema), getShiftConfiguration); router.get('/zoho/people/leave-data', auth, validate(leaveDataSchema), getLeaveData); router.get('/zoho/people/goals-data', auth, validate(goalsDataSchema), getGoalsData); router.get('/zoho/people/performance-data', auth, validate(performanceDataSchema), getPerformanceData); // Zoho People Reports API routes router.get('/zoho/people/attendance-report', auth, getUserReport); router.get('/zoho/people/leave-tracker-report', auth, getLeaveTrackerReport); router.get('/zoho/people/holidays', auth, getHolidays); // Zoho Books specific routes const organizationsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const customersSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const vendorsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const itemsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const estimatesSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const billsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const expensesSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const bankAccountsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const bankTransactionsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const reportsSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const booksSalesOrdersSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); const booksPurchaseOrdersSchema = Joi.object({ provider: Joi.string().valid('zoho').required(), page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), filters: Joi.string().optional() }); // Zoho Books specific routes with clear service identification router.get('/zoho/books/organizations', auth, validate(organizationsSchema), getOrganizations); router.get('/zoho/books/contacts', auth, validate(customersSchema), getBooksContacts); router.get('/zoho/books/vendors', auth, validate(vendorsSchema), getVendors); router.get('/zoho/books/items', auth, validate(itemsSchema), getItems); router.get('/zoho/books/customers', auth, validate(customersSchema), getCustomers); router.get('/zoho/books/invoices', auth, validate(invoicesSchema), getBooksInvoices); router.get('/zoho/books/estimates', auth, validate(estimatesSchema), getEstimates); router.get('/zoho/books/bills', auth, validate(billsSchema), getBills); router.get('/zoho/books/expenses', auth, validate(expensesSchema), getExpenses); router.get('/zoho/books/bank-accounts', auth, validate(bankAccountsSchema), getBankAccounts); router.get('/zoho/books/bank-transactions', auth, validate(bankTransactionsSchema), getBankTransactions); router.get('/zoho/books/reports', auth, validate(reportsSchema), getReports); router.get('/zoho/books/sales-orders', auth, validate(booksSalesOrdersSchema), getBooksSalesOrders); router.get('/zoho/books/purchase-orders', auth, validate(booksPurchaseOrdersSchema), getBooksPurchaseOrders); // Webhook endpoints (no auth required - uses signature verification) const zohoHandler = new ZohoHandler(); router.post('/webhooks/zoho/crm', zohoHandler.handleCrmWebhook.bind(zohoHandler)); router.post('/webhooks/zoho/people', zohoHandler.handlePeopleWebhook.bind(zohoHandler)); router.post('/webhooks/zoho/books', zohoHandler.handleBooksWebhook.bind(zohoHandler)); router.post('/webhooks/zoho/projects', zohoHandler.handleProjectsWebhook.bind(zohoHandler)); router.post('/webhooks/zoho/bulkread', zohoHandler.handleBulkReadWebhook.bind(zohoHandler)); module.exports = router;