crm data mapped to frontend and created api for zoho project ansd tasks
This commit is contained in:
parent
7445a6a156
commit
b137f8cc1a
@ -45,4 +45,72 @@ async function getResources(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getData, getServices, getResources };
|
||||
async function getPortals(req, res) {
|
||||
try {
|
||||
const { provider } = req.query;
|
||||
if (provider !== 'zoho') {
|
||||
return res.status(400).json(failure('Portals are only available for Zoho provider', 'INVALID_PROVIDER'));
|
||||
}
|
||||
|
||||
const integrationService = new IntegrationService(req.user.id);
|
||||
const portals = await integrationService.getPortals(provider);
|
||||
res.json(success('Zoho portals retrieved successfully', portals));
|
||||
} catch (error) {
|
||||
res.status(400).json(failure(error.message, 'INTEGRATION_ERROR'));
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllProjects(req, res) {
|
||||
try {
|
||||
const { provider, page, limit, filters } = req.query;
|
||||
if (provider !== 'zoho') {
|
||||
return res.status(400).json(failure('All projects are only available for Zoho provider', 'INVALID_PROVIDER'));
|
||||
}
|
||||
|
||||
const integrationService = new IntegrationService(req.user.id);
|
||||
const params = { page, limit };
|
||||
if (filters) {
|
||||
try {
|
||||
params.filters = JSON.parse(filters);
|
||||
} catch (e) {
|
||||
return res.status(400).json(failure('Invalid filters format', 'INVALID_FILTERS'));
|
||||
}
|
||||
}
|
||||
|
||||
const projects = await integrationService.getAllProjects(provider, params);
|
||||
res.json(success('All Zoho projects retrieved successfully', projects));
|
||||
} catch (error) {
|
||||
res.status(400).json(failure(error.message, 'INTEGRATION_ERROR'));
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllProjectTasks(req, res) {
|
||||
try {
|
||||
const { provider, page, limit, filters, portal_id } = req.query;
|
||||
|
||||
if (provider !== 'zoho') {
|
||||
return res.status(400).json(failure('All project tasks are only available for Zoho provider', 'INVALID_PROVIDER'));
|
||||
}
|
||||
|
||||
if (!portal_id) {
|
||||
return res.status(400).json(failure('portal_id is required in query parameters', 'MISSING_PORTAL_ID'));
|
||||
}
|
||||
|
||||
const integrationService = new IntegrationService(req.user.id);
|
||||
const params = { page, limit };
|
||||
if (filters) {
|
||||
try {
|
||||
params.filters = JSON.parse(filters);
|
||||
} catch (e) {
|
||||
return res.status(400).json(failure('Invalid filters format', 'INVALID_FILTERS'));
|
||||
}
|
||||
}
|
||||
|
||||
const tasks = await integrationService.getAllProjectTasks(provider, portal_id, params);
|
||||
res.json(success('All Zoho project tasks retrieved successfully', tasks));
|
||||
} catch (error) {
|
||||
res.status(400).json(failure(error.message, 'INTEGRATION_ERROR'));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getData, getServices, getResources, getPortals, getAllProjects, getAllProjectTasks };
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
const express = require('express');
|
||||
const Joi = require('joi');
|
||||
const { getData, getServices, getResources } = require('../controllers/integrationController');
|
||||
const { getData, getServices, getResources, getPortals, getAllProjects, getAllProjectTasks } = require('../controllers/integrationController');
|
||||
const auth = require('../middlewares/auth');
|
||||
const ZohoHandler = require('../../integrations/zoho/handler');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
function validate(schema) {
|
||||
function validate(schema, source = 'query') {
|
||||
return (req, res, next) => {
|
||||
const { error, value } = schema.validate(req.query, { abortEarly: false, stripUnknown: true });
|
||||
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',
|
||||
@ -18,7 +19,11 @@ function validate(schema) {
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
req.query = value;
|
||||
if (source === 'body') {
|
||||
req.body = value;
|
||||
} else {
|
||||
req.query = value;
|
||||
}
|
||||
next();
|
||||
};
|
||||
}
|
||||
@ -50,6 +55,34 @@ const resourcesSchema = Joi.object({
|
||||
|
||||
router.get('/resources', auth, validate(resourcesSchema), getResources);
|
||||
|
||||
// Get Zoho portals
|
||||
const portalsSchema = Joi.object({
|
||||
provider: Joi.string().valid('zoho').required()
|
||||
});
|
||||
|
||||
router.get('/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('/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('/all-project-tasks', auth, validate(allProjectTasksSchema), getAllProjectTasks);
|
||||
|
||||
// Webhook endpoints (no auth required - uses signature verification)
|
||||
const zohoHandler = new ZohoHandler();
|
||||
router.post('/webhooks/zoho/crm', zohoHandler.handleCrmWebhook.bind(zohoHandler));
|
||||
|
||||
@ -6,7 +6,11 @@ const ZohoMapper = require('./mapper');
|
||||
class ZohoClient {
|
||||
constructor(userId) {
|
||||
this.userId = userId;
|
||||
this.baseUrl = 'https://www.zohoapis.com';
|
||||
this.baseUrls = {
|
||||
crm: 'https://www.zohoapis.com',
|
||||
people: 'https://www.zohoapis.com',
|
||||
projects: 'https://projectsapi.zoho.com'
|
||||
};
|
||||
}
|
||||
|
||||
async getTokens() {
|
||||
@ -21,10 +25,11 @@ class ZohoClient {
|
||||
};
|
||||
}
|
||||
|
||||
async makeRequest(endpoint, options = {}) {
|
||||
async makeRequest(endpoint, options = {}, service = 'crm') {
|
||||
const { accessToken } = await this.getTokens();
|
||||
console.log('i am in make request with token',accessToken)
|
||||
const url = `${this.baseUrl}${endpoint}`;
|
||||
const baseUrl = this.baseUrls[service] || this.baseUrls.crm;
|
||||
const url = `${baseUrl}${endpoint}`;
|
||||
|
||||
const config = {
|
||||
...options,
|
||||
@ -101,23 +106,68 @@ class ZohoClient {
|
||||
|
||||
// Zoho People methods
|
||||
async getEmployees(params = {}) {
|
||||
const response = await this.makeRequest('/people/api/v1/employees', { params });
|
||||
const response = await this.makeRequest('/people/api/v1/employees', { params }, 'people');
|
||||
return ZohoMapper.mapApiResponse(response, 'employees');
|
||||
}
|
||||
|
||||
// Zoho Projects methods
|
||||
async getProjects(params = {}) {
|
||||
const response = await this.makeRequest('/projects/v1/projects', { params });
|
||||
async getPortals() {
|
||||
const response = await this.makeRequest('/api/v3/portals', {}, 'projects');
|
||||
return ZohoMapper.mapApiResponse(response, 'portals');
|
||||
}
|
||||
|
||||
async getProjects(portalId, params = {}) {
|
||||
const response = await this.makeRequest(`/api/v3/portal/${portalId}/projects`, { params }, 'projects');
|
||||
return ZohoMapper.mapApiResponse(response, 'projects');
|
||||
}
|
||||
|
||||
async getAllProjects(params = {}) {
|
||||
// First get all portals
|
||||
const portalsResponse = await this.getPortals();
|
||||
const portals = portalsResponse.data;
|
||||
|
||||
// Get projects for each portal
|
||||
const allProjects = [];
|
||||
for (const portal of portals) {
|
||||
try {
|
||||
const projectsResponse = await this.getProjects(portal.id, params);
|
||||
const projects = projectsResponse.data;
|
||||
console.log('all projects', projects);
|
||||
|
||||
// Add portal information to each project
|
||||
const projectsWithPortal = projects.map(project => ({
|
||||
...project,
|
||||
portal: {
|
||||
id: portal.id,
|
||||
name: portal.portal_name,
|
||||
org_name: portal.org_name,
|
||||
portal_url: portal.portal_url
|
||||
}
|
||||
}));
|
||||
allProjects.push(...projectsWithPortal);
|
||||
} catch (error) {
|
||||
console.error(`Error fetching projects for portal ${portal.id}:`, error.message);
|
||||
// Continue with other portals even if one fails
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
data: allProjects,
|
||||
info: {
|
||||
count: allProjects.length,
|
||||
moreRecords: false,
|
||||
page: 1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async getProjectTasks(projectId, params = {}) {
|
||||
const response = await this.makeRequest(`/projects/v1/projects/${projectId}/tasks`, { params });
|
||||
const response = await this.makeRequest(`/projects/v1/projects/${projectId}/tasks`, { params }, 'projects');
|
||||
return ZohoMapper.mapApiResponse(response, 'tasks');
|
||||
}
|
||||
|
||||
async getAllProjectTasks(params = {}) {
|
||||
const response = await this.makeRequest('/projects/v1/tasks', { params });
|
||||
async getAllProjectTasks(portalId, params = {}) {
|
||||
const response = await this.makeRequest(`/api/v3/portal/${portalId}/all-tasklists`, { params }, 'projects');
|
||||
return ZohoMapper.mapApiResponse(response, 'tasks');
|
||||
}
|
||||
|
||||
|
||||
@ -135,16 +135,56 @@ class ZohoMapper {
|
||||
|
||||
// Map Zoho API response to standardized format
|
||||
static mapApiResponse(zohoResponse, recordType) {
|
||||
const records = zohoResponse.data || [];
|
||||
// const mappedRecords = this.mapRecords(records, recordType);
|
||||
let records = [];
|
||||
let pageInfo = {};
|
||||
|
||||
// Handle different response structures based on record type
|
||||
switch (recordType) {
|
||||
case 'projects':
|
||||
// Projects response is directly an array
|
||||
records = zohoResponse || [];
|
||||
pageInfo = {
|
||||
count: records.length,
|
||||
moreRecords: false,
|
||||
page: 1
|
||||
};
|
||||
break;
|
||||
|
||||
case 'tasks':
|
||||
// Tasks response has tasklists array and page_info
|
||||
records = zohoResponse.tasklists || [];
|
||||
pageInfo = {
|
||||
count: zohoResponse.page_info?.per_page || records.length,
|
||||
moreRecords: zohoResponse.page_info?.has_next_page || false,
|
||||
page: zohoResponse.page_info?.page || 1,
|
||||
pageCount: zohoResponse.page_info?.page_count || 1
|
||||
};
|
||||
break;
|
||||
|
||||
case 'portals':
|
||||
// Portals response is directly an array
|
||||
records = zohoResponse || [];
|
||||
pageInfo = {
|
||||
count: records.length,
|
||||
moreRecords: false,
|
||||
page: 1
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
// Default CRM response structure (leads, contacts, deals, employees)
|
||||
records = zohoResponse.data || [];
|
||||
pageInfo = {
|
||||
count: zohoResponse.info?.count || records.length,
|
||||
moreRecords: zohoResponse.info?.more_records || false,
|
||||
page: zohoResponse.info?.page || 1
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
data: records,
|
||||
info: {
|
||||
count: zohoResponse.info?.count || mappedRecords.length,
|
||||
moreRecords: zohoResponse.info?.more_records || false,
|
||||
page: zohoResponse.info?.page || 1
|
||||
}
|
||||
info: pageInfo
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +68,39 @@ class IntegrationService {
|
||||
}
|
||||
return client.getAvailableResources(service);
|
||||
}
|
||||
|
||||
async getPortals(provider) {
|
||||
const client = this.clients[provider];
|
||||
if (!client) {
|
||||
throw new Error(`Provider ${provider} not supported`);
|
||||
}
|
||||
if (provider !== 'zoho') {
|
||||
throw new Error('Portals are only available for Zoho provider');
|
||||
}
|
||||
return await client.getPortals();
|
||||
}
|
||||
|
||||
async getAllProjects(provider, params = {}) {
|
||||
const client = this.clients[provider];
|
||||
if (!client) {
|
||||
throw new Error(`Provider ${provider} not supported`);
|
||||
}
|
||||
if (provider !== 'zoho') {
|
||||
throw new Error('All projects are only available for Zoho provider');
|
||||
}
|
||||
return await client.getAllProjects(params);
|
||||
}
|
||||
|
||||
async getAllProjectTasks(provider, portalId, params = {}) {
|
||||
const client = this.clients[provider];
|
||||
if (!client) {
|
||||
throw new Error(`Provider ${provider} not supported`);
|
||||
}
|
||||
if (provider !== 'zoho') {
|
||||
throw new Error('All project tasks are only available for Zoho provider');
|
||||
}
|
||||
return await client.getAllProjectTasks(portalId, params);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = IntegrationService;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user