Skip to content

NE-PREP-2024-2025/java

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Payroll Management System

Overview

The Payroll Management System is a Spring Boot-based application designed to manage employee payrolls, including employee details, employment records, deductions, and payslips. The system supports role-based access control with JWT authentication, automated payroll generation, and email notifications for payslip approvals. It uses Spring Data JPA for database interactions and MySQL as the database.

Features

  • Employee Management: CRUD operations for employee personal information, with role-based security (ROLE_MANAGER, ROLE_ADMIN, ROLE_EMPLOYEE).
  • Employment Management: Manage employment details such as department, position, and base salary.
  • Deduction Management: Configure and apply deductions (e.g., EmployeeTax, Pension, MedicalInsurance, Housing, Transport) to payroll calculations.
  • Payroll Processing: Generate payslips for active employees, ensuring deductions do not exceed gross salary. Approve payslips and send email notifications.
  • Security: JWT-based authentication (using email and password) and role-based authorization.
  • Email Notifications: Automated email notifications triggered by database routines when payslip status changes to PAID.

System Flow Diagram

can be found in

Entity-Relationship Diagram (ERD)

The ERD represents the database schema:

erDiagram
    Employee ||--o{ Employment : has
    Employee ||--o{ PaySlip : receives

    Employee {
        Long id PK
        String code UNIQUE
        String firstName
        String lastName
        String email UNIQUE
        String password
        Role role
        String mobile
        LocalDate dateOfBirth
        EmployeeStatus status "ACTIVE, DISABLED"
        boolean emailVerified
    }

    Employment {
        Long id PK
        String code
        Long employee_id FK
        String department
        String position
        BigDecimal baseSalary
        EmploymentStatus status "ACTIVE, INACTIVE"
        LocalDate joiningDate
    }

    Deduction {
        Long id PK
        String code
        String name
        BigDecimal percentage
    }

    PaySlip {
        Long id PK
        Long employee_id FK
        BigDecimal houseAmount
        BigDecimal transportAmount
        BigDecimal employeeTaxedAmount
        BigDecimal pensionAmount
        BigDecimal medicalInsuranceAmount
        BigDecimal otherTaxedAmount
        BigDecimal grossSalary
        BigDecimal netSalary
        int month
        int year
        PaySlipStatus status "PENDING, PAID"
    }
Loading

The diagram is rendered automatically in GitHub and other Markdown viewers that support Mermaid.

Architecture

  • Presentation Layer: RESTful APIs via Spring MVC controllers.
  • Security Layer: JWT-based authentication and role-based authorization using Spring Security.
  • Service Layer: Business logic for employee, employment, deduction, and payroll management.
  • Persistence Layer: Spring Data JPA with Hibernate for PostgreSQL database interactions.
  • Integration Layer: SMTP server for email notifications, triggered by database routines.

Tech Stack

  • Backend Framework: Spring Boot 3.x
  • ORM: Spring Data JPA with Hibernate
  • Database: PostgreSQL
  • Security: Spring Security with JWT (jjwt library)
  • Email: Spring Boot Starter Mail
  • Dependencies:
    • spring-boot-starter-web
    • spring-boot-starter-data-jpa
    • spring-boot-starter-security
    • spring-boot-starter-mail
    • postgresql
    • jjwt
    • lombok
  • Build Tool: Maven
  • Database Migration: Flyway (optional)
  • Testing: JUnit, Mockito
  • Email Testing: MailHog (recommended for local SMTP testing)

POJOs

  1. Employee: id, code, firstName, lastName, email, password, roles, mobile, dateOfBirth, status (ACTIVE, DISABLED)
  2. Employment: id, code, employee (FK), department, position, baseSalary, status (ACTIVE, INACTIVE), joiningDate
  3. Deduction: id, code, name, percentage
  4. PaySlip: id, employee (FK), houseAmount, transportAmount, employeeTaxedAmount, pensionAmount, medicalInsuranceAmount, otherTaxedAmount, grossSalary, netSalary, month, year, status (PENDING, PAID)
  5. EmailNotification: id, employeeId, message, createdAt
  6. DTOs: EmployeeDTO, DeductionDTO, LoginRequest, JwtResponse

Security Implementation

  • Authentication: Via /api/auth/login using email and password, generating a JWT token.
  • Authorization: Role-based access control:
    • ROLE_MANAGER: Manage employees, deductions, and generate payroll.
    • ROLE_ADMIN: Approve payslips.
    • ROLE_EMPLOYEE: View personal details and payslips.
  • JWT: Signed with HS512, expires after 7 days, includes roles.
  • Password Security: Hashed with BCrypt.
  • CSRF/CORS: CSRF disabled for stateless APIs; CORS configurable.

Endpoints

Authentication

  • POST /api/auth/login: Authenticate and return JWT token.
    • Request: {"email": "string", "password": "string"}
    • Response: {"token": "string"}
    • Access: Public

Employee Management

  • POST /api/employee: Create employee (ROLE_MANAGER).
  • GET /api/employee/{id}: Get employee details (ROLE_MANAGER, ROLE_ADMIN, ROLE_EMPLOYEE for self).
  • PUT /api/employee/{id}: Update employee (ROLE_MANAGER).
  • DELETE /api/employee/{id}: Disable employee (ROLE_MANAGER).
  • GET /api/employee/me: Get authenticated employee’s details (ROLE_EMPLOYEE, ROLE_MANAGER, ROLE_ADMIN).

Employment Management

  • POST /api/employment: Create employment record (ROLE_MANAGER).
  • GET /api/employment/{id}: Get employment details (ROLE_MANAGER, ROLE_ADMIN).
  • PUT /api/employment/{id}: Update employment (ROLE_MANAGER).
  • DELETE /api/employment/{id}: Deactivate employment (ROLE_MANAGER).

Deduction Management

  • POST /api/deduction: Create deduction (ROLE_MANAGER).
  • GET /api/deduction/{id}: Get deduction (ROLE_MANAGER).
  • GET /api/deduction/all: Get all deductions (ROLE_MANAGER).
  • PUT /api/deduction/{id}: Update deduction (ROLE_MANAGER).
  • DELETE /api/deduction/{id}: Delete deduction (ROLE_MANAGER).

Payroll Management

  • POST /api/payroll/generate/{month}/{year}: Generate payroll (ROLE_MANAGER).
  • POST /api/payroll/approve/{id}: Approve payslip, trigger email (ROLE_ADMIN).
  • GET /api/payroll/employee/{employeeId}/{month}/{year}: Get employee payslips (ROLE_EMPLOYEE for self, ROLE_MANAGER).
  • GET /api/payroll/{month}/{year}: Get all payslips for month/year (ROLE_MANAGER).

Setup Instructions

  1. Prerequisites:
  • Java 17+
  • Maven 3.8+
  • MySQL 8.0+
  1. Download the zip:

  2. Configure Database:

  • Create a PostgreSQL database named payroll.
  • Update src/main/resources/application.properties:
    spring.datasource.url=jdbc:postgresql://localhost:5432/payroll
    spring.datasource.username=manager
    spring.datasource.password=12345678
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
  1. Configure Email Testing with MailHog:
  • Install and run MailHog using Docker:
    docker run -d -p 1025:1025 -p 8025:8025 --name mailhog mailhog/mailhog
  • Update application.properties for email testing:
    spring.mail.host=localhost
    spring.mail.port=1025
    spring.mail.username=
    spring.mail.password=
    spring.mail.properties.mail.smtp.auth=false
    spring.mail.properties.mail.smtp.starttls.enable=false
  • Access the MailHog web UI at http://localhost:8025 to view captured emails.
  • For production, configure a real SMTP server (e.g., Gmail):
    spring.mail.host=smtp.gmail.com
    spring.mail.port=587
    spring.mail.username=your-email@gmail.com
    spring.mail.password=your-email-password
    spring.mail.properties.mail.smtp.auth=true
    spring.mail.properties.mail.smtp.starttls.enable=true
  1. Initialize Deductions:
  • The data.sql file initializes deductions:
    • EmployeeTax: 30%
    • Pension: 6%
    • MedicalInsurance: 5%
    • Others: 5%
    • Housing: 14%
    • Transport: 14%
  1. Manage Database Triggers:
  • The system uses a PostgreSQL trigger (payslip_status_update) to generate email notifications when a payslip's status changes to PAID.
  • To list all triggers in the database:
    SELECT trigger_name, event_manipulation, event_object_table, action_statement
    FROM information_schema.triggers
    WHERE trigger_schema = 'public';
  • To verify the payslip_status_update trigger:
    SELECT trigger_name, event_manipulation, event_object_table, action_statement
    FROM information_schema.triggers
    WHERE trigger_schema = 'public' AND trigger_name = 'payslip_status_update';
  • To recreate the trigger if missing:
    CREATE OR REPLACE FUNCTION notify_payslip_paid()
    RETURNS TRIGGER AS $$
    BEGIN
        IF (OLD.status = 'PENDING' AND NEW.status = 'PAID') THEN
            INSERT INTO notification (employee_id, message, created_at)
            VALUES (
                NEW.employee_id,
                'Dear ' || 
                (SELECT first_name FROM employees WHERE id = NEW.employee_id) ||
                ', your ' ||
                NEW.month || '/' || NEW.year ||
                ' salary from Institution ' ||
                NEW.net_salary ||
                ' has been credited to your ' ||
                (SELECT code FROM employees WHERE id = NEW.employee_id) ||
                ' account successfully',
                NOW()
            );
        END IF;
        RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;
    
    DROP TRIGGER IF EXISTS payslip_status_update ON payslips;
    
    CREATE TRIGGER payslip_status_update
    AFTER UPDATE ON payslips
    FOR EACH ROW
    EXECUTE FUNCTION notify_payslip_paid();
  1. Build and Run:

    mvn clean install
    mvn spring-boot:run
  2. Diagrams:

  • The system flow diagram and entity-relationship diagram (ERD) are created using Mermaid and render automatically in GitHub and other Markdown viewers that support Mermaid.

Usage

  1. Authenticate: POST to /api/auth/login with {"email": "employee@example.com", "password": "password"} to get a JWT token. Use Bearer <token> in the Authorization header.
  2. Manage Employees: Use /api/employee endpoints (ROLE_MANAGER for creation/updates).
  3. Manage Deductions: Use /api/deduction endpoints (ROLE_MANAGER).
  4. Generate Payroll: Use /api/payroll/generate/{month}/{year} (ROLE_MANAGER) and approve with /api/payroll/approve/{id} (ROLE_ADMIN).
  5. Test Email Notifications:
  • Approve a payslip to trigger an email notification.
  • View the email in MailHog’s web UI (http://localhost:8025).
  • Verify the trigger by checking the email_notifications table:
    SELECT * FROM email_notifications;
  1. View Payslips: Employees use /api/payroll/employee/{employeeId}/{month}/{year}; managers use /api/payroll/{month}/{year}.

Database Trigger

A PostgreSQL trigger generates email notifications when a payslip's status changes to PAID:

CREATE OR REPLACE FUNCTION notify_payslip_paid()
RETURNS TRIGGER AS $$
BEGIN
    IF (OLD.status = 'PENDING' AND NEW.status = 'PAID') THEN
        INSERT INTO notification (employee_id, message, created_at)
        VALUES (
            NEW.employee_id,
            'Dear ' || 
            (SELECT first_name FROM employees WHERE id = NEW.employee_id) ||
            ', your ' ||
            NEW.month || '/' || NEW.year ||
            ' salary from Institution ' ||
            NEW.net_salary ||
            ' has been credited to your ' ||
            (SELECT code FROM employees WHERE id = NEW.employee_id) ||
            ' account successfully',
            NOW()
        );
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER payslip_status_update
AFTER UPDATE ON payslips
FOR EACH ROW
EXECUTE FUNCTION notify_payslip_paid();

The EmailService processes these notifications via the configured SMTP server (MailHog for testing).

Project Structure

payroll-management-system/
├── src/
│   ├── main/
│   │   ├── java/com/sylvain/payroll_management_system/
│   │   │   ├── PayrollManagementSystemApplication.java
│   │   │   ├── config/
│   │   │   │   ├── SwaggerConfig.java
│   │   │   │   ├── ThymeleafConfig.java
│   │   │   ├── controller/
│   │   │   │   ├── AuthController.java
│   │   │   │   ├── DeductionController.java
│   │   │   │   ├── EmployeeController.java
│   │   │   │   ├── EmploymentController.java
│   │   │   │   ├── PaySlipController.java
│   │   │   ├── dto/
│   │   │   │   ├── AdminCreateDto.java
│   │   │   │   ├── AuthResponseDto.java
│   │   │   │   ├── DeductionRegisterDto.java
│   │   │   │   ├── DeductionUpdateDto.java
│   │   │   │   ├── EmailDto.java
│   │   │   │   ├── EmployeeRegisterDto.java
│   │   │   │   ├── EmployeeResponseDto.java
│   │   │   │   ├── EmploymentCreateDto.java
│   │   │   │   ├── LoginDto.java
│   │   │   │   ├── ResetPasswordDto.java
│   │   │   │   ├── SuccessResponse.java
│   │   │   │   ├── VerifyDto.java
│   │   │   ├── email/
│   │   │   │   ├── EmailService.java
│   │   │   ├── exceptions/
│   │   │   │   ├── GlobalExceptionHandler.java
│   │   │   │   ├── InvalidJwtException.java
│   │   │   ├── model/
│   │   │   │   ├── DeductionModel.java
│   │   │   │   ├── EmployeeModel.java
│   │   │   │   ├── EmploymentModel.java
│   │   │   │   ├── PaySlipModel.java
│   │   │   ├── repository/
│   │   │   │   ├── DeductionRepository.java
│   │   │   │   ├── EmployeeRepository.java
│   │   │   │   ├── EmploymentRepository.java
│   │   │   │   ├── PaySlipRepository.java
│   │   │   ├── security/
│   │   │   │   ├── ApplicationConfig.java
│   │   │   │   ├── CustomUserDetail.java
│   │   │   │   ├── EmployeeServiceImplementation.java
│   │   │   │   ├── EmployeeUserDetail.java
│   │   │   │   ├── JwtConstant.java
│   │   │   │   ├── JwtProvider.java
│   │   │   │   ├── JwtTokenValidator.java
│   │   │   │   ├── UserServiceImplementation.java
│   │   │   ├── service/
│   │   │   │   ├── DeductionService.java
│   │   │   │   ├── EmployeeService.java
│   │   │   │   ├── EmploymentService.java
│   │   │   │   ├── PaySlipService.java
│   │   │   ├── utils/
│   │   │   │   ├── CodeGenerator.java
│   │   │   │   ├── EmailVerifiedStatus.java
│   │   │   │   ├── EmployeeStatus.java
│   │   │   │   ├── EmploymentStatus.java
│   │   │   │   ├── JwtUtils.java
│   │   │   │   ├── NotificationStatus.java
│   │   │   │   ├── OtpType.java
│   │   │   │   ├── PasswordVerifiedStatus.java
│   │   │   │   ├── PaySlipStatus.java
│   │   │   │   ├── Role.java
│   │   │   ├── validator/
│   │   │   │   ├── PageableValidator.java
│   │   │   │   ├── PasswordConstraintValidator.java
│   │   │   │   ├── RwandaNationalIdValidator.java
│   │   │   │   ├── RwandanPhoneNumberValidator.java
│   │   │   │   ├── ValidPassword.java
│   │   │   │   ├── ValidRwandaId.java
│   │   │   │   ├── ValidRwandanPhoneNumber.java
│   │   ├── resources/
│   │   │   ├── application.properties
│   │   │   ├── db/migration/
│   │   │   │   ├── V1__create_payroll_trigger.sql
│   │   │   ├── templates/
│   │   │   │   ├── AccountVerificationEmailTemplate.html
│   │   │   │   ├── PayrollNotificationTemplate.html
│   │   │   │   ├── PasswordResetEmailTemplate.html
│   ├── test/
│   │   ├── java/com/sylvain/payroll_management_system/
│   │   │   ├── PayrollManagementSystemApplicationTests.java
│   │   │   ├── service/
│   │   │   │   ├── PaySlipServiceTest.java
├── pom.xml
├── README.md

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published