diff --git a/src/server/controllers/dataSheetController.ts b/src/server/controllers/dataSheetController.ts index 6ce2d32..a149bf9 100644 --- a/src/server/controllers/dataSheetController.ts +++ b/src/server/controllers/dataSheetController.ts @@ -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) { diff --git a/src/server/controllers/projectController.ts b/src/server/controllers/projectController.ts index b4f77ab..b650199 100644 --- a/src/server/controllers/projectController.ts +++ b/src/server/controllers/projectController.ts @@ -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 }); diff --git a/src/server/controllers/stockController.ts b/src/server/controllers/stockController.ts index c87d0aa..ff86d77 100644 --- a/src/server/controllers/stockController.ts +++ b/src/server/controllers/stockController.ts @@ -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(); - } }; \ No newline at end of file diff --git a/src/server/utils/caseMapper.ts b/src/server/utils/caseMapper.ts new file mode 100644 index 0000000..b4247ec --- /dev/null +++ b/src/server/utils/caseMapper.ts @@ -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; +};