import { prisma } from '../config/database'; import { Prisma } from '@prisma/client'; import { config } from '../config'; import { logger } from '../config/logger'; import jwt from 'jsonwebtoken'; import { createCategory, createCategoryResponse, deleteCategoryResponse, updateCategory, updateCategoryResponse, ListCategoriesResponse, Category } from '../types/categories.type'; import { UnauthorizedError, ValidationError, ForbiddenError } from '../middleware/errorHandler'; import { auditService } from './audit.service'; import { AuditAction } from '@prisma/client'; export class CategoryService { async listCategories(): Promise { try { const categories = await prisma.category.findMany(); return { code: 200, message: 'Categories fetched successfully', data: { categories: categories as unknown as Category[], total: categories.length } }; } catch (error) { logger.error('Failed to list categories', { error }); throw error; } } async createCategory(token: string, category: createCategory): Promise { try { const decoded = jwt.verify(token, config.jwt.secret) as { id: number; username: string; email: string; roleCode: string }; const newCategory = await prisma.category.create({ data: category }); auditService.log({ userId: decoded.id, action: AuditAction.CREATE, entityType: 'Category', entityId: newCategory.id, newValue: { name: newCategory.name as { th: string; en: string }, slug: newCategory.slug, description: newCategory.description as { th: string; en: string } }, }); return { code: 200, message: 'Category created successfully', data: { id: newCategory.id, name: newCategory.name as { th: string; en: string }, slug: newCategory.slug, description: newCategory.description as { th: string; en: string }, created_by: decoded.id, } }; } catch (error) { logger.error('Failed to create category', { error }); await auditService.logSync({ userId: 0, action: AuditAction.ERROR, entityType: 'Category', entityId: 0, metadata: { operation: 'create_category', error: error instanceof Error ? error.message : String(error) } }); throw error; } } async updateCategory(token: string, id: number, category: updateCategory): Promise { try { const decoded = jwt.verify(token, config.jwt.secret) as { id: number; username: string; email: string; roleCode: string }; const updatedCategory = await prisma.category.update({ where: { id }, data: category }); auditService.log({ userId: decoded.id, action: AuditAction.UPDATE, entityType: 'Category', entityId: id, newValue: { name: updatedCategory.name as { th: string; en: string }, slug: updatedCategory.slug, description: updatedCategory.description as { th: string; en: string } }, }); return { code: 200, message: 'Category updated successfully', data: { id: updatedCategory.id, name: updatedCategory.name as { th: string; en: string }, slug: updatedCategory.slug, description: updatedCategory.description as { th: string; en: string }, updated_by: decoded.id, } }; } catch (error) { logger.error('Failed to update category', { error }); await auditService.logSync({ userId: 0, action: AuditAction.ERROR, entityType: 'Category', entityId: 0, metadata: { operation: 'update_category', error: error instanceof Error ? error.message : String(error) } }); throw error; } } async deleteCategory(token: string, id: number): Promise { try { const decoded = jwt.verify(token, config.jwt.secret) as { id: number; username: string; email: string; roleCode: string }; const deletedCategory = await prisma.category.delete({ where: { id } }); auditService.log({ userId: decoded.id, action: AuditAction.DELETE, entityType: 'Category', entityId: id, newValue: { name: deletedCategory.name as { th: string; en: string }, slug: deletedCategory.slug, description: deletedCategory.description as { th: string; en: string } }, }); return { code: 200, message: 'Category deleted successfully', }; } catch (error) { logger.error('Failed to delete category', { error }); await auditService.logSync({ userId: 0, action: AuditAction.ERROR, entityType: 'Category', entityId: 0, metadata: { operation: 'delete_category', error: error instanceof Error ? error.message : String(error) } }); throw error; } } }