Skip to content

Service Template

This template provides a standard structure for creating new services in the PRS system, extending the BaseService class.

Usage Instructions

  1. Replace EntityName with your entity name
  2. Implement the methods below
  3. Register the service in the container

Template Code

JavaScript
/**
 * Template for creating a new service
 * 
 * Instructions:
 * 1. Replace EntityName with your entity name
 * 2. Implement the methods below
 * 3. Register the service in the container
 */
const BaseService = require('../../app/services/baseService');

class EntityNameService extends BaseService {
  constructor({ entityNameRepository, db, constants, clientErrors }) {
    super({ repository: entityNameRepository });
    this.entityNameRepository = entityNameRepository;
    this.db = db;
    this.constants = constants;
    this.clientErrors = clientErrors;
  }

  /**
   * Get all entities with optional filtering
   * 
   * @param {Object} query - Query parameters for filtering
   * @returns {Promise<Object>} - Paginated list of entities
   */
  async getAll(query = {}) {
    const { page, limit, ...filters } = query;

    // Build query options
    const options = {
      page: parseInt(page, 10) || 1,
      limit: parseInt(limit, 10) || 10,
      where: {},
      order: [['createdAt', 'DESC']],
    };

    // Add filters to query
    if (filters.status) {
      options.where.status = filters.status;
    }

    // Add other filters as needed

    return this.entityNameRepository.findAll(options);
  }

  /**
   * Get entity by ID
   * 
   * @param {number} id - Entity ID
   * @returns {Promise<Object>} - Entity object
   */
  async getById(id) {
    return this.entityNameRepository.findOne({
      where: { id },
      include: [
        // Add associations as needed
      ],
    });
  }

  /**
   * Create a new entity
   * 
   * @param {Object} payload - Entity data and transaction
   * @param {Object} payload.transaction - Sequelize transaction
   * @returns {Promise<Object>} - Created entity
   */
  async create(payload) {
    const { transaction, ...data } = payload;

    // Perform any business logic or validation

    // Create entity
    const entity = await this.entityNameRepository.create(data, { transaction });

    // Perform any additional operations

    return entity;
  }

  // Additional methods...
}

Key Features

  1. Inheritance: Extends BaseService for common functionality
  2. Business Logic: Implements business logic and validation
  3. Transaction Management: Handles database transactions
  4. Error Handling: Uses standardized error handling
  5. Repository Pattern: Delegates data access to repositories

Common Methods

  1. getAll: Retrieve all entities with optional filtering and pagination
  2. getById: Retrieve a single entity by ID
  3. create: Create a new entity
  4. update: Update an existing entity
  5. delete: Delete an entity

Business Logic Example

JavaScript
/**
 * Custom business logic method example
 * 
 * @param {Object} payload - Method parameters
 * @returns {Promise<Object>} - Result
 */
async customBusinessLogic(payload) {
  const { id, action, transaction } = payload;

  // Get entity
  const entity = await this.entityNameRepository.findOne({
    where: { id },
    transaction,
  });

  if (!entity) {
    throw this.clientErrors.NOT_FOUND({
      message: 'Entity not found',
    });
  }

  // Perform business logic based on action
  switch (action) {
    case 'approve':
      // Approval logic
      if (entity.status !== 'PENDING') {
        throw this.clientErrors.BAD_REQUEST({
          message: 'Entity cannot be approved',
        });
      }

      await this.entityNameRepository.update(
        { id },
        { status: 'APPROVED' },
        { transaction }
      );
      break;

    case 'reject':
      // Rejection logic
      if (entity.status !== 'PENDING') {
        throw this.clientErrors.BAD_REQUEST({
          message: 'Entity cannot be rejected',
        });
      }

      await this.entityNameRepository.update(
        { id },
        { status: 'REJECTED' },
        { transaction }
      );
      break;

    default:
      throw this.clientErrors.BAD_REQUEST({
        message: 'Invalid action',
      });
  }

  // Get updated entity
  const updatedEntity = await this.entityNameRepository.findOne({
    where: { id },
    transaction,
  });

  return updatedEntity;
}

Best Practices

  1. Extend BaseService for common functionality
  2. Implement business logic in service methods
  3. Use transactions for write operations
  4. Handle errors using standardized error classes
  5. Delegate data access to repositories
  6. Return complete objects after create/update operations