Move dashboard server into project
This commit is contained in:
1036
inventory-server/dashboard/gorgias-server/package-lock.json
generated
Normal file
1036
inventory-server/dashboard/gorgias-server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
inventory-server/dashboard/gorgias-server/package.json
Normal file
19
inventory-server/dashboard/gorgias-server/package.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "gorgias-server",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.9",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.7",
|
||||
"express": "^4.21.2",
|
||||
"redis": "^4.7.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const gorgiasService = require('../services/gorgias.service');
|
||||
|
||||
// Get statistics
|
||||
router.post('/stats/:name', async (req, res) => {
|
||||
try {
|
||||
const { name } = req.params;
|
||||
const filters = req.body;
|
||||
|
||||
console.log(`Fetching ${name} statistics with filters:`, filters);
|
||||
|
||||
if (!name) {
|
||||
return res.status(400).json({
|
||||
error: 'Missing statistic name',
|
||||
details: 'The name parameter is required'
|
||||
});
|
||||
}
|
||||
|
||||
const data = await gorgiasService.getStatistics(name, filters);
|
||||
|
||||
if (!data) {
|
||||
return res.status(404).json({
|
||||
error: 'No data found',
|
||||
details: `No statistics found for ${name}`
|
||||
});
|
||||
}
|
||||
|
||||
res.json({ data });
|
||||
} catch (error) {
|
||||
console.error('Statistics error:', {
|
||||
name: req.params.name,
|
||||
filters: req.body,
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
response: error.response?.data
|
||||
});
|
||||
|
||||
// Handle specific error cases
|
||||
if (error.response?.status === 401) {
|
||||
return res.status(401).json({
|
||||
error: 'Authentication failed',
|
||||
details: 'Invalid Gorgias API credentials'
|
||||
});
|
||||
}
|
||||
|
||||
if (error.response?.status === 404) {
|
||||
return res.status(404).json({
|
||||
error: 'Not found',
|
||||
details: `Statistics type '${req.params.name}' not found`
|
||||
});
|
||||
}
|
||||
|
||||
if (error.response?.status === 400) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid request',
|
||||
details: error.response?.data?.message || 'The request was invalid',
|
||||
data: error.response?.data
|
||||
});
|
||||
}
|
||||
|
||||
res.status(500).json({
|
||||
error: 'Failed to fetch statistics',
|
||||
details: error.response?.data?.message || error.message,
|
||||
data: error.response?.data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get tickets
|
||||
router.get('/tickets', async (req, res) => {
|
||||
try {
|
||||
const data = await gorgiasService.getTickets(req.query);
|
||||
res.json(data);
|
||||
} catch (error) {
|
||||
console.error('Tickets error:', {
|
||||
params: req.query,
|
||||
error: error.message,
|
||||
response: error.response?.data
|
||||
});
|
||||
|
||||
if (error.response?.status === 401) {
|
||||
return res.status(401).json({
|
||||
error: 'Authentication failed',
|
||||
details: 'Invalid Gorgias API credentials'
|
||||
});
|
||||
}
|
||||
|
||||
if (error.response?.status === 400) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid request',
|
||||
details: error.response?.data?.message || 'The request was invalid',
|
||||
data: error.response?.data
|
||||
});
|
||||
}
|
||||
|
||||
res.status(500).json({
|
||||
error: 'Failed to fetch tickets',
|
||||
details: error.response?.data?.message || error.message,
|
||||
data: error.response?.data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get customer satisfaction
|
||||
router.get('/satisfaction', async (req, res) => {
|
||||
try {
|
||||
const data = await gorgiasService.getCustomerSatisfaction(req.query);
|
||||
res.json(data);
|
||||
} catch (error) {
|
||||
console.error('Satisfaction error:', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to fetch customer satisfaction',
|
||||
details: error.response?.data || error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
31
inventory-server/dashboard/gorgias-server/server.js
Normal file
31
inventory-server/dashboard/gorgias-server/server.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
require('dotenv').config({
|
||||
path: path.resolve(__dirname, '.env')
|
||||
});
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3006;
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
// Import routes
|
||||
const gorgiasRoutes = require('./routes/gorgias.routes');
|
||||
|
||||
// Use routes
|
||||
app.use('/api/gorgias', gorgiasRoutes);
|
||||
|
||||
// Error handling middleware
|
||||
app.use((err, req, res, next) => {
|
||||
console.error(err.stack);
|
||||
res.status(500).json({ error: 'Something went wrong!' });
|
||||
});
|
||||
|
||||
// Start server
|
||||
app.listen(port, () => {
|
||||
console.log(`Gorgias API server running on port ${port}`);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
@@ -0,0 +1,119 @@
|
||||
const axios = require('axios');
|
||||
const { createClient } = require('redis');
|
||||
|
||||
class GorgiasService {
|
||||
constructor() {
|
||||
this.redis = createClient({
|
||||
url: process.env.REDIS_URL
|
||||
});
|
||||
|
||||
this.redis.on('error', err => console.error('Redis Client Error:', err));
|
||||
this.redis.connect().catch(err => console.error('Redis connection error:', err));
|
||||
|
||||
// Create base64 encoded auth string
|
||||
const auth = Buffer.from(`${process.env.GORGIAS_API_USERNAME}:${process.env.GORGIAS_API_KEY}`).toString('base64');
|
||||
|
||||
this.apiClient = axios.create({
|
||||
baseURL: `https://${process.env.GORGIAS_DOMAIN}.gorgias.com/api`,
|
||||
headers: {
|
||||
'Authorization': `Basic ${auth}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async getStatistics(name, filters = {}) {
|
||||
const cacheKey = `gorgias:stats:${name}:${JSON.stringify(filters)}`;
|
||||
|
||||
try {
|
||||
// Try Redis first
|
||||
const cachedData = await this.redis.get(cacheKey);
|
||||
if (cachedData) {
|
||||
console.log(`Statistics ${name} found in Redis cache`);
|
||||
return JSON.parse(cachedData);
|
||||
}
|
||||
|
||||
console.log(`Fetching ${name} statistics with filters:`, filters);
|
||||
|
||||
// Convert dates to UTC midnight if not already set
|
||||
if (!filters.start_datetime || !filters.end_datetime) {
|
||||
const start = new Date(filters.start_datetime || filters.start_date);
|
||||
start.setUTCHours(0, 0, 0, 0);
|
||||
const end = new Date(filters.end_datetime || filters.end_date);
|
||||
end.setUTCHours(23, 59, 59, 999);
|
||||
|
||||
filters = {
|
||||
...filters,
|
||||
start_datetime: start.toISOString(),
|
||||
end_datetime: end.toISOString()
|
||||
};
|
||||
}
|
||||
|
||||
// Fetch from API
|
||||
const response = await this.apiClient.post(`/stats/${name}`, filters);
|
||||
const data = response.data;
|
||||
|
||||
// Save to Redis with 5 minute expiry
|
||||
await this.redis.set(cacheKey, JSON.stringify(data), {
|
||||
EX: 300 // 5 minutes
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error(`Error in getStatistics for ${name}:`, {
|
||||
error: error.message,
|
||||
filters,
|
||||
response: error.response?.data
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getTickets(params = {}) {
|
||||
const cacheKey = `gorgias:tickets:${JSON.stringify(params)}`;
|
||||
|
||||
try {
|
||||
// Try Redis first
|
||||
const cachedData = await this.redis.get(cacheKey);
|
||||
if (cachedData) {
|
||||
console.log('Tickets found in Redis cache');
|
||||
return JSON.parse(cachedData);
|
||||
}
|
||||
|
||||
// Convert dates to UTC midnight
|
||||
const formattedParams = { ...params };
|
||||
if (params.start_date) {
|
||||
const start = new Date(params.start_date);
|
||||
start.setUTCHours(0, 0, 0, 0);
|
||||
formattedParams.start_datetime = start.toISOString();
|
||||
delete formattedParams.start_date;
|
||||
}
|
||||
if (params.end_date) {
|
||||
const end = new Date(params.end_date);
|
||||
end.setUTCHours(23, 59, 59, 999);
|
||||
formattedParams.end_datetime = end.toISOString();
|
||||
delete formattedParams.end_date;
|
||||
}
|
||||
|
||||
// Fetch from API
|
||||
const response = await this.apiClient.get('/tickets', { params: formattedParams });
|
||||
const data = response.data;
|
||||
|
||||
// Save to Redis with 5 minute expiry
|
||||
await this.redis.set(cacheKey, JSON.stringify(data), {
|
||||
EX: 300 // 5 minutes
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching tickets:', {
|
||||
error: error.message,
|
||||
params,
|
||||
response: error.response?.data
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new GorgiasService();
|
||||
Reference in New Issue
Block a user