fix: global camelCase mapping for all technical data tables
This commit is contained in:
@@ -1,17 +1,23 @@
|
||||
import { Request, Response } from 'express';
|
||||
import * as dataSheetService from '../services/dataSheetService.js';
|
||||
import { toCamelCase } from '../utils/caseMapper.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
export const getAllDataSheets = async (req: Request, res: Response) => {
|
||||
interface AuthRequest extends Request {
|
||||
appUser?: IAppUser;
|
||||
}
|
||||
|
||||
export const getAllDataSheets = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const organizationId = req.appUser?.organizationId;
|
||||
const sheets = await dataSheetService.getAllDataSheets(organizationId);
|
||||
res.json(sheets);
|
||||
res.json(toCamelCase(sheets));
|
||||
} catch (error: unknown) {
|
||||
res.json([]);
|
||||
}
|
||||
};
|
||||
|
||||
export const extractData = async (req: Request, res: Response) => {
|
||||
export const extractData = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const file = req.file;
|
||||
if (!file) {
|
||||
@@ -23,20 +29,20 @@ export const extractData = async (req: Request, res: Response) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const createDataSheet = async (req: Request, res: Response) => {
|
||||
export const createDataSheet = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const organizationId = req.appUser?.organizationId;
|
||||
const newSheet = await dataSheetService.createDataSheet({
|
||||
...req.body,
|
||||
organization_id: organizationId
|
||||
});
|
||||
res.status(201).json(newSheet);
|
||||
res.status(201).json(toCamelCase(newSheet));
|
||||
} catch (error: unknown) {
|
||||
res.json(req.body);
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteDataSheet = async (req: Request, res: Response) => {
|
||||
export const deleteDataSheet = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
await dataSheetService.deleteDataSheet(id as string);
|
||||
@@ -46,17 +52,17 @@ export const deleteDataSheet = async (req: Request, res: Response) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const updateDataSheet = async (req: Request, res: Response) => {
|
||||
export const updateDataSheet = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const id = req.params.id as string;
|
||||
const updatedSheet = await dataSheetService.updateDataSheet(id, req.body);
|
||||
res.json(updatedSheet || req.body);
|
||||
res.json(toCamelCase(updatedSheet || req.body));
|
||||
} catch (error: unknown) {
|
||||
res.json(req.body);
|
||||
}
|
||||
};
|
||||
|
||||
export const getFile = async (req: Request, res: Response) => {
|
||||
export const getFile = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
res.status(404).json({ error: 'File not found' });
|
||||
} catch (error: unknown) {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Request, Response } from 'express';
|
||||
import * as projectService from '../services/projectService.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
import { notificationService } from '../services/notificationService.js';
|
||||
import { toCamelCase } from '../utils/caseMapper.js';
|
||||
|
||||
interface AuthRequest extends Request {
|
||||
appUser?: IAppUser;
|
||||
@@ -11,7 +12,7 @@ export const createProject = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const organizationId = req.appUser?.organizationId;
|
||||
const project = await projectService.createProject({ ...req.body, organizationId });
|
||||
res.status(201).json(project);
|
||||
res.status(201).json(toCamelCase(project));
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
res.status(500).json({ error: message });
|
||||
@@ -23,14 +24,11 @@ export const getAllProjects = async (req: AuthRequest, res: Response) => {
|
||||
const organizationId = req.appUser?.organizationId;
|
||||
const isGlobalAdmin = req.appUser?.email === 'admtracksteel@gmail.com';
|
||||
const { status } = req.query;
|
||||
console.log('getAllProjects controller:', { organizationId, isGlobalAdmin, status });
|
||||
const projects = await projectService.getAllProjects(organizationId, isGlobalAdmin, status as string);
|
||||
console.log('getAllProjects result:', projects?.length);
|
||||
res.json(projects);
|
||||
res.json(toCamelCase(projects));
|
||||
} catch (error: unknown) {
|
||||
console.error('Error in getAllProjects controller:', error);
|
||||
const message = error instanceof Error ? error.message : JSON.stringify(error);
|
||||
console.log('Sending error response:', message);
|
||||
res.status(500).json({ error: message });
|
||||
}
|
||||
};
|
||||
@@ -40,7 +38,7 @@ export const archiveProject = async (req: AuthRequest, res: Response) => {
|
||||
const organizationId = req.appUser?.organizationId;
|
||||
const isGlobalAdmin = req.appUser?.email === 'admtracksteel@gmail.com';
|
||||
const project = await projectService.archiveProject(req.params.id as string, organizationId, isGlobalAdmin);
|
||||
res.json(project);
|
||||
res.json(toCamelCase(project));
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
res.status(500).json({ error: message });
|
||||
@@ -51,7 +49,7 @@ export const getDashboardProjects = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const organizationId = req.appUser?.organizationId;
|
||||
const projects = await projectService.getDashboardProjects(organizationId);
|
||||
res.json(projects);
|
||||
res.json(toCamelCase(projects));
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
res.status(500).json({ error: message });
|
||||
@@ -61,7 +59,7 @@ export const getDashboardProjects = async (req: AuthRequest, res: Response) => {
|
||||
export const getProjectById = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const project = await projectService.getProjectById(req.params.id as string);
|
||||
res.json(project);
|
||||
res.json(toCamelCase(project));
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
res.status(404).json({ error: message });
|
||||
@@ -83,7 +81,7 @@ export const updateProject = async (req: AuthRequest, res: Response) => {
|
||||
});
|
||||
}
|
||||
|
||||
res.json(project);
|
||||
res.json(toCamelCase(project));
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
res.status(500).json({ error: message });
|
||||
|
||||
@@ -1,106 +1,77 @@
|
||||
import { Request, Response } from 'express';
|
||||
import { supabase } from '../config/supabase.js';
|
||||
import { toCamelCase } from '../utils/caseMapper.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
export const getStockItems = async (req: Request, res: Response) => {
|
||||
interface AuthRequest extends Request {
|
||||
appUser?: IAppUser;
|
||||
}
|
||||
|
||||
export const getStockItems = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from('stock_items').select('*');
|
||||
if (error && error.code !== '42P01') throw error;
|
||||
res.json(data || []);
|
||||
res.json(toCamelCase(data || []));
|
||||
} catch (error: unknown) {
|
||||
res.json([]);
|
||||
}
|
||||
};
|
||||
|
||||
export const getStockItemById = async (req: Request, res: Response) => {
|
||||
export const getStockItemById = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from('stock_items').select('*').eq('id', req.params.id).single();
|
||||
if (error) throw error;
|
||||
res.json(data);
|
||||
res.json(toCamelCase(data));
|
||||
} catch (error: unknown) {
|
||||
res.json(null);
|
||||
}
|
||||
};
|
||||
|
||||
export const getStockMovements = async (req: Request, res: Response) => {
|
||||
export const getStockMovements = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from('stock_movements').select('*').eq('stock_item_id', req.params.id);
|
||||
if (error && error.code !== '42P01') throw error;
|
||||
res.json(data || []);
|
||||
res.json(toCamelCase(data || []));
|
||||
} catch (error: unknown) {
|
||||
res.json([]);
|
||||
}
|
||||
};
|
||||
|
||||
export const getStockAuditLogs = async (req: Request, res: Response) => {
|
||||
export const getStockAuditLogs = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from('stock_audit_logs').select('*').eq('stock_item_id', req.params.id);
|
||||
if (error && error.code !== '42P01') throw error;
|
||||
res.json(data || []);
|
||||
res.json(toCamelCase(data || []));
|
||||
} catch (error: unknown) {
|
||||
res.json([]);
|
||||
}
|
||||
};
|
||||
|
||||
export const createStockItem = async (req: Request, res: Response) => {
|
||||
export const createStockItem = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from('stock_items').insert({ ...req.body, organization_id: req.appUser?.organizationId }).select().single();
|
||||
if (error) throw error;
|
||||
res.status(201).json(data);
|
||||
res.status(201).json(toCamelCase(data));
|
||||
} catch (error: unknown) {
|
||||
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
|
||||
}
|
||||
};
|
||||
|
||||
export const updateStockItem = async (req: Request, res: Response) => {
|
||||
export const updateStockItem = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from('stock_items').update(req.body).eq('id', req.params.id).select().single();
|
||||
if (error) throw error;
|
||||
res.json(data);
|
||||
res.json(toCamelCase(data));
|
||||
} catch (error: unknown) {
|
||||
res.json(req.body);
|
||||
}
|
||||
};
|
||||
|
||||
export const adjustStock = async (req: Request, res: Response) => {
|
||||
try {
|
||||
res.json({ success: true });
|
||||
} catch (error: unknown) {
|
||||
res.json({ success: true });
|
||||
}
|
||||
};
|
||||
|
||||
export const consumeStock = async (req: Request, res: Response) => {
|
||||
try {
|
||||
res.json({ success: true });
|
||||
} catch (error: unknown) {
|
||||
res.json({ success: true });
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteStockItem = async (req: Request, res: Response) => {
|
||||
export const deleteStockItem = async (req: AuthRequest, res: Response) => {
|
||||
try {
|
||||
await supabase.from('stock_items').delete().eq('id', req.params.id);
|
||||
res.status(204).send();
|
||||
} catch (error: unknown) {
|
||||
res.status(204).send();
|
||||
}
|
||||
};
|
||||
|
||||
export const updateStockMovement = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from('stock_movements').update(req.body).eq('id', req.params.id).select().single();
|
||||
if (error) throw error;
|
||||
res.json(data);
|
||||
} catch (error: unknown) {
|
||||
res.json(req.body);
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteStockMovement = async (req: Request, res: Response) => {
|
||||
try {
|
||||
await supabase.from('stock_movements').delete().eq('id', req.params.id);
|
||||
res.status(204).send();
|
||||
} catch (error: unknown) {
|
||||
res.status(204).send();
|
||||
}
|
||||
};
|
||||
36
src/server/utils/caseMapper.ts
Normal file
36
src/server/utils/caseMapper.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
/**
|
||||
* Utility to convert snake_case object keys to camelCase
|
||||
*/
|
||||
export const toCamelCase = (obj: any): any => {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(v => toCamelCase(v));
|
||||
} else if (obj !== null && obj !== undefined && obj.constructor === Object) {
|
||||
return Object.keys(obj).reduce(
|
||||
(result, key) => ({
|
||||
...result,
|
||||
[key.replace(/(_\w)/g, m => m[1].toUpperCase())]: toCamelCase(obj[key]),
|
||||
}),
|
||||
{},
|
||||
);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility to convert camelCase object keys to snake_case (for DB inserts)
|
||||
*/
|
||||
export const toSnakeCase = (obj: any): any => {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(v => toSnakeCase(v));
|
||||
} else if (obj !== null && obj !== undefined && obj.constructor === Object) {
|
||||
return Object.keys(obj).reduce(
|
||||
(result, key) => ({
|
||||
...result,
|
||||
[key.replace(/[A-Z]/g, m => `_${m.toLowerCase()}`)]: toSnakeCase(obj[key]),
|
||||
}),
|
||||
{},
|
||||
);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
Reference in New Issue
Block a user